DIRECTORY BlackCherry, Icons, IO, PFS, PFSBackdoor, PFSNames, RefText, Rope, UnixSysCalls, UnixTypes; BlackCherryPFSImpl: CEDAR PROGRAM IMPORTS BlackCherry, Icons, IO, PFS, PFSBackdoor, PFSNames, RefText, Rope, UnixSysCalls = BEGIN OPEN BlackCherry; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; squirrelAwayMyStartingDir: PFS.PATH; PFSFullName: PROC [ fileName: ROPE, wDir: ROPE ¬ NIL ] RETURNS [ fullName: ROPE ] ~ { BEGIN ENABLE PFS.Error => { Report["\n***PFS.Error: %g\n", [rope[error.explanation]] ]; IF error.code = $illegalName THEN GOTO tryAgain ELSE GOTO Bogus }; fullNamePath: PFS.PATH ¬ PFSNames.ExpandName[PFS.PathFromRope[fileName], PFS.PathFromRope[wDir]]; fullName ¬ PFS.RopeFromPath[fullNamePath]; EXITS Bogus => { ERROR BadName }; tryAgain => NULL; END; BEGIN BEGIN ENABLE PFS.Error => { Report["\n***PFS.Error: %g (%g)\n", [rope[error.explanation]], [rope[fileName]] ]; GOTO Bogus2 }; temp: REF TEXT ¬ RefText.ObtainScratch[RefText.line]; temp.length ¬ 0; FOR i: INT IN [0..fileName.Length[]) DO c: CHAR ~ fileName.Fetch[i]; IF (c = ' ) OR ( c = '\t ) THEN LOOP; [] ¬ RefText.AppendChar[temp, c]; ENDLOOP; fileName ¬ Rope.FromRefText[temp]; RefText.ReleaseScratch[temp]; fullName ¬ PFS.RopeFromPath[ PFSNames.ExpandName[PFS.PathFromRope[fileName], PFS.PathFromRope[wDir]] ]; EXITS Bogus2 => { ERROR BadName }; END; END; }; PFSFileOpenOrCreate: PROC [ name: ROPE, how: ATOM ] RETURNS [ fileData: BCFileData] ~ { ENABLE PFS.Error => { Report["\n***PFS.Error: %g (%g)\n", [rope[error.explanation]], [rope[name]] ]; GOTO cant; }; retry: BOOL ¬ FALSE; fullFName: PFS.PATH; ownerOnlyMode: UnixTypes.Mode ~ [ owner: [true, true, false] ]; readOnly: BOOL ~ how = $openRO; ro: REF BOOL ~ NEW[BOOL ¬ readOnly]; clientData: REF ANY ~ ro; DoCreate: PROC = { strm: STREAM ¬ PFS.StreamOpen[PFS.PathFromRope[fileData.name], $create ]; fd: UnixTypes.FD ¬ PFSBackdoor.FDFromOpenStream[strm]; [] ¬ UnixSysCalls.FChMod[fd, ownerOnlyMode]; strm.Close[]; IF retry THEN fullFName ¬ PFS.FileInfo[PFS.PathFromRope[fileData.name]].fullFName; }; fileData ¬ NEW[BCFileDataRec ¬ [name: name, clientData: clientData] ]; IF how = $create THEN DoCreate[]; fullFName ¬ PFS.FileInfo[PFS.PathFromRope[fileData.name] ! PFS.Error => IF ( error.code = $unknownFile ) THEN SELECT TRUE FROM ( how = $openOrCreate ) => { retry ¬ TRUE; DoCreate[]; CONTINUE }; ( how = $openRO ) => { Report["\n*** ReadOnly requested but %g doesn't exist\n", [rope[name]] ]; GOTO cant; }; ENDCASE => REJECT; ].fullFName; fileData.name ¬ PFS.RopeFromPath[fullFName]; IF NOT readOnly THEN fileData.writeStream ¬ PFS.StreamOpen[fullFName, $write ! PFS.Error => IF ( error.code = $unknownFile ) AND ( how = $openOrCreate ) THEN { retry ¬ TRUE; DoCreate[]; CONTINUE } ELSE REJECT ]; IF retry THEN fileData.writeStream ¬ PFS.StreamOpen[fullFName, $write ! PFS.Error => Report["\n**** PFS.Error: %g, during PFSFileOpenOrCreate\n", [rope[error.explanation]]] ]; fileData.readStream ¬ PFS.StreamOpen[ fullFName ! PFS.Error => Report["\n**** PFS.Error: %g, during PFSFileOpenOrCreate\n", [rope[error.explanation]]] ]; EXITS cant => ERROR OpenFailed; }; PFSSetByteCount: PROC [ fileData: BCFileData, bytes: INT ] ~ { ro: REF BOOL ~ NARROW[fileData.clientData]; IF ro­ THEN RETURN; fileData.writeStream ¬ PFS.StreamOpen[PFS.PathFromRope[fileData.name], $write ]; fileData.writeStream.SetLength[bytes]; fileData.writeStream.Close[]; fileData.writeStream ¬ NIL; }; PFSIconSetter: PROC[iconFileName: ROPE] = { iconFile: PFS.PATH ¬ PFSNames.ExpandName[PFS.PathFromRope[iconFileName], squirrelAwayMyStartingDir]; iconFileRope: ROPE ~ PFS.RopeFromPath[iconFile]; BlackCherry.msgSetIcon ¬ Icons.NewIconFromFile[iconFileRope, 1]; IF BlackCherry.msgSetIcon = unInit THEN BlackCherry.msgSetIcon ¬ tool ELSE BlackCherry.msgIcon ¬ Icons.NewIconFromFile[iconFileRope, 2]; }; Init: PROC = { procs: BlackCherry.FileProcs ¬ NEW[BlackCherry.FileProcsRec ¬ [ fullName: PFSFullName, openOrCreate: PFSFileOpenOrCreate, setByteCount: PFSSetByteCount, iconSetter: PFSIconSetter ] ]; BlackCherry.RegisterFileProcs[procs]; squirrelAwayMyStartingDir ¬ PFS.GetWDir[]; }; Init[]; END.  BlackCherryPFSImpl.mesa Copyright Σ 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Bill Jackson (bj) July 19, 1989 6:38:17 pm PDT Willie-sue, March 13, 1992 3:47 pm PST Initial PCedar version try getting rid of spaces and tabs in the name Κ‰•NewlineDelimiter –(cedarcode) style˜šœ™Icodešœ ΟeœC™NK™.K™&K™—šΟk ˜ Kšœ ˜ K˜Kšžœ˜Kšžœ˜K˜ K˜ K˜Kšœ˜K˜ K˜ K˜—šΟbœžœž˜!šž˜Kšœžœžœ4˜O—K˜Kšœžœžœ ˜K˜Kšžœžœžœ˜Kšžœžœžœžœ˜headšΟz™šœžœžœ˜$K˜—šΟn œžœ žœžœžœžœ žœ˜Ušžœžœžœ ˜Kšœ;˜;Kš žœžœžœ žœžœ˜?Kšœ˜—Kš œžœžœžœžœ˜aKšœ žœ˜*šž˜Kšœ žœ ˜Kšœ žœ˜Kšžœ˜—K™.šž˜šžœžœžœ`žœ ˜~Kšœžœžœ'˜5K˜šžœžœžœž˜'Kšœžœ˜Kšžœ žœ žœžœ˜'K˜!Kšžœ˜—K˜"Kšœ˜Kšœ žœ#žœžœ˜gšž˜Kšœ žœ ˜—Kšžœ˜—Kšžœ˜—K˜K˜—š ‘œžœ žœžœžœ˜Wšžœžœ ˜KšœN˜NKšžœ˜ K˜—Kšœžœžœ˜Kšœ žœžœ˜K˜?Kšœ žœ˜Kš œžœžœžœžœ ˜$Kšœ žœžœ˜š‘œžœ˜Kšœžœžœ žœ(˜IKšœžœ&˜6K˜,K˜ Kšžœžœ žœ žœ(˜RK˜—Kšœ žœ8˜FKšžœžœ ˜!K˜šœ žœ žœžœ ˜Gšžœž˜%šžœžœž˜Kšœ%žœžœ˜Bšœ˜KšœI˜IKšžœ˜ K˜—Kšžœžœ˜Kšœ ˜ ——K˜—Kšœžœ˜,š žœžœ žœžœ žœ ˜[Kš žœžœžœ žœžœžœž˜tKšœ˜—Kšžœžœžœ žœd˜―Kšœžœžœe˜šKšžœ žœ ˜K˜K˜—š‘œžœ žœ˜>Kšœžœžœžœ˜+Kšžœžœžœ˜Kšœžœ žœ'˜PKšœ&˜&Kšœ˜Kšœžœ˜K˜K˜—š‘ œžœžœ˜+Kšœ žœžœžœ8˜dKšœžœžœ˜0K˜@Kšžœ!žœžœ>˜ˆKšœ˜K˜—š‘œžœ˜šœžœ˜?Kšœ˜Kšœ"˜"Kšœ˜Kšœ˜K˜—Kšœ%˜%Kšœžœ ˜*K˜K˜—K˜—K˜Kšžœ˜K˜—K˜—…—"΅