2
0

Dialog.txt 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. MODULE Dialog;
  2. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/Dialog.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT SYSTEM, Kernel, Files;
  5. CONST
  6. pressed* = 1; released* = 2; changed* = 3; included* = 5; excluded* = 6; set* = 7; (** notify ops **)
  7. ok* = 1; yes* = 2; no* = 3; cancel* = 4; (** GetOK forms & results **)
  8. persistent* = TRUE; nonPersistent* = FALSE; (** constants for SetLanguage **)
  9. stringLen = 256;
  10. bufLen = 252;
  11. rsrcDir = "Rsrc";
  12. stringFile = "Strings";
  13. TAB = 09X; CR = 0DX;
  14. update = 2; (* notify options *)
  15. listUpdate = 3;
  16. guardCheck = 4;
  17. windows32s* = 11;
  18. windows95* = 12;
  19. windowsNT3* = 13;
  20. windowsNT4* = 14;
  21. windows2000* = 15;
  22. windows98* = 16;
  23. windowsXP* = 17;
  24. windowsVista* = 18;
  25. macOS* = 21;
  26. macOSX* = 22;
  27. linux* = 30;
  28. tru64* = 40;
  29. firstPos* = 0;
  30. lastPos* = -1;
  31. TYPE
  32. String* = ARRAY stringLen OF CHAR;
  33. Buf = POINTER TO RECORD
  34. next: Buf;
  35. s: ARRAY bufLen OF CHAR
  36. END;
  37. StrList = RECORD
  38. len, max: INTEGER; (* number of items, max number of items *)
  39. strings: Buf; (* string buffer list. strings[0] = 0X -> uninitialized items appear as empty *)
  40. end: INTEGER; (* next free position in string buffer list *)
  41. scnt: INTEGER; (* number of strings in list, including unused entries *)
  42. items: POINTER TO ARRAY OF INTEGER (* indices into string buffer list *)
  43. END;
  44. List* = RECORD
  45. index*: INTEGER; (** val IN [0, n-1] **)
  46. len-: INTEGER;
  47. l: StrList
  48. END;
  49. Combo* = RECORD
  50. item*: String;
  51. len-: INTEGER;
  52. l: StrList
  53. END;
  54. Selection* = RECORD
  55. len-: INTEGER;
  56. sel: POINTER TO ARRAY OF SET;
  57. l: StrList
  58. END;
  59. Currency* = RECORD (* number = val * 10^-scale *)
  60. val*: LONGINT;
  61. scale*: INTEGER
  62. END;
  63. Color* = RECORD
  64. val*: INTEGER
  65. END;
  66. TreeNode* = POINTER TO LIMITED RECORD
  67. nofChildren: INTEGER;
  68. name: String;
  69. parent, next, prev, firstChild: TreeNode;
  70. viewAsFolder, expanded: BOOLEAN;
  71. data: ANYPTR;
  72. tree: INTEGER
  73. END;
  74. Tree* = RECORD
  75. nofRoots, nofNodes: INTEGER;
  76. firstRoot, selected: TreeNode
  77. END;
  78. (** command procedure types**)
  79. Par* = RECORD (** parameter for guard procedures **)
  80. disabled*: BOOLEAN; (** OUT, preset to FALSE **)
  81. checked*: BOOLEAN; (** OUT, preset to default **)
  82. undef*: BOOLEAN; (** OUT, preset to default **)
  83. readOnly*: BOOLEAN; (** OUT, preset to default **)
  84. label*: String (** OUT, preset to "" **)
  85. END;
  86. GuardProc* = PROCEDURE (VAR par: Par);
  87. NotifierProc* = PROCEDURE (op, from, to: INTEGER);
  88. StringPtr = POINTER TO ARRAY [untagged] OF CHAR;
  89. StringTab = POINTER TO RECORD
  90. next: StringTab;
  91. name: Files.Name;
  92. key: POINTER TO ARRAY OF StringPtr;
  93. str: POINTER TO ARRAY OF StringPtr;
  94. data: POINTER TO ARRAY OF CHAR
  95. END;
  96. LangNotifier* = POINTER TO ABSTRACT RECORD next: LangNotifier END;
  97. Language* = ARRAY 3 OF CHAR;
  98. LangTrapCleaner = POINTER TO RECORD (Kernel.TrapCleaner) END;
  99. GetHook* = POINTER TO ABSTRACT RECORD (Kernel.Hook) END;
  100. ShowHook* = POINTER TO ABSTRACT RECORD (Kernel.Hook) END;
  101. CallHook* = POINTER TO ABSTRACT RECORD (Kernel.Hook) END;
  102. NotifyHook* = POINTER TO ABSTRACT RECORD (Kernel.Hook) END;
  103. LanguageHook* = POINTER TO ABSTRACT RECORD (Kernel.Hook) END;
  104. VAR
  105. metricSystem*: BOOLEAN;
  106. showsStatus*: BOOLEAN;
  107. platform*: INTEGER;
  108. commandLinePars*: String;
  109. version*: INTEGER;
  110. appName*: ARRAY 32 OF CHAR;
  111. language-: Language;
  112. user*: ARRAY 32 OF CHAR;
  113. caretPeriod*: INTEGER;
  114. thickCaret*: BOOLEAN;
  115. tabList: StringTab;
  116. langNotifiers: LangNotifier;
  117. currentNotifier: LangNotifier;
  118. gethook: GetHook;
  119. showHook: ShowHook;
  120. callHook: CallHook;
  121. notifyHook: NotifyHook;
  122. languageHook: LanguageHook;
  123. PROCEDURE (h: GetHook) GetOK* (IN str, p0, p1, p2: ARRAY OF CHAR; form: SET;
  124. OUT res: INTEGER), NEW, ABSTRACT;
  125. PROCEDURE (h: GetHook) GetColor* (in: INTEGER; OUT out: INTEGER;
  126. OUT set: BOOLEAN), NEW, ABSTRACT;
  127. PROCEDURE (h: GetHook) GetIntSpec* (IN defType: Files.Type; VAR loc: Files.Locator;
  128. OUT name: Files.Name), NEW, ABSTRACT;
  129. PROCEDURE (h: GetHook) GetExtSpec* (IN defName: Files.Name; IN defType: Files.Type;
  130. VAR loc: Files.Locator; OUT name: Files.Name), NEW, ABSTRACT;
  131. PROCEDURE SetGetHook*(h: GetHook);
  132. BEGIN
  133. gethook := h
  134. END SetGetHook;
  135. PROCEDURE (h: ShowHook) ShowParamMsg* (IN str, p0, p1, p2: ARRAY OF CHAR), NEW, ABSTRACT;
  136. PROCEDURE (h: ShowHook) ShowParamStatus* (IN str, p0, p1, p2: ARRAY OF CHAR), NEW, ABSTRACT;
  137. PROCEDURE SetShowHook* (h: ShowHook);
  138. BEGIN
  139. showHook := h
  140. END SetShowHook;
  141. PROCEDURE (h: CallHook) Call* (IN proc, errorMsg: ARRAY OF CHAR; VAR res: INTEGER), NEW, ABSTRACT;
  142. PROCEDURE SetCallHook* (h: CallHook);
  143. BEGIN
  144. callHook := h
  145. END SetCallHook;
  146. PROCEDURE (h: NotifyHook) Notify* (id0, id1: INTEGER; opts: SET), NEW, ABSTRACT;
  147. PROCEDURE SetNotifyHook* (h: NotifyHook);
  148. BEGIN
  149. notifyHook := h
  150. END SetNotifyHook;
  151. PROCEDURE (h: LanguageHook) SetLanguage* (lang: Language; persistent: BOOLEAN;
  152. OUT ok: BOOLEAN), NEW, ABSTRACT;
  153. PROCEDURE (h: LanguageHook) GetPersistentLanguage* (OUT lang: Language), NEW, ABSTRACT;
  154. PROCEDURE SetLanguageHook* (h: LanguageHook);
  155. BEGIN
  156. languageHook := h
  157. END SetLanguageHook;
  158. PROCEDURE ReadStringFile (subsys: Files.Name; f: Files.File; VAR tab: StringTab);
  159. VAR i, j, h, n, s, x, len, next, down, end: INTEGER; in, in1: Files.Reader;
  160. ch: CHAR; b: BYTE; p, q: StringPtr;
  161. PROCEDURE ReadInt (OUT x: INTEGER);
  162. VAR b: BYTE;
  163. BEGIN
  164. in.ReadByte(b); x := b MOD 256;
  165. in.ReadByte(b); x := x + (b MOD 256) * 100H;
  166. in.ReadByte(b); x := x + (b MOD 256) * 10000H;
  167. in.ReadByte(b); x := x + b * 1000000H
  168. END ReadInt;
  169. PROCEDURE ReadHead (OUT next, down, end: INTEGER);
  170. VAR b, t: BYTE; n: INTEGER;
  171. BEGIN
  172. in.ReadByte(b);
  173. REPEAT
  174. in.ReadByte(t);
  175. IF t = -14 THEN ReadInt(n)
  176. ELSE
  177. REPEAT in.ReadByte(b) UNTIL b = 0
  178. END
  179. UNTIL t # -15;
  180. ReadInt(n);
  181. ReadInt(next); next := next + in.Pos();
  182. ReadInt(down); down := down + in.Pos();
  183. ReadInt(end); end := end + in.Pos()
  184. END ReadHead;
  185. BEGIN
  186. tab := NIL;
  187. IF f # NIL THEN (* read text file *)
  188. in := f.NewReader(NIL); in1 := f.NewReader(NIL);
  189. IF (in # NIL) & (in1 # NIL) THEN
  190. in.SetPos(8); ReadHead(next, down, end); (* document view *)
  191. in.SetPos(down); ReadHead(next, down, end); (* document model *)
  192. in.SetPos(down); ReadHead(next, down, end); (* text view *)
  193. in.SetPos(down); ReadHead(next, down, end); (* text model *)
  194. in.ReadByte(b); in.ReadByte(b); in.ReadByte(b); (* versions *)
  195. in.ReadByte(b); in.ReadByte(b); in.ReadByte(b);
  196. ReadInt(x); in1.SetPos(in.Pos() + x); (* text offset *)
  197. next := down;
  198. NEW(tab); tab.name := subsys$;
  199. NEW(tab.data, f.Length());
  200. n := 0; i := 0; s := 0; in.ReadByte(b);
  201. WHILE b # -1 DO
  202. IF next = in.Pos() THEN ReadHead(next, down, end); in.SetPos(end) END; (* skip attributes *)
  203. ReadInt(len);
  204. IF len > 0 THEN (* shortchar run *)
  205. WHILE len > 0 DO
  206. in1.ReadByte(b); ch := CHR(b MOD 256);
  207. IF ch >= " " THEN
  208. IF s = 0 THEN j := i; s := 1 END; (* start of left part *)
  209. tab.data[j] := ch; INC(j)
  210. ELSIF (s = 1) & (ch = TAB) THEN
  211. tab.data[j] := 0X; INC(j);
  212. s := 2 (* start of right part *)
  213. ELSIF (s = 2) & (ch = CR) THEN
  214. tab.data[j] := 0X; INC(j);
  215. INC(n); i := j; s := 0 (* end of line *)
  216. ELSE
  217. s := 0 (* reset *)
  218. END;
  219. DEC(len)
  220. END
  221. ELSIF len < 0 THEN (* longchar run *)
  222. WHILE len < 0 DO
  223. in1.ReadByte(b); x := b MOD 256; in1.ReadByte(b); ch := CHR(x + 256 * (b + 128));
  224. IF s = 0 THEN j := i; s := 1 END; (* start of left part *)
  225. tab.data[j] := ch; INC(j);
  226. INC(len, 2)
  227. END
  228. ELSE (* view *)
  229. ReadInt(x); ReadInt(x); in1.ReadByte(b); (* ignore *)
  230. END;
  231. IF next = in.Pos() THEN ReadHead(next, down, end); in.SetPos(end) END; (* skip view data *)
  232. in.ReadByte(b);
  233. END;
  234. IF n > 0 THEN
  235. NEW(tab.key, n); NEW(tab.str, n); i := 0; j := 0;
  236. WHILE j < n DO
  237. tab.key[j] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[i]));
  238. WHILE tab.data[i] >= " " DO INC(i) END;
  239. INC(i);
  240. tab.str[j] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[i]));
  241. WHILE tab.data[i] >= " " DO INC(i) END;
  242. INC(i); INC(j)
  243. END;
  244. (* sort keys (shellsort) *)
  245. h := 1; REPEAT h := h*3 + 1 UNTIL h > n;
  246. REPEAT h := h DIV 3; i := h;
  247. WHILE i < n DO p := tab.key[i]; q := tab.str[i]; j := i;
  248. WHILE (j >= h) & (tab.key[j-h]^ > p^) DO
  249. tab.key[j] := tab.key[j-h]; tab.str[j] := tab.str[j-h]; j := j-h
  250. END;
  251. tab.key[j] := p; tab.str[j] := q; INC(i)
  252. END
  253. UNTIL h = 1
  254. END
  255. END
  256. END
  257. END ReadStringFile;
  258. PROCEDURE MergeTabs (VAR master, extra: StringTab): StringTab;
  259. VAR tab: StringTab; nofKeys, datalength, di, mi, ei, ml, el, ti, i: INTEGER;
  260. BEGIN
  261. IF (extra = NIL) OR (extra.key = NIL) THEN RETURN master END;
  262. IF (master = NIL) OR (master.key = NIL) THEN RETURN extra END;
  263. ml := LEN(master.key); el := LEN(extra.key);
  264. mi := 0; ei := 0; datalength := 0; nofKeys := 0;
  265. (* find out how big the resulting table will be *)
  266. WHILE (mi < ml) OR (ei < el) DO
  267. INC(nofKeys);
  268. IF (mi < ml) & (ei < el) & (master.key[mi]$ = extra.key[ei]$) THEN
  269. datalength := datalength + LEN(master.key[mi]$) + LEN(master.str[mi]$) + 2; INC(mi); INC(ei)
  270. ELSIF (ei < el) & ((mi >= ml) OR (master.key[mi]$ > extra.key[ei]$)) THEN
  271. datalength := datalength + LEN(extra.key[ei]$) + LEN(extra.str[ei]$) + 2; INC(ei)
  272. ELSE
  273. datalength := datalength + LEN(master.key[mi]$) + LEN(master.str[mi]$) + 2; INC(mi)
  274. END
  275. END;
  276. NEW(tab); tab.name := master.name;
  277. NEW(tab.key, nofKeys); NEW(tab.str, nofKeys); NEW(tab.data, datalength);
  278. mi := 0; ei := 0; di := 0; ti := 0;
  279. (* do the merge *)
  280. WHILE (mi < ml) OR (ei < el) DO
  281. IF (mi < ml) & (ei < el) & (master.key[mi]$ = extra.key[ei]$) THEN
  282. i := 0; tab.key[ti] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[di]));
  283. WHILE master.key[mi][i] # 0X DO tab.data[di] := master.key[mi][i]; INC(di); INC(i) END;
  284. tab.data[di] :=0X; INC(di); i := 0;
  285. tab.str[ti] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[di]));
  286. WHILE master.str[mi][i] # 0X DO tab.data[di] := master.str[mi][i]; INC(di); INC(i) END;
  287. tab.data[di] :=0X; INC(di);
  288. INC(mi); INC(ei)
  289. ELSIF (ei < el) & ((mi >= ml) OR (master.key[mi]$ > extra.key[ei]$)) THEN
  290. i := 0; tab.key[ti] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[di]));
  291. WHILE extra.key[ei][i] # 0X DO tab.data[di] := extra.key[ei][i]; INC(di); INC(i) END;
  292. tab.data[di] :=0X; INC(di); i := 0;
  293. tab.str[ti] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[di]));
  294. WHILE extra.str[ei][i] # 0X DO tab.data[di] := extra.str[ei][i]; INC(di); INC(i) END;
  295. tab.data[di] :=0X; INC(di);
  296. INC(ei)
  297. ELSE
  298. i := 0; tab.key[ti] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[di]));
  299. WHILE master.key[mi][i] # 0X DO tab.data[di] := master.key[mi][i]; INC(di); INC(i) END;
  300. tab.data[di] :=0X; INC(di); i := 0;
  301. tab.str[ti] := SYSTEM.VAL(StringPtr, SYSTEM.ADR(tab.data[di]));
  302. WHILE master.str[mi][i] # 0X DO tab.data[di] := master.str[mi][i]; INC(di); INC(i) END;
  303. tab.data[di] :=0X; INC(di);
  304. INC(mi)
  305. END;
  306. INC(ti)
  307. END;
  308. RETURN tab
  309. END MergeTabs;
  310. PROCEDURE LoadStringTab (subsys: Files.Name; VAR tab: StringTab);
  311. VAR loc: Files.Locator; f: Files.File; name: Files.Name; ltab: StringTab;
  312. BEGIN
  313. tab := NIL;
  314. name := stringFile; Kernel.MakeFileName(name, "");
  315. loc := Files.dir.This(subsys); loc := loc.This(rsrcDir);
  316. IF loc # NIL THEN
  317. f := Files.dir.Old(loc, name, Files.shared);
  318. ReadStringFile(subsys, f, tab);
  319. IF language # "" THEN
  320. loc := loc.This(language);
  321. IF loc # NIL THEN
  322. f := Files.dir.Old(loc, name, Files.shared);
  323. ReadStringFile(subsys, f, ltab);
  324. tab := MergeTabs(ltab, tab)
  325. END
  326. END;
  327. IF tab # NIL THEN tab.next := tabList; tabList := tab END
  328. END
  329. END LoadStringTab;
  330. PROCEDURE SearchString (VAR in: ARRAY OF CHAR; OUT out: ARRAY OF CHAR);
  331. VAR i, j, k, len: INTEGER; ch: CHAR; subsys: Files.Name; tab: StringTab;
  332. BEGIN
  333. out := "";
  334. IF in[0] = "#" THEN
  335. i := 0; ch := in[1];
  336. WHILE (ch # 0X) (* & (ch # ".") *) & (ch # ":") DO subsys[i] := ch; INC(i); ch := in[i + 1] END;
  337. subsys[i] := 0X;
  338. IF ch # 0X THEN
  339. INC(i, 2); ch := in[i]; j := 0;
  340. WHILE (ch # 0X) DO in[j] := ch; INC(i); INC(j); ch := in[i] END;
  341. in[j] := 0X
  342. ELSE
  343. RETURN
  344. END;
  345. tab := tabList;
  346. WHILE (tab # NIL) & (tab.name # subsys) DO tab := tab.next END;
  347. IF tab = NIL THEN LoadStringTab(subsys, tab) END;
  348. IF tab # NIL THEN
  349. i := 0;
  350. IF tab.key = NIL THEN j := 0 ELSE j := LEN(tab.key^) END;
  351. WHILE i < j DO (* binary search *)
  352. k := (i + j) DIV 2;
  353. IF tab.key[k]^ < in THEN i := k + 1 ELSE j := k END
  354. END;
  355. IF (tab.key # NIL) & (j < LEN(tab.key^)) & (tab.key[j]^ = in) THEN
  356. k := 0; len := LEN(out)-1;
  357. WHILE (k < len) & (tab.str[j][k] # 0X) DO
  358. out[k] := tab.str[j][k]; INC(k)
  359. END;
  360. out[k] := 0X
  361. END
  362. END
  363. END
  364. END SearchString;
  365. PROCEDURE Init (VAR l: StrList);
  366. BEGIN
  367. l.len := 0; l.max := 0; l.end := 0; l.scnt := 0
  368. END Init;
  369. PROCEDURE Compact (VAR l: StrList);
  370. VAR i, j, k: INTEGER; ibuf, jbuf: Buf; ch: CHAR;
  371. BEGIN
  372. i := 1; ibuf := l.strings; j := 1; jbuf := l.strings;
  373. WHILE j < l.end DO
  374. (* find index entry k pointing to position j *)
  375. k := 0; WHILE (k < l.len) & (l.items[k] # j) DO INC(k) END;
  376. IF k < l.len THEN (* copy string *)
  377. l.items[k] := i;
  378. REPEAT
  379. ch := jbuf.s[j MOD bufLen]; INC(j);
  380. IF j MOD bufLen = 0 THEN jbuf := jbuf.next END;
  381. ibuf.s[i MOD bufLen] := ch; INC(i);
  382. IF i MOD bufLen = 0 THEN ibuf := ibuf.next END
  383. UNTIL ch = 0X
  384. ELSE (* skip next string *)
  385. REPEAT
  386. ch := jbuf.s[j MOD bufLen]; INC(j);
  387. IF j MOD bufLen = 0 THEN jbuf := jbuf.next END
  388. UNTIL ch = 0X
  389. END
  390. END;
  391. ibuf.next := NIL; (* release superfluous buffers *)
  392. l.end := i; l.scnt := l.len
  393. END Compact;
  394. PROCEDURE SetLen (VAR l: StrList; len: INTEGER);
  395. CONST D = 32;
  396. VAR i, newmax: INTEGER;
  397. items: POINTER TO ARRAY OF INTEGER;
  398. BEGIN
  399. IF l.items = NIL THEN Init(l) END;
  400. IF (l.max - D < len) & (len <= l.max) THEN
  401. (* we do not reallocate anything *)
  402. ELSE
  403. newmax := (len + D-1) DIV D * D;
  404. IF newmax > 0 THEN
  405. IF l.strings = NIL THEN NEW(l.strings); (* l.strings[0] := 0X; *) l.end := 1 END;
  406. NEW(items, newmax);
  407. IF len < l.len THEN i := len ELSE i := l.len END;
  408. WHILE i > 0 DO DEC(i); items[i] := l.items[i] END;
  409. l.items := items
  410. END;
  411. l.max := newmax
  412. END;
  413. l.len := len;
  414. IF (l.scnt > 32) & (l.scnt > 2 * l.len) THEN Compact(l) END
  415. END SetLen;
  416. PROCEDURE GetItem (VAR l: StrList; index: INTEGER; VAR item: String);
  417. VAR i, j, k: INTEGER; b: Buf; ch: CHAR;
  418. BEGIN
  419. IF l.items = NIL THEN Init(l) END;
  420. IF (index >= 0) & (index < l.len) THEN
  421. i := l.items[index]; j := i MOD bufLen; i := i DIV bufLen;
  422. b := l.strings; WHILE i # 0 DO b := b.next; DEC(i) END;
  423. k := 0;
  424. REPEAT
  425. ch := b.s[j]; INC(j); IF j = bufLen THEN j := 0; b := b.next END;
  426. item[k] := ch; INC(k)
  427. UNTIL ch = 0X
  428. ELSE
  429. item := ""
  430. END
  431. END GetItem;
  432. PROCEDURE SetItem (VAR l: StrList; index: INTEGER; item: ARRAY OF CHAR);
  433. VAR len, i, j, k: INTEGER; b: Buf; ch: CHAR;
  434. BEGIN
  435. IF l.items = NIL THEN Init(l) END;
  436. IF index >= l.len THEN SetLen(l, index + 1) END;
  437. IF (l.scnt > 32) & (l.scnt > 2 * l.len) THEN Compact(l) END;
  438. len := 0; WHILE item[len] # 0X DO INC(len) END;
  439. IF len >= stringLen THEN len := stringLen - 1; item[len] := 0X END; (* clip long strings *)
  440. l.items[index] := l.end;
  441. i := l.end; j := i MOD bufLen; i := i DIV bufLen;
  442. b := l.strings; WHILE i # 0 DO b := b.next; DEC(i) END;
  443. k := 0;
  444. REPEAT
  445. ch := item[k]; INC(k); INC(l.end);
  446. b.s[j] := ch; INC(j); IF j = bufLen THEN j := 0; NEW(b.next); b := b.next END
  447. UNTIL ch = 0X;
  448. INC(l.scnt)
  449. END SetItem;
  450. PROCEDURE SetResources (VAR l: StrList; IN key: ARRAY OF CHAR);
  451. VAR i, k, j, x: INTEGER; ch: CHAR; s, a: ARRAY 16 OF CHAR; h, item: ARRAY 256 OF CHAR;
  452. BEGIN
  453. IF l.items = NIL THEN Init(l) END;
  454. i := 0;
  455. REPEAT
  456. x := i;
  457. j := 0; REPEAT a[j] := CHR(x MOD 10 + ORD("0")); x := x DIV 10; INC(j) UNTIL x = 0;
  458. k := 0; REPEAT DEC(j); ch := a[j]; s[k] := ch; INC(k) UNTIL j = 0;
  459. s[k] := 0X;
  460. h := key + "[" + s + "]";
  461. SearchString(h, item);
  462. IF item # "" THEN SetItem(l, i, item) END;
  463. INC(i)
  464. UNTIL item = ""
  465. END SetResources;
  466. (** List **)
  467. PROCEDURE (VAR l: List) SetLen* (len: INTEGER), NEW;
  468. BEGIN
  469. ASSERT(len >= 0, 20);
  470. SetLen(l.l, len);
  471. l.len := l.l.len
  472. END SetLen;
  473. PROCEDURE (VAR l: List) GetItem* (index: INTEGER; OUT item: String), NEW;
  474. BEGIN
  475. GetItem(l.l, index, item);
  476. l.len := l.l.len
  477. END GetItem;
  478. PROCEDURE (VAR l: List) SetItem* (index: INTEGER; IN item: ARRAY OF CHAR), NEW;
  479. BEGIN
  480. ASSERT(index >= 0, 20); ASSERT(item # "", 21);
  481. SetItem(l.l, index, item);
  482. l.len := l.l.len
  483. END SetItem;
  484. PROCEDURE (VAR l: List) SetResources* (IN key: ARRAY OF CHAR), NEW;
  485. BEGIN
  486. ASSERT(key # "", 20);
  487. SetResources(l.l, key);
  488. l.len := l.l.len
  489. END SetResources;
  490. (** Selection **)
  491. PROCEDURE (VAR s: Selection) SetLen* (len: INTEGER), NEW;
  492. VAR sel: POINTER TO ARRAY OF SET; i: INTEGER;
  493. BEGIN
  494. ASSERT(len >= 0, 20);
  495. SetLen(s.l, len);
  496. len := len + (MAX(SET) - 1) DIV MAX(SET);
  497. IF len = 0 THEN s.sel := NIL
  498. ELSIF s.sel = NIL THEN NEW(s.sel, len)
  499. ELSIF LEN(s.sel^) # len THEN
  500. NEW(sel, len);
  501. IF LEN(s.sel^) < len THEN len := LEN(s.sel^) END;
  502. i := 0; WHILE i < len DO sel[i] := s.sel[i]; INC(i) END;
  503. s.sel := sel
  504. END;
  505. s.len := s.l.len
  506. END SetLen;
  507. PROCEDURE (VAR s: Selection) GetItem* (index: INTEGER; OUT item: String), NEW;
  508. BEGIN
  509. GetItem(s.l, index, item);
  510. s.len := s.l.len
  511. END GetItem;
  512. PROCEDURE (VAR s: Selection) SetItem* (index: INTEGER; IN item: ARRAY OF CHAR), NEW;
  513. BEGIN
  514. ASSERT(index >= 0, 20); (*ASSERT(index < s.l.len, 21);*) ASSERT(item # "", 21);
  515. SetItem(s.l, index, item);
  516. IF s.l.len > s.len THEN s.SetLen(s.l.len) END
  517. END SetItem;
  518. PROCEDURE (VAR s: Selection) SetResources* (IN key: ARRAY OF CHAR), NEW;
  519. BEGIN
  520. ASSERT(key # "", 20);
  521. SetResources(s.l, key);
  522. IF s.l.len > s.len THEN s.SetLen(s.l.len) END
  523. END SetResources;
  524. PROCEDURE (VAR s: Selection) In* (index: INTEGER): BOOLEAN, NEW;
  525. BEGIN
  526. IF s.l.items = NIL THEN Init(s.l); s.len := s.l.len END;
  527. IF s.sel # NIL THEN RETURN (index MOD 32) IN (s.sel[index DIV 32]) ELSE RETURN FALSE END
  528. END In;
  529. PROCEDURE (VAR s: Selection) Excl* (from, to: INTEGER), NEW;
  530. BEGIN
  531. IF s.l.items = NIL THEN Init(s.l); s.len := s.l.len END;
  532. IF from < 0 THEN from := 0 END;
  533. IF to >= s.l.len THEN to := s.l.len - 1 END;
  534. WHILE from <= to DO EXCL(s.sel[from DIV 32], from MOD 32); INC(from) END
  535. END Excl;
  536. PROCEDURE (VAR s: Selection) Incl* (from, to: INTEGER), NEW;
  537. BEGIN
  538. IF s.l.items = NIL THEN Init(s.l); s.len := s.l.len END;
  539. IF from < 0 THEN from := 0 END;
  540. IF to >= s.l.len THEN to := s.l.len - 1 END;
  541. WHILE from <= to DO INCL(s.sel[from DIV 32], from MOD 32); INC(from) END
  542. END Incl;
  543. (** Combo **)
  544. PROCEDURE (VAR c: Combo) SetLen* (len: INTEGER), NEW;
  545. BEGIN
  546. ASSERT(len >= 0, 20);
  547. SetLen(c.l, len);
  548. c.len := c.l.len
  549. END SetLen;
  550. PROCEDURE (VAR c: Combo) GetItem* (index: INTEGER; OUT item: String), NEW;
  551. BEGIN
  552. GetItem(c.l, index, item);
  553. c.len := c.l.len
  554. END GetItem;
  555. PROCEDURE (VAR c: Combo) SetItem* (index: INTEGER; IN item: ARRAY OF CHAR), NEW;
  556. BEGIN
  557. ASSERT(index >= 0, 20); ASSERT(item # "", 21);
  558. SetItem(c.l, index, item);
  559. c.len := c.l.len
  560. END SetItem;
  561. PROCEDURE (VAR c: Combo) SetResources* (IN key: ARRAY OF CHAR), NEW;
  562. BEGIN
  563. ASSERT(key # "", 20);
  564. SetResources(c.l, key);
  565. c.len := c.l.len
  566. END SetResources;
  567. (* Tree and TreeNode *)
  568. PROCEDURE (tn: TreeNode) SetName* (name: String), NEW;
  569. BEGIN
  570. tn.name := name
  571. END SetName;
  572. PROCEDURE (tn: TreeNode) GetName* (OUT name: String), NEW;
  573. BEGIN
  574. name := tn.name
  575. END GetName;
  576. PROCEDURE (tn: TreeNode) SetData* (data: ANYPTR), NEW;
  577. BEGIN
  578. tn.data := data
  579. END SetData;
  580. PROCEDURE (tn: TreeNode) Data* (): ANYPTR, NEW;
  581. BEGIN
  582. RETURN tn.data
  583. END Data;
  584. PROCEDURE (tn: TreeNode) NofChildren* (): INTEGER, NEW;
  585. BEGIN
  586. RETURN tn.nofChildren
  587. END NofChildren;
  588. PROCEDURE (tn: TreeNode) SetExpansion* (expanded: BOOLEAN), NEW;
  589. BEGIN
  590. tn.expanded := expanded
  591. END SetExpansion;
  592. PROCEDURE (tn: TreeNode) IsExpanded* (): BOOLEAN, NEW;
  593. BEGIN
  594. RETURN tn.expanded
  595. END IsExpanded;
  596. PROCEDURE (tn: TreeNode) IsFolder* (): BOOLEAN, NEW;
  597. BEGIN
  598. IF (~tn.viewAsFolder) & (tn.firstChild = NIL) THEN
  599. RETURN FALSE
  600. ELSE
  601. RETURN TRUE
  602. END
  603. END IsFolder;
  604. PROCEDURE (tn: TreeNode) ViewAsFolder* (isFolder: BOOLEAN), NEW;
  605. BEGIN
  606. tn.viewAsFolder := isFolder
  607. END ViewAsFolder;
  608. PROCEDURE (VAR t: Tree) NofNodes* (): INTEGER, NEW;
  609. BEGIN
  610. IF t.firstRoot = NIL THEN
  611. RETURN 0
  612. ELSE
  613. RETURN MAX(0, t.nofNodes)
  614. END
  615. END NofNodes;
  616. PROCEDURE (VAR t: Tree) NofRoots* (): INTEGER, NEW;
  617. BEGIN
  618. IF t.firstRoot = NIL THEN
  619. RETURN 0
  620. ELSE
  621. RETURN MAX(0, t.nofRoots)
  622. END
  623. END NofRoots;
  624. PROCEDURE (VAR t: Tree) Parent* (node: TreeNode): TreeNode, NEW;
  625. BEGIN
  626. ASSERT(node # NIL, 20); ASSERT(node.tree = SYSTEM.ADR(t), 21);
  627. RETURN node.parent
  628. END Parent;
  629. PROCEDURE (VAR t: Tree) Next* (node: TreeNode): TreeNode, NEW;
  630. BEGIN
  631. ASSERT(node # NIL, 20); ASSERT(node.tree = SYSTEM.ADR(t), 21);
  632. RETURN node.next
  633. END Next;
  634. PROCEDURE (VAR t: Tree) Prev* (node: TreeNode): TreeNode, NEW;
  635. BEGIN
  636. ASSERT(node # NIL, 20); ASSERT(node.tree = SYSTEM.ADR(t), 21);
  637. RETURN node.prev
  638. END Prev;
  639. PROCEDURE (VAR t: Tree) Child* (node: TreeNode; pos: INTEGER): TreeNode, NEW;
  640. VAR cur: TreeNode;
  641. BEGIN
  642. ASSERT(pos >= lastPos, 20); ASSERT((node = NIL) OR (node.tree = SYSTEM.ADR(t)), 21);
  643. IF node = NIL THEN cur := t.firstRoot
  644. ELSE cur := node.firstChild END;
  645. IF pos = lastPos THEN
  646. WHILE (cur # NIL) & (cur.next # NIL) DO cur := cur.next END
  647. ELSE
  648. WHILE (cur # NIL) & (pos > 0) DO cur := cur.next; DEC(pos) END
  649. END;
  650. RETURN cur
  651. END Child;
  652. PROCEDURE (VAR t: Tree) Selected* (): TreeNode, NEW;
  653. BEGIN
  654. RETURN t.selected
  655. END Selected;
  656. PROCEDURE (VAR t: Tree) Select* (node: TreeNode), NEW;
  657. BEGIN
  658. ASSERT((node = NIL) OR (node.tree = SYSTEM.ADR(t)), 20);
  659. IF (node # NIL) OR (t.nofRoots = 0) THEN
  660. t.selected := node
  661. ELSE
  662. t.selected := t.Child(NIL, 0)
  663. END
  664. END Select;
  665. PROCEDURE Include (IN t: Tree; node: TreeNode);
  666. VAR c: TreeNode;
  667. BEGIN
  668. ASSERT(node # NIL, 20); ASSERT(node.tree = 0, 100);
  669. node.tree := SYSTEM.ADR(t);
  670. c := node.firstChild;
  671. WHILE c # NIL DO Include(t, c); c := c.next END
  672. END Include;
  673. PROCEDURE (VAR t: Tree) InsertAt (parent: TreeNode; pos: INTEGER; node: TreeNode), NEW;
  674. VAR
  675. cur, prev: TreeNode;
  676. BEGIN
  677. ASSERT(node # NIL, 20); ASSERT(pos >= lastPos, 21);
  678. ASSERT((parent = NIL) OR (parent.tree = SYSTEM.ADR(t)), 22); ASSERT(node.tree = 0, 23);
  679. Include(t, node);
  680. IF parent = NIL THEN (* Add new root *)
  681. IF (t.firstRoot = NIL) OR (pos = 0) THEN
  682. node.next := t.firstRoot; node.prev := NIL;
  683. IF t.firstRoot # NIL THEN t.firstRoot.prev := node END;
  684. t.firstRoot := node
  685. ELSE
  686. cur := t.firstRoot;
  687. IF pos = lastPos THEN pos := t.nofRoots END;
  688. WHILE (cur # NIL) & (pos > 0) DO
  689. prev := cur; cur := t.Next(cur); DEC(pos)
  690. END;
  691. IF cur = NIL THEN
  692. prev.next := node; node.prev := prev
  693. ELSE
  694. node.next := cur; node.prev := cur.prev; cur.prev := node; prev.next := node
  695. END
  696. END;
  697. INC(t.nofRoots)
  698. ELSE (* Add child *)
  699. IF pos = lastPos THEN pos := parent.nofChildren END;
  700. IF (parent.firstChild = NIL) OR (pos = 0) THEN
  701. IF parent.firstChild # NIL THEN parent.firstChild.prev := node END;
  702. node.prev := NIL; node.next := parent.firstChild; parent.firstChild := node
  703. ELSE
  704. cur := parent.firstChild;
  705. WHILE (cur # NIL) & (pos > 0) DO
  706. prev := cur; cur := t.Next(cur); DEC(pos)
  707. END;
  708. IF cur = NIL THEN
  709. prev.next := node; node.prev := prev
  710. ELSE
  711. node.next := cur; node.prev := cur.prev; cur.prev := node; prev.next := node
  712. END
  713. END;
  714. INC(parent.nofChildren)
  715. END;
  716. node.parent := parent;
  717. INC(t.nofNodes)
  718. END InsertAt;
  719. PROCEDURE (VAR t: Tree) NewChild* (parent: TreeNode; pos: INTEGER; name: String): TreeNode, NEW;
  720. VAR
  721. new: TreeNode;
  722. BEGIN
  723. NEW(new); new.tree := 0;
  724. new.SetName(name); new.expanded := FALSE; new.nofChildren := 0;
  725. new.viewAsFolder := FALSE;
  726. t.InsertAt(parent, pos, new);
  727. RETURN new
  728. END NewChild;
  729. PROCEDURE (VAR t: Tree) CountChildren (node: TreeNode): INTEGER, NEW;
  730. VAR tot, nofc, i: INTEGER;
  731. BEGIN
  732. tot := 0;
  733. IF node # NIL THEN
  734. nofc := node.nofChildren; tot := nofc;
  735. FOR i := 0 TO nofc -1 DO
  736. tot := tot + t.CountChildren(t.Child(node, i))
  737. END
  738. END;
  739. RETURN tot
  740. END CountChildren;
  741. PROCEDURE Exclude (IN t: Tree; node: TreeNode);
  742. VAR c: TreeNode;
  743. BEGIN
  744. ASSERT(node # NIL, 20); ASSERT(node.tree = SYSTEM.ADR(t), 100);
  745. IF t.Selected() = node THEN t.Select(NIL) END;
  746. node.tree := 0;
  747. c := node.firstChild;
  748. WHILE c # NIL DO Exclude(t, c); c := c.next END
  749. END Exclude;
  750. PROCEDURE (VAR t: Tree) Delete* (node: TreeNode): INTEGER, NEW;
  751. VAR
  752. ndel: INTEGER;
  753. BEGIN
  754. ASSERT(node # NIL, 20); ASSERT(node.tree = SYSTEM.ADR(t), 21);
  755. ndel := t.CountChildren(node);
  756. IF node.parent = NIL THEN (* root node *)
  757. IF node.prev = NIL THEN
  758. IF node.next # NIL THEN
  759. t.firstRoot := node.next;
  760. node.next.prev := NIL
  761. ELSE
  762. t.firstRoot := NIL
  763. END
  764. ELSE
  765. node.prev.next := node.next;
  766. IF node.next # NIL THEN node.next.prev := node.prev END
  767. END;
  768. DEC(t.nofRoots)
  769. ELSE
  770. IF node.prev = NIL THEN
  771. IF node.next # NIL THEN
  772. node.parent.firstChild := node.next;
  773. node.next.prev := NIL
  774. ELSE
  775. node.parent.firstChild := NIL
  776. END
  777. ELSE
  778. node.prev.next := node.next;
  779. IF node.next # NIL THEN node.next.prev := node.prev END
  780. END;
  781. DEC(node.parent.nofChildren)
  782. END;
  783. node.parent := NIL; node.next := NIL; node.prev := NIL;
  784. Exclude(t, node);
  785. ndel := ndel + 1;
  786. t.nofNodes := t.nofNodes - ndel;
  787. RETURN ndel
  788. END Delete;
  789. PROCEDURE (VAR t: Tree) Move* (node, parent: TreeNode; pos: INTEGER), NEW;
  790. VAR ndel, nofn: INTEGER; s: TreeNode;
  791. BEGIN
  792. ASSERT(node # NIL, 20); ASSERT(pos >= lastPos, 21);
  793. ASSERT(node.tree = SYSTEM.ADR(t), 22);
  794. nofn := t.NofNodes();
  795. s := t.Selected();
  796. ndel := t.Delete(node); t.InsertAt(parent, pos, node);
  797. t.nofNodes := t.nofNodes + ndel - 1;
  798. IF (s # NIL) & (t.Selected() # s) THEN t.Select(s) END;
  799. ASSERT(nofn = t.NofNodes(), 60)
  800. END Move;
  801. PROCEDURE (VAR t: Tree) DeleteAll*, NEW;
  802. BEGIN
  803. t.nofRoots := 0; t.nofNodes := 0; t.firstRoot := NIL; t.selected := NIL
  804. END DeleteAll;
  805. PROCEDURE Notify* (id0, id1: INTEGER; opts: SET);
  806. BEGIN
  807. ASSERT(notifyHook # NIL, 100);
  808. notifyHook.Notify(id0, id1, opts)
  809. END Notify;
  810. PROCEDURE Update* (IN x: ANYREC);
  811. VAR type: Kernel.Type; adr, size: INTEGER;
  812. BEGIN
  813. adr := SYSTEM.ADR(x);
  814. type := Kernel.TypeOf(x);
  815. size := type.size;
  816. IF size = 0 THEN size := 1 END;
  817. Notify(adr, adr + size, {update, guardCheck})
  818. END Update;
  819. PROCEDURE UpdateBool* (VAR x: BOOLEAN);
  820. VAR adr: INTEGER;
  821. BEGIN
  822. adr := SYSTEM.ADR(x);
  823. Notify(adr, adr + SIZE(BOOLEAN), {update, guardCheck})
  824. END UpdateBool;
  825. PROCEDURE UpdateSChar* (VAR x: SHORTCHAR);
  826. VAR adr: INTEGER;
  827. BEGIN
  828. adr := SYSTEM.ADR(x);
  829. Notify(adr, adr + SIZE(SHORTCHAR), {update, guardCheck})
  830. END UpdateSChar;
  831. PROCEDURE UpdateChar* (VAR x: CHAR);
  832. VAR adr: INTEGER;
  833. BEGIN
  834. adr := SYSTEM.ADR(x);
  835. Notify(adr, adr + SIZE(CHAR), {update, guardCheck})
  836. END UpdateChar;
  837. PROCEDURE UpdateByte* (VAR x: BYTE);
  838. VAR adr: INTEGER;
  839. BEGIN
  840. adr := SYSTEM.ADR(x);
  841. Notify(adr, adr + SIZE(BYTE), {update, guardCheck})
  842. END UpdateByte;
  843. PROCEDURE UpdateSInt* (VAR x: SHORTINT);
  844. VAR adr: INTEGER;
  845. BEGIN
  846. adr := SYSTEM.ADR(x);
  847. Notify(adr, adr + SIZE(SHORTINT), {update, guardCheck})
  848. END UpdateSInt;
  849. PROCEDURE UpdateInt* (VAR x: INTEGER);
  850. VAR adr: INTEGER;
  851. BEGIN
  852. adr := SYSTEM.ADR(x);
  853. Notify(adr, adr + SIZE(INTEGER), {update, guardCheck})
  854. END UpdateInt;
  855. PROCEDURE UpdateLInt* (VAR x: LONGINT);
  856. VAR adr: INTEGER;
  857. BEGIN
  858. adr := SYSTEM.ADR(x);
  859. Notify(adr, adr + SIZE(LONGINT), {update, guardCheck})
  860. END UpdateLInt;
  861. PROCEDURE UpdateSReal* (VAR x: SHORTREAL);
  862. VAR adr: INTEGER;
  863. BEGIN
  864. adr := SYSTEM.ADR(x);
  865. Notify(adr, adr + SIZE(SHORTREAL), {update, guardCheck})
  866. END UpdateSReal;
  867. PROCEDURE UpdateReal* (VAR x: REAL);
  868. VAR adr: INTEGER;
  869. BEGIN
  870. adr := SYSTEM.ADR(x);
  871. Notify(adr, adr + SIZE(REAL), {update, guardCheck})
  872. END UpdateReal;
  873. PROCEDURE UpdateSet* (VAR x: SET);
  874. VAR adr: INTEGER;
  875. BEGIN
  876. adr := SYSTEM.ADR(x);
  877. Notify(adr, adr + SIZE(SET), {update, guardCheck})
  878. END UpdateSet;
  879. PROCEDURE UpdateSString* (IN x: ARRAY OF SHORTCHAR);
  880. VAR adr: INTEGER;
  881. BEGIN
  882. adr := SYSTEM.ADR(x);
  883. Notify(adr, adr + LEN(x) * SIZE(SHORTCHAR), {update, guardCheck})
  884. END UpdateSString;
  885. PROCEDURE UpdateString* (IN x: ARRAY OF CHAR);
  886. VAR adr: INTEGER;
  887. BEGIN
  888. adr := SYSTEM.ADR(x);
  889. Notify(adr, adr + LEN(x) * SIZE(CHAR), {update, guardCheck})
  890. END UpdateString;
  891. PROCEDURE UpdateList* (IN x: ANYREC);
  892. VAR type: Kernel.Type; adr, size: INTEGER;
  893. BEGIN
  894. adr := SYSTEM.ADR(x);
  895. type := Kernel.TypeOf(x);
  896. size := type.size;
  897. IF size = 0 THEN size := 1 END;
  898. Notify(adr, adr + size, {listUpdate, guardCheck})
  899. END UpdateList;
  900. PROCEDURE GetOK* (IN str, p0, p1, p2: ARRAY OF CHAR; form: SET; OUT res: INTEGER);
  901. BEGIN
  902. ASSERT(((yes IN form) = (no IN form)) & ((yes IN form) # (ok IN form)), 20);
  903. ASSERT(gethook # NIL, 100);
  904. gethook.GetOK(str, p0, p1, p2, form, res)
  905. END GetOK;
  906. PROCEDURE GetIntSpec* (defType: Files.Type; VAR loc: Files.Locator; OUT name: Files.Name);
  907. BEGIN
  908. ASSERT(gethook # NIL, 100);
  909. gethook.GetIntSpec(defType, loc, name)
  910. END GetIntSpec;
  911. PROCEDURE GetExtSpec* (defName: Files.Name; defType: Files.Type; VAR loc: Files.Locator;
  912. OUT name: Files.Name);
  913. BEGIN
  914. ASSERT(gethook # NIL, 100);
  915. gethook.GetExtSpec(defName, defType, loc, name)
  916. END GetExtSpec;
  917. PROCEDURE GetColor* (in: INTEGER; OUT out: INTEGER; OUT set: BOOLEAN);
  918. BEGIN
  919. ASSERT(gethook # NIL, 100);
  920. gethook.GetColor(in, out, set)
  921. END GetColor;
  922. PROCEDURE Subst (in: ARRAY OF CHAR; IN p0, p1, p2: ARRAY OF CHAR; VAR out: ARRAY OF CHAR);
  923. VAR len, i, j, k: INTEGER; ch, c: CHAR;
  924. BEGIN
  925. i := 0; ch := in[i]; j := 0; len := LEN(out) - 1;
  926. WHILE (ch # 0X) & (j < len) DO
  927. IF ch = "^" THEN
  928. INC(i); ch := in[i];
  929. IF ch = "0" THEN
  930. k := 0; c := p0[0];
  931. WHILE (c # 0X) & (j < len) DO out[j] := c; INC(j); INC(k); c := p0[k] END;
  932. INC(i); ch := in[i]
  933. ELSIF ch = "1" THEN
  934. k := 0; c := p1[0];
  935. WHILE (c # 0X) & (j < len) DO out[j] := c; INC(j); INC(k); c := p1[k] END;
  936. INC(i); ch := in[i]
  937. ELSIF ch = "2" THEN
  938. k := 0; c := p2[0];
  939. WHILE (c # 0X) & (j < len) DO out[j] := c; INC(j); INC(k); c := p2[k] END;
  940. INC(i); ch := in[i]
  941. ELSE out[j] := "^"; INC(j)
  942. END
  943. ELSE out[j] := ch; INC(j); INC(i); ch := in[i]
  944. END
  945. END;
  946. out[j] := 0X
  947. END Subst;
  948. PROCEDURE FlushMappings*;
  949. BEGIN
  950. tabList := NIL
  951. END FlushMappings;
  952. PROCEDURE MapParamString* (in, p0, p1, p2: ARRAY OF CHAR; OUT out: ARRAY OF CHAR);
  953. (* use in as key in string table file, and return corresponding string in out.
  954. If the resource lookup fails, return in in out *)
  955. BEGIN
  956. SearchString(in, out);
  957. IF out # "" THEN Subst(out, p0, p1, p2, out)
  958. ELSE Subst(in, p0, p1, p2, out)
  959. END
  960. END MapParamString;
  961. PROCEDURE MapString* (in: ARRAY OF CHAR; OUT out: ARRAY OF CHAR);
  962. VAR len, k: INTEGER;
  963. BEGIN
  964. SearchString(in, out);
  965. IF out = "" THEN
  966. k := 0; len := LEN(out)-1;
  967. WHILE (k < len) & (in[k] # 0X) DO out[k] := in[k]; INC(k) END;
  968. out[k] := 0X
  969. END
  970. END MapString;
  971. PROCEDURE ShowMsg* (IN str: ARRAY OF CHAR);
  972. BEGIN
  973. ASSERT(str # "", 20);
  974. ASSERT(showHook # NIL, 100);
  975. showHook.ShowParamMsg(str, "", "", "")
  976. END ShowMsg;
  977. PROCEDURE ShowParamMsg* (IN str, p0, p1, p2: ARRAY OF CHAR);
  978. BEGIN
  979. ASSERT(str # "", 20);
  980. ASSERT(showHook # NIL, 100);
  981. showHook.ShowParamMsg(str,p0, p1, p2)
  982. END ShowParamMsg;
  983. PROCEDURE ShowStatus* (IN str: ARRAY OF CHAR);
  984. BEGIN
  985. ASSERT(showHook # NIL, 100);
  986. showHook.ShowParamStatus(str, "", "", "")
  987. END ShowStatus;
  988. PROCEDURE ShowParamStatus* (IN str, p0, p1, p2: ARRAY OF CHAR);
  989. BEGIN
  990. ASSERT(showHook # NIL, 100);
  991. showHook.ShowParamStatus(str, p0, p1, p2)
  992. END ShowParamStatus;
  993. PROCEDURE Call* (IN proc, errorMsg: ARRAY OF CHAR; OUT res: INTEGER);
  994. BEGIN
  995. ASSERT(callHook # NIL, 100);
  996. callHook.Call(proc, errorMsg, res)
  997. END Call;
  998. PROCEDURE Beep*;
  999. BEGIN
  1000. Kernel.Beep
  1001. END Beep;
  1002. PROCEDURE (n: LangNotifier) Notify-(), NEW, ABSTRACT;
  1003. PROCEDURE RegisterLangNotifier* (notifier: LangNotifier);
  1004. VAR nl: LangNotifier;
  1005. BEGIN
  1006. ASSERT(notifier # NIL, 20);
  1007. nl := langNotifiers;
  1008. WHILE (nl # NIL) & (nl # notifier) DO nl := nl.next END;
  1009. IF nl = NIL THEN
  1010. notifier.next := langNotifiers; langNotifiers := notifier
  1011. END
  1012. END RegisterLangNotifier;
  1013. PROCEDURE RemoveLangNotifier* (notifier: LangNotifier);
  1014. VAR nl, prev: LangNotifier;
  1015. BEGIN
  1016. ASSERT(notifier # NIL, 20);
  1017. nl := langNotifiers; prev := NIL;
  1018. WHILE (nl # NIL) & (nl # notifier) DO prev := nl; nl := nl.next END;
  1019. IF nl # NIL THEN
  1020. IF prev = NIL THEN langNotifiers := langNotifiers.next ELSE prev.next := nl.next END;
  1021. nl.next := NIL
  1022. END
  1023. END RemoveLangNotifier;
  1024. PROCEDURE Exec (a, b, c: INTEGER);
  1025. VAR nl: LangNotifier;
  1026. BEGIN
  1027. nl := currentNotifier; currentNotifier := NIL;
  1028. nl.Notify;
  1029. currentNotifier := nl
  1030. END Exec;
  1031. PROCEDURE SetLanguage* (lang: Language; persistent: BOOLEAN);
  1032. VAR nl, t: LangNotifier; ok: BOOLEAN;
  1033. BEGIN
  1034. ASSERT((lang = "") OR (LEN(lang$) = 2), 20);
  1035. ASSERT(languageHook # NIL, 100);
  1036. IF lang # language THEN
  1037. languageHook.SetLanguage(lang, persistent, ok);
  1038. IF ok THEN
  1039. language := lang; FlushMappings;
  1040. nl := langNotifiers;
  1041. WHILE nl # NIL DO
  1042. currentNotifier := nl;
  1043. Kernel.Try(Exec, 0, 0, 0);
  1044. IF currentNotifier = NIL THEN
  1045. t := nl; nl := nl.next; RemoveLangNotifier(t) (* Notifier trapped, remove it *)
  1046. ELSE
  1047. nl := nl.next
  1048. END
  1049. END
  1050. END;
  1051. currentNotifier := NIL
  1052. END
  1053. END SetLanguage;
  1054. PROCEDURE ResetLanguage*;
  1055. VAR lang: Language;
  1056. BEGIN
  1057. ASSERT(languageHook # NIL, 100);
  1058. languageHook.GetPersistentLanguage(lang);
  1059. SetLanguage(lang, nonPersistent)
  1060. END ResetLanguage;
  1061. BEGIN
  1062. appName := "BlackBox"; showsStatus := FALSE; caretPeriod := 500; thickCaret := FALSE; user := ""
  1063. END Dialog.