home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / jËzyki_programowania / oberon / system / dir.mod (.txt) < prev    next >
Oberon Text  |  1977-12-31  |  22KB  |  617 lines

  1. Syntax10.Scn.Fnt
  2. StampElems
  3. Alloc
  4. 29 May 96
  5. VersionElems
  6. AllocBeg
  7. Syntax10.Scn.Fnt
  8. PowerMac
  9. Windows
  10. AmigaAmiga
  11. PowerMac
  12. Syntax10.Scn.Fnt
  13. DELR = 008X; PageUp = 0ACX; PageDown = 0ADX;  Home = 091X; BRK = 0B9X;Windows
  14. Syntax10.Scn.Fnt
  15. DELR = 0A1X; PageUp = 0C5X; PageDown = 0C6X;  Home = 0C8X; BRK = 0ACX;Amiga
  16. VersionElems
  17. AllocEnd
  18. Syntax10i.Scn.Fnt
  19. Syntax10b.Scn.Fnt
  20. FoldElems
  21. Syntax10i.Scn.Fnt
  22. forward declarations
  23. MarkElems
  24. Alloc
  25. Syntax10i.Scn.Fnt
  26. track mouse
  27. Syntax10i.Scn.Fnt
  28. open subdirectory
  29. Syntax10i.Scn.Fnt
  30. open file
  31. MODULE Dir;  (** HM 
  32. IMPORT Files, Display, Input, Viewers, Texts, TextFrames, MenuViewers, Oberon, Directories, Strings, In, Out;
  33. CONST
  34. DELR = 0A1X; PageUp = 0C5X; PageDown = 0C6X;  Home = 0C8X; BRK = 0ACX;
  35.     delimiter = Directories.delimiter;
  36.     left =2; middle = 1; right = 0;
  37.     delete = 0; copy = 1; move = 2; select = 3; unselect = 4;    (*opcodes for ForAllElemsDo*)
  38.     pixel = LONG(10000);
  39.     CR = 0DX; DEL = 7FX; CRSU = 0C1X; CRSD = 0C2X;
  40.     Elem* = POINTER TO ElemDesc;
  41.     ElemDesc* = RECORD (Texts.ElemDesc)
  42.         name*: ARRAY 32 OF CHAR;
  43.         sel*: BOOLEAN;
  44.         icon, iconSel, iconCopy: Display.Pattern
  45.     END ;
  46.     Text* = POINTER TO TextDesc;
  47.     TextDesc* = RECORD (Texts.TextDesc)
  48.         path*: ARRAY 128 OF CHAR
  49.     END ;
  50.     UpdateMsg = RECORD (Display.FrameMsg)
  51.         op: INTEGER;
  52.         path, name: ARRAY 128 OF CHAR
  53.     END ;
  54.     Opener = POINTER TO OpenerDesc;    (*list of commands to open files*)
  55.     OpenerDesc = RECORD
  56.         pattern, cmd: ARRAY 32 OF CHAR;
  57.         next: Opener
  58.     END ;
  59.     scratch: Texts.Text;
  60.     invalidOp: BOOLEAN; (*TRUE if text operation suppressed in Notify*)
  61.     ignoreNeutralize: BOOLEAN;
  62.     w: Texts.Writer;
  63.     fileIcon, fileIconSel, fileIconCopy: Display.Pattern;  (*x=0, y=0, w=15, h=13*)
  64.     dirIcon, dirIconSel, dirIconCopy: Display.Pattern; (*x=0, y=0, w=15, h=13*)
  65.     copyHull, moveHull: Display.Pattern;
  66.     copyMarker, moveMarker: Oberon.Marker;
  67.     mask: ARRAY 32 OF CHAR;
  68.     openers: Opener;
  69.     CBtext: Texts.Text;    (* global variable for callback procedure MakeEntry *)
  70.     oldNotifier: Directories.Notifier;
  71. PROCEDURE ^ NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);
  72. PROCEDURE ^ Notify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);
  73. PROCEDURE ^ NotifyDir* (op: INTEGER; path, name: ARRAY OF CHAR);
  74. PROCEDURE ^ HandleElem* (e: Texts.Elem; VAR m: Texts.ElemMsg);
  75. PROCEDURE ^ HandleFrame*(f: Display.Frame; VAR m: Display.FrameMsg);
  76. PROCEDURE (e: Elem) 
  77. Update;    
  78.     VAR m: TextFrames.UpdateMsg;
  79. BEGIN
  80.     m.id := TextFrames.replace; m.text := Texts.ElemBase(e);
  81.     m.beg := Texts.ElemPos(e); m.end := m.beg + 1;
  82.     Viewers.Broadcast(m)
  83. END Update;
  84. PROCEDURE (e: Elem) 
  85. Restore;    
  86.     VAR r: Texts.Reader; t: Texts.Text; pos1, pos2: LONGINT;
  87. BEGIN
  88.     t := Texts.ElemBase(e); pos1 := Texts.ElemPos(e) + 1;
  89.     Texts.OpenReader(r, t, pos1); Texts.ReadElem(r);
  90.     IF r.eot THEN pos2 := t.len -1
  91.     ELSE pos2 := Texts.Pos(r) - 2
  92.     END ;
  93.     Texts.Delete(t, pos1, pos2); Texts.WriteString(w, e.name); Texts.Insert(t, pos1, w.buf)
  94. END Restore;
  95. PROCEDURE (e: Elem) 
  96. Check;    
  97.     VAR s: Texts.Scanner; t: Texts.Text; old, new: ARRAY 256 OF CHAR;
  98.         res: INTEGER;
  99. BEGIN
  100.     t := Texts.ElemBase(e);
  101.     Texts.OpenScanner(s, t, Texts.ElemPos(e) + 1);
  102.     Texts.Scan(s);
  103.     IF (s.class = Texts.Name) & (s.line = 0) THEN
  104.         IF e.name # s.s THEN
  105.             COPY(t(Text).path, old); Strings.Append(delimiter, old);
  106.             COPY(old, new);
  107.             Strings.Append(e.name, old);
  108.             Strings.Append(s.s, new);
  109.             Files.Rename(old, new, res);
  110.             IF res > 1 THEN Out.String("-- failed$"); e.Restore END
  111.         END
  112.     ELSE Out.String("-- failed$"); e.Restore
  113. END Check;
  114. PROCEDURE 
  115. Diff (VAR a, b: ARRAY OF CHAR): INTEGER;    
  116.     VAR i, d: INTEGER;
  117. BEGIN i := 0;
  118.     LOOP
  119.         IF CAP(a[i]) = CAP(b[i]) THEN
  120.             IF a[i] = 0X THEN d := 0; EXIT END
  121.         ELSIF CAP(a[i]) < CAP(b[i]) THEN d := -1; EXIT
  122.         ELSE d := 1; EXIT
  123.         END ;
  124.         INC(i)
  125.     END ;
  126.     RETURN d
  127. END Diff;
  128. PROCEDURE 
  129. NewElem (name: ARRAY OF CHAR; isDir: BOOLEAN): Elem;    
  130.     VAR e: Elem;
  131. BEGIN
  132.     NEW(e); e.W := 15 * pixel; e.H := 13 * pixel; e.handle := HandleElem;
  133.     COPY(name, e.name); e.sel := FALSE;
  134.     IF isDir THEN e.icon := dirIcon; e.iconSel := dirIconSel; e.iconCopy := dirIconCopy
  135.     ELSE e.icon := fileIcon; e.iconSel := fileIconSel; e.iconCopy := fileIconCopy
  136.     END ;
  137.     RETURN e
  138. END NewElem;
  139. PROCEDURE 
  140. ThisElem (t: Texts.Text; pos: LONGINT): Elem;    
  141.     VAR r: Texts.Reader; ch: CHAR;
  142. BEGIN
  143.     Texts.OpenReader(r, t, pos);  Texts.Read(r, ch);
  144.     IF ch # Texts.ElemChar THEN Texts.ReadPrevElem(r) END ;
  145.     IF r.eot THEN RETURN NIL ELSE RETURN r.elem(Elem) END
  146. END ThisElem;
  147. PROCEDURE 
  148. FindElem (t: Texts.Text; name: ARRAY OF CHAR; VAR e: Elem; VAR pos: LONGINT; VAR d: INTEGER);    
  149.     VAR r: Texts.Reader;
  150. BEGIN
  151.     Texts.OpenReader(r, t, 0); Texts.ReadElem(r);
  152.     LOOP
  153.         IF r.eot THEN e := NIL; d := 1; pos := t.len; RETURN END ;
  154.         IF r.elem IS Elem THEN
  155.             e := r.elem(Elem);
  156.             d := Diff(e.name, name);
  157.             IF d >= 0 THEN pos := Texts.ElemPos(e); EXIT END
  158.         END ;
  159.         Texts.ReadElem(r)
  160. END FindElem;
  161. PROCEDURE 
  162. CopyFile (e:Elem; src, dst: Text);    
  163.     CONST bufSize = 4096;
  164.     VAR sn, dn: ARRAY 128 OF CHAR; sf, df: Files.File; sr, dr: Files.Rider;
  165.         len: LONGINT; buf: ARRAY bufSize OF CHAR;
  166. BEGIN
  167.     COPY(src.path, sn); Strings.Append(delimiter, sn); Strings.Append(e.name, sn);
  168.     COPY(dst.path, dn); Strings.Append(delimiter, dn); Strings.Append(e.name, dn);
  169.     sf := Files.Old(sn); Files.Set(sr, sf, 0);
  170.     df := Files.New(dn); Files.Set(dr, df, 0);
  171.     REPEAT
  172.         Files.ReadBytes(sr, buf, bufSize); Files.WriteBytes(dr, buf, bufSize - sr.res)
  173.     UNTIL sr.res # 0;
  174.     Files.Register(df);
  175. END CopyFile;
  176. PROCEDURE 
  177. MoveFile (e:Elem; src, dst: Text);    
  178.     VAR sn, dn: ARRAY 256 OF CHAR; res: INTEGER;
  179. BEGIN
  180.     COPY(src.path, sn); Strings.Append(delimiter, sn); Strings.Append(e.name, sn);
  181.     COPY(dst.path, dn); Strings.Append(delimiter, dn); Strings.Append(e.name, dn);
  182.     Files.Rename(sn, dn, res); 
  183. END MoveFile;
  184. PROCEDURE 
  185. MakeEntry(d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);
  186.     VAR e: Elem; pos: LONGINT; found: INTEGER;
  187. BEGIN
  188.     Texts.WriteElem(w, NewElem(name, isDir)); Texts.WriteString(w, name); Texts.WriteLn(w);
  189.     FindElem(CBtext, name, e, pos, found); Texts.Insert(CBtext, pos, w.buf)
  190. END MakeEntry;
  191. PROCEDURE 
  192. OpenDir (d: Directories.Directory);    
  193.     VAR t: Text; f: TextFrames.Frame; x, y: INTEGER; v: Viewers.Viewer;
  194. BEGIN
  195.     NEW(t); Texts.Open(t, ""); COPY(d.path, t.path);
  196.     t.notify := NoNotify; CBtext := t;
  197.     Directories.Enumerate(d, MakeEntry);
  198.     CBtext := NIL; t.notify := Notify;
  199.     NEW(f); TextFrames.Open(f, t, 0); f.handle := HandleFrame;
  200.     Oberon.AllocateSystemViewer(0, x, y);
  201.     v := MenuViewers.New(
  202.         TextFrames.NewMenu(d.path, "^Dir.Menu.Text"),
  203.         f, TextFrames.menuH, x, y)
  204. END OpenDir;
  205. PROCEDURE 
  206. ForAllElemsDo (op: INTEGER; src, dst: Text);    
  207.     VAR r: Texts.Reader; beg, end: LONGINT; f: TextFrames.Frame; e: Elem; path: ARRAY 256 OF CHAR; res: INTEGER;
  208.     m: UpdateMsg;
  209. BEGIN
  210.     IF src = NIL THEN RETURN END ;
  211.     end := src.len; Texts.OpenReader(r, src, end);
  212.     LOOP
  213.         Texts.ReadPrevElem(r); IF r.eot THEN EXIT END ;
  214.         IF r.elem IS Elem THEN
  215.             e := r.elem(Elem); beg := Texts.Pos(r);
  216.             IF e.sel THEN
  217.                 IF op = delete THEN
  218.                     COPY(src.path, path); Strings.Append(delimiter, path); Strings.Append(e.name, path);
  219.                     Files.Delete(path, res);     
  220.                     IF res # 0 THEN 
  221.                         Out.String("-- failed$") 
  222.                     ELSE     
  223.                         m.op := Directories.delete; COPY(src.path, m.path); COPY(e.name, m.name);     (*<<FF*)
  224.                         Viewers.Broadcast(m);
  225.                     END;
  226.                 ELSIF op = copy THEN
  227.                     CopyFile(e, src, dst);
  228.                     e.sel := FALSE; e.Update;
  229.                     m.op := Directories.insert; COPY(dst.path, m.path); COPY(e.name, m.name);     (*<<FF*)
  230.                     Viewers.Broadcast(m);
  231.                 ELSIF op = move THEN
  232.                     MoveFile(e, src, dst);
  233.                     m.op := Directories.delete; COPY(src.path, m.path); COPY(e.name, m.name);      (*<<FF*)
  234.                     Viewers.Broadcast(m);
  235.                     m.op := Directories.insert; COPY(dst.path, m.path); COPY(e.name, m.name);
  236.                     Viewers.Broadcast(m);
  237.                 ELSIF op = unselect THEN
  238.                     e.sel := FALSE; e.Update
  239.                 END ;
  240.                 Texts.OpenReader(r, src, beg)
  241.             ELSIF (op = select) & Strings.Match(e.name, mask) THEN
  242.                 e.sel := TRUE; e.Update
  243.             END ;
  244.             end := beg
  245.         END
  246. END ForAllElemsDo;
  247. PROCEDURE 
  248. DrawCopy (x, y: INTEGER);    
  249. BEGIN
  250.     Display.CopyPattern(Display.white, copyHull, x, y, Display.invert)
  251. END DrawCopy;
  252. PROCEDURE 
  253. DrawMove (x, y: INTEGER);    
  254. BEGIN
  255.     Display.CopyPattern(Display.white, moveHull, x, y, Display.invert)
  256. END DrawMove;
  257. PROCEDURE 
  258. ThisFrame (x, y: INTEGER): TextFrames.Frame;    
  259.     VAR v: Viewers.Viewer; f: Display.Frame;
  260. BEGIN
  261.     v := Viewers.This(x, y); f := v.dsc;
  262.     WHILE (f # NIL)
  263.     & ((x < f.X) OR (x > f.X+f.W) OR (y < f.Y) OR (y > f.Y+f.H)) DO
  264.         f := f.next
  265.     END ;
  266.     IF f IS TextFrames.Frame THEN RETURN f(TextFrames.Frame)
  267.     ELSE RETURN NIL
  268. END ThisFrame;
  269. PROCEDURE 
  270. TargetText(): Text;    
  271.     VAR f: TextFrames.Frame;
  272. BEGIN
  273.     IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN
  274.         f := Oberon.Par.frame.next(TextFrames.Frame)
  275.     ELSE
  276.         f := ThisFrame(Oberon.Pointer.X, Oberon.Pointer.Y);
  277.     END ;
  278.     IF f.text IS Text THEN RETURN f.text(Text) ELSE RETURN NIL END
  279. END TargetText;
  280. PROCEDURE 
  281. Init;    
  282.     VAR line: ARRAY 14 OF SET; s: Texts.Scanner; x: Opener;
  283. BEGIN
  284.     line[1] := {};
  285.     line[2] := {1..8};
  286.     line[3] := {1, 8};
  287.     line[4] := {1, 8};
  288.     line[5] := {1, 8};
  289.     line[6] := {1, 8};
  290.     line[7] := {1, 8};
  291.     line[8] := {1, 8};
  292.     line[9] := {1, 5..8};
  293.     line[10] := {1, 5, 7};
  294.     line[11] := {1, 5, 6};
  295.     line[12] := {1..5};
  296.     line[13] := {};
  297.     fileIcon := Display.NewPattern(line, 15, 13);
  298.     line[1] := {};
  299.     line[2] := {1..8};
  300.     line[3] := {1, 4, 8};
  301.     line[4] := {1, 4, 8};
  302.     line[5] := {1, 2..6, 8};
  303.     line[6] := {1, 4, 8};
  304.     line[7] := {1, 4, 8};
  305.     line[8] := {1, 8};
  306.     line[9] := {1, 5..8};
  307.     line[10] := {1, 5, 7};
  308.     line[11] := {1, 5, 6};
  309.     line[12] := {1..5};
  310.     line[13] := {};
  311.     fileIconCopy := Display.NewPattern(line, 15, 13);
  312.     line[1] := {};
  313.     line[2] := {1..8};
  314.     line[3] := {1..8};
  315.     line[4] := {1..8};
  316.     line[5] := {1..8};
  317.     line[6] := {1..8};
  318.     line[7] := {1..8};
  319.     line[8] := {1..8};
  320.     line[9] := {1..8};
  321.     line[10] := {1..5, 7};
  322.     line[11] := {1..6};
  323.     line[12] := {1..5};
  324.     line[13] := {};
  325.     fileIconSel := Display.NewPattern(line, 15, 13);
  326.     line[1] := {};
  327.     line[2] := {};
  328.     line[3] := {1..10};
  329.     line[4] := {1, 10};
  330.     line[5] := {1, 10};
  331.     line[6] := {1, 10};
  332.     line[7] := {1, 10};
  333.     line[8] := {1, 10};
  334.     line[9] := {1, 10};
  335.     line[10] := {1..10};
  336.     line[11] := {1, 5};
  337.     line[12] := {1..4};
  338.     line[13] := {};
  339.     dirIcon := Display.NewPattern(line, 15, 13);
  340.     line[1] := {};
  341.     line[2] := {};
  342.     line[3] := {1..10};
  343.     line[4] := {1, 6, 10};
  344.     line[5] := {1, 6, 10};
  345.     line[6] := {1, 4..8, 10};
  346.     line[7] := {1, 6, 10};
  347.     line[8] := {1, 6, 10};
  348.     line[9] := {1, 10};
  349.     line[10] := {1..10};
  350.     line[11] := {1, 5};
  351.     line[12] := {1..4};
  352.     line[13] := {};
  353.     dirIconCopy := Display.NewPattern(line, 15, 13);
  354.     line[1] := {};
  355.     line[2] := {};
  356.     line[3] := {1..10};
  357.     line[4] := {1..10};
  358.     line[5] := {1..10};
  359.     line[6] := {1..10};
  360.     line[7] := {1..10};
  361.     line[8] := {1..10};
  362.     line[9] := {1..10};
  363.     line[10] := {1..10};
  364.     line[11] := {1, 5};
  365.     line[12] := {1..4};
  366.     line[13] := {};
  367.     dirIconSel := Display.NewPattern(line, 15, 13);
  368.     copyMarker.Draw := DrawCopy; copyMarker.Fade := DrawCopy;
  369.     moveMarker.Draw := DrawMove; moveMarker.Fade := DrawMove;
  370.     Texts.OpenWriter(w);
  371.     ignoreNeutralize := FALSE;
  372.     oldNotifier := Directories.notify;
  373.     Directories.notify := NotifyDir;
  374.     NEW(scratch); Texts.Open(scratch, "Dir.Menu.Text"); scratch.notify := NoNotify;
  375.     Texts.OpenScanner(s, scratch, 0); openers := NIL;
  376.     REPEAT Texts.Scan(s) UNTIL s.eot OR (s.line # 0);
  377.     WHILE s.class = Texts.String DO
  378.         NEW(x); COPY(s.s, x.pattern); Texts.Scan(s);
  379.         IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, x.cmd); Texts.Scan(s); x.next := openers; openers := x END
  380. END Init;
  381. PROCEDURE 
  382. NoNotify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);    
  383. END NoNotify;
  384. PROCEDURE 
  385. Notify (t: Texts.Text; op: INTEGER; beg, end: LONGINT);    
  386.     VAR b: Texts.Buffer; r: Texts.Reader; ch: CHAR; pos: LONGINT;
  387. BEGIN
  388.     IF op = TextFrames.delete THEN
  389.         pos := scratch.len; Texts.Recall(b); Texts.Append(scratch, b);
  390.         Texts.OpenReader(r, scratch, pos);
  391.         REPEAT
  392.             Texts.Read(r, ch)
  393.         UNTIL r.eot OR (ch = CR) OR (ch = Texts.ElemChar) & (r.elem IS Elem);
  394.         IF ~r.eot THEN
  395.             invalidOp := TRUE;
  396.             t.notify := NoNotify;
  397.             Texts.Save(scratch, pos, t.len, b);
  398.             Texts.Insert(t, beg, b);
  399.             t.notify := Notify;
  400.             op := TextFrames.replace; end := beg
  401.         END
  402.     ELSIF op = TextFrames.insert THEN
  403.         Texts.OpenReader(r, t, beg); pos := beg;
  404.         REPEAT
  405.             Texts.Read(r, ch); INC(pos)
  406.         UNTIL (pos > end) OR (ch = CR)
  407.         OR (ch = Texts.ElemChar) & (r.elem IS Elem);
  408.         IF pos <= end THEN
  409.             invalidOp := TRUE;
  410.             t.notify := NoNotify;
  411.             Texts.Delete(t, beg, end);
  412.             t.notify := Notify;
  413.             op := TextFrames.replace; end := beg
  414.         END
  415.     END ;
  416.     ignoreNeutralize := TRUE;
  417.     TextFrames.NotifyDisplay(t, op, beg, end);
  418.     ignoreNeutralize := FALSE
  419. END Notify;
  420. PROCEDURE 
  421. NotifyDir* (op: INTEGER; path, name: ARRAY OF CHAR);    
  422.     VAR m: UpdateMsg;
  423. BEGIN
  424.     m.op := op; COPY(path, m.path); COPY(name, m.name);
  425.     Viewers.Broadcast(m);
  426.     oldNotifier(op, path, name)
  427. END NotifyDir;
  428. PROCEDURE 
  429. HandleElem* (e: Texts.Elem; VAR m: Texts.ElemMsg);    
  430.     CONST moved = -1000;
  431.     VAR e1: Elem; x, y, x0, y0, dsr, res: INTEGER; keys: SET; t: Texts.Text;
  432.         path: ARRAY 128 OF CHAR; marker: Oberon.Marker;
  433.         f: TextFrames.Frame; src, dst: Text; d: Directories.Directory; name: ARRAY 256 OF CHAR; o: Opener;
  434. BEGIN
  435.     WITH e: Elem DO
  436.         WITH m: Texts.CopyMsg DO
  437.             IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END ;
  438.             Texts.CopyElem(e, e1);
  439.             COPY(e.name, e1.name);
  440.             e1.sel := e.sel; e1.icon := e.icon; e1.iconSel := e.iconSel; e1.iconCopy := e.iconCopy
  441.         | m: TextFrames.DisplayMsg DO
  442.             IF ~m.prepare THEN
  443.                 IF e.sel THEN
  444.                     Display.CopyPattern(Display.white, e.iconSel, m.X0, m.Y0+1, Display.replace)
  445.                 ELSE
  446.                     Display.CopyPattern(Display.white, e.icon, m.X0, m.Y0+1, Display.replace)
  447.                 END
  448.             END
  449.         | m: TextFrames.TrackMsg DO
  450.                 IF middle IN m.keys THEN
  451.                     e.sel := ~e.sel; e.Update;
  452.                     src := m.frame(TextFrames.Frame).text(Text);
  453.                     
  454. Input.Mouse(keys, x0, y0);
  455.                     marker := Oberon.Arrow; copyHull := e.iconCopy; moveHull := e.icon;
  456.                     REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
  457.                         IF (e.icon # dirIcon) & ((ABS(x-x0) > 10) OR (ABS(y-y0) > 10)) THEN
  458.                             x0 := moved;
  459.                             IF m.keys = {middle, left} THEN marker := copyMarker ELSE marker := moveMarker END
  460.                         END ;
  461.                         Oberon.DrawCursor(Oberon.Mouse, marker, x, y)
  462.                     UNTIL keys = {};
  463.                     IF m.keys = {middle, right} THEN
  464.                         IF e.icon = dirIcon THEN
  465.                             
  466. t := Texts.ElemBase(e);
  467.                             COPY(t(Text).path, path); Strings.Append(delimiter, path); Strings.Append(e.name, path);
  468.                             OpenDir(Directories.This(path))
  469.                         ELSE
  470.                             
  471. d := Directories.Current(); name := "";
  472.                             IF src.path # d.path THEN
  473.                                 Strings.Append(src.path, name); Strings.Append(delimiter, name)
  474.                             END ;
  475.                             Strings.Append(e.name, name);
  476.                             o := openers;
  477.                             WHILE (o # NIL) & ~Strings.Match(e.name, o.pattern) DO o := o.next END ;
  478.                             IF o = NIL THEN NEW(o); o.cmd := "Edit.Open" END ;
  479.                             Oberon.Par.vwr := Viewers.This(m.X, m.Y); Oberon.Par.frame := m.frame;
  480.                             Oberon.Par.pos := scratch.len; Oberon.Par.text := scratch;
  481.                             Texts.WriteString(w, name); Texts.Append(scratch, w.buf);
  482.                             Oberon.Call(o.cmd, Oberon.Par, FALSE, res)
  483.                         END ;
  484.                         e.sel := FALSE; e.Update
  485.                     ELSIF (x0 = moved) & e.sel THEN
  486.                         f := ThisFrame(x, y);
  487.                         IF (f # NIL) & (f # m.frame) & (f.text IS Text) THEN
  488.                             dst := f.text(Text);
  489.                             IF m.keys = {middle} THEN
  490.                                 ForAllElemsDo(move, src, dst)
  491.                             ELSIF m.keys = {middle, left} THEN
  492.                                 ForAllElemsDo(copy, src, dst)
  493.                             END
  494.                         END
  495.                     END
  496.                 END
  497.         ELSE
  498.         END
  499. END HandleElem;
  500. PROCEDURE 
  501. HandleFrame* (f: Display.Frame; VAR m: Display.FrameMsg);    
  502.     VAR ready: BOOLEAN; e: Elem; keys: SET; x, y, d: INTEGER; t: Texts.Text;
  503.         pos, pos2: LONGINT; r: Texts.Reader; ch: CHAR; path: ARRAY 256 OF CHAR; dir: Directories.Directory;
  504.     PROCEDURE CheckChar(ch: CHAR): BOOLEAN;
  505.     BEGIN
  506.         RETURN (ch=".") OR 
  507.                     ((ch>="0") & (ch<="9")) OR 
  508.                     ((ch>="A") & (ch<="Z")) OR 
  509.                     ((ch>="a") & (ch<="z"));
  510.     END CheckChar;
  511. BEGIN
  512.     ready := FALSE;
  513.     WITH f: TextFrames.Frame DO
  514.         WITH m: Oberon.InputMsg DO
  515.             IF m.id = Oberon.consume THEN
  516.                 pos := f.carloc.pos; e := ThisElem(f.text, pos);
  517.                 IF (m.ch = CR) OR (m.ch = PageUp) OR (m.ch = PageDown) OR (m.ch = Home) OR (m.ch = BRK) THEN
  518.                     e.Check; TextFrames.RemoveCaret(f); ready := TRUE
  519.                 ELSIF (m.ch = CRSU) OR (m.ch = CRSD) THEN
  520.                     e.Check
  521.                 ELSIF m.ch = DEL THEN
  522.                     invalidOp := FALSE;
  523.                     TextFrames.Handle(f, m); ready := TRUE;
  524.                     IF invalidOp THEN
  525.                         e := ThisElem(f.text, pos);
  526.                         e.Check; TextFrames.RemoveCaret(f)
  527.                     END
  528.                 ELSE
  529.                     Texts.OpenReader(r, f.text, f.carloc.pos); Texts.Read(r, ch);
  530.                     ready := (ch = Texts.ElemChar) & (r.elem IS Elem);
  531.                     (* We have to check here wether the char is allowed or not. 
  532.                         Allowed chars; letters, digits, "." *)    
  533.                     IF ~CheckChar(m.ch) THEN ready := TRUE END; 
  534.                 END
  535.             ELSIF (m.id = Oberon.track) & f.hasCar & (m.keys * {middle, right} # {}) THEN
  536.                 e := ThisElem(f.text, f.carloc.pos);
  537.                 IF (e # NIL) & (ThisElem(f.text, TextFrames.Pos(f, x, y)) # e) THEN e.Check END
  538.             END
  539.         | m: Oberon.ControlMsg DO
  540.             IF m.id = Oberon.defocus THEN
  541.                 e := ThisElem(f.text, f.carloc.pos);
  542.                 Input.Mouse(keys, x, y);
  543.                 IF (e # NIL) & ((f # ThisFrame(x, y)) OR (ThisElem(f.text, TextFrames.Pos(f, x, y)) # e)) THEN
  544.                     e.Check
  545.                 END
  546.             ELSIF (m.id = Oberon.neutralize) & ~ignoreNeutralize & f.hasCar THEN
  547.                 e := ThisElem(f.text, f.carloc.pos);
  548.                 IF e # NIL THEN e.Check END
  549.             END
  550.         | m: UpdateMsg DO
  551.             IF (Diff(f.text(Text).path, m.path) = 0)  THEN 
  552.                 t := f.text; FindElem(t, m.name, e, pos, d);
  553.                 t.notify := TextFrames.NotifyDisplay;
  554.                 CASE m.op OF
  555.                  | Directories.insert:
  556.                     IF d # 0 THEN
  557.                         COPY(m.path, path); Strings.Append(delimiter, path); Strings.Append(m.name, path);
  558.                         dir := Directories.This(path); 
  559.                         Texts.WriteElem(w, NewElem(m.name, dir # NIL)); Texts.WriteString(w, m.name); Texts.WriteLn(w);
  560.                         Texts.Insert(t, pos, w.buf)
  561.                     END
  562.                 | Directories.delete:
  563.                     IF d = 0 THEN
  564.                         Texts.OpenReader(r, t, pos+1); Texts.ReadElem(r);
  565.                         IF r.eot THEN pos2 := t.len ELSE pos2 := Texts.Pos(r) - 1 END ;
  566.                         Texts.Delete(t, pos, pos2)
  567.                     END
  568.                 | Directories.change:
  569.                 END ;
  570.                 t.notify := Notify
  571.             END
  572.         ELSE
  573.         END
  574.     END ;
  575.     IF ~ready THEN TextFrames.Handle(f, m) END
  576. END HandleFrame;
  577. PROCEDURE 
  578. Open*;
  579.     dir: Directories.Directory;        (*<<FF*)
  580. BEGIN
  581.     NEW(dir);                            
  582.     COPY(Files.CurrentDir, dir.path);
  583.     OpenDir(dir);
  584.     dir := NIL;
  585. END Open;
  586. PROCEDURE 
  587. New*;    
  588.     VAR name: ARRAY 256 OF CHAR; i: INTEGER;
  589. BEGIN
  590.     In.Open;
  591.     IF In.Next() = In.string THEN In.String(name) ELSE In.Name(name) END ;
  592.     IF In.Done THEN Directories.Create(name) END
  593. END New;
  594. PROCEDURE 
  595. Delete*;    
  596. BEGIN
  597.     ForAllElemsDo(delete, TargetText(), NIL)
  598. END Delete;
  599. PROCEDURE 
  600. Select*;    
  601.     VAR ch: CHAR; i: INTEGER;
  602. BEGIN
  603.     In.Open; i := 0;
  604.     REPEAT In.Char(ch) UNTIL ch >= " ";
  605.     REPEAT mask[i] := ch; INC(i); In.Char(ch) UNTIL (ch <= " ") OR (ch > 7FX);
  606.     mask[i] := 0X;
  607.     ForAllElemsDo(select, TargetText(), NIL)
  608. END Select;
  609. PROCEDURE 
  610. Deselect*;    
  611. BEGIN
  612.     ForAllElemsDo(unselect, TargetText(), NIL)
  613. END Deselect;
  614. BEGIN
  615.     Init
  616. END Dir.
  617.