Graphics.Mod.txt 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. MODULE Graphics; (*NW 21.12.89 / 18.11.201 / 8.4.2016*)
  2. IMPORT SYSTEM, Files, Modules, Fonts, (*Printer,*) Texts, Oberon;
  3. CONST NameLen* = 32; GraphFileId = 0FAX; LibFileId = 0FBX;
  4. TYPE
  5. Graph* = POINTER TO GraphDesc;
  6. Object* = POINTER TO ObjectDesc;
  7. Method* = POINTER TO MethodDesc;
  8. Line* = POINTER TO LineDesc;
  9. Caption* = POINTER TO CaptionDesc;
  10. Macro* = POINTER TO MacroDesc;
  11. ObjectDesc* = RECORD
  12. x*, y*, w*, h*: INTEGER;
  13. col*: BYTE;
  14. selected*, marked*: BOOLEAN;
  15. do*: Method;
  16. next: Object
  17. END ;
  18. Msg* = RECORD END ;
  19. WidMsg* = RECORD (Msg) w*: INTEGER END ;
  20. ColorMsg* = RECORD (Msg) col*: INTEGER END ;
  21. FontMsg* = RECORD (Msg) fnt*: Fonts.Font END ;
  22. Name* = ARRAY NameLen OF CHAR;
  23. GraphDesc* = RECORD
  24. time*: LONGINT;
  25. sel*, first: Object;
  26. changed*: BOOLEAN
  27. END ;
  28. MacHead* = POINTER TO MacHeadDesc;
  29. MacExt* = POINTER TO MacExtDesc;
  30. Library* = POINTER TO LibraryDesc;
  31. MacHeadDesc* = RECORD
  32. name*: Name;
  33. w*, h*: INTEGER;
  34. ext*: MacExt;
  35. lib*: Library;
  36. first: Object;
  37. next: MacHead
  38. END ;
  39. LibraryDesc* = RECORD
  40. name*: Name;
  41. first: MacHead;
  42. next: Library
  43. END ;
  44. MacExtDesc* = RECORD END ;
  45. Context* = RECORD
  46. nofonts, noflibs, nofclasses: INTEGER;
  47. font: ARRAY 10 OF Fonts.Font;
  48. lib: ARRAY 4 OF Library;
  49. class: ARRAY 6 OF Modules.Command
  50. END;
  51. MethodDesc* = RECORD
  52. module*, allocator*: Name;
  53. new*: Modules.Command;
  54. copy*: PROCEDURE (from, to: Object);
  55. draw*, change*: PROCEDURE (obj: Object; VAR msg: Msg);
  56. selectable*: PROCEDURE (obj: Object; x, y: INTEGER): BOOLEAN;
  57. read*: PROCEDURE (obj: Object; VAR R: Files.Rider; VAR C: Context);
  58. write*: PROCEDURE (obj: Object; cno: INTEGER; VAR R: Files.Rider; VAR C: Context);
  59. print*: PROCEDURE (obj: Object; x, y: INTEGER)
  60. END ;
  61. LineDesc* = RECORD (ObjectDesc)
  62. unused*: INTEGER
  63. END ;
  64. CaptionDesc* = RECORD (ObjectDesc)
  65. pos*, len*: INTEGER
  66. END ;
  67. MacroDesc* = RECORD (ObjectDesc)
  68. mac*: MacHead
  69. END ;
  70. VAR width*, res*: INTEGER;
  71. new: Object;
  72. T*: Texts.Text; (*captions*)
  73. LineMethod*, CapMethod*, MacMethod* : Method;
  74. GetLib0: PROCEDURE (name: ARRAY OF CHAR; replace: BOOLEAN; VAR Lib: Library);
  75. FirstLib: Library;
  76. W, TW, XW: Texts.Writer;
  77. PROCEDURE New*(obj: Object);
  78. BEGIN new := obj
  79. END New;
  80. PROCEDURE Add*(G: Graph; obj: Object);
  81. BEGIN obj.marked := FALSE; obj.selected := TRUE; obj.next := G.first;
  82. G.first := obj; G.sel := obj; G.time := Oberon.Time(); G.changed := TRUE
  83. END Add;
  84. PROCEDURE ThisObj*(G: Graph; x, y: INTEGER): Object;
  85. VAR obj: Object;
  86. BEGIN obj := G.first;
  87. WHILE (obj # NIL) & ~obj.do.selectable(obj, x ,y) DO obj := obj.next END ;
  88. RETURN obj
  89. END ThisObj;
  90. PROCEDURE SelectObj*(G: Graph; obj: Object);
  91. BEGIN
  92. IF obj # NIL THEN obj.selected := TRUE; G.sel := obj; G.time := Oberon.Time() END
  93. END SelectObj;
  94. PROCEDURE SelectArea*(G: Graph; x0, y0, x1, y1: INTEGER);
  95. VAR obj: Object; t: INTEGER;
  96. BEGIN obj := G.first;
  97. IF x1 < x0 THEN t := x0; x0 := x1; x1 := t END ;
  98. IF y1 < y0 THEN t := y0; y0 := y1; y1 := t END ;
  99. WHILE obj # NIL DO
  100. IF (x0 <= obj.x) & (obj.x + obj.w <= x1) & (y0 <= obj.y) & (obj.y + obj.h <= y1) THEN
  101. obj.selected := TRUE; G.sel := obj
  102. END ;
  103. obj := obj.next
  104. END ;
  105. IF G.sel # NIL THEN G.time := Oberon.Time() END
  106. END SelectArea;
  107. PROCEDURE Draw*(G: Graph; VAR M: Msg);
  108. VAR obj: Object;
  109. BEGIN obj := G.first;
  110. WHILE obj # NIL DO obj.do.draw(obj, M); obj := obj.next END
  111. END Draw;
  112. PROCEDURE List*(G: Graph);
  113. VAR obj: Object; tag: INTEGER;
  114. BEGIN obj := G.first;
  115. WHILE obj # NIL DO
  116. Texts.Write(XW, 9X); Texts.WriteHex(XW, ORD(obj)); Texts.Write(XW, 9X);
  117. Texts.WriteInt(XW, obj.x, 5); Texts.WriteInt(XW, obj.y, 5); Texts.WriteInt(XW, obj.w, 5); Texts.WriteInt(XW, obj.h, 5);
  118. Texts.Write(XW, "/"); SYSTEM.GET(ORD(obj)-8, tag); Texts.WriteHex(XW, tag);
  119. SYSTEM.GET(ORD(obj)-4, tag); Texts.WriteHex(XW, tag); Texts.WriteLn(XW); obj := obj.next
  120. END ;
  121. Texts.Append(Oberon.Log, XW.buf)
  122. END List;
  123. (*----------------procedures operating on selection -------------------*)
  124. PROCEDURE Deselect*(G: Graph);
  125. VAR obj: Object;
  126. BEGIN obj := G.first; G.sel := NIL; G.time := 0;
  127. WHILE obj # NIL DO obj.selected := FALSE; obj := obj.next END
  128. END Deselect;
  129. PROCEDURE DrawSel*(G: Graph; VAR M: Msg);
  130. VAR obj: Object;
  131. BEGIN obj := G.first;
  132. WHILE obj # NIL DO
  133. IF obj.selected THEN obj.do.draw(obj, M) END ;
  134. obj := obj.next
  135. END
  136. END DrawSel;
  137. PROCEDURE Change*(G: Graph; VAR M: Msg);
  138. VAR obj: Object;
  139. BEGIN obj := G.first; G.changed := TRUE;
  140. WHILE obj # NIL DO
  141. IF obj.selected THEN obj.do.change(obj, M) END ;
  142. obj := obj.next
  143. END
  144. END Change;
  145. PROCEDURE Move*(G: Graph; dx, dy: INTEGER);
  146. VAR obj, ob0: Object; x0, x1, y0, y1: INTEGER;
  147. BEGIN obj := G.first; G.changed := TRUE;
  148. WHILE obj # NIL DO
  149. IF obj.selected & ~(obj IS Caption) THEN
  150. x0 := obj.x; x1 := obj.w + x0; y0 := obj.y; y1 := obj.h + y0;
  151. IF dx = 0 THEN (*vertical move*)
  152. ob0 := G.first;
  153. WHILE ob0 # NIL DO
  154. IF ~ob0.selected & (ob0 IS Line) & (x0 <= ob0.x) & (ob0.x <= x1) & (ob0.w < ob0.h) THEN
  155. IF (y0 <= ob0.y) & (ob0.y <= y1) THEN
  156. INC(ob0.y, dy); DEC(ob0.h, dy); ob0.marked := TRUE
  157. ELSIF (y0 <= ob0.y + ob0.h) & (ob0.y + ob0.h <= y1) THEN
  158. INC(ob0.h, dy); ob0.marked := TRUE
  159. END
  160. END ;
  161. ob0 := ob0.next
  162. END
  163. ELSIF dy = 0 THEN (*horizontal move*)
  164. ob0 := G.first;
  165. WHILE ob0 # NIL DO
  166. IF ~ob0.selected & (ob0 IS Line) & (y0 <= ob0.y) & (ob0.y <= y1) & (ob0.h < ob0.w) THEN
  167. IF (x0 <= ob0.x) & (ob0.x <= x1) THEN
  168. INC(ob0.x, dx); DEC(ob0.w, dx); ob0.marked := TRUE
  169. ELSIF (x0 <= ob0.x + ob0.w) & (ob0.x + ob0.w <= x1) THEN
  170. INC(ob0.w, dx); ob0.marked := TRUE
  171. END
  172. END ;
  173. ob0 := ob0.next
  174. END
  175. END
  176. END ;
  177. obj := obj.next
  178. END ;
  179. obj := G.first; (*now move*)
  180. WHILE obj # NIL DO
  181. IF obj.selected THEN INC(obj.x, dx); INC(obj.y, dy) END ;
  182. obj.marked := FALSE; obj := obj.next
  183. END
  184. END Move;
  185. PROCEDURE Copy*(Gs, Gd: Graph; dx, dy: INTEGER);
  186. VAR obj: Object;
  187. BEGIN obj := Gs.first; Gd.changed := TRUE;
  188. WHILE obj # NIL DO
  189. IF obj.selected THEN
  190. obj.do.new; obj.do.copy(obj, new); INC(new.x, dx); INC(new.y, dy);
  191. obj.selected := FALSE; Add(Gd, new)
  192. END ;
  193. obj := obj.next
  194. END ;
  195. new := NIL
  196. END Copy;
  197. PROCEDURE Delete*(G: Graph);
  198. VAR obj, pred: Object;
  199. BEGIN G.sel := NIL; G.changed := TRUE; obj := G.first;
  200. WHILE (obj # NIL) & obj.selected DO obj := obj.next END ;
  201. G.first := obj;
  202. IF obj # NIL THEN
  203. pred := obj; obj := obj.next;
  204. WHILE obj # NIL DO
  205. IF obj.selected THEN pred.next := obj.next ELSE pred := obj END ;
  206. obj := obj.next
  207. END
  208. END
  209. END Delete;
  210. (* ---------------------- Storing ----------------------- *)
  211. PROCEDURE WMsg(s0, s1: ARRAY OF CHAR);
  212. BEGIN Texts.WriteString(W, s0); Texts.WriteString(W, s1);
  213. Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  214. END WMsg;
  215. PROCEDURE InitContext(VAR C: Context);
  216. BEGIN C.nofonts := 0; C.noflibs := 0; C.nofclasses := 4;
  217. C.class[1] := LineMethod.new; C.class[2] := CapMethod.new; C.class[3] := MacMethod.new
  218. END InitContext;
  219. PROCEDURE FontNo*(VAR W: Files.Rider; VAR C: Context; fnt: Fonts.Font): INTEGER;
  220. VAR fno: INTEGER;
  221. BEGIN fno := 0;
  222. WHILE (fno < C.nofonts) & (C.font[fno] # fnt) DO INC(fno) END ;
  223. IF fno = C.nofonts THEN
  224. Files.WriteByte(W, 0); Files.WriteByte(W, 0); Files.WriteByte(W, fno);
  225. Files.WriteString(W, fnt.name); C.font[fno] := fnt; INC(C.nofonts)
  226. END ;
  227. RETURN fno
  228. END FontNo;
  229. PROCEDURE StoreElems(VAR W: Files.Rider; VAR C: Context; obj: Object);
  230. VAR cno: INTEGER;
  231. BEGIN
  232. WHILE obj # NIL DO
  233. cno := 1;
  234. WHILE (cno < C.nofclasses) & (obj.do.new # C.class[cno]) DO INC(cno) END ;
  235. IF cno = C.nofclasses THEN
  236. Files.WriteByte(W, 0); Files.WriteByte(W, 2); Files.WriteByte(W, cno);
  237. Files.WriteString(W, obj.do.module); Files.WriteString(W, obj.do.allocator);
  238. C.class[cno] := obj.do.new; INC(C.nofclasses)
  239. END ;
  240. obj.do.write(obj, cno, W, C); obj := obj.next
  241. END ;
  242. Files.WriteByte(W, 255)
  243. END StoreElems;
  244. PROCEDURE Store*(G: Graph; VAR W: Files.Rider);
  245. VAR C: Context;
  246. BEGIN InitContext(C); StoreElems(W, C, G.first); G.changed := FALSE
  247. END Store;
  248. PROCEDURE WriteObj*(VAR W: Files.Rider; cno: INTEGER; obj: Object);
  249. BEGIN Files.WriteByte(W, cno); Files.WriteInt(W, obj.y * 10000H + obj.x);
  250. Files.WriteInt(W, obj.h * 10000H + obj.w); Files.WriteByte(W, obj.col)
  251. END WriteObj;
  252. PROCEDURE WriteFile*(G: Graph; name: ARRAY OF CHAR);
  253. VAR F: Files.File; W: Files.Rider; C: Context;
  254. BEGIN F := Files.New(name); Files.Set(W, F, 0); Files.Write(W, GraphFileId);
  255. InitContext(C); StoreElems(W, C, G.first); Files.Register(F)
  256. END WriteFile;
  257. PROCEDURE Print*(G: Graph; x0, y0: INTEGER);
  258. VAR obj: Object;
  259. BEGIN obj := G.first;
  260. WHILE obj # NIL DO obj.do.print(obj, x0, y0); obj := obj.next END
  261. END Print;
  262. (* ---------------------- Loading ------------------------ *)
  263. PROCEDURE GetClass*(module, allocator: ARRAY OF CHAR; VAR com: Modules.Command);
  264. VAR mod: Modules.Module;
  265. BEGIN Modules.Load(module, mod);
  266. IF mod # NIL THEN
  267. com := Modules.ThisCommand(mod, allocator);
  268. IF com = NIL THEN WMsg(allocator, " unknown") END
  269. ELSE WMsg(module, " not available"); com := NIL
  270. END
  271. END GetClass;
  272. PROCEDURE Font*(VAR R: Files.Rider; VAR C: Context): Fonts.Font;
  273. VAR fno: BYTE;
  274. BEGIN Files.ReadByte(R, fno); RETURN C.font[fno]
  275. END Font;
  276. PROCEDURE ReadObj(VAR R: Files.Rider; obj: Object);
  277. VAR xy, wh: INTEGER; dmy: BYTE;
  278. BEGIN Files.ReadInt(R, xy); obj.y := xy DIV 10000H; obj.x := xy * 10000H DIV 10000H;
  279. Files.ReadInt(R, wh); obj.h := wh DIV 10000H; obj.w := wh * 10000H DIV 10000H;
  280. Files.ReadByte(R, obj.col)
  281. END ReadObj;
  282. PROCEDURE LoadElems(VAR R: Files.Rider; VAR C: Context; VAR fobj: Object);
  283. VAR cno, m, n, len: BYTE; pos: INTEGER;
  284. obj: Object;
  285. fnt: Fonts.Font;
  286. name, name1: ARRAY 32 OF CHAR;
  287. BEGIN obj := NIL; Files.ReadByte(R, cno);
  288. WHILE ~R.eof & (cno < 255) DO
  289. IF cno = 0 THEN
  290. Files.ReadByte(R, m); Files.ReadByte(R, n); Files.ReadString(R, name);
  291. IF m = 0 THEN fnt := Fonts.This(name); C.font[n] := fnt
  292. ELSIF m = 1 THEN GetLib0(name, FALSE, C.lib[n])
  293. ELSIF m = 2 THEN Files.ReadString(R, name1); GetClass(name, name1, C.class[n])
  294. END
  295. ELSIF C.class[cno] # NIL THEN
  296. C.class[cno];
  297. ReadObj(R, new);
  298. new.selected := FALSE; new.marked := FALSE; new.next := obj; obj := new;
  299. new.do.read(new, R, C)
  300. ELSE ReadObj(R, new); Files.ReadByte(R, len); pos := Files.Pos(R); Files.Set(R, Files.Base(R), pos + len)
  301. END ;
  302. Files.ReadByte(R, cno)
  303. END ;
  304. new := NIL; fobj := obj
  305. END LoadElems;
  306. PROCEDURE Load*(G: Graph; VAR R: Files.Rider);
  307. VAR C: Context;
  308. BEGIN G.sel := NIL; InitContext(C); LoadElems(R, C, G.first)
  309. END Load;
  310. PROCEDURE Open*(G: Graph; name: ARRAY OF CHAR);
  311. VAR tag: CHAR;
  312. F: Files.File; R: Files.Rider; C: Context;
  313. BEGIN G.first := NIL; G.sel := NIL; G.time := 0; G.changed := FALSE; F := Files.Old(name);
  314. IF F # NIL THEN
  315. Files.Set(R, F, 0); Files.Read(R, tag);
  316. IF tag = GraphFileId THEN InitContext(C); LoadElems(R, C, G.first); res := 0 ELSE res := 1 END
  317. ELSE res := 2
  318. END
  319. END Open;
  320. PROCEDURE SetWidth*(w: INTEGER);
  321. BEGIN width := w
  322. END SetWidth;
  323. (* --------------------- Macros / Libraries ----------------------- *)
  324. PROCEDURE GetLib*(name: ARRAY OF CHAR; replace: BOOLEAN; VAR Lib: Library);
  325. VAR i, wh: INTEGER; ch: CHAR;
  326. L: Library; mh: MacHead; obj: Object;
  327. F: Files.File; R: Files.Rider; C: Context;
  328. Lname, Fname: ARRAY 32 OF CHAR;
  329. BEGIN L := FirstLib; i := 0;
  330. WHILE (L # NIL) & (L.name # name) DO L := L.next END ;
  331. IF L = NIL THEN
  332. (*load library from file*) i := 0;
  333. WHILE name[i] > 0X DO Fname[i] := name[i]; INC(i) END ;
  334. Fname[i] := "."; Fname[i+1] := "L"; Fname[i+2] := "i"; Fname[i+3] := "b"; Fname[i+4] := 0X;
  335. F := Files.Old(Fname);
  336. IF F # NIL THEN
  337. WMsg("loading ", Fname); Files.Set(R, F, 0); Files.Read(R, ch);
  338. IF ch = LibFileId THEN
  339. IF L = NIL THEN NEW(L); L.name := name; L.next := FirstLib; FirstLib := L END ;
  340. L.first := NIL; InitContext(C);
  341. LoadElems(R, C, obj);
  342. WHILE obj # NIL DO
  343. NEW(mh); mh.first := obj;
  344. Files.ReadInt(R, wh); mh.h := wh DIV 10000H MOD 10000H; mh.w := wh MOD 10000H;
  345. Files.ReadString(R, mh.name);
  346. mh.lib := L; mh.next := L.first; L.first := mh; LoadElems(R, C, obj)
  347. END ;
  348. ELSE L := NIL
  349. END
  350. ELSE L := NIL
  351. END
  352. END ;
  353. Lib := L
  354. END GetLib;
  355. PROCEDURE NewLib*(Lname: ARRAY OF CHAR): Library;
  356. VAR L: Library;
  357. BEGIN NEW(L); L.name := Lname; L.first := NIL;
  358. L.next := FirstLib; FirstLib := L; RETURN L
  359. END NewLib;
  360. PROCEDURE StoreLib*(L: Library; Fname: ARRAY OF CHAR);
  361. VAR i: INTEGER;
  362. mh: MacHead;
  363. F: Files.File; W: Files.Rider;
  364. C: Context;
  365. Gname: ARRAY 32 OF CHAR;
  366. BEGIN L := FirstLib;
  367. WHILE (L # NIL) & (L.name # Fname) DO L := L.next END ;
  368. IF L # NIL THEN i := 0;
  369. WHILE Fname[i] > 0X DO Gname[i] := Fname[i]; INC(i) END ;
  370. Gname[i] := "."; Gname[i+1] := "L"; Gname[i+2] := "i"; Gname[i+3] := "b"; Gname[i+4] := 0X;
  371. F := Files.New(Gname); Files.Set(W, F, 0); Files.Write(W, LibFileId);
  372. InitContext(C); mh := L.first;
  373. WHILE mh # NIL DO
  374. StoreElems(W, C, mh.first); Files.WriteInt(W, mh.h * 10000H + mh.w);
  375. Files.WriteString(W, mh.name); mh := mh.next
  376. END ;
  377. Files.WriteByte(W, 255); Files.Register(F)
  378. ELSE Texts.WriteString(TW, Fname); Texts.WriteString(TW, " not found");
  379. Texts.WriteLn(TW); Texts.Append(Oberon.Log, TW.buf)
  380. END
  381. END StoreLib;
  382. PROCEDURE RemoveLibraries*;
  383. BEGIN FirstLib := NIL
  384. END RemoveLibraries;
  385. PROCEDURE ThisMac*(L: Library; Mname: ARRAY OF CHAR): MacHead;
  386. VAR mh: MacHead;
  387. BEGIN mh := L.first;
  388. WHILE (mh # NIL) & (mh.name # Mname) DO mh := mh.next END ;
  389. RETURN mh
  390. END ThisMac;
  391. PROCEDURE DrawMac*(mh: MacHead; VAR M: Msg);
  392. VAR elem: Object;
  393. BEGIN elem := mh.first;
  394. WHILE elem # NIL DO elem.do.draw(elem, M); elem := elem.next END
  395. END DrawMac;
  396. (* -------------------- Procedures for designing macros---------------------*)
  397. PROCEDURE OpenMac*(mh: MacHead; G: Graph; x, y: INTEGER);
  398. VAR obj: Object;
  399. BEGIN obj := mh.first;
  400. WHILE obj # NIL DO
  401. obj.do.new; obj.do.copy(obj, new); INC(new.x, x); INC(new.y, y); new.selected := TRUE;
  402. Add(G, new); obj := obj.next
  403. END ;
  404. new := NIL
  405. END OpenMac;
  406. PROCEDURE MakeMac*(G: Graph; VAR head: MacHead);
  407. VAR x0, y0, x1, y1: INTEGER;
  408. obj, last: Object;
  409. mh: MacHead;
  410. BEGIN obj := G.first; last := NIL; x0 := 1024; x1 := 0; y0 := 1024; y1 := 0;
  411. WHILE obj # NIL DO
  412. IF obj.selected THEN
  413. obj.do.new; obj.do.copy(obj, new); new.next := last; new.selected := FALSE; last := new;
  414. IF obj.x < x0 THEN x0 := obj.x END ;
  415. IF obj.x + obj.w > x1 THEN x1 := obj.x + obj.w END ;
  416. IF obj.y < y0 THEN y0 := obj.y END ;
  417. IF obj.y + obj.h > y1 THEN y1 := obj.y + obj.h END
  418. END ;
  419. obj := obj.next
  420. END ;
  421. obj := last;
  422. WHILE obj # NIL DO
  423. obj.x := obj.x - x0; obj.y := obj.y - y0; obj := obj.next
  424. END ;
  425. NEW(mh); mh.w := x1 - x0; mh.h := y1 - y0; mh.first := last; mh.ext := NIL;
  426. new := NIL; head := mh
  427. END MakeMac;
  428. PROCEDURE InsertMac*(mh: MacHead; L: Library; VAR new: BOOLEAN);
  429. VAR mh1: MacHead;
  430. BEGIN mh.lib := L; mh1 := L.first;
  431. WHILE (mh1 # NIL) & (mh1.name # mh.name) DO mh1 := mh1.next END ;
  432. IF mh1 = NIL THEN
  433. new := TRUE; mh.next := L.first; L.first := mh
  434. ELSE
  435. new := FALSE; mh1.w := mh.w; mh1.h := mh.h; mh1.first := mh.first
  436. END
  437. END InsertMac;
  438. (* ---------------------------- Line Methods -----------------------------*)
  439. PROCEDURE NewLine;
  440. VAR line: Line;
  441. BEGIN NEW(line); new := line; line.do := LineMethod
  442. END NewLine;
  443. PROCEDURE CopyLine(src, dst: Object);
  444. BEGIN dst.x := src.x; dst.y := src.y; dst.w := src.w; dst.h := src.h; dst.col := src.col
  445. END CopyLine;
  446. PROCEDURE ChangeLine(obj: Object; VAR M: Msg);
  447. BEGIN
  448. CASE M OF
  449. WidMsg:
  450. IF obj.w < obj.h THEN
  451. IF obj.w <= 7 THEN obj.w := M.w END
  452. ELSIF obj.h <= 7 THEN obj.h := M.w
  453. END |
  454. ColorMsg: obj.col := M.col
  455. END
  456. END ChangeLine;
  457. PROCEDURE LineSelectable(obj: Object; x, y: INTEGER): BOOLEAN;
  458. BEGIN
  459. RETURN (obj.x <= x) & (x < obj.x + obj.w) & (obj.y <= y) & (y < obj.y + obj.h)
  460. END LineSelectable;
  461. PROCEDURE ReadLine(obj: Object; VAR R: Files.Rider; VAR C: Context);
  462. BEGIN
  463. END ReadLine;
  464. PROCEDURE WriteLine(obj: Object; cno: INTEGER; VAR W: Files.Rider; VAR C: Context);
  465. BEGIN WriteObj(W, cno, obj)
  466. END WriteLine;
  467. (*PROCEDURE PrintLine(obj: Object; x, y: INTEGER);
  468. VAR w, h: INTEGER;
  469. BEGIN w := obj.w * 2; h := obj.h * 2;
  470. IF w < h THEN h := 2*h ELSE w := 2*w END ;
  471. Printer.ReplConst(obj.x * 4 + x, obj.y *4 + y, w, h)
  472. END PrintLine; *)
  473. (* ---------------------- Caption Methods ------------------------ *)
  474. PROCEDURE NewCaption;
  475. VAR cap: Caption;
  476. BEGIN NEW(cap); new := cap; cap.do := CapMethod
  477. END NewCaption;
  478. PROCEDURE CopyCaption(src, dst: Object);
  479. VAR ch: CHAR; R: Texts.Reader;
  480. BEGIN
  481. dst.x := src.x; dst.y := src.y; dst.w := src.w; dst.h := src.h; dst.col := src.col;
  482. dst(Caption).pos := T.len + 1; dst(Caption).len := src(Caption).len;
  483. Texts.Write(TW, 0DX); Texts.OpenReader(R, T, src(Caption).pos);
  484. Texts.Read(R, ch); TW.fnt := R.fnt;
  485. WHILE ch > 0DX DO Texts.Write(TW, ch); Texts.Read(R, ch) END ;
  486. Texts.Append(T, TW.buf)
  487. END CopyCaption;
  488. PROCEDURE ChangeCaption(obj: Object; VAR M: Msg);
  489. VAR dx, x1, dy, y1, w, w1, h1, len: INTEGER;
  490. pos: LONGINT;
  491. ch: CHAR; patadr: INTEGER; fnt: Fonts.Font;
  492. R: Texts.Reader;
  493. BEGIN
  494. CASE M OF
  495. FontMsg: fnt := M(FontMsg).fnt; w := 0; len := 0; pos := obj(Caption).pos;
  496. Texts.OpenReader(R, T, pos); Texts.Read(R, ch); dy := R.fnt.minY;
  497. WHILE ch > 0DX DO
  498. Fonts.GetPat(fnt, ch, dx, x1, y1, w1, h1, patadr);
  499. INC(w, dx); INC(len); Texts.Read(R, ch)
  500. END ;
  501. INC(obj.y, fnt.minY-dy); obj.w := w; obj.h := fnt.height;
  502. Texts.ChangeLooks(T, pos, pos+len, {0}, fnt, 0 , 0) |
  503. ColorMsg: obj.col := M(ColorMsg).col
  504. END
  505. END ChangeCaption;
  506. PROCEDURE CaptionSelectable(obj: Object; x, y: INTEGER): BOOLEAN;
  507. BEGIN
  508. RETURN (obj.x <= x) & (x < obj.x + obj.w) & (obj.y <= y) & (y < obj.y + obj.h)
  509. END CaptionSelectable;
  510. PROCEDURE ReadCaption(obj: Object; VAR R: Files.Rider; VAR C: Context);
  511. VAR ch: CHAR; fno: BYTE; len: INTEGER;
  512. BEGIN obj(Caption).pos := T.len + 1; Texts.Write(TW, 0DX);
  513. Files.ReadByte(R, fno); TW.fnt := C.font[fno]; len := 0; Files.Read(R, ch);
  514. WHILE ch > 0DX DO Texts.Write(TW, ch); INC(len); Files.Read(R, ch) END ;
  515. obj(Caption).len := len; Texts.Append(T, TW.buf)
  516. END ReadCaption;
  517. PROCEDURE WriteCaption(obj: Object; cno: INTEGER; VAR W: Files.Rider; VAR C: Context);
  518. VAR ch: CHAR; fno: BYTE;
  519. TR: Texts.Reader;
  520. BEGIN
  521. IF obj(Caption).len > 0 THEN
  522. Texts.OpenReader(TR, T, obj(Caption).pos); Texts.Read(TR, ch);
  523. fno := FontNo(W, C, TR.fnt);
  524. WriteObj(W, cno, obj); Files.WriteByte(W, fno);
  525. WHILE ch > 0DX DO Files.Write(W, ch); Texts.Read(TR, ch) END ;
  526. Files.Write(W, 0X)
  527. END
  528. END WriteCaption;
  529. (* PROCEDURE PrintCaption(obj: Object; x, y: INTEGER);
  530. VAR fnt: Fonts.Font;
  531. i: INTEGER; ch: CHAR;
  532. R: Texts.Reader;
  533. s: ARRAY 128 OF CHAR;
  534. BEGIN
  535. IF obj(Caption).len > 0 THEN
  536. Texts.OpenReader(R, T, obj(Caption).pos); Texts.Read(R, ch);
  537. fnt := R.fnt; DEC(y, fnt.minY*4); i := 0;
  538. WHILE ch >= " " DO s[i] := ch; INC(i); Texts.Read(R, ch) END ;
  539. s[i] := 0X;
  540. IF i > 0 THEN Printer.String(obj.x*4 + x, obj.y*4 + y, s, fnt.name) END
  541. END
  542. END PrintCaption; *)
  543. (* ---------------------- Macro Methods ------------------------ *)
  544. PROCEDURE NewMacro;
  545. VAR mac: Macro;
  546. BEGIN NEW(mac); new := mac; mac.do := MacMethod
  547. END NewMacro;
  548. PROCEDURE CopyMacro(src, dst: Object);
  549. BEGIN dst.x := src.x; dst.y := src.y; dst.w := src.w; dst.h := src.h;
  550. dst.col := src.col; dst(Macro).mac := src(Macro).mac
  551. END CopyMacro;
  552. PROCEDURE ChangeMacro(obj: Object; VAR M: Msg);
  553. BEGIN
  554. CASE M OF ColorMsg: obj.col := M.col END
  555. END ChangeMacro;
  556. PROCEDURE MacroSelectable(obj: Object; x, y: INTEGER): BOOLEAN;
  557. BEGIN
  558. RETURN (obj.x <= x) & (x <= obj.x + 8) & (obj.y <= y) & (y <= obj.y + 8)
  559. END MacroSelectable;
  560. PROCEDURE ReadMacro(obj: Object; VAR R: Files.Rider; VAR C: Context);
  561. VAR lno: BYTE; name: ARRAY 32 OF CHAR;
  562. BEGIN Files.ReadByte(R, lno);
  563. Files.ReadString(R, name); obj(Macro).mac := ThisMac(C.lib[lno], name)
  564. END ReadMacro;
  565. PROCEDURE WriteMacro(obj: Object; cno: INTEGER; VAR W1: Files.Rider; VAR C: Context);
  566. VAR lno: INTEGER;
  567. BEGIN lno := 0;
  568. WHILE (lno < C.noflibs) & (obj(Macro).mac.lib # C.lib[lno]) DO INC(lno) END ;
  569. IF lno = C.noflibs THEN
  570. Files.WriteByte(W1, 0); Files.WriteByte(W1, 1); Files.WriteByte(W1, lno);
  571. Files.WriteString(W1, obj(Macro).mac.lib.name); C.lib[lno] := obj(Macro).mac.lib; INC(C.noflibs)
  572. END ;
  573. WriteObj(W1, cno, obj); Files.WriteByte(W1, lno); Files.WriteString(W1, obj(Macro).mac.name)
  574. END WriteMacro;
  575. (* PROCEDURE PrintMacro(obj: Object; x, y: INTEGER);
  576. VAR elem: Object; mh: MacHead;
  577. BEGIN mh := obj(Macro).mac;
  578. IF mh # NIL THEN elem := mh.first;
  579. WHILE elem # NIL DO elem.do.print(elem, obj.x*4 + x, obj.y*4 + y); elem := elem.next END
  580. END
  581. END PrintMacro; *)
  582. PROCEDURE Notify(T: Texts.Text; op: INTEGER; beg, end: LONGINT);
  583. BEGIN
  584. END Notify;
  585. PROCEDURE InstallDrawMethods*(drawLine, drawCaption, drawMacro: PROCEDURE (obj: Object; VAR msg: Msg));
  586. BEGIN LineMethod.draw := drawLine; CapMethod.draw := drawCaption; MacMethod.draw := drawMacro
  587. END InstallDrawMethods;
  588. BEGIN Texts.OpenWriter(W); Texts.OpenWriter(TW); Texts.OpenWriter(XW);
  589. width := 1; GetLib0 := GetLib;
  590. NEW(T); Texts.Open(T, ""); T.notify := Notify;
  591. NEW(LineMethod); LineMethod.new := NewLine; LineMethod.copy := CopyLine;
  592. LineMethod.selectable := LineSelectable; LineMethod.change := ChangeLine;
  593. LineMethod.read := ReadLine; LineMethod.write := WriteLine; (*LineMethod.print := PrintLine;*)
  594. NEW(CapMethod); CapMethod.new := NewCaption; CapMethod.copy := CopyCaption;
  595. CapMethod.selectable := CaptionSelectable; CapMethod.change := ChangeCaption;
  596. CapMethod.read := ReadCaption; CapMethod.write := WriteCaption; (*CapMethod.print := PrintCaption;*)
  597. NEW(MacMethod); MacMethod.new := NewMacro; MacMethod.copy := CopyMacro;
  598. MacMethod.selectable := MacroSelectable; MacMethod.change := ChangeMacro;
  599. MacMethod.read := ReadMacro; MacMethod.write := WriteMacro; (*MacMethod.print := PrintMacro*)
  600. END Graphics.