Windows.Oberon.Directories.Mod 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. (* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
  2. Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
  3. MODULE Directories IN Oberon; (** portable / source: Win32.Directories.Mod *) (* ps, *)
  4. IMPORT
  5. Kernel32 IN A2, FileDir, Files, Modules, Input, Strings, Display, Pictures, Display3, Printer, Printer3, Objects, Attributes,
  6. Texts, Gadgets, Oberon, ListRiders, ListGadgets, Win32FS := WinFS IN A2, AosFS := Files IN A2;
  7. CONST
  8. (* drive types *)
  9. None = Kernel32.DriveNoRootDir; Removable = Kernel32.DriveRemovable; Fixed = Kernel32.DriveFixed;
  10. Remote = Kernel32.DriveRemote; CDROM = Kernel32.DriveCDRom; RAMDisk = Kernel32.DriveRamDisk; Floppy = 7;
  11. FoldC = 8; FoldO = 9;
  12. Picts = 9;
  13. NoDataStr = "INVALID DATA";
  14. TYPE
  15. Data = POINTER TO DataDesc;
  16. DataDesc = RECORD (ListRiders.StringDesc)
  17. pictNr: LONGINT
  18. END;
  19. Item = POINTER TO ItemDesc;
  20. ItemDesc = RECORD
  21. s: ARRAY 64 OF CHAR; (* Data value *)
  22. key, pos, stamp, state: LONGINT;
  23. dsc, asc, next, prev: Item (* asc: parent; dsc: first child (sentinel); next, prev: brothers *)
  24. END;
  25. Model* = POINTER TO ModelDesc;
  26. ModelDesc* = RECORD (Gadgets.ObjDesc)
  27. tail: Item; (* top of tree (sentinel) *)
  28. mask: ARRAY 32 OF CHAR; (* filename mask *)
  29. rootDir: FileDir.FileName; (* root Directory *)
  30. key: LONGINT (* Next unique-key *)
  31. END;
  32. Rider* = POINTER TO RiderDesc;
  33. RiderDesc* = RECORD (ListRiders.RiderDesc)
  34. item: Item (* Rider's current item *)
  35. END;
  36. VAR
  37. model: Model; (* global used in Enum *)
  38. root: Item; (* global used in Enum *)
  39. R: ListRiders.Rider; (* global used in EnumForList *)
  40. writePath: BOOLEAN; (* global used in EnumForList *)
  41. mMethod: ListRiders.Method;
  42. vMethod: ListGadgets.Method;
  43. drvPicts: ARRAY Picts OF Pictures.Picture;
  44. maxW: INTEGER;
  45. drv: Objects.Object;
  46. StringHandler: Objects.Handler;
  47. task : Oberon.Task;
  48. (*========== aux. procs ==========*)
  49. PROCEDURE IsDriveAvailable (drv: ARRAY OF CHAR): BOOLEAN;
  50. BEGIN RETURN (drv[0] = "C") OR (Kernel32.GetDriveType(drv) > None)
  51. END IsDriveAvailable;
  52. PROCEDURE IsOnlyDrive (path: ARRAY OF CHAR): BOOLEAN;
  53. BEGIN RETURN (path[0] # 0X) & (path[1] = ":") & (path[2] = 0X)
  54. END IsOnlyDrive;
  55. PROCEDURE IsDirectory (path: ARRAY OF CHAR): BOOLEAN;
  56. VAR attrs: SET; res: BOOLEAN;
  57. BEGIN
  58. IF IsOnlyDrive(path) THEN res := IsDriveAvailable(path)
  59. ELSE
  60. attrs := Kernel32.GetFileAttributes(path);
  61. IF attrs # {0 .. 31} THEN res := Kernel32.FileAttributeDirectory IN attrs
  62. ELSE res := FALSE
  63. END
  64. END;
  65. RETURN res
  66. END IsDirectory;
  67. PROCEDURE CheckPath (VAR path: ARRAY OF CHAR);
  68. VAR i: LONGINT;
  69. BEGIN
  70. IF (path[0] # 0X) & (path[1] = ":") THEN (* path with dirve *)
  71. path[0] := CAP(path[0]);
  72. IF (path[2] = FileDir.PathChar) & (path[3] = 0X) THEN path[2] := 0X END
  73. END;
  74. i := 0; WHILE path[i] # 0X DO INC(i) END;
  75. WHILE (i > 0) & ~IsDirectory(path) DO
  76. REPEAT DEC(i) UNTIL (i = 0) OR (path[i] = FileDir.PathChar);
  77. path[i] := 0X
  78. END
  79. END CheckPath;
  80. PROCEDURE GetKey (obj: Model): LONGINT;
  81. BEGIN INC(obj.key); RETURN obj.key - 1
  82. END GetKey;
  83. (*========== Item handling ==========*)
  84. (* creates a new item *)
  85. PROCEDURE NewItem (name: ARRAY OF CHAR; key: LONGINT): Item;
  86. VAR n: Item;
  87. BEGIN
  88. NEW(n); COPY(name, n.s); n.key := key; n.stamp := -1;
  89. n.next := n; n.prev := n; n.dsc := NIL; n.asc := NIL;
  90. RETURN n
  91. END NewItem;
  92. (* Insert item "n" after "item" *)
  93. PROCEDURE InsertItem (item, n: Item);
  94. BEGIN
  95. n.next := item.next; n.prev := item; item.next.prev := n; item.next := n;
  96. n.pos := item.pos; n.asc := item.asc;
  97. WHILE n.key >= 0 DO INC(n.pos); n := n.next END
  98. END InsertItem;
  99. (* FileDir.FileEnumerator. Global variable "model" has to be preset. *)
  100. PROCEDURE Enum (path, name: ARRAY OF CHAR; time, date, size: LONGINT; attrs: SET);
  101. VAR new, cur: Item;
  102. PROCEDURE CAPCompare (VAR s1, s2: ARRAY OF CHAR): INTEGER;
  103. VAR i: LONGINT;
  104. BEGIN
  105. i := 0;
  106. WHILE (s1[i] # 0X) & (s2[i] # 0X) & (CAP(s1[i]) = CAP(s2[i])) DO INC(i) END;
  107. RETURN ORD(CAP(s1[i])) - ORD(CAP(s2[i]))
  108. END CAPCompare;
  109. BEGIN
  110. new := NewItem(name, GetKey(model));
  111. cur := root;
  112. IF FileDir.Directory IN attrs THEN
  113. new.dsc := NewItem("", -1); new.dsc.pos := -1; new.dsc.asc := new;
  114. REPEAT cur := cur.next UNTIL (cur = root) OR (cur.dsc = NIL) OR (CAPCompare(cur.s, name) > 0)
  115. ELSE
  116. REPEAT cur := cur.next UNTIL (cur = root) OR ((cur.dsc = NIL) & (CAPCompare(cur.s, name) > 0))
  117. END;
  118. InsertItem(cur.prev, new)
  119. END Enum;
  120. PROCEDURE BuildList (obj: Model; tail: Item; path, mask: ARRAY OF CHAR);
  121. BEGIN
  122. model := obj; root := tail;
  123. FileDir.EnumerateFiles(path, mask, FALSE, Enum);
  124. root := NIL; model := NIL
  125. END BuildList;
  126. (*========== Rider handling ==========*)
  127. PROCEDURE SetItem (R: Rider; item: Item);
  128. VAR d: Data; res: LONGINT;
  129. BEGIN
  130. R.item := item; R.eol := item.key < 0; R.dsc := item.dsc # NIL;
  131. IF (R.d = NIL) OR ~(R.d IS Data) THEN NEW(d); R.d := d ELSE d := R.d(Data) END;
  132. COPY(item.s, d.s);
  133. IF IsOnlyDrive(item.s) THEN (* item is a drive *)
  134. IF CAP(item.s[0]) = "C" THEN res := Fixed
  135. ELSIF CAP(item.s[0]) < "C" THEN res := Floppy
  136. ELSE
  137. res := Kernel32.GetDriveType(item.s);
  138. IF res > RAMDisk THEN res := Fixed ELSIF res < None THEN res := None END
  139. END;
  140. d.pictNr := res
  141. ELSIF R.dsc THEN d.pictNr := FoldC
  142. ELSE d.pictNr := -1
  143. END
  144. END SetItem;
  145. (* Get the current item's key *)
  146. PROCEDURE Key (R: ListRiders.Rider): LONGINT;
  147. BEGIN RETURN R(Rider).item.key
  148. END Key;
  149. (* Position rider R on the item having the given key *)
  150. PROCEDURE Seek (R: ListRiders.Rider; key: LONGINT);
  151. PROCEDURE Traverse (this: Item; key: LONGINT): Item;
  152. VAR found: Item;
  153. BEGIN
  154. this := this.next;
  155. WHILE (this.key >= 0) & (this.key # key) DO
  156. IF this.dsc # NIL THEN
  157. found := Traverse(this.dsc, key);
  158. IF found.key = key THEN RETURN found END
  159. END;
  160. this := this.next
  161. END;
  162. RETURN this
  163. END Traverse;
  164. BEGIN
  165. SetItem(R(Rider), Traverse(R.base(Model).tail, key))
  166. END Seek;
  167. (* Get current position of the rider *)
  168. PROCEDURE Pos (R: ListRiders.Rider): LONGINT;
  169. BEGIN RETURN R(Rider).item.pos
  170. END Pos;
  171. (* Position rider R on the item having the given pos *)
  172. PROCEDURE Set (R: ListRiders.Rider; pos: LONGINT);
  173. VAR n : Item;
  174. BEGIN
  175. WITH R: Rider DO
  176. n := R.item;
  177. ASSERT(n # NIL);
  178. IF n.pos > pos THEN REPEAT n := n.prev UNTIL (n.pos = pos) OR (n.key < 0)
  179. ELSIF n.pos < pos THEN REPEAT n := n.next UNTIL (n.pos = pos) OR (n.key < 0)
  180. END;
  181. SetItem(R, n)
  182. END
  183. END Set;
  184. (* Insert data at the current position of R. This Method is disabled *)
  185. PROCEDURE Write (R: ListRiders.Rider; d: ListRiders.Data);
  186. END Write;
  187. (* Link the item at the position of linkR to the current position of R. This Method is disabled *)
  188. PROCEDURE WriteLink (R, linkR: ListRiders.Rider);
  189. END WriteLink;
  190. (* Delete item at the current position of R. This Method is disabled *)
  191. PROCEDURE DeleteLink (R, linkR: ListRiders.Rider);
  192. END DeleteLink;
  193. (* Get a rider working on the descendants of the item on the position of R. If old is NIL, then a new rider
  194. is allocated. old is recycled if not NIL *)
  195. PROCEDURE Desc (R, old: ListRiders.Rider): ListRiders.Rider;
  196. VAR new: Rider; base: Model; item: Item; path: FileDir.FileName; pos: LONGINT;
  197. PROCEDURE MakePath (item: Item; VAR path: ARRAY OF CHAR; VAR pos: LONGINT);
  198. VAR i: LONGINT;
  199. BEGIN
  200. IF item.asc # NIL THEN MakePath(item.asc, path, pos) END;
  201. i:= 0;
  202. WHILE item.s[i] # 0X DO path[pos] := item.s[i]; INC(pos); INC(i) END;
  203. path[pos] := "/"; INC(pos); path[pos] := 0X
  204. END MakePath;
  205. BEGIN
  206. IF old = NIL THEN NEW(new) ELSE new := old(Rider) END;
  207. WITH R: Rider DO
  208. new.do := R.do; new.base := R.base;
  209. IF R.item.dsc # NIL THEN
  210. item := R.item.dsc;
  211. IF item.next = item THEN
  212. path := ""; pos := 0;
  213. MakePath(R.item, path, pos);
  214. base := R.base(Model);
  215. BuildList(base, item, path, base.mask);
  216. END;
  217. item := item.next
  218. ELSE item := R.item
  219. END;
  220. SetItem(new, item)
  221. END;
  222. RETURN new
  223. END Desc;
  224. (* Get stamp value of the item at the current position of R *)
  225. PROCEDURE GetStamp (R: ListRiders.Rider): LONGINT;
  226. BEGIN RETURN R(Rider).item.stamp
  227. END GetStamp;
  228. (* Set stamp value of the item at the current position of R *)
  229. PROCEDURE SetStamp (R: ListRiders.Rider; stamp: LONGINT);
  230. BEGIN R(Rider).item.stamp := stamp
  231. END SetStamp;
  232. (* Get the state of the current item *)
  233. PROCEDURE State (R: ListRiders.Rider): LONGINT;
  234. BEGIN RETURN R(Rider).item.state
  235. END State;
  236. (* Set the state of the current item *)
  237. PROCEDURE SetState (R: ListRiders.Rider; s: LONGINT);
  238. BEGIN R(Rider).item.state := SHORT(s)
  239. END SetState;
  240. PROCEDURE ConnectRider (R: Rider; base: Model);
  241. BEGIN R.do := mMethod; R.base := base; SetItem(R, base.tail.next)
  242. END ConnectRider;
  243. (*========== Model handling ==========*)
  244. (** Update the model (not yet implemented) *)
  245. PROCEDURE UpdateModel* (obj: Model);
  246. BEGIN
  247. InitModel(obj, obj.rootDir, obj.mask);
  248. END UpdateModel;
  249. PROCEDURE ModelAttr (obj: Model; VAR M: Objects.AttrMsg);
  250. BEGIN
  251. IF M.id = Objects.get THEN
  252. IF M.name = "Gen" THEN COPY("Directories.New", M.s); M.class := Objects.String; M.res := 0
  253. ELSIF M.name = "Mask" THEN COPY(obj.mask, M.s); M.class := Objects.String; M.res := 0
  254. ELSIF M.name = "RootDir" THEN COPY(obj.rootDir, M.s); M.class := Objects.String; M.res := 0
  255. ELSE Gadgets.objecthandle(obj, M)
  256. END
  257. ELSIF M.id = Objects.set THEN
  258. IF M.name = "Mask" THEN
  259. IF (M.class = Objects.String) THEN
  260. IF M.s # obj.mask THEN
  261. COPY(M.s, obj.mask); UpdateModel(obj)
  262. END;
  263. M.res := 0
  264. END
  265. ELSIF M.name = "RootDir" THEN
  266. IF M.class = Objects.String THEN
  267. IF ~Strings.CAPCompare(M.s, obj.rootDir) THEN
  268. COPY(M.s, obj.rootDir); UpdateModel(obj)
  269. END;
  270. M.res := 0
  271. END
  272. ELSE Gadgets.objecthandle(obj, M)
  273. END
  274. ELSIF M.id = Objects.enum THEN
  275. M.Enum("Mask"); M.Enum("RootDir"); Gadgets.objecthandle(obj, M)
  276. ELSE Gadgets.objecthandle(obj, M)
  277. END
  278. END ModelAttr;
  279. (** Standard handler for directory models *)
  280. PROCEDURE ModelHandler* (obj: Objects.Object; VAR M: Objects.ObjMsg);
  281. VAR R: Rider;
  282. BEGIN
  283. WITH obj: Model DO
  284. IF M IS Objects.AttrMsg THEN
  285. ModelAttr(obj, M(Objects.AttrMsg))
  286. ELSIF M IS Objects.CopyMsg THEN
  287. M(Objects.CopyMsg).obj := obj (* Too heavyweight to copy ==> returning myself*)
  288. ELSIF M IS ListRiders.ConnectMsg THEN
  289. NEW(R); ConnectRider(R, obj); M(ListRiders.ConnectMsg).R := R
  290. ELSIF M IS Objects.FileMsg THEN
  291. WITH M: Objects.FileMsg DO
  292. IF M.id = Objects.load THEN
  293. Files.ReadString(M.R, obj.mask);
  294. Files.ReadString(M.R, obj.rootDir);
  295. UpdateModel(obj)
  296. ELSIF M.id = Objects.store THEN
  297. Files.WriteString(M.R, obj.mask);
  298. Files.WriteString(M.R, obj.rootDir)
  299. END;
  300. Gadgets.objecthandle(obj, M)
  301. END
  302. ELSE Gadgets.objecthandle(obj, M)
  303. END
  304. END
  305. END ModelHandler;
  306. (** Initialize a directory model *)
  307. PROCEDURE InitModel* (obj: Model; rootDir, mask: ARRAY OF CHAR);
  308. VAR tail: Item; i: LONGINT; drvName: ARRAY 4 OF CHAR;
  309. PROCEDURE NewDrv (name: ARRAY OF CHAR);
  310. VAR drv, dsc: Item;
  311. BEGIN
  312. drv := NewItem(name, GetKey(obj));
  313. dsc := NewItem("", -1); dsc.pos := -1; dsc.asc := drv;
  314. drv.dsc := dsc;
  315. InsertItem(tail.prev, drv)
  316. END NewDrv;
  317. BEGIN
  318. obj.handle := ModelHandler; obj.key := 0;
  319. COPY(rootDir, obj.rootDir); CheckPath(obj.rootDir);
  320. COPY(mask, obj.mask);
  321. tail := NewItem("", -1); tail.pos := -1; obj.tail := tail;
  322. IF obj.rootDir = "" THEN
  323. COPY("A:", drvName);
  324. FOR i := 0 TO 25 DO
  325. drvName[0] := CHR(ORD("A") + i);
  326. IF IsDriveAvailable(drvName) THEN NewDrv(drvName) END
  327. END
  328. ELSE NewDrv(obj.rootDir)
  329. END
  330. END InitModel;
  331. (** Generator for directory models *)
  332. PROCEDURE New*;
  333. VAR obj: Model;
  334. BEGIN NEW(obj); InitModel(obj, "", "*"); Objects.NewObj := obj
  335. END New;
  336. (* ------------ view stuff ------------ *)
  337. PROCEDURE FormatLine (F: ListGadgets.Frame; R: ListRiders.Rider; L: ListGadgets.Line);
  338. VAR d: Data; pict: Pictures.Picture;
  339. BEGIN
  340. IF (R.d # NIL) & (R.d IS Data) THEN
  341. d := R.d(Data);
  342. Display3.StringSize(d.s, F.fnt, L.w, L.h, L.dsr);
  343. IF d.pictNr >= None THEN
  344. pict := drvPicts[d.pictNr-1];
  345. IF (pict # NIL) & (pict.height + 2 > L.h) THEN L.h := pict.height + 2 END
  346. END
  347. ELSE
  348. Display3.StringSize(NoDataStr, F.fnt, L.w, L.h, L.dsr)
  349. END;
  350. L.dx := maxW + 2 + L.lev*F.tab
  351. END FormatLine;
  352. PROCEDURE DisplayLine (F: ListGadgets.Frame; Q: Display3.Mask; x, y, w, h: INTEGER; R: ListRiders.Rider; L: ListGadgets.Line);
  353. VAR d: Data; pict: Pictures.Picture; str: ARRAY 64 OF CHAR;
  354. BEGIN
  355. Display3.ReplConst(Q, F.backC, x, y, w, h, Display.replace);
  356. INC(x, L.lev*F.tab);
  357. IF (R.d # NIL) & (R.d IS Data) THEN
  358. d := R.d(Data);
  359. IF d.pictNr >= None THEN
  360. IF (d.pictNr = FoldC) & ~L.folded THEN INC(d.pictNr) END;
  361. pict := drvPicts[d.pictNr-1];
  362. Display3.Pict(Q, pict, 0, 0, pict.width, pict.height, x, y + 2, Display.replace)
  363. END;
  364. COPY(d.s, str)
  365. ELSE str := NoDataStr
  366. END;
  367. INC(x, maxW + 2);
  368. Display3.String(Q, F.textC, x, y + L.dsr, F.fnt, str, Display.paint)
  369. END DisplayLine;
  370. PROCEDURE P (x: LONGINT): INTEGER;
  371. BEGIN RETURN SHORT((x * Display.Unit) DIV Printer.Unit)
  372. END P;
  373. PROCEDURE PrintFormatLine (F: ListGadgets.Frame; R: ListRiders.Rider; L: ListGadgets.Line);
  374. VAR d: Data; pict: Pictures.Picture;
  375. BEGIN
  376. IF (R.d # NIL) & (R.d IS Data) THEN
  377. d := R.d(Data);
  378. Printer3.StringSize(d.s, F.fnt, L.w, L.h, L.dsr);
  379. IF d.pictNr >= None THEN
  380. pict := drvPicts[d.pictNr-1];
  381. IF (pict # NIL) & (P(pict.height + 2) > L.h) THEN L.h := P(pict.height + 2) END
  382. END
  383. ELSE
  384. Printer3.StringSize("INVALID DATA", F.fnt, L.w, L.h, L.dsr)
  385. END;
  386. L.dx := P(maxW + 2 + L.lev*F.tab)
  387. END PrintFormatLine;
  388. PROCEDURE PrintLine (F: ListGadgets.Frame; Q: Display3.Mask; x, y, w, h: INTEGER; R: ListRiders.Rider; L: ListGadgets.Line);
  389. VAR d: Data; pict: Pictures.Picture; str: ARRAY 64 OF CHAR;
  390. BEGIN
  391. Printer3.ReplConst(Q, F.backC, x, y, w, h, Display.replace);
  392. INC(x, P(L.lev*F.tab));
  393. IF (R.d # NIL) & (R.d IS Data) THEN
  394. d := R.d(Data);
  395. IF d.pictNr >= None THEN
  396. IF (d.pictNr = FoldC) & ~L.folded THEN INC(d.pictNr) END;
  397. pict := drvPicts[d.pictNr-1];
  398. Printer3.Pict(Q, pict, x, y+2, P(pict.width), P(pict.height), Display.replace)
  399. END;
  400. COPY(d.s, str)
  401. ELSE str := NoDataStr
  402. END;
  403. INC(x, P(maxW + 2));
  404. Printer3.String(Q, F.textC, x, y + L.dsr, F.fnt, str, Display.paint)
  405. END PrintLine;
  406. PROCEDURE GadgetHandler (F: Objects.Object; VAR M: Objects.ObjMsg);
  407. BEGIN
  408. IF M IS Objects.AttrMsg THEN
  409. WITH M: Objects.AttrMsg DO
  410. IF (M.id = Objects.get) & (M.name = "Gen") THEN
  411. M.class := Objects.String; M.s := "Directories.NewDirList"; M.res := 0
  412. ELSE ListGadgets.FrameHandler(F, M)
  413. END
  414. END
  415. ELSE ListGadgets.FrameHandler(F, M)
  416. END
  417. END GadgetHandler;
  418. PROCEDURE NewDirList*;
  419. VAR F: ListGadgets.Frame;
  420. BEGIN
  421. NEW(F); ListGadgets.InitFrame(F);
  422. F.handle := GadgetHandler; F.do := vMethod;
  423. F.tab := 8;
  424. INCL(F.state0, ListGadgets.inclpath); INCL(F.state0, ListGadgets.extendsel);
  425. Objects.NewObj := F
  426. END NewDirList;
  427. (* ------------ working dir. model ------------ *)
  428. PROCEDURE TaskHandler (me : Oberon.Task);
  429. VAR old, s: ARRAY 64 OF CHAR;
  430. BEGIN
  431. Win32FS.GetWorkingDirectory(s);
  432. Attributes.GetString(drv, "Value", old);
  433. IF old # s THEN
  434. Attributes.SetString(drv, "Value", s); Gadgets.Update(drv)
  435. END;
  436. me.time := Oberon.Time() + Input.TimeUnit DIV 2
  437. END TaskHandler;
  438. PROCEDURE HandleDrv (obj: Objects.Object; VAR M: Objects.ObjMsg);
  439. BEGIN
  440. IF M IS Objects.CopyMsg THEN
  441. M(Objects.CopyMsg).obj := drv;
  442. ELSIF M IS Objects.AttrMsg THEN
  443. WITH M : Objects.AttrMsg DO
  444. IF (M.id = Objects.get) & (M.name = "Gen") THEN M.s := "Directories.NewDrv"
  445. ELSE StringHandler(obj, M)
  446. END
  447. END
  448. ELSE StringHandler(obj,M)
  449. END
  450. END HandleDrv;
  451. PROCEDURE NewDrv*;
  452. BEGIN Objects.NewObj := drv
  453. END NewDrv;
  454. (* ------------ aux. Commands ------------ *)
  455. PROCEDURE EnumForList (path, name: ARRAY OF CHAR; time, date, size: LONGINT; attrs: SET);
  456. VAR d: ListRiders.String; full: ARRAY 256 OF CHAR; i, j: LONGINT;
  457. BEGIN
  458. IF ~(FileDir.Directory IN attrs) THEN
  459. NEW(d);
  460. IF writePath THEN
  461. i := 0; j := 0;
  462. WHILE path[j] # 0X DO full[i] := path[j]; INC(i); INC(j) END;
  463. full[i] := FileDir.PathChar; INC(i);
  464. j := 0;
  465. WHILE name[j] # 0X DO full[i] := name[j]; INC(i); INC(j) END;
  466. full[i] := 0X;
  467. (*
  468. FileDir.RelFileName(full, d.s)
  469. *)
  470. COPY(full,d.s);
  471. ELSE
  472. COPY(name, d.s)
  473. END;
  474. R.do.Write(R, d)
  475. END
  476. END EnumForList;
  477. (** Finds all the filenames in the search path that match a specified pattern and inserts them
  478. into a list model gadget (ListModel, Tree or Dag) named <Objname> in the current context.
  479. If the option p is specified, the filenames are prefixed with their relative path in the current
  480. working directory.
  481. Usage: Directories.Directory [\p] "<pattern>" <Objname> ~
  482. *)
  483. PROCEDURE Directory*;
  484. VAR obj: Objects.Object; i, j: LONGINT; path, pattern: AosFS.FileName; C: ListRiders.ConnectMsg; S: Texts.Scanner;
  485. BEGIN
  486. writePath := FALSE;
  487. Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
  488. IF (S.class = Texts.Char) & (S.c = Oberon.OptionChar) THEN
  489. S.s := ""; Texts.Scan(S);
  490. i := 0;
  491. WHILE S.s[i] # 0X DO writePath := writePath OR (S.s[i] = "p"); INC(i) END;
  492. Texts.Scan(S)
  493. END;
  494. IF S.class IN {Texts.Name, Texts.String} THEN
  495. COPY(S.s, path); Texts.Scan(S);
  496. i := 0; j := 0;
  497. WHILE path[i] # 0X DO
  498. IF path[i] = FileDir.PathChar THEN
  499. j := i+1
  500. END;
  501. INC(i)
  502. END;
  503. i := 0;
  504. WHILE path[j] # 0X DO
  505. pattern[i] := path[j]; INC(j); INC(i)
  506. END;
  507. pattern[i] := 0X; path[j-i] := 0X;
  508. IF S.class IN {Texts.Name, Texts.String} THEN
  509. obj := Gadgets.FindObj(Gadgets.context, S.s);
  510. IF obj # NIL THEN
  511. C.R := NIL; Objects.Stamp(C); obj.handle(obj, C);
  512. IF C.R # NIL THEN
  513. R := C.R;
  514. WHILE ~R.eol DO R.do.DeleteLink(NIL, R) END;
  515. R.do.Set(R, 0);
  516. FileDir.EnumerateFiles(path, pattern, FALSE, EnumForList);
  517. Gadgets.Update(obj);
  518. R := NIL (* for carbage collection *)
  519. END
  520. END
  521. END
  522. END
  523. END Directory;
  524. (* ------------ aux. Porcs ------------ *)
  525. PROCEDURE GetPicts;
  526. PROCEDURE Set (i: LONGINT; pict: Objects.Object);
  527. BEGIN
  528. DEC(i);
  529. IF (pict = NIL) OR ~(pict IS Pictures.Picture) THEN drvPicts[i] := NIL
  530. ELSE
  531. WITH pict: Pictures.Picture DO
  532. drvPicts[i] := pict;
  533. IF maxW < pict.width THEN maxW := pict.width END
  534. END
  535. END
  536. END Set;
  537. BEGIN
  538. maxW := 0;
  539. Set(None, Gadgets.FindPublicObj("Symbols.None"));
  540. Set(Removable, Gadgets.FindPublicObj("Symbols.Removable"));
  541. Set(Fixed, Gadgets.FindPublicObj("Symbols.Fixed"));
  542. Set(Remote, Gadgets.FindPublicObj("Symbols.Remote"));
  543. Set(CDROM, Gadgets.FindPublicObj("Symbols.CDROM"));
  544. Set(RAMDisk, Gadgets.FindPublicObj("Symbols.RAMDisk"));
  545. Set(Floppy, Gadgets.FindPublicObj("Symbols.Floppy"));
  546. Set(FoldC, Gadgets.FindPublicObj("Symbols.FoldC"));
  547. Set(FoldO, Gadgets.FindPublicObj("Symbols.FoldO"))
  548. END GetPicts;
  549. PROCEDURE Cleanup;
  550. BEGIN
  551. Oberon.Remove(task)
  552. END Cleanup;
  553. BEGIN
  554. NEW(mMethod);
  555. mMethod.Key := Key; mMethod.Seek := Seek; mMethod.Pos := Pos; mMethod.Set := Set;
  556. mMethod.State := State; mMethod.SetState := SetState;
  557. mMethod.Write := Write; mMethod.WriteLink := WriteLink; mMethod.DeleteLink := DeleteLink;
  558. mMethod.Desc := Desc; mMethod.GetStamp := GetStamp; mMethod.SetStamp := SetStamp;
  559. NEW(vMethod);
  560. vMethod^ := ListGadgets.methods^;
  561. vMethod.Format := FormatLine; vMethod.Display := DisplayLine;
  562. vMethod.PrintFormat := PrintFormatLine; vMethod.Print := PrintLine;
  563. NEW(task); task.handle := TaskHandler; task.time := Oberon.Time(); task.safe := TRUE; Oberon.Install(task);
  564. drv := Gadgets.CreateObject("String"); StringHandler := drv.handle; drv.handle := HandleDrv;
  565. Modules.InstallTermHandler(Cleanup);
  566. GetPicts
  567. END Directories.
  568. Gadgets.Insert TextFields.NewTextField Directories.NewDrv ~
  569. Gadgets.Insert Directories.NewDirList Directories.New ~