123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560 |
- MODULE Graph;
- IMPORT Out, Al := Allegro5, Utf8, Files, Dir, Strings, SYSTEM, Platform;
- CONST
- fontPlanes = 4; (*!TODO*)
- (** Settings set members **)
- manual* = 0;
- fullscreen* = 1;
- window* = 2;
- exact* = 3;
- smooth* = 4;
- software* = 5;
- noMouse* = 6;
- center* = 7;
- resizable* = 8;
- maximized* = 9;
- minimized* = 10;
- frameless* = 11;
- nobuffer* = 12;
- topleft* = 13;
- (** Event.type possible values **)
- noEvent = 0;
- quit* = 1;
- timer* = 2;
- windowEvent* = 3;
- keyDown* = 4;
- keyUp* = 5;
- char* = 6;
- mouseMove* = 7;
- mouseDown* = 8;
- mouseUp* = 9;
- mouseWheel* = 10;
- resize* = 11;
- eventUserResize = 2005;
- (** Window.zoom possible values **)
- noZoom = 0; (** The screen is not zoomed *)
- intZoom = 1; (** The zoom value is an integer: 2x, 3x etc. *)
- realZoom = 2; (** The zoom value is not an integer, i.e. 2.5x *)
- (** Flip flags for DrawFlip, DrawEx etc. **)
- flipHor* = 0;
- flipVert* = 1;
- (** Key Codes **)
- kA* = 1;
- kB* = 2;
- kC* = 3;
- kD* = 4;
- kE* = 5;
- kF* = 6;
- kG* = 7;
- kH* = 8;
- kI* = 9;
- kJ* = 10;
- kK* = 11;
- kL* = 12;
- kM* = 13;
- kN* = 14;
- kO* = 15;
- kP* = 16;
- kQ* = 17;
- kR* = 18;
- kS* = 19;
- kT* = 20;
- kU* = 21;
- kV* = 22;
- kW* = 23;
- kX* = 24;
- kY* = 25;
- kZ* = 26;
- k0* = 27;
- k1* = 28;
- k2* = 29;
- k3* = 30;
- k4* = 31;
- k5* = 32;
- k6* = 33;
- k7* = 34;
- k8* = 35;
- k9* = 36;
- k0Pad* = 37;
- k1Pad* = 38;
- k2Pad* = 39;
- k3Pad* = 40;
- k4Pad* = 41;
- k5Pad* = 42;
- k6Pad* = 43;
- k7Pad* = 44;
- k8Pad* = 45;
- k9Pad* = 46;
- kF1* = 47;
- kF2* = 48;
- kF3* = 49;
- kF4* = 50;
- kF5* = 51;
- kF6* = 52;
- kF7* = 53;
- kF8* = 54;
- kF9* = 55;
- kF10* = 56;
- kF11* = 57;
- kF12* = 58;
- kEsc* = 59;
- kTilde* = 60;
- kMinus* = 61;
- kEquals* = 62;
- kBackspace* = 63;
- kTab* = 64;
- kOpenBrace* = 65;
- kCloseBrace* = 66;
- kEnter* = 67;
- kColon* = 68;
- kQuote* = 69;
- kBackslash* = 70;
- kBackslash2* = 71;
- kComma* = 72;
- kStop* = 73;
- kSlash* = 74;
- kSpace* = 75;
- kInsert* = 76;
- kDel* = 77;
- kHome* = 78;
- kEnd* = 79;
- kPgUp* = 80;
- kPgDn* = 81;
- kLeft* = 82;
- kRight* = 83;
- kUp* = 84;
- kDown* = 85;
- kSlashPad* = 86;
- kAsterisk* = 87;
- kMinusPad* = 88;
- kPlusPad* = 89;
- kDelPad* = 90;
- kEnterPad* = 91;
- kPrtScr* = 92;
- kPause* = 93;
- kEqualsPad* = 103;
- kBackquote* = 104;
- kSemicolon2* = 105;
- kCommand* = 106;
- kBack* = 107;
- kVolumeUp* = 108;
- kVolumeDown* = 109;
- kModifers* = 215;
- kLShift* = 215;
- kRShift* = 216;
- kLCtrl* = 217;
- kRCtrl* = 218;
- kAlt* = 219;
- kAltGr* = 220;
- kLMeta* = 221;
- kRMeta* = 222;
- kMenu* = 223;
- kScrLock* = 224;
- kNumLock* = 225;
- kCapsLock* = 226;
- kMax* = 226;
- (** Modifiers Set **)
- mShift* = 0;
- mCtrl* = 1;
- mAlt* = 2;
- mLwin* = 3;
- mRwin* = 4;
- mMenu* = 5;
- mAltGr* = 6;
- mCommand* = 7;
- mScrolllock* = 8;
- mNumlock* = 9;
- mCapslock* = 10;
- TYPE
- ADRINT = SYSTEM.ADRINT;
- REAL = SYSTEM.REAL32;
- LONGREAL = SYSTEM.REAL64;
- LONGINT = SYSTEM.INT64;
- SHORTCHAR = SYSTEM.CHAR8;
- Color* = RECORD
- r, g, b, a: REAL
- END;
- Transform* = RECORD
- m: ARRAY 4, 4 OF REAL
- END;
- Timer* = POINTER TO TimerDesc;
- TimerDesc* = RECORD
- tmr: Al.Timer;
- next: Timer (** See timerList below *)
- END;
- Bitmap* = POINTER TO BitmapDesc;
- BitmapDesc* = RECORD
- bmp: Al.Bitmap;
- w*, h*: INTEGER
- END;
- Window* = POINTER TO WindowDesc;
- WindowDesc* = RECORD(BitmapDesc) (** This is a window. *)
- display: Al.Display; (** Allegro Display *)
- winW, winH*: INTEGER; (** Window size in real pixels *)
- initX*, initY*: INTEGER; (** Window position upon its creation *)
- initW, initH: INTEGER; (** Window size upon its creation *)
- fsW*, fsH*: INTEGER; (** Fullscreen size *)
- wantZoom: REAL; (** Window zoom upon its creation *)
- lastX, lastY: INTEGER; (** Last mouse position in virtual pixels *)
- lastW, lastH: INTEGER; (** Last stepped size in virtual pixels *)
- zoom: INTEGER; (** See constants above; based on this rzoom/izoom is used *)
- izoom: INTEGER; (** Window.izoom is used if Window.zoom = intZoom *)
- rzoom: REAL; (** Window.rzoom is used if Window.zoom = realZoom *)
- scaleOn: BOOLEAN; (** If TRUE, scaleX and scaleY are used *)
- scaleX, scaleY: REAL; (** Deforms pixels on Flip, but zoom is for drawing *)
- sizeStepX, sizeStepY: INTEGER;
- flipX, flipY, flipW, flipH: REAL; (** Where to flip the window bitmap to *)
- iFlipX, iFlipY: INTEGER; (** Same as flipX, flipY, which are always whole *)
- options: SET;
- pressedButtons: SET; (** Mouse buttons that are currenty being pressed *)
- title: ARRAY 256 OF CHAR;
- resized: BOOLEAN; (** TRUE if fullscreen mode has been toggled for window *)
- showMouse: BOOLEAN;
- icons: ARRAY 64 OF Al.Bitmap;
- noficons: INTEGER;
- next: Window (** See windowList below *)
- END;
- Event* = RECORD
- type*: INTEGER;
- time*: REAL;
- x*, y*, z*, w*, h*: INTEGER;
- dx*, dy*, dz*, dw*: INTEGER;
- button*: INTEGER;
- buttons*: SET; (** What mouse buttons are pressed *)
- count*: LONGINT; (** Timer counter *)
- key*: INTEGER; (** Physical key code *)
- ch*: CHAR; (** Typed character for event.type = char *)
- mod*: SET; (** Key modifiers *)
- repeat*: BOOLEAN;
- window*: Window;
- timer*: Timer;
- display: Al.Display
- END;
- FontMessage* = POINTER TO FontMessageDesc;
- FontMessageDesc* = RECORD
- END;
- FontDrawMsg* = POINTER TO FontDrawMsgDesc;
- FontDrawMsgDesc* = RECORD(FontMessage)
- END;
- Font* = POINTER TO FontDesc;
- FontDesc* = RECORD
- fname: ARRAY 256 OF CHAR;
- handle: PROCEDURE (font: Font; VAR msg: FontMessage);
- draw: PROCEDURE (font: Font; VAR msg: FontDrawMsg);
- loaded*: BOOLEAN
- END;
- MonoFont* = POINTER TO MonoFontDesc;
- MonoFontDesc* = RECORD(FontDesc)
- bmp: Bitmap;
- charW*, charH*: INTEGER;
- rows, cols: INTEGER
- END;
- VAR
- Done*: BOOLEAN;
- settings: SET; (** See list of constants Settings above *)
- wantW, wantH: INTEGER; (** Assigned in procedure Settings *)
- wantZoom: REAL; (** Assigned in procedure SetZoom *)
- wantSizeStepX, wantSizeStepY: INTEGER; (** Assigned in SetSizeStep *)
- wantScaleX, wantScaleY: REAL; (** Assigned in procedure SetScale *)
- wantTitle: ARRAY 256 OF CHAR; (** Assigned in procedure SetTitle *)
- queue: Al.EventQueue;
- userEventSource: Al.EventSource;
- windowList: Window;
- timerList: Timer;
- screen: Window;
- target: Bitmap;
- black: Color;
- charRead: CHAR; (** For KeyPressed and ReadKey *)
- specialChar: BOOLEAN; (** For charRead *)
- PROCEDURE Error(s: ARRAY OF CHAR);
- BEGIN Out.String(s); Out.Ln
- END Error;
- PROCEDURE GetDesktopResolution*(VAR w, h: INTEGER);
- VAR info: Al.MonitorInfo;
- n, i: INTEGER;
- ok: BOOLEAN;
- BEGIN
- n := Al.get_num_video_adapters();
- i := 0;
- ok := Al.get_monitor_info(0, info);
- WHILE (i < n) & ~(ok & (info.x1 = 0) & (info.y1 = 0)) DO
- INC(i); ok := Al.get_monitor_info(i, info)
- END;
- IF i >= n THEN ok := Al.get_monitor_info(0, info) END;
- IF ok THEN
- w := info.x2 - info.x1;
- h := info.y2 - info.y1
- ELSE w := -1; h := -1
- END
- END GetDesktopResolution;
- PROCEDURE GetScreen*(): Window;
- RETURN screen END GetScreen;
- PROCEDURE GetScreenSize*(VAR width, height: INTEGER);
- BEGIN
- IF screen # NIL THEN width := screen.w; height := screen.h
- ELSE width := 0; height := 0
- END
- END GetScreenSize;
- PROCEDURE Settings*(w, h: INTEGER; flags: SET);
- BEGIN wantW := w; wantH := h; settings := flags
- END Settings;
- PROCEDURE SetSizeStep*(w, h: INTEGER);
- BEGIN wantSizeStepX := w; wantSizeStepY := h
- END SetSizeStep;
- PROCEDURE ApplySizeStep(W: Window; VAR w, h: INTEGER);
- BEGIN
- IF W.sizeStepX # 1 THEN
- w := w DIV W.sizeStepX * W.sizeStepX;
- IF w < W.sizeStepX THEN w := W.sizeStepX END
- END;
- IF W.sizeStepY # 1 THEN
- h := h DIV W.sizeStepY * W.sizeStepY;
- IF h < W.sizeStepY THEN h := W.sizeStepY END
- END
- END ApplySizeStep;
- PROCEDURE GetTarget*(): Bitmap;
- RETURN target END GetTarget;
- PROCEDURE GetTargetSize*(VAR width, height: INTEGER);
- BEGIN
- IF target # NIL THEN width := target.w; height := target.h
- ELSE width := 0; height := 0
- END
- END GetTargetSize;
- PROCEDURE Target*(bitmap: Bitmap);
- VAR T: Al.Transform;
- W: Window;
- BEGIN target := bitmap;
- IF bitmap # NIL THEN
- IF (bitmap IS Window) & (bitmap.bmp = NIL) THEN W := bitmap(Window);
- Al.set_target_backbuffer(W.display);
- Al.build_transform(T, W.flipX, W.flipY, W.scaleX, W.scaleY, 0.0);
- Al.use_transform(T)
- ELSE Al.set_target_bitmap(SYSTEM.VAL(Al.Bitmap, bitmap.bmp))
- END
- END
- END Target;
- PROCEDURE TargetScreen*;
- BEGIN
- IF screen # NIL THEN Target(screen)
- ELSIF windowList # NIL THEN Target(windowList)
- ELSE Target(NIL)
- END
- END TargetScreen;
- PROCEDURE ClearBitmapToColor*(bmp: Bitmap; c: Color);
- BEGIN
- IF bmp # NIL THEN
- Target(bmp);
- Al.clear_to_color(SYSTEM.VAL(Al.Color, c))
- END
- END ClearBitmapToColor;
- PROCEDURE ClearBitmap*(bmp: Bitmap);
- BEGIN ClearBitmapToColor(bmp, black)
- END ClearBitmap;
- PROCEDURE ClearToColor*(c: Color);
- BEGIN ClearBitmapToColor(GetScreen(), c)
- END ClearToColor;
- PROCEDURE ClearScreen*;
- BEGIN ClearBitmapToColor(GetScreen(), black)
- END ClearScreen;
- PROCEDURE ResetFlipVars(W: Window);
- VAR w, h: INTEGER;
- BEGIN
- IF W.zoom = intZoom THEN
- w := W.w * W.izoom; h := W.h * W.izoom;
- IF W.scaleOn THEN
- W.flipW := FLT(FLOOR(FLT(w) * W.scaleX + 0.9));
- W.flipH := FLT(FLOOR(FLT(h) * W.scaleY + 0.9));
- W.iFlipX := (W.winW - FLOOR(W.flipW + 0.1)) DIV 2;
- W.iFlipY := (W.winH - FLOOR(W.flipH + 0.1)) DIV 2
- ELSE W.flipW := FLT(w); W.flipH := FLT(h);
- W.iFlipX := (W.winW - w) DIV 2; W.iFlipY := (W.winH - h) DIV 2
- END
- ELSE
- W.flipW := FLT(FLOOR(W.w * W.rzoom * W.scaleX + 0.9));
- W.flipH := FLT(FLOOR(W.h * W.rzoom * W.scaleY + 0.9));
- W.iFlipX := (W.winW - FLOOR(W.flipW + 0.1)) DIV 2;
- W.iFlipY := (W.winH - FLOOR(W.flipH + 0.1)) DIV 2
- END;
- IF topleft IN W.options THEN W.iFlipX := 0; W.iFlipY := 0 END;
- W.flipX := FLT(W.iFlipX); W.flipY := FLT(W.iFlipY);
- IF ~(exact IN W.options) & (smooth IN W.options) &
- ~(topleft IN W.options) & (W.winW - W.flipX - W.flipW < W.rzoom) &
- (W.winH - W.flipY - W.flipH < W.rzoom) THEN
- W.iFlipX := 0; W.iFlipY := 0; W.flipX := 0.0; W.flipY := 0.0;
- W.flipW := FLT(W.winW); W.flipH := FLT(W.winH)
- END
- END ResetFlipVars;
- PROCEDURE ResetWindowBitmap(W: Window);
- VAR opt: SET;
- w, h, bw, bh: INTEGER;
- fw, fh: REAL;
- scaled, wasTarget: BOOLEAN;
- tmp: Bitmap;
- BEGIN scaled := FALSE;
- IF W.bmp = NIL THEN bw := -1
- ELSE bw := Al.get_bitmap_width(W.bmp); bh := Al.get_bitmap_height(W.bmp)
- END;
- IF ~(exact IN W.options) THEN
- IF W.zoom = noZoom THEN w := W.winW; h := W.winH
- ELSIF (W.zoom = intZoom) & ~W.scaleOn THEN
- w := W.winW DIV W.izoom; h := W.winH DIV W.izoom
- ELSE scaled := TRUE;
- w := FLOOR(W.winW / W.rzoom / W.scaleX + 0.1);
- h := FLOOR(W.winH / W.rzoom / W.scaleY + 0.1)
- END
- ELSE w := W.w; h := W.h
- END;
- IF W.scaleOn & ~scaled THEN
- w := FLOOR(w / W.scaleX + 0.1); h := FLOOR(h / W.scaleY + 0.1)
- END;
- ApplySizeStep(W, w, h);
- IF (w > bw) OR (h > bh) OR (W.zoom = noZoom) THEN
- IF W.bmp # NIL THEN
- wasTarget := Al.get_target_bitmap() = W.bmp;
- Al.destroy_bitmap(W.bmp)
- END;
- IF (W.zoom = noZoom) & (nobuffer IN W.options) THEN
- W.bmp := NIL;
- IF wasTarget THEN Target(NIL) END
- ELSE opt := {Al.convertBitmap};
- IF smooth IN W.options THEN
- opt := opt + {Al.minLinear, Al.magLinear}
- END;
- Al.set_new_bitmap_flags(opt);
- W.bmp := Al.create_bitmap(w, h);
- tmp := GetTarget(); ClearBitmap(W);
- IF wasTarget THEN Target(W) ELSE Target(tmp) END
- END
- END;
- W.w := w; W.h := h;
- ResetFlipVars(W)
- END ResetWindowBitmap;
- PROCEDURE GetWindowOptions*(W: Window): SET;
- RETURN W.options END GetWindowOptions;
- PROCEDURE GetWindowZoom*(W: Window): REAL;
- RETURN W.rzoom END GetWindowZoom;
- PROCEDURE SetWindowZoomF*(W: Window; zoom: REAL);
- BEGIN W.rzoom := zoom;
- IF zoom = 1.0 THEN W.zoom := noZoom
- ELSIF FLOOR(zoom + 0.001) * 100 = FLOOR(zoom * 100 + 0.001) THEN
- W.zoom := intZoom; W.izoom := FLOOR(zoom + 0.001)
- ELSE W.zoom := realZoom
- END;
- ResetWindowBitmap(W)
- END SetWindowZoomF;
- PROCEDURE SetWindowZoom*(W: Window; zoom: INTEGER);
- BEGIN W.rzoom := FLT(zoom);
- IF zoom = 1 THEN W.zoom := noZoom
- ELSE W.zoom := intZoom; W.izoom := zoom
- END;
- ResetWindowBitmap(W)
- END SetWindowZoom;
- PROCEDURE SetNewWindowZoomF*(zoom: REAL);
- BEGIN wantZoom := zoom
- END SetNewWindowZoomF;
- PROCEDURE SetZoomF*(zoom: REAL);
- BEGIN wantZoom := zoom;
- IF screen # NIL THEN SetWindowZoomF(screen, zoom) END
- END SetZoomF;
- PROCEDURE SetNewWindowZoom*(zoom: INTEGER);
- BEGIN wantZoom := FLT(zoom)
- END SetNewWindowZoom;
- PROCEDURE SetZoom*(zoom: INTEGER);
- BEGIN wantZoom := FLT(zoom);
- IF screen # NIL THEN SetWindowZoom(screen, zoom) END
- END SetZoom;
- PROCEDURE SetWindowFullscreenSize*(win: Window; width, height: INTEGER);
- BEGIN win.fsW := width; win.fsH := height
- END SetWindowFullscreenSize;
- PROCEDURE ShowWindowMouse*(W: Window; show: BOOLEAN);
- BEGIN
- IF show THEN
- IF Al.show_mouse_cursor(W.display) THEN W.showMouse := TRUE END
- ELSE
- IF Al.hide_mouse_cursor(W.display) THEN W.showMouse := FALSE END
- END
- END ShowWindowMouse;
- PROCEDURE ShowMouse*(show: BOOLEAN);
- BEGIN IF screen # NIL THEN ShowWindowMouse(screen, show) END
- END ShowMouse;
- PROCEDURE SetWindowOption*(W: Window; key: INTEGER; on: BOOLEAN);
- BEGIN IF on THEN INCL(W.options, key) ELSE EXCL(W.options, key) END
- END SetWindowOption;
- PROCEDURE SetWindowScale*(W: Window; x, y: REAL);
- BEGIN W.scaleOn := (x # 1.0) OR (y # 1.0);
- W.scaleX := x; W.scaleY := y
- END SetWindowScale;
- PROCEDURE SetNewWindowScale*(x, y: REAL);
- BEGIN wantScaleX := x; wantScaleY := y
- END SetNewWindowScale;
- PROCEDURE SetScale*(x, y: REAL);
- BEGIN wantScaleX := x; wantScaleY := y;
- IF screen # NIL THEN SetWindowScale(screen, x, y) END
- END SetScale;
- PROCEDURE SetThisWindowTitle*(W: Window; title: ARRAY OF CHAR);
- VAR q: ARRAY 256 OF SHORTCHAR;
- BEGIN Utf8.Encode(title, q); Al.set_window_title(W.display, q)
- END SetThisWindowTitle;
- PROCEDURE SetNewWindowTitle*(title: ARRAY OF CHAR);
- BEGIN wantTitle := title
- END SetNewWindowTitle;
- PROCEDURE SetTitle*(title: ARRAY OF CHAR);
- BEGIN wantTitle := title;
- IF screen # NIL THEN SetThisWindowTitle(screen, title) END
- END SetTitle;
- PROCEDURE LoadBitmap*(fname: ARRAY OF CHAR): Bitmap;
- VAR B: Bitmap;
- q: ARRAY 2048 OF SHORTCHAR;
- BEGIN Al.set_new_bitmap_flags({Al.convertBitmap});
- NEW(B); Utf8.Encode(fname, q); B.bmp := Al.load_bitmap(q);
- IF B.bmp = NIL THEN B := NIL
- ELSE B.w := Al.get_bitmap_width(B.bmp); B.h := Al.get_bitmap_height(B.bmp)
- END
- RETURN B END LoadBitmap;
- PROCEDURE Flip*;
- VAR tmp: Al.Bitmap;
- W: Window;
- T: Al.Transform;
- x, y, w, h: REAL;
- BEGIN
- IF ((target = NIL) OR ~(target IS Window)) & (screen # NIL) THEN
- Target(screen)
- END;
- IF (target # NIL) & (target IS Window) THEN
- W := target(Window);
- tmp := Al.get_target_bitmap();
- Al.set_target_backbuffer(W.display);
- Al.identity_transform(T);
- Al.use_transform(T);
- IF target.bmp # NIL THEN
- Al.clear_to_color(SYSTEM.VAL(Al.Color, black));
- Al.draw_scaled_bitmap(W.bmp, 0.0, 0.0, FLT(W.w), FLT(W.h),
- W.flipX, W.flipY, W.flipW, W.flipH, {})
- ELSE w := FLT(W.winW); h := FLT(W.winH);
- x := FLT(FLOOR(W.flipX + W.flipW + 0.1));
- y := FLT(FLOOR(W.flipY + W.flipH + 0.1));
- Al.draw_filled_rectangle(0.0, 0.0, w, W.flipY,
- SYSTEM.VAL(Al.Color, black));
- Al.draw_filled_rectangle(0.0, y, w, h, SYSTEM.VAL(Al.Color, black));
- Al.draw_filled_rectangle(0.0, W.flipY, W.flipX, y,
- SYSTEM.VAL(Al.Color, black));
- Al.draw_filled_rectangle(x, W.flipY, w, y, SYSTEM.VAL(Al.Color, black))
- END;
- Al.flip_display();
- Al.set_target_bitmap(tmp)
- END
- END Flip;
- PROCEDURE PutPixel2*(x, y: INTEGER; c: Color);
- BEGIN Al.draw_filled_rectangle(FLT(x), FLT(y), FLT(x + 1), FLT(y + 1),
- SYSTEM.VAL(Al.Color, c))
- END PutPixel2;
- PROCEDURE PutPixel*(x, y: INTEGER; c: Color);
- BEGIN Al.draw_pixel(FLT(x) + 0.5, FLT(y) + 0.5, SYSTEM.VAL(Al.Color, c))
- END PutPixel;
- PROCEDURE MakeRGBA*(VAR color: Color; r, g, b, a: INTEGER);
- BEGIN color.r := r / 255; color.g := g / 255;
- color.b := b / 255; color.a := a / 255
- END MakeRGBA;
- PROCEDURE MakeCol*(VAR color: Color; r, g, b: INTEGER);
- BEGIN color.r := r / 255; color.g := g / 255;
- color.b := b / 255; color.a := 1.0
- END MakeCol;
- PROCEDURE ColorToRGB*(color: Color; VAR r, g, b: INTEGER);
- BEGIN r := FLOOR(color.r * 255 + 0.1) MOD 256;
- g := FLOOR(color.g * 255 + 0.1) MOD 256;
- b := FLOOR(color.b * 255 + 0.1) MOD 256
- END ColorToRGB;
- PROCEDURE ColorToRGBA*(color: Color; VAR r, g, b, a: INTEGER);
- BEGIN r := FLOOR(color.r * 255 + 0.1) MOD 256;
- g := FLOOR(color.g * 255 + 0.1) MOD 256;
- b := FLOOR(color.b * 255 + 0.1) MOD 256;
- a := FLOOR(color.a * 255 + 0.1) MOD 256
- END ColorToRGBA;
- PROCEDURE ThickLineF*(x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
- BEGIN Al.draw_line(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), thickness)
- END ThickLineF;
- PROCEDURE ThickLine*(x1, y1, x2, y2: INTEGER; color: Color;
- thickness: INTEGER);
- BEGIN
- Al.draw_line(FLT(x1) + 0.5, FLT(y1) + 0.5, FLT(x2) + 0.5, FLT(y2) + 0.5,
- SYSTEM.VAL(Al.Color, color), FLT(thickness))
- END ThickLine;
- PROCEDURE LineF(x1, y1, x2, y2: REAL; color: Color);
- BEGIN
- IF x1 < x2 THEN x2 := x2 + 1
- ELSIF x1 > x2 THEN x1 := x1 + 1
- ELSE x1 := x1 + 0.5; x2 := x1
- END;
- IF y1 < y2 THEN y1 := y1 + 0.01; y2 := y2 + 0.99
- ELSIF y1 > y2 THEN y1 := y1 + 1
- ELSE y1 := y1 + 0.5; y2 := y1
- END;
- Al.draw_line(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), 0.0)
- END LineF;
- PROCEDURE Line*(x1, y1, x2, y2: INTEGER; color: Color);
- BEGIN LineF(FLT(x1), FLT(y1), FLT(x2), FLT(y2), color)
- END Line;
- PROCEDURE HLine*(x1, y, x2: INTEGER; color: Color);
- BEGIN LineF(FLT(x1), FLT(y), FLT(x2), FLT(y), color)
- END HLine;
- PROCEDURE VLine*(x, y1, y2: INTEGER; color: Color);
- BEGIN LineF(FLT(x), FLT(y1), FLT(x), FLT(y2), color)
- END VLine;
- PROCEDURE FillRectF*(x1, y1, x2, y2: REAL; color: Color);
- BEGIN Al.draw_filled_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color))
- END FillRectF;
- PROCEDURE FillRect*(x1, y1, x2, y2: INTEGER; color: Color);
- BEGIN
- Al.draw_filled_rectangle(FLT(x1), FLT(y1),
- FLT(x2 + 1), FLT(y2 + 1), SYSTEM.VAL(Al.Color, color))
- END FillRect;
- PROCEDURE ThickRectF*(x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
- BEGIN Al.draw_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), thickness)
- END ThickRectF;
- PROCEDURE ThickRect*(x1, y1, x2, y2: INTEGER; color: Color;
- thickness: INTEGER);
- BEGIN
- Al.draw_rectangle(FLT(x1) + 0.5, FLT(y1) + 0.5,
- FLT(x2) + 0.5, FLT(y2) + 0.5, SYSTEM.VAL(Al.Color, color), FLT(thickness))
- END ThickRect;
- PROCEDURE RectF*(x1, y1, x2, y2: REAL; color: Color);
- BEGIN Al.draw_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), 1.0)
- END RectF;
- PROCEDURE Rect*(x1, y1, x2, y2: INTEGER; color: Color);
- BEGIN
- Al.draw_rectangle(FLT(x1) + 0.5, FLT(y1) + 0.5,
- FLT(x2) + 0.5, FLT(y2) + 0.5, SYSTEM.VAL(Al.Color, color), 1.0)
- END Rect;
- PROCEDURE CircleF*(x, y, r: REAL; color: Color);
- BEGIN
- Al.draw_circle(x, y, r, SYSTEM.VAL(Al.Color, color), 1.0)
- END CircleF;
- PROCEDURE Circle*(x, y, r: INTEGER; color: Color);
- BEGIN
- Al.draw_circle(FLT(x) + 0.5, FLT(y) + 0.5, FLT(r),
- SYSTEM.VAL(Al.Color, color), 1.0)
- END Circle;
- PROCEDURE ThickCircleF*(x, y, r: REAL; color: Color; thickness: REAL);
- BEGIN
- Al.draw_circle(x, y, r, SYSTEM.VAL(Al.Color, color), thickness)
- END ThickCircleF;
- PROCEDURE ThickCircle*(x, y, r: INTEGER; color: Color; thickness: INTEGER);
- BEGIN
- Al.draw_circle(FLT(x) + 0.5, FLT(y) + 0.5, FLT(r),
- SYSTEM.VAL(Al.Color, color), FLT(thickness))
- END ThickCircle;
- PROCEDURE FillCircleF*(x, y, r: REAL; color: Color);
- BEGIN
- Al.draw_filled_circle(x, y, r, SYSTEM.VAL(Al.Color, color))
- END FillCircleF;
- PROCEDURE FillCircle*(x, y, r: INTEGER; color: Color);
- BEGIN
- Al.draw_filled_circle(FLT(x) + 0.5, FLT(y) + 0.5, FLT(r),
- SYSTEM.VAL(Al.Color, color))
- END FillCircle;
- PROCEDURE NewBitmap*(w, h: INTEGER): Bitmap;
- VAR b: Bitmap;
- BEGIN NEW(b);
- Al.set_new_bitmap_flags({Al.convertBitmap});
- b.bmp := Al.create_bitmap(w, h);
- IF b.bmp = NIL THEN b := NIL ELSE b.w := w; b.h := h END
- RETURN b END NewBitmap;
- PROCEDURE DrawPartFlip*(bmp: Bitmap; sx, sy, sw, sh, dx, dy: INTEGER;
- flags: SET);
- BEGIN
- Al.draw_bitmap_region(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
- FLT(dx), FLT(dy), flags)
- END DrawPartFlip;
- PROCEDURE DrawPart*(bmp: Bitmap; sx, sy, sw, sh, dx, dy: INTEGER);
- BEGIN
- Al.draw_bitmap_region(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
- FLT(dx), FLT(dy), {})
- END DrawPart;
- PROCEDURE DrawTintedPart*(bmp: Bitmap; color: Color;
- sx, sy, sw, sh, dx, dy: INTEGER);
- BEGIN
- IF ~Al.is_compatible_bitmap(bmp.bmp) THEN
- (*Error('Graph: NON-COMPAT');*)
- Al.convert_bitmap(bmp.bmp)
- END;
- Al.draw_tinted_bitmap_region(bmp.bmp, SYSTEM.VAL(Al.Color, color),
- FLT(sx), FLT(sy), FLT(sw), FLT(sh), FLT(dx), FLT(dy), {})
- END DrawTintedPart;
- PROCEDURE DrawFlip*(bmp: Bitmap; x, y: INTEGER; flip: SET);
- BEGIN Al.draw_bitmap(bmp.bmp, FLT(x), FLT(y), flip)
- END DrawFlip;
- PROCEDURE Draw*(bmp: Bitmap; x, y: INTEGER);
- BEGIN Al.draw_bitmap(bmp.bmp, FLT(x), FLT(y), {})
- END Draw;
- PROCEDURE DrawEx*(bmp: Bitmap; sx, sy, sw, sh, dx, dy, dw, dh: INTEGER;
- flip: SET);
- BEGIN
- Al.draw_scaled_bitmap(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
- FLT(dx), FLT(dy), FLT(dw), FLT(dh), flip)
- END DrawEx;
- PROCEDURE DrawRotated*(bmp: Bitmap; cx, cy, dx, dy: INTEGER;
- angle: REAL; flip: SET);
- BEGIN
- Al.draw_rotated_bitmap(bmp.bmp, FLT(cx), FLT(cy),
- FLT(dx), FLT(dy), angle, flip)
- END DrawRotated;
- PROCEDURE DrawScaledRotated*(bmp: Bitmap; cx, cy, dx, dy: INTEGER;
- xScale, yScale, angle: REAL; flip: SET);
- BEGIN
- Al.draw_scaled_rotated_bitmap(bmp.bmp, FLT(cx), FLT(cy),
- FLT(dx), FLT(dy), xScale, yScale, angle, flip)
- END DrawScaledRotated;
- PROCEDURE GetClip*(VAR x, y, w, h: INTEGER);
- BEGIN Al.get_clipping_rectangle(x, y, w, h)
- END GetClip;
- PROCEDURE SetClip*(x, y, w, h: INTEGER);
- BEGIN Al.set_clipping_rectangle(x, y, w, h)
- END SetClip;
- PROCEDURE UnsetClip*;
- BEGIN Al.reset_clipping_rectangle
- END UnsetClip;
- PROCEDURE DelayF*(n: REAL);
- BEGIN Al.rest(n)
- END DelayF;
- PROCEDURE Delay*(n: INTEGER);
- BEGIN Al.rest(n / 1000)
- END Delay;
- PROCEDURE ConvertMemoryBitmaps*;
- BEGIN Al.convert_memory_bitmaps
- END ConvertMemoryBitmaps;
- PROCEDURE RecreateDisplay(W: Window; alterSize: BOOLEAN);
- VAR d: Al.Display;
- q: ARRAY 256 OF SHORTCHAR;
- opt: SET;
- n, x, y, w, h, dw, dh, nw, nh, sw, sh: INTEGER;
- nwf, nhf: REAL;
- isCurTarget: BOOLEAN;
- BEGIN isCurTarget := target = W;
- IF W.display # NIL THEN Al.destroy_display(W.display) END;
- W.rzoom := W.wantZoom;
- IF W.wantZoom = 1.0 THEN W.zoom := noZoom
- ELSIF FLOOR(W.wantZoom + 0.001) * 100 = FLOOR(W.wantZoom * 100 + 0.001) THEN
- W.zoom := intZoom; W.izoom := FLOOR(W.wantZoom + 0.001)
- ELSE W.zoom := realZoom
- END;
- Utf8.Encode(W.title, q); Al.set_new_window_title(q);
- IF software IN W.options THEN n := 0 ELSE n := 1 END;
- Al.set_new_display_option(Al.renderMethod, n, Al.suggest);
- Al.set_new_display_option(Al.vsync, 2(*off*), Al.suggest);
- (*Al.set_new_display_option(Al.singleBuffer, 1, Al.suggest);*)
- IF smooth IN W.options THEN n := 1;
- Al.set_new_display_option(Al.samples, 8, Al.suggest)
- ELSE n := 0
- END;
- (* Al.set_new_display_option(Al.sampleBuffers, n, Al.suggest); *)
- GetDesktopResolution(dw, dh);
- dw := FLOOR(FLT(dw) / wantScaleX + 0.1);
- dh := FLOOR(FLT(dh) / wantScaleY + 0.1);
- W.scaleOn := (wantScaleX # 1.0) OR (wantScaleY # 1.0);
- W.scaleX := wantScaleX; W.scaleY := wantScaleY;
- IF fullscreen IN W.options THEN w := W.fsW; h := W.fsH
- ELSE w := W.initW; h := W.initH
- END;
- IF (w < 0) OR (h < 0) THEN
- IF fullscreen IN W.options THEN
- w := FLOOR(dw / W.wantZoom + 0.1); h := FLOOR(dh / W.wantZoom + 0.1);
- ApplySizeStep(W, w, h);
- sw := FLOOR(w * W.wantZoom + 0.1); sh := FLOOR(h * W.wantZoom + 0.1)
- ELSE w := 640; h := 400; W.zoom := noZoom;
- ApplySizeStep(W, w, h); sw := w; sh := h
- END
- ELSIF fullscreen IN W.options THEN
- IF smooth IN W.options THEN nwf := dw / w; nhf := dh / h;
- IF nhf < nwf THEN nwf := nhf END;
- W.zoom := realZoom; W.rzoom := nwf;
- IF exact IN W.options THEN
- sw := FLOOR(w * nwf + 0.1); sh := FLOOR(h * nwf + 0.1)
- ELSE sw := dw; sh := dh
- END
- ELSE nw := dw DIV w; nh := dh DIV h;
- IF nh < nw THEN nw := nh END;
- W.zoom := intZoom; W.izoom := nw; W.rzoom := FLT(nw);
- IF exact IN W.options THEN sw := w * nw; sh := h * nw
- ELSE sw := dw DIV nw * nw; sh := dh DIV nw * nw
- END
- END;
- IF W.zoom = realZoom THEN
- w := FLOOR(sw / W.rzoom + 0.1); h := FLOOR(sh / W.rzoom + 0.1)
- ELSIF W.zoom = intZoom THEN w := sw DIV W.izoom; h := sh DIV W.izoom
- ELSE w := sw; h := sh
- END;
- ApplySizeStep(W, w, h); sw := w; sh := h;
- IF alterSize THEN W.initW := w; W.initH := h END
- ELSE ApplySizeStep(W, w, h);
- sw := FLOOR(w * W.wantZoom * W.scaleX + 0.999);
- sh := FLOOR(h * W.wantZoom * W.scaleY + 0.999)
- END;
- W.lastW := 0; W.lastH := 0;
- IF center IN W.options THEN GetDesktopResolution(dw, dh);
- x := (dw - sw) DIV 2; y := (dh - sh) DIV 2;
- IF x < 0 THEN x := 0 END; IF y < 0 THEN y := 0 END
- ELSIF (W.initX < 0) OR (W.initY < 0) THEN x := Al.intMax; y := Al.intMax
- ELSE x := W.initX; y := W.initY
- END;
- Al.set_new_window_position(x, y);
- opt := {};
- IF fullscreen IN W.options THEN INCL(opt, Al.fullscreenWindow)
- ELSE INCL(opt, Al.windowed)
- END;
- IF resizable IN W.options THEN INCL(opt, Al.resizable) END;
- IF maximized IN W.options THEN INCL(opt, Al.maximized) END;
- IF minimized IN W.options THEN INCL(opt, Al.minimized) END;
- IF frameless IN W.options THEN INCL(opt, Al.frameless) END;
- Al.set_new_display_flags(opt);
- IF W.bmp # NIL THEN Al.destroy_bitmap(W.bmp); W.bmp := NIL END;
- W.display := Al.create_display(sw, sh);
- IF W.display # NIL THEN
- (*IF isCurTarget OR (windowList = NIL) OR (windowList.next = NIL) THEN
- Al.set_target_backbuffer(W.display);
- ConvertMemoryBitmaps;
- END;*)
- W.winW := Al.get_display_width(W.display);
- W.winH := Al.get_display_height(W.display);
- W.w := w; W.h := h;
- ApplySizeStep(W, w, h);
- W.lastW := W.w; W.lastH := W.h;
- ResetWindowBitmap(W);
- Al.register_event_source(queue, Al.get_display_event_source(W.display));
- IF isCurTarget THEN Target(W) END;
- IF ~W.showMouse THEN ShowWindowMouse(W, FALSE) END;
- IF W.noficons > 0 THEN
- Al.set_display_icons(W.display, W.noficons, W.icons)
- END
- END
- END RecreateDisplay;
- PROCEDURE NewWindow*(x, y, w, h: INTEGER; title: ARRAY OF CHAR;
- options: SET): Window;
- VAR W: Window;
- d: Al.Display;
- q: ARRAY 256 OF SHORTCHAR;
- opt: SET;
- i, n, dw, dh, nw, nh, sw, sh: INTEGER;
- nwf, nhf: REAL;
- BEGIN NEW(W); W.lastX := -1; W.lastY := -1; W.resized := FALSE;
- W.sizeStepX := wantSizeStepX; W.sizeStepY := wantSizeStepY;
- IF {fullscreen, window} * options = {} THEN INCL(options, window)
- ELSIF window IN options THEN EXCL(options, fullscreen)
- END;
- W.options := options;
- W.pressedButtons := {};
- W.title := title;
- W.wantZoom := wantZoom;
- W.scaleOn := (wantScaleX # 1.0) OR (wantScaleY # 1.0);
- W.scaleX := wantScaleX; W.scaleY := wantScaleY;
- W.initX := x; W.initY := y; W.initW := w; W.initH := h;
- W.fsW := w; W.fsH := h;
- W.showMouse := TRUE;
- FOR i := 0 TO LEN(W.icons) - 1 DO W.icons[i] := NIL END;
- W.noficons := 0;
- W.display := NIL; RecreateDisplay(W, TRUE);
- IF W.display # NIL THEN W.next := windowList; windowList := W
- ELSE Error('Could not create dispaly.'); W := NIL
- END;
- IF (screen = NIL) & (W # NIL) THEN screen := W; Target(screen) END
- RETURN W END NewWindow;
- PROCEDURE CloseWindow*(W: Window);
- BEGIN Al.destroy_display(W.display)
- END CloseWindow;
- PROCEDURE NewTimer*(speed: REAL): Timer;
- VAR T: Timer;
- BEGIN NEW(T); T.tmr := Al.create_timer(speed);
- IF T.tmr # NIL THEN
- Al.register_event_source(queue, Al.get_timer_event_source(T.tmr));
- T.next := timerList; timerList := T
- ELSE T := NIL
- END;
- RETURN T END NewTimer;
- PROCEDURE GetWindow(d: Al.Display): Window;
- VAR W: Window;
- BEGIN W := windowList;
- WHILE (W # NIL) & (W.display # d) DO W := W.next END
- RETURN W END GetWindow;
- PROCEDURE GetTimer(a: Al.Timer): Timer;
- VAR t: Timer;
- BEGIN t := timerList;
- WHILE (t # NIL) & (t.tmr # a) DO t := t.next END
- RETURN t END GetTimer;
- PROCEDURE EmitResizeEvent(W: Window);
- VAR E: Al.UserEvent;
- BEGIN
- E.type := eventUserResize;
- E.data4 := SYSTEM.VAL(ADRINT, W.display);
- IF Al.emit_user_event(userEventSource, SYSTEM.VAL(Al.Event, E), 0) THEN END
- END EmitResizeEvent;
- PROCEDURE ToggleFS*(win: Window);
- VAR fs: BOOLEAN;
- w, h: REAL;
- BEGIN
- IF (win = NIL) & (screen # NIL) THEN win := screen END;
- IF (win # NIL) & (win.display # NIL) THEN
- fs := ~(Al.windowed IN Al.get_display_flags(win.display));
- IF fs THEN EXCL(win.options, fullscreen); INCL(win.options, window)
- ELSE INCL(win.options, fullscreen); EXCL(win.options, window);
- w := Al.get_display_width(win.display) / win.rzoom;
- h := Al.get_display_height(win.display) / win.rzoom;
- IF win.scaleOn THEN w := w / win.scaleX; h := h / win.scaleY END;
- win.initW := FLOOR(w + 0.1); win.initH := FLOOR(h + 0.1);
- EXCL(win.options, center);
- Al.get_window_position(win.display, win.initX, win.initY);
- ApplySizeStep(win, win.initW, win.initH)
- END;
- win.scaleX := wantScaleX;
- win.scaleY := wantScaleY;
- RecreateDisplay(win, FALSE);
- EmitResizeEvent(win)
- END
- END ToggleFS;
- PROCEDURE SwitchToWindow*(win: Window);
- BEGIN IF ~(window IN GetWindowOptions(screen)) THEN ToggleFS(win) END
- END SwitchToWindow;
- PROCEDURE SwitchToFS*(win: Window);
- BEGIN IF window IN GetWindowOptions(screen) THEN ToggleFS(win) END
- END SwitchToFS;
- PROCEDURE ParseEvent(E: Al.Event; peek: BOOLEAN; VAR event: Event);
- VAR DE: Al.PDisplayEvent;
- TE: Al.PTimerEvent;
- KE: Al.PKeyboardEvent;
- ME: Al.PMouseEvent;
- UE: Al.PUserEvent;
- W: Window;
- d: Al.Display;
- x, y, w, h: INTEGER;
- fw, fh: REAL;
- BEGIN
- event.time := E.timestamp;
- IF E.type = Al.eventMouseAxes THEN
- ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
- W := GetWindow(ME.display);
- IF W.zoom = noZoom THEN x := ME.x - W.iFlipX; y := ME.y - W.iFlipY
- ELSIF W.zoom = intZoom THEN
- x := (ME.x - W.iFlipX) DIV W.izoom; y := (ME.y - W.iFlipY) DIV W.izoom
- ELSE x := FLOOR((ME.x - W.flipX) / W.rzoom + 0.1);
- y := FLOOR((ME.y - W.flipY) / W.rzoom + 0.1)
- END;
- IF W.scaleOn THEN
- x := FLOOR(x / W.scaleX + 0.1); y := FLOOR(y / W.scaleY + 0.1)
- END;
- IF (x # W.lastX) OR (y # W.lastY) OR (ME.dz # 0) OR (ME.dw # 0) THEN
- IF (ME.dz # 0) OR (ME.dw # 0) THEN event.type := mouseWheel;
- event.dz := ME.dz; event.dw := ME.dw;
- event.x := W.lastX; event.y := W.lastY;
- event.z := ME.z; event.w := ME.w;
- event.dx := 0; event.dy := 0
- ELSE event.type := mouseMove;
- IF x = -1 THEN event.dx := 0; event.dy := 0
- ELSE event.dx := x - W.lastX; event.dy := y - W.lastY
- END;
- event.buttons := W.pressedButtons;
- event.x := x; event.y := y;
- IF ~peek THEN W.lastX := event.x; W.lastY := event.y END
- END;
- event.button := ME.button; (*!FIXME does ME.button work in Allegro 5 MouseAxes? *)
- event.buttons := W.pressedButtons;
- event.mod := {};
- event.display := ME.display; event.window := W
- ELSE event.type := noEvent
- END
- ELSIF E.type = Al.eventMouseButtonDown THEN
- event.type := mouseDown;
- ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
- W := GetWindow(ME.display); event.window := W;
- IF W.zoom = noZoom THEN x := ME.x - W.iFlipX; y := ME.y - W.iFlipY
- ELSIF W.zoom = intZoom THEN
- x := (ME.x - W.iFlipX) DIV W.izoom; y := (ME.y - W.iFlipY) DIV W.izoom
- ELSE x := FLOOR((ME.x - W.flipX) / W.rzoom + 0.1);
- y := FLOOR((ME.y - W.flipY) / W.rzoom + 0.1)
- END;
- IF W.scaleOn THEN
- x := FLOOR(x / W.scaleX + 0.1); y := FLOOR(y / W.scaleY + 0.1)
- END;
- event.x := x; event.y := y;
- event.z := ME.z; event.w := ME.w;
- event.button := ME.button;
- INCL(W.pressedButtons, event.button);
- event.mod := {};
- event.display := ME.display
- ELSIF E.type = Al.eventMouseButtonUp THEN
- event.type := mouseUp;
- ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
- W := GetWindow(ME.display); event.window := W;
- IF W.zoom = noZoom THEN x := ME.x - W.iFlipX; y := ME.y - W.iFlipY
- ELSIF W.zoom = intZoom THEN
- x := (ME.x - W.iFlipX) DIV W.izoom; y := (ME.y - W.iFlipY) DIV W.izoom
- ELSE x := FLOOR((ME.x - W.flipX) / W.rzoom + 0.1);
- y := FLOOR((ME.y - W.flipY) / W.rzoom + 0.1)
- END;
- IF W.scaleOn THEN
- x := FLOOR(x / W.scaleX + 0.1); y := FLOOR(y / W.scaleY + 0.1)
- END;
- event.x := x; event.y := y;
- event.z := ME.z; event.w := ME.w;
- event.button := ME.button;
- EXCL(W.pressedButtons, event.button);
- event.mod := {};
- event.display := ME.display
- ELSIF E.type = Al.eventTimer THEN
- event.type := timer;
- TE := SYSTEM.VAL(Al.PTimerEvent, SYSTEM.ADR(E));
- event.count := TE.count;
- event.timer := GetTimer(SYSTEM.VAL(Al.Timer, TE.source))
- ELSIF E.type = Al.eventKeyDown THEN
- event.type := keyDown;
- KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
- event.key := KE.keycode;
- event.mod := {};
- event.display := KE.display;
- event.window := GetWindow(event.display)
- ELSIF E.type = Al.eventKeyUp THEN
- event.type := keyUp;
- KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
- event.key := KE.keycode;
- event.mod := {};
- event.display := KE.display;
- event.window := GetWindow(event.display)
- ELSIF E.type = Al.eventKeyChar THEN
- KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
- event.type := char;
- event.key := KE.keycode;
- event.ch := CHR(KE.unichar);
- event.mod := KE.modifiers;
- event.repeat := KE.repeat;
- event.display := KE.display;
- event.window := GetWindow(event.display)
- ELSIF (E.type = Al.eventDisplayResize) OR (E.type = eventUserResize) THEN
- IF E.type = Al.eventDisplayResize THEN
- DE := SYSTEM.VAL(Al.PDisplayEvent, SYSTEM.ADR(E));
- d := DE.source; W := GetWindow(d);
- IF ~peek THEN W.winW := DE.width; W.winH := DE.height END
- ELSE UE := SYSTEM.VAL(Al.PUserEvent, SYSTEM.ADR(E));
- d := SYSTEM.VAL(Al.Display, UE.data4); W := GetWindow(d);
- IF ~peek THEN
- W.winW := Al.get_display_width(d); W.winH := Al.get_display_height(d)
- END
- END;
- fw := W.winW / W.rzoom; fh := W.winH / W.rzoom;
- IF W.scaleOn THEN fw := fw / W.scaleX; fh := fh / W.scaleY END;
- w := FLOOR(fw + 0.1); h := FLOOR(fh + 0.1);
- IF E.type = Al.eventDisplayResize THEN
- Al.acknowledge_resize(d);
- ApplySizeStep(W, w, h)
- END;
- IF (w # W.lastW) OR (h # W.lastH) THEN
- IF ~peek THEN W.lastW := w; W.lastH := h END;
- event.type := resize; event.window := W; event.display := d;
- event.w := w; event.h := h;
- IF E.type = Al.eventDisplayResize THEN event.x := DE.x; event.y := DE.y
- ELSE Al.get_window_position(d, event.x, event.y)
- END;
- IF ~peek THEN ResetWindowBitmap(W) END
- ELSE ResetFlipVars(W); Flip; event.type := noEvent
- END
- ELSIF E.type = Al.eventDisplayClose THEN
- event.type := quit;
- event.display := SYSTEM.VAL(Al.Display, E.source);
- event.window := GetWindow(event.display)
- ELSE event.type := noEvent
- END
- END ParseEvent;
- PROCEDURE WaitAndParseEvent(VAR event: Event);
- VAR E: Al.Event;
- BEGIN
- Al.wait_for_event(queue, E);
- ParseEvent(E, FALSE, event)
- END WaitAndParseEvent;
- PROCEDURE PeekAndParseEvent(VAR event: Event): BOOLEAN;
- VAR E: Al.Event;
- got: BOOLEAN;
- BEGIN
- got := Al.peek_next_event(queue, E);
- IF got THEN ParseEvent(E, TRUE, event) END
- RETURN got END PeekAndParseEvent;
- PROCEDURE WaitEvent*(VAR event: Event);
- BEGIN REPEAT WaitAndParseEvent(event) UNTIL event.type # noEvent
- END WaitEvent;
- PROCEDURE PeekEvent*(VAR event: Event): BOOLEAN;
- VAR got: BOOLEAN;
- BEGIN
- got := PeekAndParseEvent(event);
- WHILE got & (event.type = noEvent) DO
- IF Al.drop_next_event(queue) THEN END;
- got := PeekAndParseEvent(event)
- END
- RETURN got END PeekEvent;
- PROCEDURE HasEvents*(): BOOLEAN;
- VAR e: Event;
- RETURN PeekEvent(e) END HasEvents;
- PROCEDURE WaitAndParseKeyEvent;
- VAR e: Event;
- BEGIN WaitEvent(e);
- IF e.type = char THEN charRead := e.ch; specialChar := FALSE
- ELSIF (e.type = keyDown) &
- ((kF1 <= e.key) & (e.key <= kF12) OR
- (kHome <= e.key) & (e.key <= kDown) OR
- (e.key = kInsert) OR (e.key = kPause))
- THEN charRead := CHR(e.key); specialChar := TRUE
- END
- END WaitAndParseKeyEvent;
- PROCEDURE KeyPressed*(): BOOLEAN;
- BEGIN
- WHILE ~specialChar & (charRead = 0X) & HasEvents() DO WaitAndParseKeyEvent END
- RETURN specialChar OR (charRead # 0X) END KeyPressed;
- PROCEDURE ReadKey*(): CHAR;
- VAR c: CHAR;
- BEGIN
- WHILE ~specialChar & (charRead = 0X) DO WaitAndParseKeyEvent END;
- IF specialChar THEN c := 0X; specialChar := FALSE
- ELSE c := charRead; charRead := 0X
- END
- RETURN c END ReadKey;
- PROCEDURE Pause*;
- BEGIN
- IF KeyPressed() THEN
- IF ReadKey() = 0X THEN END
- END;
- IF ReadKey() = 0X THEN END
- END Pause;
- PROCEDURE DropNextEvent*;
- VAR e: Event;
- BEGIN (*WaitEvent(e)*)
- IF Al.drop_next_event(queue) THEN END
- END DropNextEvent;
- PROCEDURE StartTimer*(timer: Timer);
- BEGIN Al.start_timer(timer.tmr)
- END StartTimer;
- PROCEDURE StopTimer*(timer: Timer);
- BEGIN Al.stop_timer(timer.tmr)
- END StopTimer;
- PROCEDURE ResumeTimer*(timer: Timer);
- BEGIN Al.resume_timer(timer.tmr)
- END ResumeTimer;
- (* Font *)
- PROCEDURE GetMonoFontSize*(font: Font; VAR charW, charH: INTEGER);
- BEGIN charW := font(MonoFont).charW; charH := font(MonoFont).charH
- END GetMonoFontSize;
- PROCEDURE FindFontChar(font: Font; c: CHAR; VAR bmp: Bitmap;
- VAR x, y, w, h: INTEGER);
- VAR n: INTEGER;
- m: MonoFont;
- BEGIN m := font(MonoFont);
- IF c < 200X THEN n := ORD(c)
- ELSIF (400X <= c) & (c < 500X) THEN n := ORD(c) + (300H - 400H)
- ELSIF (2500X <= c) & (c < 2600X) THEN n := ORD(c) + (200H - 2500H)
- ELSE n := -1
- END;
- IF n < 0 THEN n := 1 (* "Bad" character *) END;
- bmp := m.bmp;
- x := n MOD m.cols * m.charW; y := n DIV m.cols * m.charH;
- w := m.charW; h := m.charH
- END FindFontChar;
- PROCEDURE DrawCharEx*(ch: CHAR; x, y: INTEGER; font: Font; color: Color;
- VAR w: INTEGER);
- VAR sx, sy, h: INTEGER;
- bmp: Bitmap;
- BEGIN FindFontChar(font, ch, bmp, sx, sy, w, h);
- DrawTintedPart(bmp, color, sx, sy, w, h, x, y)
- END DrawCharEx;
- PROCEDURE DrawChar*(ch: CHAR; x, y: INTEGER; font: Font; color: Color);
- VAR w: INTEGER;
- BEGIN DrawCharEx(ch, x, y, font, color, w)
- END DrawChar;
- PROCEDURE DrawString*(s: ARRAY OF CHAR; x, y: INTEGER;
- font: Font; color: Color);
- VAR i, cx, cy, charW, destW, destH: INTEGER;
- m: MonoFont;
- BEGIN m := font(MonoFont); i := 0; cx := x; cy := y;
- GetTargetSize(destW, destH);
- WHILE (s[i] # 0X) & (cx < destW) & (cy < destH) DO
- IF s[i] = 0AX THEN cx := x; INC(cy, m.charH)
- ELSE DrawCharEx(s[i], cx, cy, font, color, charW);
- INC(i); INC(cx, charW)
- END
- END
- END DrawString;
- PROCEDURE MonoFontDraw(f: Font; VAR msg: FontDrawMsg);
- VAR m: MonoFont;
- BEGIN m := f(MonoFont);
- (*!TODO*)
- END MonoFontDraw;
- PROCEDURE MonoFontHandle(f: Font; VAR msg: FontMessage);
- VAR m: MonoFont;
- BEGIN m := f(MonoFont)
- (*!TODO*)
- END MonoFontHandle;
- PROCEDURE ReadWord(VAR r: Files.Rider; VAR s: ARRAY OF CHAR);
- VAR ch: CHAR;
- i: INTEGER;
- BEGIN
- Files.ReadChar(r, ch);
- WHILE ~r.eof & (ch <= ' ') DO Files.ReadChar(r, ch) END;
- i := 0;
- WHILE ~r.eof & (ch > ' ') DO
- IF (i # LEN(s) - 1) THEN s[i] := ch; INC(i) END;
- Files.ReadChar(r, ch)
- END;
- s[i] := 0X
- END ReadWord;
- PROCEDURE ReadInt(VAR r: Files.Rider; VAR n: INTEGER);
- VAR ch: CHAR;
- i: INTEGER;
- BEGIN
- Files.ReadChar(r, ch);
- WHILE ~r.eof & (ch <= ' ') DO Files.ReadChar(r, ch) END;
- n := 0;
- WHILE ~r.eof & ('0' <= ch) & (ch <= '9') DO
- n := n * 10 + ORD(ch) - ORD('0');
- Files.ReadChar(r, ch)
- END
- END ReadInt;
- PROCEDURE ReadFontInfo(VAR r: Files.Rider): Font;
- VAR f: Font;
- mf: MonoFont;
- s: ARRAY 4096 OF CHAR;
- BEGIN f := NIL;
- ReadWord(r, s);
- IF s = 'mono' THEN
- NEW(mf); mf.bmp := NIL;
- ReadInt(r, mf.charW); ReadInt(r, mf.charH);
- IF (mf.charW > 0) & (mf.charH > 0) THEN
- mf.cols := 16; mf.rows := 16 * fontPlanes
- ELSE mf := NIL
- END;
- f := mf
- END
- RETURN f END ReadFontInfo;
- PROCEDURE LoadFontInfo*(fname: ARRAY OF CHAR): Font;
- VAR f: Font;
- F: Files.File;
- r: Files.Rider;
- s: ARRAY 4096 OF CHAR;
- BEGIN f := NIL;
- s := fname; Strings.Append('.ofi', s);
- F := Files.Old(s);
- IF F # NIL THEN
- s := fname; Strings.Append('.png', s);
- IF Dir.FileExists(s) THEN
- Files.Set(r, F, 0);
- f := ReadFontInfo(r);
- IF f # NIL THEN
- f.loaded := FALSE;
- f.fname := fname;
- f.draw := MonoFontDraw;
- f.handle := MonoFontHandle
- END
- END
- END
- RETURN f END LoadFontInfo;
- PROCEDURE LoadFontBitmap*(f: Font);
- VAR s: ARRAY 4096 OF CHAR;
- BEGIN
- s := ''; Strings.Append(f.fname, s); Strings.Append('.png', s);
- f(MonoFont).bmp := LoadBitmap(s);
- IF f(MonoFont).bmp # NIL THEN f.loaded := TRUE END
- END LoadFontBitmap;
- PROCEDURE LoadFont*(fname: ARRAY OF CHAR): Font;
- VAR f: Font;
- BEGIN f := LoadFontInfo(fname);
- IF f # NIL THEN LoadFontBitmap(f) END
- RETURN f END LoadFont;
- (** Clipboard **)
- PROCEDURE GetClipboardText*(win: Window; VAR s: ARRAY OF CHAR);
- TYPE P = POINTER [1] TO ARRAY 50000 OF SHORTCHAR;
- VAR a: Al.ADRINT; p: P;
- i: INTEGER;
- BEGIN
- a := Al.get_clipboard_text(win.display);
- IF ~Platform.Windows THEN (* Workaround for an Allegro bug on X11 *)
- FOR i := 1 TO 6 DO (* Maybe "TO 1" is enough *)
- Al.free_with_context(a, 1429, 'Graph.Mod', 'GetClipboardText');
- Delay(1);
- a := Al.get_clipboard_text(win.display)
- END
- END;
- IF a # 0 THEN p := SYSTEM.VAL(P, a); Utf8.Decode(p^, s);
- Al.free_with_context(a, 1434, 'Graph.Mod', 'GetClipboardText')
- ELSE s[0] := 0X
- END
- END GetClipboardText;
- PROCEDURE SetClipboardText*(win: Window; s: ARRAY OF CHAR);
- TYPE P = POINTER [1] TO ARRAY 50000 OF SHORTCHAR;
- VAR q: ARRAY 200000 OF SHORTCHAR;
- BEGIN
- Utf8.Encode(s, q);
- IF Al.set_clipboard_text(win.display, SYSTEM.VAL(Al.ADRINT, SYSTEM.ADR(q)))
- THEN END
- END SetClipboardText;
- (** Time **)
- PROCEDURE Time*(): REAL;
- RETURN Al.get_time() END Time;
- (** Window Icons **)
- PROCEDURE SetWindowIconsEx*(win: Window; icons: ARRAY OF Bitmap;
- from, len: INTEGER);
- VAR m: ARRAY 64 OF Al.Bitmap;
- i: INTEGER;
- BEGIN
- FOR i := 0 TO len - 1 DO m[i] := icons[from + i].bmp END;
- FOR i := 0 TO len - 1 DO win.icons[i] := m[i] END;
- win.noficons := len;
- Al.set_display_icons(win.display, len, m)
- END SetWindowIconsEx;
- PROCEDURE SetWindowIcons*(win: Window; icons: ARRAY OF Bitmap);
- BEGIN SetWindowIconsEx(win, icons, 0, LEN(icons))
- END SetWindowIcons;
- PROCEDURE SetWindowIcon*(win: Window; icon: Bitmap);
- VAR i: INTEGER;
- BEGIN
- FOR i := 1 TO LEN(win.icons) - 1 DO win.icons[i] := NIL END;
- win.icons[0] := icon.bmp; win.noficons := 1;
- Al.set_display_icon(win.display, icon.bmp)
- END SetWindowIcon;
- (** Init **)
- PROCEDURE InitScreen(): BOOLEAN;
- VAR opt: SET;
- BEGIN
- opt := settings;
- IF {fullscreen, window} * opt = {} THEN INCL(opt, fullscreen)
- ELSIF fullscreen IN opt THEN EXCL(opt, window)
- END;
- IF (wantW <= 0) OR (wantH <= 0) THEN
- IF fullscreen IN opt THEN wantW := -1; wantH := -1
- ELSE wantW := 640; wantH := 400
- END
- END
- RETURN NewWindow(-1, -1, wantW, wantH, wantTitle, opt) # NIL END InitScreen;
- PROCEDURE Init*;
- VAR ok: BOOLEAN;
- BEGIN ok := TRUE;
- IF Al.install_system(Al.get_allegro_version(), 0) THEN
- IF ~Al.install_keyboard() THEN
- Error('Could not install keyboard.'); ok := FALSE
- END;
- IF ~(noMouse IN settings) & ~Al.install_mouse() THEN
- Error('Could not install mouse.'); ok := FALSE
- END;
- IF ~Al.init_primitives_addon() THEN
- Error('Could not init primitives addon.'); ok := FALSE
- END;
- IF ~Al.init_image_addon() THEN
- Error('Could not init image addon.'); ok := FALSE
- END;
- queue := Al.create_event_queue();
- IF queue = NIL THEN
- Error('Could not create queue.'); ok := FALSE
- END;
- IF ok THEN
- Al.init_user_event_source(userEventSource);
- Al.register_event_source(queue,
- SYSTEM.VAL(Al.PEventSource, SYSTEM.ADR(userEventSource)));
- Al.register_event_source(queue, Al.get_keyboard_event_source());
- IF ~(noMouse IN settings) THEN
- Al.register_event_source(queue, Al.get_mouse_event_source())
- END
- END;
- IF ~(manual IN settings) THEN
- IF ~InitScreen() THEN ok := FALSE END
- END
- ELSE Error('Could not init Allegro.'); ok := FALSE
- END;
- charRead := 0X; specialChar := FALSE;
- Done := ok
- END Init;
- PROCEDURE ResetDefaults;
- BEGIN
- wantW := 640; wantH := 400; wantSizeStepX := 1; wantSizeStepY := 1;
- wantScaleX := 1.0; wantScaleY := 1.0; wantZoom := 1.0;
- settings := {};
- wantTitle := 'Oberon';
- (* Reset global variables *)
- queue := NIL; windowList := NIL; timerList := NIL;
- screen := NIL; target := NIL
- END ResetDefaults;
- PROCEDURE Close*;
- BEGIN
- Al.uninstall_system;
- ResetDefaults
- END Close;
- BEGIN Done := FALSE;
- MakeCol(black, 0, 0, 0);
- ResetDefaults
- END Graph.
|