`VSyntax10.Scn.FntJSStampElemsAlloc6 Oct 98i?p_VersionElemsAllocBeg#Syntax10.Scn.FntWindows PowerMac LinuxLinuxWindows#Syntax10.Scn.FntWINDOWS VERSIONPowerMac#Syntax10.Scn.FntPOWERMAC VERSIONLinux  p_VersionElemsAllocEnd# 8FoldElemsNew#Syntax10.Scn.Fnt (**************************************************** Revision History: 15.11.96: CM String.Cap removed 960126: GO added Writer object ****************************************************) 8Gp_#Syntax10.Scn.FntWindows PowerMac LinuxLinuxWindows#Syntax10.Scn.Fnt, Win32PowerMac#Syntax10.Scn.Fnt, Macintosh, SysLinux p_<p_#Syntax10.Scn.FntWindows PowerMac LinuxLinuxWindows#Syntax10.Scn.Fnt))noErr = Directories.noErr; (* no error *)PowerMac#Syntax10.Scn.FntnoErr = Directories.noErr; (* no error *) eofErr = -39; (* logical end of file reached *) fnfErr = -43; (* directory not found or incomplete pathname *)Linux )p_W8#Syntax10.Scn.FntFF BEGIN Texts.WriteLn(w); Texts.Append(Oberon.Log, w.buf) END LogLn; 8*8#Syntax10.Scn.FntSS BEGIN Texts.WriteString(w, str); Texts.Append(Oberon.Log, w.buf) END LogString; 8<R8#Syntax10.Scn.Fnt VAR clone: FolderElem; BEGIN IF de = NIL THEN NEW(clone); de := clone END; folder.Copy^(de); de(FolderElem).dir := folder.dir END Copy; 8m8#Syntax10.Scn.Fntqq BEGIN FMElems.InitFolderElem(e, name, pattern, sortOrder, attributes, open); e.dir := dir END InitFolderElem; 8PX8#Syntax10.Scn.Fnt BEGIN len := SHORT(LEN(buffer)); Files.ReadBytes(r.r, buffer, len); IF r.r.eof THEN len := len - SHORT(r.r.res) END END GetBytes; 8Kn8#Syntax10.Scn.Fntpp BEGIN IF len = 0 THEN Files.Register(w.file) ELSE Files.WriteBytes(w.r, buffer, len) END END PutBytes; 8i8#Syntax10.Scn.Fnt33 BEGIN RETURN elem.name = name END CheckIdentity; 8'p#Syntax10.Scn.FntWindows PowerMac LinuxLinuxWindowsSyntax10.Scn.Fntpl8FoldElemsNew#Syntax10.Scn.Fntrr VAR e: FMElems.Elem; f: FolderElem; dir: Directories.Directory; path: FMDevObj.Path; size, date, time: LONGINT; file: Files.File; fullName: FMDevObj.Path; BEGIN continue := TRUE; IF (name = ".") OR (name = "..") THEN RETURN END; IF isDir THEN COPY(d.path, path); devObj.Append(path, name); dir := Directories.This(path); IF dir = NIL THEN RETURN END; NEW(f); InitFolderElem(f, name, folder.pattern, folder.sortOrder, folder.attributes, FALSE, dir); enumerateList.Insert(f) ELSIF Strings.Match(name, pat) THEN size := 0; date := 0; time := 0; IF setData THEN COPY(d.path, fullName); devObj.Append(fullName, name); file := Files.Old(fullName); IF file # NIL THEN Files.GetDate(file, time, date); size := Files.Length(file) END END; NEW(e); FMElems.InitElem(e, name, size, date, time); enumerateList.Insert(e) END END InsertDirEntry; 8rPROCEDURE InsertDirEntry (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);PowerMacSyntax10.Scn.Fntp8FoldElemsNew#Syntax10.Scn.Fnt?? VAR e: FMElems.Elem; f: FolderElem; dir: Directories.Directory; path: FMDevObj.Path; size, date, time: LONGINT; file: Files.File; fullName: FMDevObj.Path; BEGIN continue := TRUE; IF isDir THEN COPY(d.path, path); devObj.Append(path, name); dir := Directories.This(path); IF dir = NIL THEN RETURN END; NEW(f); InitFolderElem(f, name, folder.pattern, folder.sortOrder, folder.attributes, FALSE, dir); enumerateList.Insert(f) ELSIF Strings.Match(name, pat) THEN size := 0; date := 0; time := 0; IF setData THEN COPY(d.path, fullName); devObj.Append(fullName, name); file := Files.Old(fullName); IF file # NIL THEN Files.GetDate(file, time, date); size := Files.Length(file) END END; NEW(e); FMElems.InitElem(e, name, size, date, time); enumerateList.Insert(e) END END InsertDirEntry; 8rPROCEDURE InsertDirEntry (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);Linux pl8#Syntax10.Scn.Fntrr VAR e: FMElems.Elem; f: FolderElem; dir: Directories.Directory; path: FMDevObj.Path; size, date, time: LONGINT; file: Files.File; fullName: FMDevObj.Path; BEGIN continue := TRUE; IF (name = ".") OR (name = "..") THEN RETURN END; IF isDir THEN COPY(d.path, path); devObj.Append(path, name); dir := Directories.This(path); IF dir = NIL THEN RETURN END; NEW(f); InitFolderElem(f, name, folder.pattern, folder.sortOrder, folder.attributes, FALSE, dir); enumerateList.Insert(f) ELSIF Strings.Match(name, pat) THEN size := 0; date := 0; time := 0; IF setData THEN COPY(d.path, fullName); devObj.Append(fullName, name); file := Files.Old(fullName); IF file # NIL THEN Files.GetDate(file, time, date); size := Files.Length(file) END END; NEW(e); FMElems.InitElem(e, name, size, date, time); enumerateList.Insert(e) END END InsertDirEntry; 8pl88`N8#Syntax10.Scn.Fnt VAR e: FMElems.Elem; dir: Directories.Directory; fullName: FMDevObj.Path; f: FolderElem; file: Files.File; size, date, time: LONGINT; BEGIN WITH parent: FolderElem DO COPY(parent.dir.path, fullName); d.Append(fullName, name); dir := Directories.This(fullName); IF dir # NIL THEN NEW(f); InitFolderElem(f, name, parent.pattern, parent.sortOrder, parent.attributes, FALSE, dir); RETURN f ELSE file := Files.Old(fullName); IF file # NIL THEN Files.GetDate(file, time, date); size := Files.Length(file); NEW(e); FMElems.InitElem(e, name, size, date, time); RETURN e END END ELSE END; RETURN NIL END GetElem; 8V8#Syntax10.Scn.Fnt VAR i: INTEGER; BEGIN WITH folder: FolderElem DO COPY(folder.dir.path, path); i := 0; WHILE path[i] # 0X DO INC(i) END; IF (i > 0) & (path[i-1] # d.delimiter) THEN path[i] := d.delimiter; path[i+1] := 0X END ELSE END END GetPath; 8t8#Syntax10.Scn.Fnt VAR f: FolderElem; pattern: ARRAY 2 OF CHAR; BEGIN IF trashE # NIL THEN pattern := "*"; NEW(f); InitFolderElem(f, trashE.name, pattern, sortOrder, attributes, FALSE, trashE.dir); RETURN f END; RETURN NIL END GetTrash; 8d8#Syntax10.Scn.Fnt VAR r: Reader; fullName: FMDevObj.Path; BEGIN d.GetPath(parent, fullName); d.Append(fullName, elem.name); NEW(r); r.file := Files.Old(fullName); IF r.file # NIL THEN Files.Set(r.r, r.file, 0); RETURN r END; RETURN NIL END NewReader; 8d8#Syntax10.Scn.Fnt VAR w: Writer; fullName: FMDevObj.Path; BEGIN d.GetPath(parent, fullName); d.Append(fullName, elem.name); NEW(w); w.file := Files.New(fullName); IF w.file # NIL THEN Files.Set(w.r, w.file, 0); RETURN w END; RETURN NIL END NewWriter; 8W8#Syntax10.Scn.Fnt VAR fullName: FMDevObj.Path; BEGIN d.done := FALSE; WITH parent: FolderElem DO COPY(parent.dir.path, fullName); d.Append(fullName, name); Directories.Create(fullName); d.done := Directories.res = noErr; ELSE END END NewDirectory; 868#Syntax10.Scn.Fnt VAR i, j: INTEGER; name: ARRAY 256 OF CHAR; d, d0: Directories.Directory; BEGIN d := Directories.This(curDirName); d0 := Directories.Startup(); i := 0; WHILE (d0.path[i] # 0X) & (CAP(d0.path[i]) = CAP(d.path[i])) DO INC(i) END; IF (d0.path[i] = 0X) & ((d.path[i] = 0X) OR (d.path[i] = Directories.delimiter)) THEN IF d.path[i] = Directories.delimiter THEN name[0] := "$"; INC(i); j := 0; REPEAT INC(j); name[j] := d.path[i]; INC(i) UNTIL name[j] = 0X ELSE name := "$" END ELSE COPY(d.path, name) END; i := 0; WHILE name[i] # 0X DO INC(i) END; IF i < 32 THEN COPY(name, curDirName) ELSE curDirName[31] := 0X; j := 31; REPEAT DEC(i); DEC(j); curDirName[j] := name[i] UNTIL j = 1; curDirName[0] := "*" END END SetDirName; 8N88[878i8#Syntax10.Scn.Fnt VAR oldFullName, newFullName: FMDevObj.Path; res: INTEGER; BEGIN d.done := FALSE; WITH parent: FolderElem DO IF d.GetElem(parent, name) = NIL THEN COPY(parent.dir.path, oldFullName); d.Append(oldFullName, elem.name); COPY(parent.dir.path, newFullName); d.Append(newFullName, name); IF elem IS FMElems.FolderElem THEN Directories.Rename(oldFullName, newFullName); d.done := Directories.res = noErr ELSE Files.Rename(oldFullName, newFullName, res); d.done := res = noErr END END ELSE END END Rename; 8OC8Syntax10.Scn.FntA8FoldElemsNew#Syntax10.Scn.Fnt VAR fullName: FMDevObj.Path; res: INTEGER; BEGIN COPY(parent.dir.path, fullName); d.Append(fullName, elem.name); Files.Delete(fullName, res); d.done := res = noErr; IF ~d.done THEN LogString(elem.name); LogString(" deleting failed"); LogLn END END DeleteFile; 8?&8#Syntax10.Scn.Fnt VAR list: FMDevObj.List; iter: FMDevObj.Iterator; e: FMElems.Elem; msg: FMDevObj.NotifyMsg; fullName: FMDevObj.Path; BEGIN WITH elem: FolderElem DO COPY(parent.dir.path, fullName); d.Append(fullName, elem.name); list := d.NewSortList(elem); d.Enumerate(elem, list, "*"); iter := FMDevObj.NewIterator(list); IF iter # NIL THEN WHILE iter.NextElem(e) DO IF e IS FolderElem THEN DeleteDir(elem, e(FolderElem)) ELSE DeleteFile(elem, e) END END END; Kernel.GC; Directories.Delete(fullName); d.done := Directories.res = noErr; IF ~d.done THEN LogString(elem.name); LogString(" deleting failed"); LogLn END END END DeleteDir;8, PROCEDURE DeleteFile (parent: FolderElem; elem: FMElems.Elem); PROCEDURE DeleteDir (parent: FolderElem; elem: FMElems.Elem); BEGIN WITH parent: FolderElem DO WITH elem: FolderElem DO Kernel.GC; DeleteDir(parent, elem) ELSE DeleteFile(parent, elem) END ELSE END END Delete; 8$p_#Syntax10.Scn.FntWindows PowerMac LinuxLinuxWindowsSyntax10.Scn.FntuQ8FoldElemsNew#Syntax10.Scn.Fnt VAR reader: FMDevObj.Reader; fullName: FMDevObj.Path; file: Files.File; r: Files.Rider; len: INTEGER; BEGIN d.done := FALSE; WITH destParent: FolderElem DO reader:= srcDev.NewReader(srcParent, elem); COPY(destParent.dir.path, fullName); d.Append(fullName, elem.name); file := Files.New(fullName); IF (reader # NIL) & (file # NIL) THEN Files.Set(r, file, 0); reader.GetBytes(buf^, len); WHILE len > 0 DO Files.WriteBytes(r, buf^, len); reader.GetBytes(buf^, len) END; IF len = 0 THEN Files.Register(file); d.done := TRUE END END ELSE END; IF ~d.done THEN LogString(" file copying failed"); LogLn END END Copy; 8wPROCEDURE (d: Device) Copy* (destParent, srcParent: FMElems.FolderElem; elem: FMElems.Elem; srcDev: FMDevObj.Device);PowerMac Syntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.Fnt BEGIN info.ioCompletion := 0; info.ioNamePtr := SYSTEM.ADR(str255); info.ioVRefNum := vRefNum; info.ioDirID := parID; info.ioFDirIndex := index; RETURN (Sys.PBGetCatInfo(SYSTEM.VAL(Sys.CInfoPBFilePtr, SYSTEM.ADR(info))) = noErr) END GetFileDirInfo; 8'8#Syntax10.Scn.Fnt VAR len: LONGINT; res: INTEGER; BEGIN len := BufSize; res := Sys.FSRead(src, len, SYSTEM.ADR(buf^)); WHILE res = noErr DO res := Sys.FSWrite(des, len, SYSTEM.ADR(buf^)); ASSERT(res = 0, 99); len := BufSize; res := Sys.FSRead(src, len, SYSTEM.ADR(buf^)) END; ASSERT (res = eofErr, 98); IF len # 0 THEN res := Sys.FSWrite(des, len, SYSTEM.ADR(buf^)); ASSERT(res = 0, 99); END; res := Sys.FSClose(src); res := Sys.FSClose(des) END CopyData; 88!8#Syntax10.Scn.Fnt VAR info: Sys.CInfoPBFileRec; src, des: INTEGER; res: INTEGER; len: LONGINT; BEGIN IF GetFileDirInfo(srcSpec.vRefNum, srcSpec.parID, 0, srcSpec.name, info) THEN res := Sys.FSpCreate(desSpec, info.ioFlFndrInfo.fdCreator, info.ioFlFndrInfo.fdType, Sys.smSystemScript); IF res # noErr THEN RETURN FALSE END; IF Sys.FSpOpenDF(srcSpec, 0, src) # noErr THEN RETURN FALSE END; IF Sys.FSpOpenDF(desSpec, 0, des)# noErr THEN RETURN FALSE END; CopyData(src, des); IF info.ioFlRLgLen > 0 THEN res := Sys.FSpOpenRF(srcSpec, 0, src); ASSERT(res = 0, 95); res := Sys.FSpOpenRF(desSpec, 0, des); ASSERT(res = 0, 94); CopyData(src, des); END; RETURN TRUE END; RETURN FALSE END Copy; 8v8#Syntax10.Scn.Fnt VAR srcSpec, destSpec: Sys.FSSpec; str255: Sys.Str255; reader: FMDevObj.Reader; fullName: FMDevObj.Path; file: Files.File; r: Files.Rider; len, res: INTEGER; BEGIN d.done := FALSE; WITH destParent: FolderElem DO IF srcDev IS Device THEN WITH srcParent: FolderElem DO Macintosh.SetStr255(str255, elem.name); res := Sys.FSMakeFSSpec(destParent.dir.spec.vRefNum, destParent.dir.dirID, str255, destSpec); IF (res = fnfErr) & (Sys.FSMakeFSSpec(srcParent.dir.spec.vRefNum, srcParent.dir.dirID, str255, srcSpec) = noErr) THEN d.done := Copy(srcSpec, destSpec); IF d.done THEN Directories.notify(FMDevObj.insert, destParent.dir.path, elem.name) END END ELSE END ELSE reader:= srcDev.NewReader(srcParent, elem); COPY(destParent.dir.path, fullName); d.Append(fullName, elem.name); file := Files.New(fullName); IF (reader # NIL) & (file # NIL) THEN Files.Set(r, file, 0); reader.GetBytes(buf^, len); WHILE len > 0 DO Files.WriteBytes(r, buf^, len); reader.GetBytes(buf^, len) END; IF len = 0 THEN Files.Register(file); d.done := TRUE END END END ELSE END; IF ~d.done THEN LogString(" file copying failed"); LogLn END END Copy; 8l PROCEDURE GetFileDirInfo(vRefNum: INTEGER; parID: LONGINT; index: INTEGER; VAR str255: ARRAY OF CHAR; VAR info: Sys.CInfoPBFileRec): BOOLEAN; PROCEDURE CopyData(src, des: INTEGER); PROCEDURE Copy (srcSpec, desSpec: Sys.FSSpec): BOOLEAN; PROCEDURE (d: Device) Copy* (destParent, srcParent: FMElems.FolderElem; elem: FMElems.Elem; srcDev: FMDevObj.Device); Linux p_v8#Syntax10.Scn.Fnt VAR oldFullName, newFullName: FMDevObj.Path; res: INTEGER; BEGIN d.done := FALSE; WITH destParent: FolderElem DO WITH srcParent: FolderElem DO COPY(srcParent.dir.path, oldFullName); d.Append(oldFullName, elem.name); COPY(destParent.dir.path, newFullName); d.Append(newFullName, elem.name); Files.Rename(oldFullName, newFullName, res); d.done := res = noErr ELSE END ELSE END; IF ~d.done THEN LogString(elem.name); LogString(" moving failed"); LogLn END END Move; 8p_#Syntax10.Scn.FntWindows PowerMac LinuxLinuxWindowsSSyntax10.Scn.Fnt~8FoldElemsNew#Syntax10.Scn.Fnt VAR list: FMDevObj.List; iter: FMDevObj.Iterator; e, p: FMElems.Elem; fullName: FMDevObj.Path; BEGIN d.done := FALSE; WITH destParent: FolderElem DO IF (srcParent IS FolderElem) & (elem IS FolderElem) THEN d.NewDirectory(destParent, elem.name); p := d.GetElem(destParent, elem.name); IF p # NIL THEN list := srcDev.NewSortList(elem); srcDev.Enumerate(elem(FolderElem), list, "*"); iter := FMDevObj.NewIterator(list); IF iter # NIL THEN WHILE iter.NextElem(e) DO IF e IS FolderElem THEN d.MoveDir(p(FolderElem), elem(FolderElem), e(FolderElem),srcDev) ELSE d.Move(p(FolderElem), elem(FolderElem), e, srcDev) END END END; Kernel.GC; COPY(srcParent(FolderElem).dir.path, fullName); d.Append(fullName, elem.name); Directories.Delete(fullName); d.done := Directories.res = noErr END END ELSE END; IF ~d.done THEN LogString(elem.name); LogString(" moving failded"); LogLn END END MoveDir; 8PROCEDURE (d: Device) MoveDir* (destParent, srcParent: FMElems.FolderElem; elem: FMElems.FolderElem; srcDev: FMDevObj.Device);PowerMacbSyntax10.Scn.Fnt~8FoldElemsNew#Syntax10.Scn.Fnt VAR oldFullName, newFullName: FMDevObj.Path; BEGIN d.done := FALSE; WITH destParent: FolderElem DO WITH srcParent: FolderElem DO COPY(srcParent.dir.path, oldFullName); d.Append(oldFullName, elem.name); COPY(destParent.dir.path, newFullName); d.Append(newFullName, elem.name); Directories.Rename(oldFullName, newFullName); d.done := Directories.res = noErr ELSE END ELSE END; IF ~d.done THEN LogString(elem.name); LogString(" moving failed"); LogLn END END MoveDir; 8PROCEDURE (d: Device) MoveDir* (destParent, srcParent: FMElems.FolderElem; elem: FMElems.FolderElem; srcDev: FMDevObj.Device);Linux p_U8#Syntax10.Scn.Fnt00 VAR e: FMElems.Elem; path: FMDevObj.Path; BEGIN d.done := TRUE; WITH parent: FolderElem DO elem := d.GetElem(parent, elem.name); IF elem # NIL THEN d.GetPath(parent, path); IF (trashE # NIL) & (trashPath # path) THEN e := d.GetElem(trashE, elem.name); IF e # NIL THEN d.Delete(trashE, e); IF ~d.done THEN RETURN END END; IF elem IS FolderElem THEN d.MoveDir(trashE, parent, elem(FolderElem), d) ELSE d.Move(trashE, parent, elem, d) END ELSE d.Delete(parent, elem) END END ELSE END END MoveToTrash; 8 8#Syntax10.Scn.Fnt VAR d: Device; dir: Directories.Directory; name, pattern, pat: FMElems.Name; path: FMDevObj.Path; f: FolderElem; i, j, k: INTEGER; BEGIN i := 0; j := 0; WHILE fullName[i] # 0X DO IF (fullName[i] = Directories.delimiter) OR (fullName[i] = "$") THEN j := i + 1 END; INC(i) END; FOR k := 0 TO i - j DO pattern[k] := fullName[j + k] END; IF pattern[0] = 0X THEN pattern := "*" END; IF j = 0 THEN dir := Directories.Current() ELSE fullName[j] := 0X;dir := Directories.This(fullName) END; IF dir # NIL THEN NEW(d); d.delimiter := Directories.delimiter; i := 0; j := 0; WHILE dir.path[i] # 0X DO IF (dir.path[i] = d.delimiter) & (dir.path[i+1] # 0X) THEN j := i + 1 END; INC(i) END; FOR k := 0 TO i - j DO name[k] := dir.path[j+k] END; IF ((i-j) > 0) & (name[i-j-1] = d.delimiter) THEN name[i-j-1] := 0X END; NEW(f); InitFolderElem(f, name, pattern, sortOrder, attributes, FALSE, dir); folder := f; RETURN d END; RETURN NIL END NewDevObj; 8<8#Syntax10.Scn.Fnt00 (* delete op = 0, insert op = 1 *) VAR msg: FMDevObj.NotifyMsg; d: Device; BEGIN IF op <= 1 THEN NEW(d); d.delimiter := Directories.delimiter; msg.devObj := d; msg.id := op; COPY(path, msg.path); COPY(name, msg.name); Viewers.Broadcast(msg) END; oldNotifier(op, path, name) END Notify; 8^8#Syntax10.Scn.Fnt BEGIN Texts.OpenScanner(S, T, 0); REPEAT Texts.Scan(S) UNTIL S.eot OR ((S.class = Texts.Char) & (S.c = "[")); REPEAT Texts.Scan(S) UNTIL S.eot OR ((S.class = Texts.Name) & (S.s = name) & (S.nextCh = "]")); RETURN ~S.eot END SearchSection; 8(8#Syntax10.Scn.Fnt VAR attributes: FMElems.Attributes; S: Texts.Scanner; fullPath, path: FMDevObj.Path; name, pattern: FMElems.Name; dir: Directories.Directory; i, j, k: INTEGER; BEGIN trashE := NIL; IF SearchSection(TextFrames.Text(ConfigurationFile), S, "Trash") THEN REPEAT Texts.Scan(S) UNTIL S.eot OR ((S.class = Texts.Name) & (S.s = "Trash")); REPEAT Texts.Scan(S) UNTIL S.eot OR ((S.class = Texts.Char) & (S.c = "=")); REPEAT Texts.Scan(S) UNTIL S.eot OR (S.class = Texts.String); IF S.class = Texts.String THEN COPY(S.s, path) END; IF path[0] # 0X THEN dir := Directories.This(path); IF dir = NIL THEN Directories.Create(path); IF Directories.res # noErr THEN LogString("can not create trash "); LogLn; RETURN END; dir := Directories.This(path) END; IF dir # NIL THEN i := 0; j := 0; WHILE dir.path[i] # 0X DO IF (dir.path[i] = Directories.delimiter) & (dir.path[i+1] # 0X) THEN j := i + 1 END; INC(i) END; FOR k := 0 TO i - j DO name[k] := dir.path[j + k] END; attributes.nOfAttributes := 0; NEW(trashE); InitFolderElem(trashE, name, pattern, FMDevObj.sortName, attributes, FALSE, dir); COPY(dir.path, trashPath); i := 0; WHILE trashPath[i] # 0X DO INC(i) END; IF (i > 0) & (trashPath[i-1] # Directories.delimiter) THEN trashPath[i] := Directories.delimiter; trashPath[i+1] := 0X END END ELSE LogString(" no trash specified "); LogLn END END END InitTrash; 8MODULE FMSysDevObj; (* Christian Maryhofer, 24 Jan 96; Gnter Obiltschnig  *) (* This module contains two versions. Versions: - PowerMac - Windows To switch versions click on LINUX VERSION with the middle mouse button. *) Revision History IMPORT SYSTEM, Directories, Files, Kernel, MenuViewers, Oberon, Strings, Texts, TextFrames, Viewers, FMDevObj, FMElems, FMFrames, Unix; (* dummy import to force error on wrong system *) CONST noErr = Directories.noErr; (* no error *) BufSize = 4096; N = 64; ConfigurationFile = "FileManager.Profile"; menu = "^FileManager.Menu.Text"; TYPE Reader* = POINTER TO ReaderDesc; ReaderDesc* = RECORD (FMDevObj.ReaderDesc) file: Files.File; r: Files.Rider END; Writer* = POINTER TO WriterDesc; (* GO 270196 *) WriterDesc* = RECORD (FMDevObj.WriterDesc) file: Files.File; r: Files.Rider END; Device* = POINTER TO DeviceDesc; DeviceDesc* = RECORD (FMDevObj.DeviceDesc) END; FolderElem* = POINTER TO FolderElemDesc; FolderElemDesc* = RECORD (FMElems.FolderElemDesc) dir: Directories.Directory END; VAR oldNotifier: Directories.Notifier; trashE: FolderElem; trashPath: FMDevObj.Path; buf: POINTER TO ARRAY OF CHAR; w: Texts.Writer; enumerateList: FMDevObj.List; setData: BOOLEAN; devObj: Device; folder: FolderElem; pat: FMElems.Name; PROCEDURE LogLn (); PROCEDURE LogString (str: ARRAY OF CHAR); PROCEDURE (folder: FolderElem) Copy* (VAR de: Texts.Elem); PROCEDURE InitFolderElem*(e: FolderElem; name, pattern, sortOrder: ARRAY OF CHAR; VAR attributes: FMElems.Attributes; open: BOOLEAN; dir: Directories.Directory); PROCEDURE (r: Reader) GetBytes* (VAR buffer: ARRAY OF CHAR; VAR len: INTEGER); PROCEDURE (w: Writer) PutBytes* (VAR buffer: ARRAY OF CHAR; len: INTEGER); (* GO 270196 *) PROCEDURE (d: Device) CheckIdentity* (elem: FMElems.Elem; name: ARRAY OF CHAR): BOOLEAN; PROCEDURE InsertDirEntry (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN); PROCEDURE (d: Device) Enumerate* (parent: FMElems.FolderElem; list: FMDevObj.List; pattern: ARRAY OF CHAR); VAR i, n: INTEGER; BEGIN Kernel.GC; (* for temporary files *) WITH parent: FolderElem DO enumerateList := list; folder := parent; COPY(pattern, pat); devObj := d; setData := FALSE; i := 0; n := parent.attributes.nOfAttributes; WHILE ~setData & (i < n) DO setData := (parent.attributes.names[i] = FMElems.showDate) OR (parent.attributes.names[i] = FMElems.showSize); INC(i) END; Directories.Enumerate(parent.dir, InsertDirEntry); ELSE END END Enumerate;  PROCEDURE (d: Device) GetElem* (parent: FMElems.FolderElem; name: ARRAY OF CHAR): FMElems.Elem; PROCEDURE (d: Device) GetPath* (folder: FMElems.FolderElem; VAR path: ARRAY OF CHAR); PROCEDURE (d: Device) GetTrash* (VAR attributes: FMElems.Attributes; sortOrder: ARRAY OF CHAR): FMElems.FolderElem; PROCEDURE (d: Device) NewReader* (parent: FMElems.FolderElem; elem: FMElems.Elem): FMDevObj.Reader; PROCEDURE (d: Device) NewWriter* (parent: FMElems.FolderElem; elem: FMElems.Elem): FMDevObj.Writer; PROCEDURE (d: Device) NewDirectory* (parent: FMElems.FolderElem; name: ARRAY OF CHAR); PROCEDURE SetDirName (VAR curDirName: ARRAY OF CHAR); PROCEDURE (d: Device) Open* (parent: FMElems.FolderElem; elem: FMElems.Elem); VAR w: Texts.Writer; i: INTEGER; e: FMElems.Elem; path: FMDevObj.Path; x, y: INTEGER; v: Viewers.Viewer; PROCEDURE CallCmd (cmd, path, name: ARRAY OF CHAR); VAR par: Oberon.ParList; res: INTEGER; BEGIN NEW(par); par.text := TextFrames.Text(""); par.frame := TextFrames.NewText(par.text, 0); par.pos := 0; Texts.Write(w, '"'); Texts.WriteString(w, path); Texts.WriteString(w, name); Texts.Write(w, '"'); Texts.Append(par.text, w.buf); Oberon.Call(cmd, par, FALSE, res) END CallCmd;  BEGIN Texts.OpenWriter(w); IF elem IS FMElems.FolderElem THEN e := d.GetElem(parent, elem.name); IF e = NIL THEN RETURN END; Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, x, y); d.GetPath(e(FolderElem), path); SetDirName(path); v := MenuViewers.New(TextFrames.NewMenu(path, menu), FMFrames.NewFrame(FMFrames.NewText(d, e(FolderElem))), TextFrames.menuH, x, y) ELSE d.GetPath(parent, path); SetDirName(path); d.Append(path,""); IF path[0] = "*" THEN d.GetPath(parent, path) END; CallCmd("Documents.Open", path, elem.name) END END Open;  PROCEDURE (d: Device) Rename* (parent: FMElems.FolderElem; elem: FMElems.Elem; VAR name: ARRAY OF CHAR); PROCEDURE (d: Device) Delete (parent: FMElems.FolderElem; elem: FMElems.Elem);  PROCEDURE (d: Device) Move* (destParent, srcParent: FMElems.FolderElem; elem: FMElems.Elem; srcDev: FMDevObj.Device);  PROCEDURE (d: Device) MoveToTrash* (parent: FMElems.FolderElem; elem: FMElems.Elem); PROCEDURE NewDevObj* (fullName: ARRAY OF CHAR; VAR folder: FMElems.FolderElem; VAR attributes: FMElems.Attributes; sortOrder: ARRAY OF CHAR): Device; PROCEDURE Notify (op: INTEGER; path, name: ARRAY OF CHAR); PROCEDURE SearchSection (T: Texts.Text; VAR S: Texts.Scanner; name: ARRAY OF CHAR): BOOLEAN; PROCEDURE InitTrash; BEGIN Texts.OpenWriter(w); oldNotifier := Directories.notify; Directories.notify := Notify; NEW(buf, BufSize); InitTrash END FMSysDevObj.