Graph.Mod 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
  1. MODULE Graph;
  2. IMPORT Out, Al := Allegro5, Utf8, Files, Dir, Strings, SYSTEM, Platform;
  3. CONST
  4. fontPlanes = 4; (*!TODO*)
  5. (** Settings set members **)
  6. manual* = 0;
  7. fullscreen* = 1;
  8. window* = 2;
  9. exact* = 3;
  10. smooth* = 4;
  11. software* = 5;
  12. noMouse* = 6;
  13. center* = 7;
  14. resizable* = 8;
  15. maximized* = 9;
  16. minimized* = 10;
  17. frameless* = 11;
  18. nobuffer* = 12;
  19. topleft* = 13;
  20. (** Event.type possible values **)
  21. noEvent = 0;
  22. quit* = 1;
  23. timer* = 2;
  24. windowEvent* = 3;
  25. keyDown* = 4;
  26. keyUp* = 5;
  27. char* = 6;
  28. mouseMove* = 7;
  29. mouseDown* = 8;
  30. mouseUp* = 9;
  31. mouseWheel* = 10;
  32. resize* = 11;
  33. eventUserResize = 2005;
  34. (** Window.zoom possible values **)
  35. noZoom = 0; (** The screen is not zoomed *)
  36. intZoom = 1; (** The zoom value is an integer: 2x, 3x etc. *)
  37. realZoom = 2; (** The zoom value is not an integer, i.e. 2.5x *)
  38. (** Flip flags for DrawFlip, DrawEx etc. **)
  39. flipHor* = 0;
  40. flipVert* = 1;
  41. (** Key Codes **)
  42. kA* = 1;
  43. kB* = 2;
  44. kC* = 3;
  45. kD* = 4;
  46. kE* = 5;
  47. kF* = 6;
  48. kG* = 7;
  49. kH* = 8;
  50. kI* = 9;
  51. kJ* = 10;
  52. kK* = 11;
  53. kL* = 12;
  54. kM* = 13;
  55. kN* = 14;
  56. kO* = 15;
  57. kP* = 16;
  58. kQ* = 17;
  59. kR* = 18;
  60. kS* = 19;
  61. kT* = 20;
  62. kU* = 21;
  63. kV* = 22;
  64. kW* = 23;
  65. kX* = 24;
  66. kY* = 25;
  67. kZ* = 26;
  68. k0* = 27;
  69. k1* = 28;
  70. k2* = 29;
  71. k3* = 30;
  72. k4* = 31;
  73. k5* = 32;
  74. k6* = 33;
  75. k7* = 34;
  76. k8* = 35;
  77. k9* = 36;
  78. k0Pad* = 37;
  79. k1Pad* = 38;
  80. k2Pad* = 39;
  81. k3Pad* = 40;
  82. k4Pad* = 41;
  83. k5Pad* = 42;
  84. k6Pad* = 43;
  85. k7Pad* = 44;
  86. k8Pad* = 45;
  87. k9Pad* = 46;
  88. kF1* = 47;
  89. kF2* = 48;
  90. kF3* = 49;
  91. kF4* = 50;
  92. kF5* = 51;
  93. kF6* = 52;
  94. kF7* = 53;
  95. kF8* = 54;
  96. kF9* = 55;
  97. kF10* = 56;
  98. kF11* = 57;
  99. kF12* = 58;
  100. kEsc* = 59;
  101. kTilde* = 60;
  102. kMinus* = 61;
  103. kEquals* = 62;
  104. kBackspace* = 63;
  105. kTab* = 64;
  106. kOpenBrace* = 65;
  107. kCloseBrace* = 66;
  108. kEnter* = 67;
  109. kColon* = 68;
  110. kQuote* = 69;
  111. kBackslash* = 70;
  112. kBackslash2* = 71;
  113. kComma* = 72;
  114. kStop* = 73;
  115. kSlash* = 74;
  116. kSpace* = 75;
  117. kInsert* = 76;
  118. kDel* = 77;
  119. kHome* = 78;
  120. kEnd* = 79;
  121. kPgUp* = 80;
  122. kPgDn* = 81;
  123. kLeft* = 82;
  124. kRight* = 83;
  125. kUp* = 84;
  126. kDown* = 85;
  127. kSlashPad* = 86;
  128. kAsterisk* = 87;
  129. kMinusPad* = 88;
  130. kPlusPad* = 89;
  131. kDelPad* = 90;
  132. kEnterPad* = 91;
  133. kPrtScr* = 92;
  134. kPause* = 93;
  135. kEqualsPad* = 103;
  136. kBackquote* = 104;
  137. kSemicolon2* = 105;
  138. kCommand* = 106;
  139. kBack* = 107;
  140. kVolumeUp* = 108;
  141. kVolumeDown* = 109;
  142. kModifers* = 215;
  143. kLShift* = 215;
  144. kRShift* = 216;
  145. kLCtrl* = 217;
  146. kRCtrl* = 218;
  147. kAlt* = 219;
  148. kAltGr* = 220;
  149. kLMeta* = 221;
  150. kRMeta* = 222;
  151. kMenu* = 223;
  152. kScrLock* = 224;
  153. kNumLock* = 225;
  154. kCapsLock* = 226;
  155. kMax* = 226;
  156. (** Modifiers Set **)
  157. mShift* = 0;
  158. mCtrl* = 1;
  159. mAlt* = 2;
  160. mLwin* = 3;
  161. mRwin* = 4;
  162. mMenu* = 5;
  163. mAltGr* = 6;
  164. mCommand* = 7;
  165. mScrolllock* = 8;
  166. mNumlock* = 9;
  167. mCapslock* = 10;
  168. TYPE
  169. ADRINT = SYSTEM.ADRINT;
  170. REAL = SYSTEM.REAL32;
  171. LONGREAL = SYSTEM.REAL64;
  172. LONGINT = SYSTEM.INT64;
  173. SHORTCHAR = SYSTEM.CHAR8;
  174. Color* = RECORD
  175. r, g, b, a: REAL
  176. END;
  177. Transform* = RECORD
  178. m: ARRAY 4, 4 OF REAL
  179. END;
  180. Timer* = POINTER TO TimerDesc;
  181. TimerDesc* = RECORD
  182. tmr: Al.Timer;
  183. next: Timer (** See timerList below *)
  184. END;
  185. Bitmap* = POINTER TO BitmapDesc;
  186. BitmapDesc* = RECORD
  187. bmp: Al.Bitmap;
  188. w*, h*: INTEGER
  189. END;
  190. Window* = POINTER TO WindowDesc;
  191. WindowDesc* = RECORD(BitmapDesc) (** This is a window. *)
  192. display: Al.Display; (** Allegro Display *)
  193. winW, winH*: INTEGER; (** Window size in real pixels *)
  194. initX*, initY*: INTEGER; (** Window position upon its creation *)
  195. initW, initH: INTEGER; (** Window size upon its creation *)
  196. fsW*, fsH*: INTEGER; (** Fullscreen size *)
  197. wantZoom: REAL; (** Window zoom upon its creation *)
  198. lastX, lastY: INTEGER; (** Last mouse position in virtual pixels *)
  199. lastW, lastH: INTEGER; (** Last stepped size in virtual pixels *)
  200. zoom: INTEGER; (** See constants above; based on this rzoom/izoom is used *)
  201. izoom: INTEGER; (** Window.izoom is used if Window.zoom = intZoom *)
  202. rzoom: REAL; (** Window.rzoom is used if Window.zoom = realZoom *)
  203. scaleOn: BOOLEAN; (** If TRUE, scaleX and scaleY are used *)
  204. scaleX, scaleY: REAL; (** Deforms pixels on Flip, but zoom is for drawing *)
  205. sizeStepX, sizeStepY: INTEGER;
  206. flipX, flipY, flipW, flipH: REAL; (** Where to flip the window bitmap to *)
  207. iFlipX, iFlipY: INTEGER; (** Same as flipX, flipY, which are always whole *)
  208. options: SET;
  209. pressedButtons: SET; (** Mouse buttons that are currenty being pressed *)
  210. title: ARRAY 256 OF CHAR;
  211. resized: BOOLEAN; (** TRUE if fullscreen mode has been toggled for window *)
  212. showMouse: BOOLEAN;
  213. icons: ARRAY 64 OF Al.Bitmap;
  214. noficons: INTEGER;
  215. next: Window (** See windowList below *)
  216. END;
  217. Event* = RECORD
  218. type*: INTEGER;
  219. time*: REAL;
  220. x*, y*, z*, w*, h*: INTEGER;
  221. dx*, dy*, dz*, dw*: INTEGER;
  222. button*: INTEGER;
  223. buttons*: SET; (** What mouse buttons are pressed *)
  224. count*: LONGINT; (** Timer counter *)
  225. key*: INTEGER; (** Physical key code *)
  226. ch*: CHAR; (** Typed character for event.type = char *)
  227. mod*: SET; (** Key modifiers *)
  228. repeat*: BOOLEAN;
  229. window*: Window;
  230. timer*: Timer;
  231. display: Al.Display
  232. END;
  233. FontMessage* = POINTER TO FontMessageDesc;
  234. FontMessageDesc* = RECORD
  235. END;
  236. FontDrawMsg* = POINTER TO FontDrawMsgDesc;
  237. FontDrawMsgDesc* = RECORD(FontMessage)
  238. END;
  239. Font* = POINTER TO FontDesc;
  240. FontDesc* = RECORD
  241. fname: ARRAY 256 OF CHAR;
  242. handle: PROCEDURE (font: Font; VAR msg: FontMessage);
  243. draw: PROCEDURE (font: Font; VAR msg: FontDrawMsg);
  244. loaded*: BOOLEAN
  245. END;
  246. MonoFont* = POINTER TO MonoFontDesc;
  247. MonoFontDesc* = RECORD(FontDesc)
  248. bmp: Bitmap;
  249. charW*, charH*: INTEGER;
  250. rows, cols: INTEGER
  251. END;
  252. VAR
  253. Done*: BOOLEAN;
  254. settings: SET; (** See list of constants Settings above *)
  255. wantW, wantH: INTEGER; (** Assigned in procedure Settings *)
  256. wantZoom: REAL; (** Assigned in procedure SetZoom *)
  257. wantSizeStepX, wantSizeStepY: INTEGER; (** Assigned in SetSizeStep *)
  258. wantScaleX, wantScaleY: REAL; (** Assigned in procedure SetScale *)
  259. wantTitle: ARRAY 256 OF CHAR; (** Assigned in procedure SetTitle *)
  260. queue: Al.EventQueue;
  261. userEventSource: Al.EventSource;
  262. windowList: Window;
  263. timerList: Timer;
  264. screen: Window;
  265. target: Bitmap;
  266. black: Color;
  267. charRead: CHAR; (** For KeyPressed and ReadKey *)
  268. specialChar: BOOLEAN; (** For charRead *)
  269. PROCEDURE Error(s: ARRAY OF CHAR);
  270. BEGIN Out.String(s); Out.Ln
  271. END Error;
  272. PROCEDURE GetDesktopResolution*(VAR w, h: INTEGER);
  273. VAR info: Al.MonitorInfo;
  274. n, i: INTEGER;
  275. ok: BOOLEAN;
  276. BEGIN
  277. n := Al.get_num_video_adapters();
  278. i := 0;
  279. ok := Al.get_monitor_info(0, info);
  280. WHILE (i < n) & ~(ok & (info.x1 = 0) & (info.y1 = 0)) DO
  281. INC(i); ok := Al.get_monitor_info(i, info)
  282. END;
  283. IF i >= n THEN ok := Al.get_monitor_info(0, info) END;
  284. IF ok THEN
  285. w := info.x2 - info.x1;
  286. h := info.y2 - info.y1
  287. ELSE w := -1; h := -1
  288. END
  289. END GetDesktopResolution;
  290. PROCEDURE GetScreen*(): Window;
  291. RETURN screen END GetScreen;
  292. PROCEDURE GetScreenSize*(VAR width, height: INTEGER);
  293. BEGIN
  294. IF screen # NIL THEN width := screen.w; height := screen.h
  295. ELSE width := 0; height := 0
  296. END
  297. END GetScreenSize;
  298. PROCEDURE Settings*(w, h: INTEGER; flags: SET);
  299. BEGIN wantW := w; wantH := h; settings := flags
  300. END Settings;
  301. PROCEDURE SetSizeStep*(w, h: INTEGER);
  302. BEGIN wantSizeStepX := w; wantSizeStepY := h
  303. END SetSizeStep;
  304. PROCEDURE ApplySizeStep(W: Window; VAR w, h: INTEGER);
  305. BEGIN
  306. IF W.sizeStepX # 1 THEN
  307. w := w DIV W.sizeStepX * W.sizeStepX;
  308. IF w < W.sizeStepX THEN w := W.sizeStepX END
  309. END;
  310. IF W.sizeStepY # 1 THEN
  311. h := h DIV W.sizeStepY * W.sizeStepY;
  312. IF h < W.sizeStepY THEN h := W.sizeStepY END
  313. END
  314. END ApplySizeStep;
  315. PROCEDURE GetTarget*(): Bitmap;
  316. RETURN target END GetTarget;
  317. PROCEDURE GetTargetSize*(VAR width, height: INTEGER);
  318. BEGIN
  319. IF target # NIL THEN width := target.w; height := target.h
  320. ELSE width := 0; height := 0
  321. END
  322. END GetTargetSize;
  323. PROCEDURE Target*(bitmap: Bitmap);
  324. VAR T: Al.Transform;
  325. W: Window;
  326. BEGIN target := bitmap;
  327. IF bitmap # NIL THEN
  328. IF (bitmap IS Window) & (bitmap.bmp = NIL) THEN W := bitmap(Window);
  329. Al.set_target_backbuffer(W.display);
  330. Al.build_transform(T, W.flipX, W.flipY, W.scaleX, W.scaleY, 0.0);
  331. Al.use_transform(T)
  332. ELSE Al.set_target_bitmap(SYSTEM.VAL(Al.Bitmap, bitmap.bmp))
  333. END
  334. END
  335. END Target;
  336. PROCEDURE TargetScreen*;
  337. BEGIN
  338. IF screen # NIL THEN Target(screen)
  339. ELSIF windowList # NIL THEN Target(windowList)
  340. ELSE Target(NIL)
  341. END
  342. END TargetScreen;
  343. PROCEDURE ClearBitmapToColor*(bmp: Bitmap; c: Color);
  344. BEGIN
  345. IF bmp # NIL THEN
  346. Target(bmp);
  347. Al.clear_to_color(SYSTEM.VAL(Al.Color, c))
  348. END
  349. END ClearBitmapToColor;
  350. PROCEDURE ClearBitmap*(bmp: Bitmap);
  351. BEGIN ClearBitmapToColor(bmp, black)
  352. END ClearBitmap;
  353. PROCEDURE ClearToColor*(c: Color);
  354. BEGIN ClearBitmapToColor(GetScreen(), c)
  355. END ClearToColor;
  356. PROCEDURE ClearScreen*;
  357. BEGIN ClearBitmapToColor(GetScreen(), black)
  358. END ClearScreen;
  359. PROCEDURE ResetFlipVars(W: Window);
  360. VAR w, h: INTEGER;
  361. BEGIN
  362. IF W.zoom = intZoom THEN
  363. w := W.w * W.izoom; h := W.h * W.izoom;
  364. IF W.scaleOn THEN
  365. W.flipW := FLT(FLOOR(FLT(w) * W.scaleX + 0.9));
  366. W.flipH := FLT(FLOOR(FLT(h) * W.scaleY + 0.9));
  367. W.iFlipX := (W.winW - FLOOR(W.flipW + 0.1)) DIV 2;
  368. W.iFlipY := (W.winH - FLOOR(W.flipH + 0.1)) DIV 2
  369. ELSE W.flipW := FLT(w); W.flipH := FLT(h);
  370. W.iFlipX := (W.winW - w) DIV 2; W.iFlipY := (W.winH - h) DIV 2
  371. END
  372. ELSE
  373. W.flipW := FLT(FLOOR(W.w * W.rzoom * W.scaleX + 0.9));
  374. W.flipH := FLT(FLOOR(W.h * W.rzoom * W.scaleY + 0.9));
  375. W.iFlipX := (W.winW - FLOOR(W.flipW + 0.1)) DIV 2;
  376. W.iFlipY := (W.winH - FLOOR(W.flipH + 0.1)) DIV 2
  377. END;
  378. IF topleft IN W.options THEN W.iFlipX := 0; W.iFlipY := 0 END;
  379. W.flipX := FLT(W.iFlipX); W.flipY := FLT(W.iFlipY);
  380. IF ~(exact IN W.options) & (smooth IN W.options) &
  381. ~(topleft IN W.options) & (W.winW - W.flipX - W.flipW < W.rzoom) &
  382. (W.winH - W.flipY - W.flipH < W.rzoom) THEN
  383. W.iFlipX := 0; W.iFlipY := 0; W.flipX := 0.0; W.flipY := 0.0;
  384. W.flipW := FLT(W.winW); W.flipH := FLT(W.winH)
  385. END
  386. END ResetFlipVars;
  387. PROCEDURE ResetWindowBitmap(W: Window);
  388. VAR opt: SET;
  389. w, h, bw, bh: INTEGER;
  390. fw, fh: REAL;
  391. scaled, wasTarget: BOOLEAN;
  392. tmp: Bitmap;
  393. BEGIN scaled := FALSE;
  394. IF W.bmp = NIL THEN bw := -1
  395. ELSE bw := Al.get_bitmap_width(W.bmp); bh := Al.get_bitmap_height(W.bmp)
  396. END;
  397. IF ~(exact IN W.options) THEN
  398. IF W.zoom = noZoom THEN w := W.winW; h := W.winH
  399. ELSIF (W.zoom = intZoom) & ~W.scaleOn THEN
  400. w := W.winW DIV W.izoom; h := W.winH DIV W.izoom
  401. ELSE scaled := TRUE;
  402. w := FLOOR(W.winW / W.rzoom / W.scaleX + 0.1);
  403. h := FLOOR(W.winH / W.rzoom / W.scaleY + 0.1)
  404. END
  405. ELSE w := W.w; h := W.h
  406. END;
  407. IF W.scaleOn & ~scaled THEN
  408. w := FLOOR(w / W.scaleX + 0.1); h := FLOOR(h / W.scaleY + 0.1)
  409. END;
  410. ApplySizeStep(W, w, h);
  411. IF (w > bw) OR (h > bh) OR (W.zoom = noZoom) THEN
  412. IF W.bmp # NIL THEN
  413. wasTarget := Al.get_target_bitmap() = W.bmp;
  414. Al.destroy_bitmap(W.bmp)
  415. END;
  416. IF (W.zoom = noZoom) & (nobuffer IN W.options) THEN
  417. W.bmp := NIL;
  418. IF wasTarget THEN Target(NIL) END
  419. ELSE opt := {Al.convertBitmap};
  420. IF smooth IN W.options THEN
  421. opt := opt + {Al.minLinear, Al.magLinear}
  422. END;
  423. Al.set_new_bitmap_flags(opt);
  424. W.bmp := Al.create_bitmap(w, h);
  425. tmp := GetTarget(); ClearBitmap(W);
  426. IF wasTarget THEN Target(W) ELSE Target(tmp) END
  427. END
  428. END;
  429. W.w := w; W.h := h;
  430. ResetFlipVars(W)
  431. END ResetWindowBitmap;
  432. PROCEDURE GetWindowOptions*(W: Window): SET;
  433. RETURN W.options END GetWindowOptions;
  434. PROCEDURE GetWindowZoom*(W: Window): REAL;
  435. RETURN W.rzoom END GetWindowZoom;
  436. PROCEDURE SetWindowZoomF*(W: Window; zoom: REAL);
  437. BEGIN W.rzoom := zoom;
  438. IF zoom = 1.0 THEN W.zoom := noZoom
  439. ELSIF FLOOR(zoom + 0.001) * 100 = FLOOR(zoom * 100 + 0.001) THEN
  440. W.zoom := intZoom; W.izoom := FLOOR(zoom + 0.001)
  441. ELSE W.zoom := realZoom
  442. END;
  443. ResetWindowBitmap(W)
  444. END SetWindowZoomF;
  445. PROCEDURE SetWindowZoom*(W: Window; zoom: INTEGER);
  446. BEGIN W.rzoom := FLT(zoom);
  447. IF zoom = 1 THEN W.zoom := noZoom
  448. ELSE W.zoom := intZoom; W.izoom := zoom
  449. END;
  450. ResetWindowBitmap(W)
  451. END SetWindowZoom;
  452. PROCEDURE SetNewWindowZoomF*(zoom: REAL);
  453. BEGIN wantZoom := zoom
  454. END SetNewWindowZoomF;
  455. PROCEDURE SetZoomF*(zoom: REAL);
  456. BEGIN wantZoom := zoom;
  457. IF screen # NIL THEN SetWindowZoomF(screen, zoom) END
  458. END SetZoomF;
  459. PROCEDURE SetNewWindowZoom*(zoom: INTEGER);
  460. BEGIN wantZoom := FLT(zoom)
  461. END SetNewWindowZoom;
  462. PROCEDURE SetZoom*(zoom: INTEGER);
  463. BEGIN wantZoom := FLT(zoom);
  464. IF screen # NIL THEN SetWindowZoom(screen, zoom) END
  465. END SetZoom;
  466. PROCEDURE SetWindowFullscreenSize*(win: Window; width, height: INTEGER);
  467. BEGIN win.fsW := width; win.fsH := height
  468. END SetWindowFullscreenSize;
  469. PROCEDURE ShowWindowMouse*(W: Window; show: BOOLEAN);
  470. BEGIN
  471. IF show THEN
  472. IF Al.show_mouse_cursor(W.display) THEN W.showMouse := TRUE END
  473. ELSE
  474. IF Al.hide_mouse_cursor(W.display) THEN W.showMouse := FALSE END
  475. END
  476. END ShowWindowMouse;
  477. PROCEDURE ShowMouse*(show: BOOLEAN);
  478. BEGIN IF screen # NIL THEN ShowWindowMouse(screen, show) END
  479. END ShowMouse;
  480. PROCEDURE SetWindowOption*(W: Window; key: INTEGER; on: BOOLEAN);
  481. BEGIN IF on THEN INCL(W.options, key) ELSE EXCL(W.options, key) END
  482. END SetWindowOption;
  483. PROCEDURE SetWindowScale*(W: Window; x, y: REAL);
  484. BEGIN W.scaleOn := (x # 1.0) OR (y # 1.0);
  485. W.scaleX := x; W.scaleY := y
  486. END SetWindowScale;
  487. PROCEDURE SetNewWindowScale*(x, y: REAL);
  488. BEGIN wantScaleX := x; wantScaleY := y
  489. END SetNewWindowScale;
  490. PROCEDURE SetScale*(x, y: REAL);
  491. BEGIN wantScaleX := x; wantScaleY := y;
  492. IF screen # NIL THEN SetWindowScale(screen, x, y) END
  493. END SetScale;
  494. PROCEDURE SetThisWindowTitle*(W: Window; title: ARRAY OF CHAR);
  495. VAR q: ARRAY 256 OF SHORTCHAR;
  496. BEGIN Utf8.Encode(title, q); Al.set_window_title(W.display, q)
  497. END SetThisWindowTitle;
  498. PROCEDURE SetNewWindowTitle*(title: ARRAY OF CHAR);
  499. BEGIN wantTitle := title
  500. END SetNewWindowTitle;
  501. PROCEDURE SetTitle*(title: ARRAY OF CHAR);
  502. BEGIN wantTitle := title;
  503. IF screen # NIL THEN SetThisWindowTitle(screen, title) END
  504. END SetTitle;
  505. PROCEDURE LoadBitmap*(fname: ARRAY OF CHAR): Bitmap;
  506. VAR B: Bitmap;
  507. q: ARRAY 2048 OF SHORTCHAR;
  508. BEGIN Al.set_new_bitmap_flags({Al.convertBitmap});
  509. NEW(B); Utf8.Encode(fname, q); B.bmp := Al.load_bitmap(q);
  510. IF B.bmp = NIL THEN B := NIL
  511. ELSE B.w := Al.get_bitmap_width(B.bmp); B.h := Al.get_bitmap_height(B.bmp)
  512. END
  513. RETURN B END LoadBitmap;
  514. PROCEDURE Flip*;
  515. VAR tmp: Al.Bitmap;
  516. W: Window;
  517. T: Al.Transform;
  518. x, y, w, h: REAL;
  519. BEGIN
  520. IF ((target = NIL) OR ~(target IS Window)) & (screen # NIL) THEN
  521. Target(screen)
  522. END;
  523. IF (target # NIL) & (target IS Window) THEN
  524. W := target(Window);
  525. tmp := Al.get_target_bitmap();
  526. Al.set_target_backbuffer(W.display);
  527. Al.identity_transform(T);
  528. Al.use_transform(T);
  529. IF target.bmp # NIL THEN
  530. Al.clear_to_color(SYSTEM.VAL(Al.Color, black));
  531. Al.draw_scaled_bitmap(W.bmp, 0.0, 0.0, FLT(W.w), FLT(W.h),
  532. W.flipX, W.flipY, W.flipW, W.flipH, {})
  533. ELSE w := FLT(W.winW); h := FLT(W.winH);
  534. x := FLT(FLOOR(W.flipX + W.flipW + 0.1));
  535. y := FLT(FLOOR(W.flipY + W.flipH + 0.1));
  536. Al.draw_filled_rectangle(0.0, 0.0, w, W.flipY,
  537. SYSTEM.VAL(Al.Color, black));
  538. Al.draw_filled_rectangle(0.0, y, w, h, SYSTEM.VAL(Al.Color, black));
  539. Al.draw_filled_rectangle(0.0, W.flipY, W.flipX, y,
  540. SYSTEM.VAL(Al.Color, black));
  541. Al.draw_filled_rectangle(x, W.flipY, w, y, SYSTEM.VAL(Al.Color, black))
  542. END;
  543. Al.flip_display();
  544. Al.set_target_bitmap(tmp)
  545. END
  546. END Flip;
  547. PROCEDURE PutPixel2*(x, y: INTEGER; c: Color);
  548. BEGIN Al.draw_filled_rectangle(FLT(x), FLT(y), FLT(x + 1), FLT(y + 1),
  549. SYSTEM.VAL(Al.Color, c))
  550. END PutPixel2;
  551. PROCEDURE PutPixel*(x, y: INTEGER; c: Color);
  552. BEGIN Al.draw_pixel(FLT(x) + 0.5, FLT(y) + 0.5, SYSTEM.VAL(Al.Color, c))
  553. END PutPixel;
  554. PROCEDURE MakeRGBA*(VAR color: Color; r, g, b, a: INTEGER);
  555. BEGIN color.r := r / 255; color.g := g / 255;
  556. color.b := b / 255; color.a := a / 255
  557. END MakeRGBA;
  558. PROCEDURE MakeCol*(VAR color: Color; r, g, b: INTEGER);
  559. BEGIN color.r := r / 255; color.g := g / 255;
  560. color.b := b / 255; color.a := 1.0
  561. END MakeCol;
  562. PROCEDURE ColorToRGB*(color: Color; VAR r, g, b: INTEGER);
  563. BEGIN r := FLOOR(color.r * 255 + 0.1) MOD 256;
  564. g := FLOOR(color.g * 255 + 0.1) MOD 256;
  565. b := FLOOR(color.b * 255 + 0.1) MOD 256
  566. END ColorToRGB;
  567. PROCEDURE ColorToRGBA*(color: Color; VAR r, g, b, a: INTEGER);
  568. BEGIN r := FLOOR(color.r * 255 + 0.1) MOD 256;
  569. g := FLOOR(color.g * 255 + 0.1) MOD 256;
  570. b := FLOOR(color.b * 255 + 0.1) MOD 256;
  571. a := FLOOR(color.a * 255 + 0.1) MOD 256
  572. END ColorToRGBA;
  573. PROCEDURE ThickLineF*(x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
  574. BEGIN Al.draw_line(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), thickness)
  575. END ThickLineF;
  576. PROCEDURE ThickLine*(x1, y1, x2, y2: INTEGER; color: Color;
  577. thickness: INTEGER);
  578. BEGIN
  579. Al.draw_line(FLT(x1) + 0.5, FLT(y1) + 0.5, FLT(x2) + 0.5, FLT(y2) + 0.5,
  580. SYSTEM.VAL(Al.Color, color), FLT(thickness))
  581. END ThickLine;
  582. PROCEDURE LineF(x1, y1, x2, y2: REAL; color: Color);
  583. BEGIN
  584. IF x1 < x2 THEN x2 := x2 + 1
  585. ELSIF x1 > x2 THEN x1 := x1 + 1
  586. ELSE x1 := x1 + 0.5; x2 := x1
  587. END;
  588. IF y1 < y2 THEN y1 := y1 + 0.01; y2 := y2 + 0.99
  589. ELSIF y1 > y2 THEN y1 := y1 + 1
  590. ELSE y1 := y1 + 0.5; y2 := y1
  591. END;
  592. Al.draw_line(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), 0.0)
  593. END LineF;
  594. PROCEDURE Line*(x1, y1, x2, y2: INTEGER; color: Color);
  595. BEGIN LineF(FLT(x1), FLT(y1), FLT(x2), FLT(y2), color)
  596. END Line;
  597. PROCEDURE HLine*(x1, y, x2: INTEGER; color: Color);
  598. BEGIN LineF(FLT(x1), FLT(y), FLT(x2), FLT(y), color)
  599. END HLine;
  600. PROCEDURE VLine*(x, y1, y2: INTEGER; color: Color);
  601. BEGIN LineF(FLT(x), FLT(y1), FLT(x), FLT(y2), color)
  602. END VLine;
  603. PROCEDURE FillRectF*(x1, y1, x2, y2: REAL; color: Color);
  604. BEGIN Al.draw_filled_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color))
  605. END FillRectF;
  606. PROCEDURE FillRect*(x1, y1, x2, y2: INTEGER; color: Color);
  607. BEGIN
  608. Al.draw_filled_rectangle(FLT(x1), FLT(y1),
  609. FLT(x2 + 1), FLT(y2 + 1), SYSTEM.VAL(Al.Color, color))
  610. END FillRect;
  611. PROCEDURE ThickRectF*(x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
  612. BEGIN Al.draw_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), thickness)
  613. END ThickRectF;
  614. PROCEDURE ThickRect*(x1, y1, x2, y2: INTEGER; color: Color;
  615. thickness: INTEGER);
  616. BEGIN
  617. Al.draw_rectangle(FLT(x1) + 0.5, FLT(y1) + 0.5,
  618. FLT(x2) + 0.5, FLT(y2) + 0.5, SYSTEM.VAL(Al.Color, color), FLT(thickness))
  619. END ThickRect;
  620. PROCEDURE RectF*(x1, y1, x2, y2: REAL; color: Color);
  621. BEGIN Al.draw_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), 1.0)
  622. END RectF;
  623. PROCEDURE Rect*(x1, y1, x2, y2: INTEGER; color: Color);
  624. BEGIN
  625. Al.draw_rectangle(FLT(x1) + 0.5, FLT(y1) + 0.5,
  626. FLT(x2) + 0.5, FLT(y2) + 0.5, SYSTEM.VAL(Al.Color, color), 1.0)
  627. END Rect;
  628. PROCEDURE CircleF*(x, y, r: REAL; color: Color);
  629. BEGIN
  630. Al.draw_circle(x, y, r, SYSTEM.VAL(Al.Color, color), 1.0)
  631. END CircleF;
  632. PROCEDURE Circle*(x, y, r: INTEGER; color: Color);
  633. BEGIN
  634. Al.draw_circle(FLT(x) + 0.5, FLT(y) + 0.5, FLT(r),
  635. SYSTEM.VAL(Al.Color, color), 1.0)
  636. END Circle;
  637. PROCEDURE ThickCircleF*(x, y, r: REAL; color: Color; thickness: REAL);
  638. BEGIN
  639. Al.draw_circle(x, y, r, SYSTEM.VAL(Al.Color, color), thickness)
  640. END ThickCircleF;
  641. PROCEDURE ThickCircle*(x, y, r: INTEGER; color: Color; thickness: INTEGER);
  642. BEGIN
  643. Al.draw_circle(FLT(x) + 0.5, FLT(y) + 0.5, FLT(r),
  644. SYSTEM.VAL(Al.Color, color), FLT(thickness))
  645. END ThickCircle;
  646. PROCEDURE FillCircleF*(x, y, r: REAL; color: Color);
  647. BEGIN
  648. Al.draw_filled_circle(x, y, r, SYSTEM.VAL(Al.Color, color))
  649. END FillCircleF;
  650. PROCEDURE FillCircle*(x, y, r: INTEGER; color: Color);
  651. BEGIN
  652. Al.draw_filled_circle(FLT(x) + 0.5, FLT(y) + 0.5, FLT(r),
  653. SYSTEM.VAL(Al.Color, color))
  654. END FillCircle;
  655. PROCEDURE NewBitmap*(w, h: INTEGER): Bitmap;
  656. VAR b: Bitmap;
  657. BEGIN NEW(b);
  658. Al.set_new_bitmap_flags({Al.convertBitmap});
  659. b.bmp := Al.create_bitmap(w, h);
  660. IF b.bmp = NIL THEN b := NIL ELSE b.w := w; b.h := h END
  661. RETURN b END NewBitmap;
  662. PROCEDURE DrawPartFlip*(bmp: Bitmap; sx, sy, sw, sh, dx, dy: INTEGER;
  663. flags: SET);
  664. BEGIN
  665. Al.draw_bitmap_region(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
  666. FLT(dx), FLT(dy), flags)
  667. END DrawPartFlip;
  668. PROCEDURE DrawPart*(bmp: Bitmap; sx, sy, sw, sh, dx, dy: INTEGER);
  669. BEGIN
  670. Al.draw_bitmap_region(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
  671. FLT(dx), FLT(dy), {})
  672. END DrawPart;
  673. PROCEDURE DrawTintedPart*(bmp: Bitmap; color: Color;
  674. sx, sy, sw, sh, dx, dy: INTEGER);
  675. BEGIN
  676. IF ~Al.is_compatible_bitmap(bmp.bmp) THEN
  677. (*Error('Graph: NON-COMPAT');*)
  678. Al.convert_bitmap(bmp.bmp)
  679. END;
  680. Al.draw_tinted_bitmap_region(bmp.bmp, SYSTEM.VAL(Al.Color, color),
  681. FLT(sx), FLT(sy), FLT(sw), FLT(sh), FLT(dx), FLT(dy), {})
  682. END DrawTintedPart;
  683. PROCEDURE DrawFlip*(bmp: Bitmap; x, y: INTEGER; flip: SET);
  684. BEGIN Al.draw_bitmap(bmp.bmp, FLT(x), FLT(y), flip)
  685. END DrawFlip;
  686. PROCEDURE Draw*(bmp: Bitmap; x, y: INTEGER);
  687. BEGIN Al.draw_bitmap(bmp.bmp, FLT(x), FLT(y), {})
  688. END Draw;
  689. PROCEDURE DrawEx*(bmp: Bitmap; sx, sy, sw, sh, dx, dy, dw, dh: INTEGER;
  690. flip: SET);
  691. BEGIN
  692. Al.draw_scaled_bitmap(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
  693. FLT(dx), FLT(dy), FLT(dw), FLT(dh), flip)
  694. END DrawEx;
  695. PROCEDURE DrawRotated*(bmp: Bitmap; cx, cy, dx, dy: INTEGER;
  696. angle: REAL; flip: SET);
  697. BEGIN
  698. Al.draw_rotated_bitmap(bmp.bmp, FLT(cx), FLT(cy),
  699. FLT(dx), FLT(dy), angle, flip)
  700. END DrawRotated;
  701. PROCEDURE DrawScaledRotated*(bmp: Bitmap; cx, cy, dx, dy: INTEGER;
  702. xScale, yScale, angle: REAL; flip: SET);
  703. BEGIN
  704. Al.draw_scaled_rotated_bitmap(bmp.bmp, FLT(cx), FLT(cy),
  705. FLT(dx), FLT(dy), xScale, yScale, angle, flip)
  706. END DrawScaledRotated;
  707. PROCEDURE GetClip*(VAR x, y, w, h: INTEGER);
  708. BEGIN Al.get_clipping_rectangle(x, y, w, h)
  709. END GetClip;
  710. PROCEDURE SetClip*(x, y, w, h: INTEGER);
  711. BEGIN Al.set_clipping_rectangle(x, y, w, h)
  712. END SetClip;
  713. PROCEDURE UnsetClip*;
  714. BEGIN Al.reset_clipping_rectangle
  715. END UnsetClip;
  716. PROCEDURE DelayF*(n: REAL);
  717. BEGIN Al.rest(n)
  718. END DelayF;
  719. PROCEDURE Delay*(n: INTEGER);
  720. BEGIN Al.rest(n / 1000)
  721. END Delay;
  722. PROCEDURE ConvertMemoryBitmaps*;
  723. BEGIN Al.convert_memory_bitmaps
  724. END ConvertMemoryBitmaps;
  725. PROCEDURE RecreateDisplay(W: Window; alterSize: BOOLEAN);
  726. VAR d: Al.Display;
  727. q: ARRAY 256 OF SHORTCHAR;
  728. opt: SET;
  729. n, x, y, w, h, dw, dh, nw, nh, sw, sh: INTEGER;
  730. nwf, nhf: REAL;
  731. isCurTarget: BOOLEAN;
  732. BEGIN isCurTarget := target = W;
  733. IF W.display # NIL THEN Al.destroy_display(W.display) END;
  734. W.rzoom := W.wantZoom;
  735. IF W.wantZoom = 1.0 THEN W.zoom := noZoom
  736. ELSIF FLOOR(W.wantZoom + 0.001) * 100 = FLOOR(W.wantZoom * 100 + 0.001) THEN
  737. W.zoom := intZoom; W.izoom := FLOOR(W.wantZoom + 0.001)
  738. ELSE W.zoom := realZoom
  739. END;
  740. Utf8.Encode(W.title, q); Al.set_new_window_title(q);
  741. IF software IN W.options THEN n := 0 ELSE n := 1 END;
  742. Al.set_new_display_option(Al.renderMethod, n, Al.suggest);
  743. Al.set_new_display_option(Al.vsync, 2(*off*), Al.suggest);
  744. (*Al.set_new_display_option(Al.singleBuffer, 1, Al.suggest);*)
  745. IF smooth IN W.options THEN n := 1;
  746. Al.set_new_display_option(Al.samples, 8, Al.suggest)
  747. ELSE n := 0
  748. END;
  749. (* Al.set_new_display_option(Al.sampleBuffers, n, Al.suggest); *)
  750. GetDesktopResolution(dw, dh);
  751. dw := FLOOR(FLT(dw) / wantScaleX + 0.1);
  752. dh := FLOOR(FLT(dh) / wantScaleY + 0.1);
  753. W.scaleOn := (wantScaleX # 1.0) OR (wantScaleY # 1.0);
  754. W.scaleX := wantScaleX; W.scaleY := wantScaleY;
  755. IF fullscreen IN W.options THEN w := W.fsW; h := W.fsH
  756. ELSE w := W.initW; h := W.initH
  757. END;
  758. IF (w < 0) OR (h < 0) THEN
  759. IF fullscreen IN W.options THEN
  760. w := FLOOR(dw / W.wantZoom + 0.1); h := FLOOR(dh / W.wantZoom + 0.1);
  761. ApplySizeStep(W, w, h);
  762. sw := FLOOR(w * W.wantZoom + 0.1); sh := FLOOR(h * W.wantZoom + 0.1)
  763. ELSE w := 640; h := 400; W.zoom := noZoom;
  764. ApplySizeStep(W, w, h); sw := w; sh := h
  765. END
  766. ELSIF fullscreen IN W.options THEN
  767. IF smooth IN W.options THEN nwf := dw / w; nhf := dh / h;
  768. IF nhf < nwf THEN nwf := nhf END;
  769. W.zoom := realZoom; W.rzoom := nwf;
  770. IF exact IN W.options THEN
  771. sw := FLOOR(w * nwf + 0.1); sh := FLOOR(h * nwf + 0.1)
  772. ELSE sw := dw; sh := dh
  773. END
  774. ELSE nw := dw DIV w; nh := dh DIV h;
  775. IF nh < nw THEN nw := nh END;
  776. W.zoom := intZoom; W.izoom := nw; W.rzoom := FLT(nw);
  777. IF exact IN W.options THEN sw := w * nw; sh := h * nw
  778. ELSE sw := dw DIV nw * nw; sh := dh DIV nw * nw
  779. END
  780. END;
  781. IF W.zoom = realZoom THEN
  782. w := FLOOR(sw / W.rzoom + 0.1); h := FLOOR(sh / W.rzoom + 0.1)
  783. ELSIF W.zoom = intZoom THEN w := sw DIV W.izoom; h := sh DIV W.izoom
  784. ELSE w := sw; h := sh
  785. END;
  786. ApplySizeStep(W, w, h); sw := w; sh := h;
  787. IF alterSize THEN W.initW := w; W.initH := h END
  788. ELSE ApplySizeStep(W, w, h);
  789. sw := FLOOR(w * W.wantZoom * W.scaleX + 0.999);
  790. sh := FLOOR(h * W.wantZoom * W.scaleY + 0.999)
  791. END;
  792. W.lastW := 0; W.lastH := 0;
  793. IF center IN W.options THEN GetDesktopResolution(dw, dh);
  794. x := (dw - sw) DIV 2; y := (dh - sh) DIV 2;
  795. IF x < 0 THEN x := 0 END; IF y < 0 THEN y := 0 END
  796. ELSIF (W.initX < 0) OR (W.initY < 0) THEN x := Al.intMax; y := Al.intMax
  797. ELSE x := W.initX; y := W.initY
  798. END;
  799. Al.set_new_window_position(x, y);
  800. opt := {};
  801. IF fullscreen IN W.options THEN INCL(opt, Al.fullscreenWindow)
  802. ELSE INCL(opt, Al.windowed)
  803. END;
  804. IF resizable IN W.options THEN INCL(opt, Al.resizable) END;
  805. IF maximized IN W.options THEN INCL(opt, Al.maximized) END;
  806. IF minimized IN W.options THEN INCL(opt, Al.minimized) END;
  807. IF frameless IN W.options THEN INCL(opt, Al.frameless) END;
  808. Al.set_new_display_flags(opt);
  809. IF W.bmp # NIL THEN Al.destroy_bitmap(W.bmp); W.bmp := NIL END;
  810. W.display := Al.create_display(sw, sh);
  811. IF W.display # NIL THEN
  812. (*IF isCurTarget OR (windowList = NIL) OR (windowList.next = NIL) THEN
  813. Al.set_target_backbuffer(W.display);
  814. ConvertMemoryBitmaps;
  815. END;*)
  816. W.winW := Al.get_display_width(W.display);
  817. W.winH := Al.get_display_height(W.display);
  818. W.w := w; W.h := h;
  819. ApplySizeStep(W, w, h);
  820. W.lastW := W.w; W.lastH := W.h;
  821. ResetWindowBitmap(W);
  822. Al.register_event_source(queue, Al.get_display_event_source(W.display));
  823. IF isCurTarget THEN Target(W) END;
  824. IF ~W.showMouse THEN ShowWindowMouse(W, FALSE) END;
  825. IF W.noficons > 0 THEN
  826. Al.set_display_icons(W.display, W.noficons, W.icons)
  827. END
  828. END
  829. END RecreateDisplay;
  830. PROCEDURE NewWindow*(x, y, w, h: INTEGER; title: ARRAY OF CHAR;
  831. options: SET): Window;
  832. VAR W: Window;
  833. d: Al.Display;
  834. q: ARRAY 256 OF SHORTCHAR;
  835. opt: SET;
  836. i, n, dw, dh, nw, nh, sw, sh: INTEGER;
  837. nwf, nhf: REAL;
  838. BEGIN NEW(W); W.lastX := -1; W.lastY := -1; W.resized := FALSE;
  839. W.sizeStepX := wantSizeStepX; W.sizeStepY := wantSizeStepY;
  840. IF {fullscreen, window} * options = {} THEN INCL(options, window)
  841. ELSIF window IN options THEN EXCL(options, fullscreen)
  842. END;
  843. W.options := options;
  844. W.pressedButtons := {};
  845. W.title := title;
  846. W.wantZoom := wantZoom;
  847. W.scaleOn := (wantScaleX # 1.0) OR (wantScaleY # 1.0);
  848. W.scaleX := wantScaleX; W.scaleY := wantScaleY;
  849. W.initX := x; W.initY := y; W.initW := w; W.initH := h;
  850. W.fsW := w; W.fsH := h;
  851. W.showMouse := TRUE;
  852. FOR i := 0 TO LEN(W.icons) - 1 DO W.icons[i] := NIL END;
  853. W.noficons := 0;
  854. W.display := NIL; RecreateDisplay(W, TRUE);
  855. IF W.display # NIL THEN W.next := windowList; windowList := W
  856. ELSE Error('Could not create dispaly.'); W := NIL
  857. END;
  858. IF (screen = NIL) & (W # NIL) THEN screen := W; Target(screen) END
  859. RETURN W END NewWindow;
  860. PROCEDURE CloseWindow*(W: Window);
  861. BEGIN Al.destroy_display(W.display)
  862. END CloseWindow;
  863. PROCEDURE NewTimer*(speed: REAL): Timer;
  864. VAR T: Timer;
  865. BEGIN NEW(T); T.tmr := Al.create_timer(speed);
  866. IF T.tmr # NIL THEN
  867. Al.register_event_source(queue, Al.get_timer_event_source(T.tmr));
  868. T.next := timerList; timerList := T
  869. ELSE T := NIL
  870. END;
  871. RETURN T END NewTimer;
  872. PROCEDURE GetWindow(d: Al.Display): Window;
  873. VAR W: Window;
  874. BEGIN W := windowList;
  875. WHILE (W # NIL) & (W.display # d) DO W := W.next END
  876. RETURN W END GetWindow;
  877. PROCEDURE GetTimer(a: Al.Timer): Timer;
  878. VAR t: Timer;
  879. BEGIN t := timerList;
  880. WHILE (t # NIL) & (t.tmr # a) DO t := t.next END
  881. RETURN t END GetTimer;
  882. PROCEDURE EmitResizeEvent(W: Window);
  883. VAR E: Al.UserEvent;
  884. BEGIN
  885. E.type := eventUserResize;
  886. E.data4 := SYSTEM.VAL(ADRINT, W.display);
  887. IF Al.emit_user_event(userEventSource, SYSTEM.VAL(Al.Event, E), 0) THEN END
  888. END EmitResizeEvent;
  889. PROCEDURE ToggleFS*(win: Window);
  890. VAR fs: BOOLEAN;
  891. w, h: REAL;
  892. BEGIN
  893. IF (win = NIL) & (screen # NIL) THEN win := screen END;
  894. IF (win # NIL) & (win.display # NIL) THEN
  895. fs := ~(Al.windowed IN Al.get_display_flags(win.display));
  896. IF fs THEN EXCL(win.options, fullscreen); INCL(win.options, window)
  897. ELSE INCL(win.options, fullscreen); EXCL(win.options, window);
  898. w := Al.get_display_width(win.display) / win.rzoom;
  899. h := Al.get_display_height(win.display) / win.rzoom;
  900. IF win.scaleOn THEN w := w / win.scaleX; h := h / win.scaleY END;
  901. win.initW := FLOOR(w + 0.1); win.initH := FLOOR(h + 0.1);
  902. EXCL(win.options, center);
  903. Al.get_window_position(win.display, win.initX, win.initY);
  904. ApplySizeStep(win, win.initW, win.initH)
  905. END;
  906. win.scaleX := wantScaleX;
  907. win.scaleY := wantScaleY;
  908. RecreateDisplay(win, FALSE);
  909. EmitResizeEvent(win)
  910. END
  911. END ToggleFS;
  912. PROCEDURE SwitchToWindow*(win: Window);
  913. BEGIN IF ~(window IN GetWindowOptions(screen)) THEN ToggleFS(win) END
  914. END SwitchToWindow;
  915. PROCEDURE SwitchToFS*(win: Window);
  916. BEGIN IF window IN GetWindowOptions(screen) THEN ToggleFS(win) END
  917. END SwitchToFS;
  918. PROCEDURE ParseEvent(E: Al.Event; peek: BOOLEAN; VAR event: Event);
  919. VAR DE: Al.PDisplayEvent;
  920. TE: Al.PTimerEvent;
  921. KE: Al.PKeyboardEvent;
  922. ME: Al.PMouseEvent;
  923. UE: Al.PUserEvent;
  924. W: Window;
  925. d: Al.Display;
  926. x, y, w, h: INTEGER;
  927. fw, fh: REAL;
  928. BEGIN
  929. event.time := E.timestamp;
  930. IF E.type = Al.eventMouseAxes THEN
  931. ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
  932. W := GetWindow(ME.display);
  933. IF W.zoom = noZoom THEN x := ME.x - W.iFlipX; y := ME.y - W.iFlipY
  934. ELSIF W.zoom = intZoom THEN
  935. x := (ME.x - W.iFlipX) DIV W.izoom; y := (ME.y - W.iFlipY) DIV W.izoom
  936. ELSE x := FLOOR((ME.x - W.flipX) / W.rzoom + 0.1);
  937. y := FLOOR((ME.y - W.flipY) / W.rzoom + 0.1)
  938. END;
  939. IF W.scaleOn THEN
  940. x := FLOOR(x / W.scaleX + 0.1); y := FLOOR(y / W.scaleY + 0.1)
  941. END;
  942. IF (x # W.lastX) OR (y # W.lastY) OR (ME.dz # 0) OR (ME.dw # 0) THEN
  943. IF (ME.dz # 0) OR (ME.dw # 0) THEN event.type := mouseWheel;
  944. event.dz := ME.dz; event.dw := ME.dw;
  945. event.x := W.lastX; event.y := W.lastY;
  946. event.z := ME.z; event.w := ME.w;
  947. event.dx := 0; event.dy := 0
  948. ELSE event.type := mouseMove;
  949. IF x = -1 THEN event.dx := 0; event.dy := 0
  950. ELSE event.dx := x - W.lastX; event.dy := y - W.lastY
  951. END;
  952. event.buttons := W.pressedButtons;
  953. event.x := x; event.y := y;
  954. IF ~peek THEN W.lastX := event.x; W.lastY := event.y END
  955. END;
  956. event.button := ME.button; (*!FIXME does ME.button work in Allegro 5 MouseAxes? *)
  957. event.buttons := W.pressedButtons;
  958. event.mod := {};
  959. event.display := ME.display; event.window := W
  960. ELSE event.type := noEvent
  961. END
  962. ELSIF E.type = Al.eventMouseButtonDown THEN
  963. event.type := mouseDown;
  964. ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
  965. W := GetWindow(ME.display); event.window := W;
  966. IF W.zoom = noZoom THEN x := ME.x - W.iFlipX; y := ME.y - W.iFlipY
  967. ELSIF W.zoom = intZoom THEN
  968. x := (ME.x - W.iFlipX) DIV W.izoom; y := (ME.y - W.iFlipY) DIV W.izoom
  969. ELSE x := FLOOR((ME.x - W.flipX) / W.rzoom + 0.1);
  970. y := FLOOR((ME.y - W.flipY) / W.rzoom + 0.1)
  971. END;
  972. IF W.scaleOn THEN
  973. x := FLOOR(x / W.scaleX + 0.1); y := FLOOR(y / W.scaleY + 0.1)
  974. END;
  975. event.x := x; event.y := y;
  976. event.z := ME.z; event.w := ME.w;
  977. event.button := ME.button;
  978. INCL(W.pressedButtons, event.button);
  979. event.mod := {};
  980. event.display := ME.display
  981. ELSIF E.type = Al.eventMouseButtonUp THEN
  982. event.type := mouseUp;
  983. ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
  984. W := GetWindow(ME.display); event.window := W;
  985. IF W.zoom = noZoom THEN x := ME.x - W.iFlipX; y := ME.y - W.iFlipY
  986. ELSIF W.zoom = intZoom THEN
  987. x := (ME.x - W.iFlipX) DIV W.izoom; y := (ME.y - W.iFlipY) DIV W.izoom
  988. ELSE x := FLOOR((ME.x - W.flipX) / W.rzoom + 0.1);
  989. y := FLOOR((ME.y - W.flipY) / W.rzoom + 0.1)
  990. END;
  991. IF W.scaleOn THEN
  992. x := FLOOR(x / W.scaleX + 0.1); y := FLOOR(y / W.scaleY + 0.1)
  993. END;
  994. event.x := x; event.y := y;
  995. event.z := ME.z; event.w := ME.w;
  996. event.button := ME.button;
  997. EXCL(W.pressedButtons, event.button);
  998. event.mod := {};
  999. event.display := ME.display
  1000. ELSIF E.type = Al.eventTimer THEN
  1001. event.type := timer;
  1002. TE := SYSTEM.VAL(Al.PTimerEvent, SYSTEM.ADR(E));
  1003. event.count := TE.count;
  1004. event.timer := GetTimer(SYSTEM.VAL(Al.Timer, TE.source))
  1005. ELSIF E.type = Al.eventKeyDown THEN
  1006. event.type := keyDown;
  1007. KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
  1008. event.key := KE.keycode;
  1009. event.mod := {};
  1010. event.display := KE.display;
  1011. event.window := GetWindow(event.display)
  1012. ELSIF E.type = Al.eventKeyUp THEN
  1013. event.type := keyUp;
  1014. KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
  1015. event.key := KE.keycode;
  1016. event.mod := {};
  1017. event.display := KE.display;
  1018. event.window := GetWindow(event.display)
  1019. ELSIF E.type = Al.eventKeyChar THEN
  1020. KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
  1021. event.type := char;
  1022. event.key := KE.keycode;
  1023. event.ch := CHR(KE.unichar);
  1024. event.mod := KE.modifiers;
  1025. event.repeat := KE.repeat;
  1026. event.display := KE.display;
  1027. event.window := GetWindow(event.display)
  1028. ELSIF (E.type = Al.eventDisplayResize) OR (E.type = eventUserResize) THEN
  1029. IF E.type = Al.eventDisplayResize THEN
  1030. DE := SYSTEM.VAL(Al.PDisplayEvent, SYSTEM.ADR(E));
  1031. d := DE.source; W := GetWindow(d);
  1032. IF ~peek THEN W.winW := DE.width; W.winH := DE.height END
  1033. ELSE UE := SYSTEM.VAL(Al.PUserEvent, SYSTEM.ADR(E));
  1034. d := SYSTEM.VAL(Al.Display, UE.data4); W := GetWindow(d);
  1035. IF ~peek THEN
  1036. W.winW := Al.get_display_width(d); W.winH := Al.get_display_height(d)
  1037. END
  1038. END;
  1039. fw := W.winW / W.rzoom; fh := W.winH / W.rzoom;
  1040. IF W.scaleOn THEN fw := fw / W.scaleX; fh := fh / W.scaleY END;
  1041. w := FLOOR(fw + 0.1); h := FLOOR(fh + 0.1);
  1042. IF E.type = Al.eventDisplayResize THEN
  1043. Al.acknowledge_resize(d);
  1044. ApplySizeStep(W, w, h)
  1045. END;
  1046. IF (w # W.lastW) OR (h # W.lastH) THEN
  1047. IF ~peek THEN W.lastW := w; W.lastH := h END;
  1048. event.type := resize; event.window := W; event.display := d;
  1049. event.w := w; event.h := h;
  1050. IF E.type = Al.eventDisplayResize THEN event.x := DE.x; event.y := DE.y
  1051. ELSE Al.get_window_position(d, event.x, event.y)
  1052. END;
  1053. IF ~peek THEN ResetWindowBitmap(W) END
  1054. ELSE ResetFlipVars(W); Flip; event.type := noEvent
  1055. END
  1056. ELSIF E.type = Al.eventDisplayClose THEN
  1057. event.type := quit;
  1058. event.display := SYSTEM.VAL(Al.Display, E.source);
  1059. event.window := GetWindow(event.display)
  1060. ELSE event.type := noEvent
  1061. END
  1062. END ParseEvent;
  1063. PROCEDURE WaitAndParseEvent(VAR event: Event);
  1064. VAR E: Al.Event;
  1065. BEGIN
  1066. Al.wait_for_event(queue, E);
  1067. ParseEvent(E, FALSE, event)
  1068. END WaitAndParseEvent;
  1069. PROCEDURE PeekAndParseEvent(VAR event: Event): BOOLEAN;
  1070. VAR E: Al.Event;
  1071. got: BOOLEAN;
  1072. BEGIN
  1073. got := Al.peek_next_event(queue, E);
  1074. IF got THEN ParseEvent(E, TRUE, event) END
  1075. RETURN got END PeekAndParseEvent;
  1076. PROCEDURE WaitEvent*(VAR event: Event);
  1077. BEGIN REPEAT WaitAndParseEvent(event) UNTIL event.type # noEvent
  1078. END WaitEvent;
  1079. PROCEDURE PeekEvent*(VAR event: Event): BOOLEAN;
  1080. VAR got: BOOLEAN;
  1081. BEGIN
  1082. got := PeekAndParseEvent(event);
  1083. WHILE got & (event.type = noEvent) DO
  1084. IF Al.drop_next_event(queue) THEN END;
  1085. got := PeekAndParseEvent(event)
  1086. END
  1087. RETURN got END PeekEvent;
  1088. PROCEDURE HasEvents*(): BOOLEAN;
  1089. VAR e: Event;
  1090. RETURN PeekEvent(e) END HasEvents;
  1091. PROCEDURE WaitAndParseKeyEvent;
  1092. VAR e: Event;
  1093. BEGIN WaitEvent(e);
  1094. IF e.type = char THEN charRead := e.ch; specialChar := FALSE
  1095. ELSIF (e.type = keyDown) &
  1096. ((kF1 <= e.key) & (e.key <= kF12) OR
  1097. (kHome <= e.key) & (e.key <= kDown) OR
  1098. (e.key = kInsert) OR (e.key = kPause))
  1099. THEN charRead := CHR(e.key); specialChar := TRUE
  1100. END
  1101. END WaitAndParseKeyEvent;
  1102. PROCEDURE KeyPressed*(): BOOLEAN;
  1103. BEGIN
  1104. WHILE ~specialChar & (charRead = 0X) & HasEvents() DO WaitAndParseKeyEvent END
  1105. RETURN specialChar OR (charRead # 0X) END KeyPressed;
  1106. PROCEDURE ReadKey*(): CHAR;
  1107. VAR c: CHAR;
  1108. BEGIN
  1109. WHILE ~specialChar & (charRead = 0X) DO WaitAndParseKeyEvent END;
  1110. IF specialChar THEN c := 0X; specialChar := FALSE
  1111. ELSE c := charRead; charRead := 0X
  1112. END
  1113. RETURN c END ReadKey;
  1114. PROCEDURE Pause*;
  1115. BEGIN
  1116. IF KeyPressed() THEN
  1117. IF ReadKey() = 0X THEN END
  1118. END;
  1119. IF ReadKey() = 0X THEN END
  1120. END Pause;
  1121. PROCEDURE DropNextEvent*;
  1122. VAR e: Event;
  1123. BEGIN (*WaitEvent(e)*)
  1124. IF Al.drop_next_event(queue) THEN END
  1125. END DropNextEvent;
  1126. PROCEDURE StartTimer*(timer: Timer);
  1127. BEGIN Al.start_timer(timer.tmr)
  1128. END StartTimer;
  1129. PROCEDURE StopTimer*(timer: Timer);
  1130. BEGIN Al.stop_timer(timer.tmr)
  1131. END StopTimer;
  1132. PROCEDURE ResumeTimer*(timer: Timer);
  1133. BEGIN Al.resume_timer(timer.tmr)
  1134. END ResumeTimer;
  1135. (* Font *)
  1136. PROCEDURE GetMonoFontSize*(font: Font; VAR charW, charH: INTEGER);
  1137. BEGIN charW := font(MonoFont).charW; charH := font(MonoFont).charH
  1138. END GetMonoFontSize;
  1139. PROCEDURE FindFontChar(font: Font; c: CHAR; VAR bmp: Bitmap;
  1140. VAR x, y, w, h: INTEGER);
  1141. VAR n: INTEGER;
  1142. m: MonoFont;
  1143. BEGIN m := font(MonoFont);
  1144. IF c < 200X THEN n := ORD(c)
  1145. ELSIF (400X <= c) & (c < 500X) THEN n := ORD(c) + (300H - 400H)
  1146. ELSIF (2500X <= c) & (c < 2600X) THEN n := ORD(c) + (200H - 2500H)
  1147. ELSE n := -1
  1148. END;
  1149. IF n < 0 THEN n := 1 (* "Bad" character *) END;
  1150. bmp := m.bmp;
  1151. x := n MOD m.cols * m.charW; y := n DIV m.cols * m.charH;
  1152. w := m.charW; h := m.charH
  1153. END FindFontChar;
  1154. PROCEDURE DrawCharEx*(ch: CHAR; x, y: INTEGER; font: Font; color: Color;
  1155. VAR w: INTEGER);
  1156. VAR sx, sy, h: INTEGER;
  1157. bmp: Bitmap;
  1158. BEGIN FindFontChar(font, ch, bmp, sx, sy, w, h);
  1159. DrawTintedPart(bmp, color, sx, sy, w, h, x, y)
  1160. END DrawCharEx;
  1161. PROCEDURE DrawChar*(ch: CHAR; x, y: INTEGER; font: Font; color: Color);
  1162. VAR w: INTEGER;
  1163. BEGIN DrawCharEx(ch, x, y, font, color, w)
  1164. END DrawChar;
  1165. PROCEDURE DrawString*(s: ARRAY OF CHAR; x, y: INTEGER;
  1166. font: Font; color: Color);
  1167. VAR i, cx, cy, charW, destW, destH: INTEGER;
  1168. m: MonoFont;
  1169. BEGIN m := font(MonoFont); i := 0; cx := x; cy := y;
  1170. GetTargetSize(destW, destH);
  1171. WHILE (s[i] # 0X) & (cx < destW) & (cy < destH) DO
  1172. IF s[i] = 0AX THEN cx := x; INC(cy, m.charH)
  1173. ELSE DrawCharEx(s[i], cx, cy, font, color, charW);
  1174. INC(i); INC(cx, charW)
  1175. END
  1176. END
  1177. END DrawString;
  1178. PROCEDURE MonoFontDraw(f: Font; VAR msg: FontDrawMsg);
  1179. VAR m: MonoFont;
  1180. BEGIN m := f(MonoFont);
  1181. (*!TODO*)
  1182. END MonoFontDraw;
  1183. PROCEDURE MonoFontHandle(f: Font; VAR msg: FontMessage);
  1184. VAR m: MonoFont;
  1185. BEGIN m := f(MonoFont)
  1186. (*!TODO*)
  1187. END MonoFontHandle;
  1188. PROCEDURE ReadWord(VAR r: Files.Rider; VAR s: ARRAY OF CHAR);
  1189. VAR ch: CHAR;
  1190. i: INTEGER;
  1191. BEGIN
  1192. Files.ReadChar(r, ch);
  1193. WHILE ~r.eof & (ch <= ' ') DO Files.ReadChar(r, ch) END;
  1194. i := 0;
  1195. WHILE ~r.eof & (ch > ' ') DO
  1196. IF (i # LEN(s) - 1) THEN s[i] := ch; INC(i) END;
  1197. Files.ReadChar(r, ch)
  1198. END;
  1199. s[i] := 0X
  1200. END ReadWord;
  1201. PROCEDURE ReadInt(VAR r: Files.Rider; VAR n: INTEGER);
  1202. VAR ch: CHAR;
  1203. i: INTEGER;
  1204. BEGIN
  1205. Files.ReadChar(r, ch);
  1206. WHILE ~r.eof & (ch <= ' ') DO Files.ReadChar(r, ch) END;
  1207. n := 0;
  1208. WHILE ~r.eof & ('0' <= ch) & (ch <= '9') DO
  1209. n := n * 10 + ORD(ch) - ORD('0');
  1210. Files.ReadChar(r, ch)
  1211. END
  1212. END ReadInt;
  1213. PROCEDURE ReadFontInfo(VAR r: Files.Rider): Font;
  1214. VAR f: Font;
  1215. mf: MonoFont;
  1216. s: ARRAY 4096 OF CHAR;
  1217. BEGIN f := NIL;
  1218. ReadWord(r, s);
  1219. IF s = 'mono' THEN
  1220. NEW(mf); mf.bmp := NIL;
  1221. ReadInt(r, mf.charW); ReadInt(r, mf.charH);
  1222. IF (mf.charW > 0) & (mf.charH > 0) THEN
  1223. mf.cols := 16; mf.rows := 16 * fontPlanes
  1224. ELSE mf := NIL
  1225. END;
  1226. f := mf
  1227. END
  1228. RETURN f END ReadFontInfo;
  1229. PROCEDURE LoadFontInfo*(fname: ARRAY OF CHAR): Font;
  1230. VAR f: Font;
  1231. F: Files.File;
  1232. r: Files.Rider;
  1233. s: ARRAY 4096 OF CHAR;
  1234. BEGIN f := NIL;
  1235. s := fname; Strings.Append('.ofi', s);
  1236. F := Files.Old(s);
  1237. IF F # NIL THEN
  1238. s := fname; Strings.Append('.png', s);
  1239. IF Dir.FileExists(s) THEN
  1240. Files.Set(r, F, 0);
  1241. f := ReadFontInfo(r);
  1242. IF f # NIL THEN
  1243. f.loaded := FALSE;
  1244. f.fname := fname;
  1245. f.draw := MonoFontDraw;
  1246. f.handle := MonoFontHandle
  1247. END
  1248. END
  1249. END
  1250. RETURN f END LoadFontInfo;
  1251. PROCEDURE LoadFontBitmap*(f: Font);
  1252. VAR s: ARRAY 4096 OF CHAR;
  1253. BEGIN
  1254. s := ''; Strings.Append(f.fname, s); Strings.Append('.png', s);
  1255. f(MonoFont).bmp := LoadBitmap(s);
  1256. IF f(MonoFont).bmp # NIL THEN f.loaded := TRUE END
  1257. END LoadFontBitmap;
  1258. PROCEDURE LoadFont*(fname: ARRAY OF CHAR): Font;
  1259. VAR f: Font;
  1260. BEGIN f := LoadFontInfo(fname);
  1261. IF f # NIL THEN LoadFontBitmap(f) END
  1262. RETURN f END LoadFont;
  1263. (** Clipboard **)
  1264. PROCEDURE GetClipboardText*(win: Window; VAR s: ARRAY OF CHAR);
  1265. TYPE P = POINTER [1] TO ARRAY 50000 OF SHORTCHAR;
  1266. VAR a: Al.ADRINT; p: P;
  1267. i: INTEGER;
  1268. BEGIN
  1269. a := Al.get_clipboard_text(win.display);
  1270. IF ~Platform.Windows THEN (* Workaround for an Allegro bug on X11 *)
  1271. FOR i := 1 TO 6 DO (* Maybe "TO 1" is enough *)
  1272. Al.free_with_context(a, 1429, 'Graph.Mod', 'GetClipboardText');
  1273. Delay(1);
  1274. a := Al.get_clipboard_text(win.display)
  1275. END
  1276. END;
  1277. IF a # 0 THEN p := SYSTEM.VAL(P, a); Utf8.Decode(p^, s);
  1278. Al.free_with_context(a, 1434, 'Graph.Mod', 'GetClipboardText')
  1279. ELSE s[0] := 0X
  1280. END
  1281. END GetClipboardText;
  1282. PROCEDURE SetClipboardText*(win: Window; s: ARRAY OF CHAR);
  1283. TYPE P = POINTER [1] TO ARRAY 50000 OF SHORTCHAR;
  1284. VAR q: ARRAY 200000 OF SHORTCHAR;
  1285. BEGIN
  1286. Utf8.Encode(s, q);
  1287. IF Al.set_clipboard_text(win.display, SYSTEM.VAL(Al.ADRINT, SYSTEM.ADR(q)))
  1288. THEN END
  1289. END SetClipboardText;
  1290. (** Time **)
  1291. PROCEDURE Time*(): REAL;
  1292. RETURN Al.get_time() END Time;
  1293. (** Window Icons **)
  1294. PROCEDURE SetWindowIconsEx*(win: Window; icons: ARRAY OF Bitmap;
  1295. from, len: INTEGER);
  1296. VAR m: ARRAY 64 OF Al.Bitmap;
  1297. i: INTEGER;
  1298. BEGIN
  1299. FOR i := 0 TO len - 1 DO m[i] := icons[from + i].bmp END;
  1300. FOR i := 0 TO len - 1 DO win.icons[i] := m[i] END;
  1301. win.noficons := len;
  1302. Al.set_display_icons(win.display, len, m)
  1303. END SetWindowIconsEx;
  1304. PROCEDURE SetWindowIcons*(win: Window; icons: ARRAY OF Bitmap);
  1305. BEGIN SetWindowIconsEx(win, icons, 0, LEN(icons))
  1306. END SetWindowIcons;
  1307. PROCEDURE SetWindowIcon*(win: Window; icon: Bitmap);
  1308. VAR i: INTEGER;
  1309. BEGIN
  1310. FOR i := 1 TO LEN(win.icons) - 1 DO win.icons[i] := NIL END;
  1311. win.icons[0] := icon.bmp; win.noficons := 1;
  1312. Al.set_display_icon(win.display, icon.bmp)
  1313. END SetWindowIcon;
  1314. (** Init **)
  1315. PROCEDURE InitScreen(): BOOLEAN;
  1316. VAR opt: SET;
  1317. BEGIN
  1318. opt := settings;
  1319. IF {fullscreen, window} * opt = {} THEN INCL(opt, fullscreen)
  1320. ELSIF fullscreen IN opt THEN EXCL(opt, window)
  1321. END;
  1322. IF (wantW <= 0) OR (wantH <= 0) THEN
  1323. IF fullscreen IN opt THEN wantW := -1; wantH := -1
  1324. ELSE wantW := 640; wantH := 400
  1325. END
  1326. END
  1327. RETURN NewWindow(-1, -1, wantW, wantH, wantTitle, opt) # NIL END InitScreen;
  1328. PROCEDURE Init*;
  1329. VAR ok: BOOLEAN;
  1330. BEGIN ok := TRUE;
  1331. IF Al.install_system(Al.get_allegro_version(), 0) THEN
  1332. IF ~Al.install_keyboard() THEN
  1333. Error('Could not install keyboard.'); ok := FALSE
  1334. END;
  1335. IF ~(noMouse IN settings) & ~Al.install_mouse() THEN
  1336. Error('Could not install mouse.'); ok := FALSE
  1337. END;
  1338. IF ~Al.init_primitives_addon() THEN
  1339. Error('Could not init primitives addon.'); ok := FALSE
  1340. END;
  1341. IF ~Al.init_image_addon() THEN
  1342. Error('Could not init image addon.'); ok := FALSE
  1343. END;
  1344. queue := Al.create_event_queue();
  1345. IF queue = NIL THEN
  1346. Error('Could not create queue.'); ok := FALSE
  1347. END;
  1348. IF ok THEN
  1349. Al.init_user_event_source(userEventSource);
  1350. Al.register_event_source(queue,
  1351. SYSTEM.VAL(Al.PEventSource, SYSTEM.ADR(userEventSource)));
  1352. Al.register_event_source(queue, Al.get_keyboard_event_source());
  1353. IF ~(noMouse IN settings) THEN
  1354. Al.register_event_source(queue, Al.get_mouse_event_source())
  1355. END
  1356. END;
  1357. IF ~(manual IN settings) THEN
  1358. IF ~InitScreen() THEN ok := FALSE END
  1359. END
  1360. ELSE Error('Could not init Allegro.'); ok := FALSE
  1361. END;
  1362. charRead := 0X; specialChar := FALSE;
  1363. Done := ok
  1364. END Init;
  1365. PROCEDURE ResetDefaults;
  1366. BEGIN
  1367. wantW := 640; wantH := 400; wantSizeStepX := 1; wantSizeStepY := 1;
  1368. wantScaleX := 1.0; wantScaleY := 1.0; wantZoom := 1.0;
  1369. settings := {};
  1370. wantTitle := 'Oberon';
  1371. (* Reset global variables *)
  1372. queue := NIL; windowList := NIL; timerList := NIL;
  1373. screen := NIL; target := NIL
  1374. END ResetDefaults;
  1375. PROCEDURE Close*;
  1376. BEGIN
  1377. Al.uninstall_system;
  1378. ResetDefaults
  1379. END Close;
  1380. BEGIN Done := FALSE;
  1381. MakeCol(black, 0, 0, 0);
  1382. ResetDefaults
  1383. END Graph.