Syntax10.Scn.FntzIStampElemsAlloc2 Sep 97xp_VersionElemsAllocBeg#Syntax10.Scn.FntWindows PowerMacWindowsWindows PowerMac$Syntax14b.Scn.FntPOWERMAC VERSIONSyntax14b.Scn.Fntp_VersionElemsAllocEndyPp_#Syntax10.Scn.FntPowerMac WindowsWindowsPowerMac#Syntax10.Scn.Fnt99PageUp = 0ACX; PageDown = 0ADX; Home = 091X; BRK = 0B9X;Windows 9p_Syntax10i.Scn.FntPSyntax10b.Scn.Fnt>+k9p_#Syntax10.Scn.FntWindows PowerMacWindowsWindows PowerMac Jp_8FoldElemsNew$Syntax10i.Scn.Fntforward declarationsN86MarkElemsAlloc!88# 8J8$828 9)88 S58B8 ".88 #^838 f:#8 8 4;#88 %a8p_#Syntax10.Scn.FntWindows PowerMacWindowsWindows PowerMac +p_p_#Syntax10.Scn.FntWindows PowerMacWindowsWindows PowerMac Hp_8 &$8~5p_#Syntax10.Scn.FntPowerMac WindowsWindowsPowerMac#Syntax10.Scn.FntTT Directories.Enumerate(d, MakeEntry); t.notify := NoNotify; Texts.Append(t, w.buf);Windows Yp_8 [؈-88 ~_8Y8 ~_8Y8 V-8*8 P88 +88 ':88 (888   ,88 ) )88$Syntax10i.Scn.Fnt track mouse8M8$Syntax10i.Scn.Fntopen subdirectory88$Syntax10i.Scn.Fnt open file88 * -8op_#Syntax10.Scn.FntPowerMac WindowsWindowsPowerMac#Syntax10.Scn.Fntf.text(Text).path = m.pathWindows #p_x8 ,88 (?88 -8=8 5/88 ?8A8#HMODULE Dir; (** HM  WINDOWS VERSION*) IMPORT Files, Display, Input, Viewers, Texts, TextFrames, MenuViewers, Oberon, Directories, Strings, In, Out; CONST PageUp = 0C5X; PageDown = 0C6X; Home = 0C8X; BRK = 0ACX; delimiter = Directories.delimiter; left =2; middle = 1; right = 0; delete = 0; copy = 1; move = 2; select = 3; unselect = 4; (*opcodes for ForAllElemsDo*) pixel = LONG(10000); CR = 0DX; DEL = 7FX; CRSU = 0C1X; CRSD = 0C2X; TYPE Elem* = POINTER TO ElemDesc; ElemDesc* = RECORD (Texts.ElemDesc) name*: ARRAY 32 OF CHAR; sel*: BOOLEAN; icon, iconSel, iconCopy: Display.Pattern END; Text* = POINTER TO TextDesc; TextDesc* = RECORD (Texts.TextDesc) path*: ARRAY 128 OF CHAR END; UpdateMsg = RECORD (Display.FrameMsg) op: INTEGER; path, name: ARRAY 128 OF CHAR END; VAR scratch: Texts.Text; invalidOp: BOOLEAN; (*TRUE if text operation suppressed in Notify*) ignoreNeutralize: BOOLEAN; w: Texts.Writer; fileIcon, fileIconSel, fileIconCopy: Display.Pattern; (*x=0, y=0, w=15, h=13*) dirIcon, dirIconSel, dirIconCopy: Display.Pattern; (*x=0, y=0, w=15, h=13*) copyHull, moveHull: Display.Pattern; copyMarker, moveMarker: Oberon.Marker; mask: ARRAY 32 OF CHAR; oldNotifier: Directories.Notifier; CBtext: Texts.Text; (* global variable for callback procedure MakeEntry *) PROCEDURE ^ NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT); PROCEDURE ^ Notify (t: Texts.Text; op: INTEGER; beg, end: LONGINT); PROCEDURE ^ NotifyDir* (op: INTEGER; path, name: ARRAY OF CHAR); PROCEDURE ^ HandleElem* (e: Texts.Elem; VAR m: Texts.ElemMsg); PROCEDURE ^ HandleFrame*(f: Display.Frame; VAR m: Display.FrameMsg); PROCEDURE WriteName (name: ARRAY OF CHAR); VAR ch: CHAR; i: INTEGER; quote: CHAR; BEGIN ch := name[0]; i := 0; quote := '"'; WHILE (ch # 0X) & (("a" <= ch) & (ch <= "z") OR ("A" <= ch) & (ch <= "Z") OR (ch = ".") OR (ch = "/") OR (ch = "$") OR (i > 0) & (("0" <= ch) & (ch <= "9") OR (ch = ":"))) DO IF ch = '"' THEN quote := "'" ELSIF ch = "'" THEN quote := '"' END ; INC(i); ch := name[i] END ; IF ch # 0X THEN Texts.Write(w, quote) END ; Texts.WriteString(w, name); IF ch # 0X THEN Texts.Write(w, quote) END END WriteName; PROCEDURE (e: Elem) Update;  VAR m: TextFrames.UpdateMsg; BEGIN m.id := TextFrames.replace; m.text := Texts.ElemBase(e); m.beg := Texts.ElemPos(e); m.end := m.beg + 1; Viewers.Broadcast(m) END Update;  PROCEDURE (e: Elem) Restore;  VAR r: Texts.Reader; t: Texts.Text; pos1, pos2: LONGINT; BEGIN t := Texts.ElemBase(e); pos1 := Texts.ElemPos(e) + 1; Texts.OpenReader(r, t, pos1); Texts.ReadElem(r); IF r.eot THEN pos2 := t.len -1 ELSE pos2 := Texts.Pos(r) - 2 END; Texts.Delete(t, pos1, pos2); WriteName(e.name); Texts.Insert(t, pos1, w.buf) END Restore;  PROCEDURE (e: Elem) Check;  VAR s: Texts.Scanner; t: Texts.Text; old, new: ARRAY 256 OF CHAR; res: INTEGER; BEGIN t := Texts.ElemBase(e); Texts.OpenScanner(s, t, Texts.ElemPos(e) + 1); Texts.Scan(s); IF (s.class = Texts.Name) & (s.line = 0) & (s.nextCh = CR) THEN IF e.name # s.s THEN COPY(t(Text).path, old); Strings.Append(delimiter, old); COPY(old, new); Strings.Append(e.name, old); Strings.Append(s.s, new); Files.Rename(old, new, res); IF res > 1 THEN Out.String("-- failed$"); e.Restore END END ELSE Out.String("-- failed$"); e.Restore END END Check;  PROCEDURE Diff (VAR a, b: ARRAY OF CHAR): INTEGER;  VAR i, d: INTEGER; BEGIN i := 0; LOOP IF CAP(a[i]) = CAP(b[i]) THEN IF a[i] = 0X THEN d := 0; EXIT END ELSIF CAP(a[i]) < CAP(b[i]) THEN d := -1; EXIT ELSE d := 1; EXIT END; INC(i) END; RETURN d END Diff;  PROCEDURE NewElem (name: ARRAY OF CHAR; isDir: BOOLEAN): Elem;  VAR e: Elem; BEGIN NEW(e); e.W := 15 * pixel; e.H := 13 * pixel; e.handle := HandleElem; COPY(name, e.name); e.sel := FALSE; IF isDir THEN e.icon := dirIcon; e.iconSel := dirIconSel; e.iconCopy := dirIconCopy ELSE e.icon := fileIcon; e.iconSel := fileIconSel; e.iconCopy := fileIconCopy END; RETURN e END NewElem;  PROCEDURE ThisElem (t: Texts.Text; pos: LONGINT): Elem;  VAR r: Texts.Reader; ch: CHAR; BEGIN Texts.OpenReader(r, t, pos); Texts.Read(r, ch); IF ch # Texts.ElemChar THEN Texts.ReadPrevElem(r) END; IF r.eot THEN RETURN NIL ELSE RETURN r.elem(Elem) END END ThisElem;  PROCEDURE FindElem (t: Texts.Text; name: ARRAY OF CHAR; VAR e: Elem; VAR pos: LONGINT; VAR d: INTEGER);  VAR r: Texts.Reader; BEGIN Texts.OpenReader(r, t, 0); Texts.ReadElem(r); LOOP IF r.eot THEN e := NIL; d := 1; pos := t.len; RETURN END; IF r.elem IS Elem THEN d := Diff(r.elem(Elem).name, name); IF d >= 0 THEN e := r.elem(Elem); pos := Texts.ElemPos(e); EXIT END END; Texts.ReadElem(r) END END FindElem;  PROCEDURE CopyFile (e:Elem; src, dst: Text);  CONST bufSize = 4096; VAR sn, dn: ARRAY 128 OF CHAR; sf, df: Files.File; sr, dr: Files.Rider; buf: ARRAY bufSize OF CHAR; BEGIN COPY(src.path, sn); Strings.Append(delimiter, sn); Strings.Append(e.name, sn); COPY(dst.path, dn); Strings.Append(delimiter, dn); Strings.Append(e.name, dn); sf := Files.Old(sn); Files.Set(sr, sf, 0); df := Files.New(dn); Files.Set(dr, df, 0); REPEAT Files.ReadBytes(sr, buf, bufSize); Files.WriteBytes(dr, buf, bufSize - sr.res) UNTIL sr.res # 0; Files.Register(df) END CopyFile;  PROCEDURE MoveFile (e:Elem; src, dst: Text);  VAR sn, dn: ARRAY 256 OF CHAR; res: INTEGER; BEGIN COPY(src.path, sn); Strings.Append(delimiter, sn); Strings.Append(e.name, sn); COPY(dst.path, dn); Strings.Append(delimiter, dn); Strings.Append(e.name, dn); Files.Rename(sn, dn, res) END MoveFile;  PROCEDURE MakeEntry(d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);  CONST blue = 3;  VAR e: Elem; pos: LONGINT; found: INTEGER; BEGIN IF isDir THEN Texts.SetColor(w, blue) ELSE Texts.SetColor(w, Display.white) END ; Texts.WriteElem(w, NewElem(name, isDir)); WriteName(name); Texts.WriteLn(w) ;FindElem(CBtext, name, e, pos, found); Texts.Insert(CBtext, pos, w.buf) END MakeEntry;  PROCEDURE OpenDir (d: Directories.Directory);  VAR t: Text; f: TextFrames.Frame; x, y: INTEGER; v: Viewers.Viewer; BEGIN NEW(t); Texts.Open(t, ""); COPY(d.path, t.path);  t.notify := NoNotify; CBtext := t; Directories.Enumerate(d, MakeEntry); CBtext := NIL; t.notify := Notify; NEW(f); TextFrames.Open(f, t, 0); f.handle := HandleFrame; Oberon.AllocateSystemViewer(0, x, y); v := MenuViewers.New( TextFrames.NewMenu(d.path, "^Dir.Menu.Text"), f, TextFrames.menuH, x, y) END OpenDir;  PROCEDURE ForAllElemsDo (op: INTEGER; src, dst: Text);  VAR r: Texts.Reader; beg, end: LONGINT; e: Elem; path: ARRAY 256 OF CHAR; res: INTEGER; BEGIN IF src = NIL THEN RETURN END; end := src.len; Texts.OpenReader(r, src, end); LOOP Texts.ReadPrevElem(r); IF r.eot THEN EXIT END; IF r.elem IS Elem THEN e := r.elem(Elem); beg := Texts.Pos(r); IF e.sel THEN IF op = delete THEN COPY(src.path, path); Strings.Append(delimiter, path); Strings.Append(e.name, path); Files.Delete(path, res); IF res # 0 THEN Out.String("-- failed$") END ELSIF op = copy THEN IF e.icon # dirIcon THEN CopyFile(e, src, dst) ELSE Out.String("--- directories cannot be copied$") END; e.sel := FALSE; e.Update ELSIF op = move THEN MoveFile(e, src, dst); ELSIF op = unselect THEN e.sel := FALSE; e.Update END; Texts.OpenReader(r, src, beg) ELSIF (op = select) & Strings.Match(e.name, mask) THEN e.sel := TRUE; e.Update END; end := beg END END END ForAllElemsDo;  PROCEDURE DrawCopy (x, y: INTEGER);  BEGIN Display.CopyPattern(Display.white, copyHull, x, y, Display.invert) END DrawCopy;  PROCEDURE DrawMove (x, y: INTEGER);  BEGIN Display.CopyPattern(Display.white, moveHull, x, y, Display.invert) END DrawMove;  PROCEDURE ThisFrame (x, y: INTEGER): TextFrames.Frame;  VAR v: Viewers.Viewer; f: Display.Frame; BEGIN v := Viewers.This(x, y); f := v.dsc; WHILE (f # NIL) & ((x < f.X) OR (x > f.X+f.W) OR (y < f.Y) OR (y > f.Y+f.H)) DO f := f.next END; IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame) ELSE RETURN NIL END END ThisFrame;  PROCEDURE TargetText(): Text;  VAR f: TextFrames.Frame; BEGIN IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN f := Oberon.Par.frame.next(TextFrames.Frame) ELSE f := ThisFrame(Oberon.Pointer.X, Oberon.Pointer.Y); END; IF f.text IS Text THEN RETURN f.text(Text) ELSE RETURN NIL END END TargetText;  PROCEDURE Init;  VAR line: ARRAY 14 OF SET; BEGIN line[1] := {}; line[2] := {1..8}; line[3] := {1, 8}; line[4] := {1, 8}; line[5] := {1, 8}; line[6] := {1, 8}; line[7] := {1, 8}; line[8] := {1, 8}; line[9] := {1, 5..8}; line[10] := {1, 5, 7}; line[11] := {1, 5, 6}; line[12] := {1..5}; line[13] := {}; fileIcon := Display.NewPattern(line, 15, 13); line[1] := {}; line[2] := {1..8}; line[3] := {1, 4, 8}; line[4] := {1, 4, 8}; line[5] := {1, 2..6, 8}; line[6] := {1, 4, 8}; line[7] := {1, 4, 8}; line[8] := {1, 8}; line[9] := {1, 5..8}; line[10] := {1, 5, 7}; line[11] := {1, 5, 6}; line[12] := {1..5}; line[13] := {}; fileIconCopy := Display.NewPattern(line, 15, 13); line[1] := {}; line[2] := {1..8}; line[3] := {1..8}; line[4] := {1..8}; line[5] := {1..8}; line[6] := {1..8}; line[7] := {1..8}; line[8] := {1..8}; line[9] := {1..8}; line[10] := {1..5, 7}; line[11] := {1..6}; line[12] := {1..5}; line[13] := {}; fileIconSel := Display.NewPattern(line, 15, 13); line[1] := {}; line[2] := {}; line[3] := {1..10}; line[4] := {1, 10}; line[5] := {1, 10}; line[6] := {1, 10}; line[7] := {1, 10}; line[8] := {1, 10}; line[9] := {1, 10}; line[10] := {1..10}; line[11] := {1, 5}; line[12] := {1..4}; line[13] := {}; dirIcon := Display.NewPattern(line, 15, 13); line[1] := {}; line[2] := {}; line[3] := {1..10}; line[4] := {1, 6, 10}; line[5] := {1, 6, 10}; line[6] := {1, 4..8, 10}; line[7] := {1, 6, 10}; line[8] := {1, 6, 10}; line[9] := {1, 10}; line[10] := {1..10}; line[11] := {1, 5}; line[12] := {1..4}; line[13] := {}; dirIconCopy := Display.NewPattern(line, 15, 13); line[1] := {}; line[2] := {}; line[3] := {1..10}; line[4] := {1..10}; line[5] := {1..10}; line[6] := {1..10}; line[7] := {1..10}; line[8] := {1..10}; line[9] := {1..10}; line[10] := {1..10}; line[11] := {1, 5}; line[12] := {1..4}; line[13] := {}; dirIconSel := Display.NewPattern(line, 15, 13); copyMarker.Draw := DrawCopy; copyMarker.Fade := DrawCopy; moveMarker.Draw := DrawMove; moveMarker.Fade := DrawMove; Texts.OpenWriter(w); ignoreNeutralize := FALSE; oldNotifier := Directories.notify; Directories.notify := NotifyDir; NEW(scratch); Texts.Open(scratch, ""); scratch.notify := NoNotify; END Init;  PROCEDURE NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);  END NoNotify;  PROCEDURE Notify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);  VAR b: Texts.Buffer; r: Texts.Reader; ch: CHAR; pos: LONGINT; BEGIN IF op = TextFrames.delete THEN pos := scratch.len; Texts.Recall(b); Texts.Append(scratch, b); Texts.OpenReader(r, scratch, pos); REPEAT Texts.Read(r, ch) UNTIL r.eot OR (ch = CR) OR (ch = Texts.ElemChar) & (r.elem IS Elem); IF ~r.eot THEN invalidOp := TRUE; t.notify := NoNotify; Texts.Save(scratch, pos, t.len, b); Texts.Insert(t, beg, b); t.notify := Notify; op := TextFrames.replace; end := beg END ELSIF op = TextFrames.insert THEN Texts.OpenReader(r, t, beg); pos := beg; REPEAT Texts.Read(r, ch); INC(pos) UNTIL (pos > end) OR (ch = CR) OR (ch = Texts.ElemChar) & (r.elem IS Elem); IF pos <= end THEN invalidOp := TRUE; t.notify := NoNotify; Texts.Delete(t, beg, end); t.notify := Notify; op := TextFrames.replace; end := beg END END; ignoreNeutralize := TRUE; TextFrames.NotifyDisplay(t, op, beg, end); ignoreNeutralize := FALSE END Notify;  PROCEDURE NotifyDir* (op: INTEGER; path, name: ARRAY OF CHAR);  VAR m: UpdateMsg; BEGIN m.op := op; COPY(path, m.path); COPY(name, m.name); Viewers.Broadcast(m); oldNotifier(op, path, name) END NotifyDir;  PROCEDURE HandleElem* (e: Texts.Elem; VAR m: Texts.ElemMsg);  CONST moved = -1000; blue = 3; VAR e1: Elem; x, y, x0, y0, res: INTEGER; keys: SET; t: Texts.Text; path: ARRAY 128 OF CHAR; marker: Oberon.Marker; f: TextFrames.Frame; src, dst: Text; d: Directories.Directory; name: ARRAY 256 OF CHAR; col: INTEGER; BEGIN WITH e: Elem DO WITH m: Texts.CopyMsg DO IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END; Texts.CopyElem(e, e1); COPY(e.name, e1.name); e1.sel := e.sel; e1.icon := e.icon; e1.iconSel := e.iconSel; e1.iconCopy := e.iconCopy | m: TextFrames.DisplayMsg DO IF ~m.prepare THEN IF e.icon = dirIcon THEN col := blue ELSE col := Display.white END ; IF e.sel THEN Display.CopyPattern(col, e.iconSel, m.X0, m.Y0+1, Display.replace) ELSE Display.CopyPattern(col, e.icon, m.X0, m.Y0+1, Display.replace) END END | m: TextFrames.TrackMsg DO IF middle IN m.keys THEN e.sel := ~e.sel; e.Update; src := m.frame(TextFrames.Frame).text(Text); Input.Mouse(keys, x0, y0); marker := Oberon.Arrow; copyHull := e.iconCopy; moveHull := e.icon; REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys; IF (ABS(x-x0) > 10) OR (ABS(y-y0) > 10) THEN x0 := moved; IF m.keys = {middle, left} THEN marker := copyMarker ELSE marker := moveMarker END END; Oberon.DrawCursor(Oberon.Mouse, marker, x, y) UNTIL keys = {}; IF m.keys = {middle, right} THEN IF e.icon = dirIcon THEN t := Texts.ElemBase(e); COPY(t(Text).path, path); Strings.Append(delimiter, path); Strings.Append(e.name, path); OpenDir(Directories.This(path)) ELSE d := Directories.Current(); name := ""; IF src.path # d.path THEN Strings.Append(src.path, name); Strings.Append(delimiter, name) END; Strings.Append(e.name, name); WriteName(name); Oberon.Par.vwr := Viewers.This(m.X, m.Y); Oberon.Par.frame := m.frame; Oberon.Par.pos := scratch.len; Oberon.Par.text := scratch; Texts.Append(scratch, w.buf); Oberon.Call("Documents.Open", Oberon.Par, FALSE, res) END; e.sel := FALSE; e.Update ELSIF (x0 = moved) & e.sel THEN f := ThisFrame(x, y); IF (f # NIL) & (f # m.frame) & (f.text IS Text) THEN dst := f.text(Text); IF m.keys = {middle} THEN ForAllElemsDo(move, src, dst) ELSIF m.keys = {middle, left} THEN ForAllElemsDo(copy, src, dst) END END END END ELSE END END END HandleElem;  PROCEDURE HandleFrame* (f: Display.Frame; VAR m: Display.FrameMsg);  CONST blue = 3; VAR ready: BOOLEAN; e: Elem; keys: SET; x, y, d: INTEGER; t: Texts.Text; pos, pos2: LONGINT; r: Texts.Reader; ch: CHAR; path: ARRAY 256 OF CHAR; dir: Directories.Directory; BEGIN ready := FALSE; WITH f: TextFrames.Frame DO WITH m: Oberon.InputMsg DO IF m.id = Oberon.consume THEN pos := f.carloc.pos; e := ThisElem(f.text, pos); IF (m.ch = CR) OR (m.ch = PageUp) OR (m.ch = PageDown) OR (m.ch = Home) OR (m.ch = BRK) THEN e.Check; TextFrames.RemoveCaret(f); ready := TRUE ELSIF (m.ch = CRSU) OR (m.ch = CRSD) THEN e.Check ELSIF m.ch = DEL THEN invalidOp := FALSE; TextFrames.Handle(f, m); ready := TRUE; IF invalidOp THEN e := ThisElem(f.text, pos); e.Check; TextFrames.RemoveCaret(f) END ELSE Texts.OpenReader(r, f.text, f.carloc.pos); Texts.Read(r, ch); ready := (ch = Texts.ElemChar) & (r.elem IS Elem) END ELSIF (m.id = Oberon.track) & f.hasCar & (m.keys * {middle, right} # {}) THEN e := ThisElem(f.text, f.carloc.pos); IF (e # NIL) & (ThisElem(f.text, TextFrames.Pos(f, x, y)) # e) THEN e.Check END END | m: Oberon.ControlMsg DO IF m.id = Oberon.defocus THEN e := ThisElem(f.text, f.carloc.pos); Input.Mouse(keys, x, y); IF (e # NIL) & ((f # ThisFrame(x, y)) OR (ThisElem(f.text, TextFrames.Pos(f, x, y)) # e)) THEN e.Check END ELSIF (m.id = Oberon.neutralize) & ~ignoreNeutralize & f.hasCar THEN e := ThisElem(f.text, f.carloc.pos); IF e # NIL THEN e.Check END END | m: UpdateMsg DO IF Diff(f.text(Text).path, m.path) = 0 THEN t := f.text; FindElem(t, m.name, e, pos, d); t.notify := TextFrames.NotifyDisplay; CASE m.op OF Directories.insert: IF d # 0 THEN COPY(m.path, path); Strings.Append(delimiter, path); Strings.Append(m.name, path); dir := Directories.This(path); IF Directories.This(path) # NIL THEN Texts.SetColor(w, blue) ELSE Texts.SetColor(w, Display.white) END ; Texts.WriteElem(w, NewElem(m.name, dir # NIL)); WriteName(m.name); Texts.WriteLn(w); Texts.Insert(t, pos, w.buf) END | Directories.delete: IF d = 0 THEN Texts.OpenReader(r, t, pos+1); Texts.ReadElem(r); IF r.eot THEN pos2 := t.len ELSE pos2 := Texts.Pos(r) - 1 END; Texts.Delete(t, pos, pos2) END END; t.notify := Notify END ELSE END END; IF ~ready THEN TextFrames.Handle(f, m) END END HandleFrame;  PROCEDURE Open*;  VAR str: ARRAY 256 OF CHAR; dir: Directories.Directory; BEGIN In.Open; In.Name(str); IF ~In.Done THEN In.Open; In.String(str) END ; IF In.Done THEN dir := Directories.This(str) ELSE dir := NIL END ; IF dir = NIL THEN dir := Directories.Current() END ; OpenDir(dir) END Open;  PROCEDURE New*;  VAR name: ARRAY 256 OF CHAR; i: INTEGER; t: Text; BEGIN In.Open; IF In.Next() = In.string THEN In.String(name) ELSE In.Name(name) END; IF In.Done THEN t := TargetText(); IF t # NIL THEN i := 0; WHILE (name[i] # 0X) & (name[i] # delimiter) & (name[i] # "$") DO INC(i) END; IF name[i] = 0X THEN Strings.Insert(delimiter, 0, name); Strings.Insert(t.path, 0, name) END END; Directories.Create(name) END END New;  PROCEDURE Delete*;  BEGIN ForAllElemsDo(delete, TargetText(), NIL) END Delete;  PROCEDURE Select*;  VAR ch: CHAR; i: INTEGER; BEGIN In.Open; i := 0; REPEAT In.Char(ch) UNTIL ch >= " "; REPEAT mask[i] := ch; INC(i); In.Char(ch) UNTIL (ch <= " ") OR (ch > 7FX); mask[i] := 0X; ForAllElemsDo(select, TargetText(), NIL) END Select;  PROCEDURE Deselect*;  BEGIN ForAllElemsDo(unselect, TargetText(), NIL) END Deselect;  BEGIN Init END Dir.