123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089 |
- { GPC demo program for the CRT unit.
- Copyright (C) 1999-2006 Free Software Foundation, Inc.
- Author: Frank Heckenbach <frank@pascal.gnu.de>
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation, version 2.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- As a special exception, if you incorporate even large parts of the
- code of this demo program into another program with substantially
- different functionality, this does not cause the other program to
- be covered by the GNU General Public License. This exception does
- not however invalidate any other reasons why it might be covered
- by the GNU General Public License. }
- {$gnu-pascal,I+}
- program CRTDemo;
- uses GPC, CRT;
- type
- TFrameChars = array [1 .. 8] of Char;
- TSimulateBlockCursorKind = (bc_None, bc_Blink, bc_Static);
- const
- SingleFrame: TFrameChars = (chCornerTLS, chLineHS, chCornerTRS, chLineVS, chLineVS, chCornerBLS, chLineHS, chCornerBRS);
- DoubleFrame: TFrameChars = (chCornerTLD, chLineHD, chCornerTRD, chLineVD, chLineVD, chCornerBLD, chLineHD, chCornerBRD);
- var
- ScrollState: Boolean = True;
- SimulateBlockCursorKind: TSimulateBlockCursorKind = bc_None;
- CursorShape: TCursorShape = CursorNormal;
- MainPanel: TPanel;
- OrigScreenSize: TPoint;
- procedure FrameWin (const Title: String; const Frame: TFrameChars; TitleInverse: Boolean);
- var
- w, h, y, Color: Integer;
- Attr: TTextAttr;
- begin
- HideCursor;
- SetPCCharSet (True);
- ClrScr;
- w := GetXMax;
- h := GetYMax;
- WriteCharAt (1, 1, 1, Frame[1], TextAttr);
- WriteCharAt (2, 1, w - 2, Frame[2], TextAttr);
- WriteCharAt (w, 1, 1, Frame[3], TextAttr);
- for y := 2 to h - 1 do
- begin
- WriteCharAt (1, y, 1, Frame[4], TextAttr);
- WriteCharAt (w, y, 1, Frame[5], TextAttr)
- end;
- WriteCharAt (1, h, 1, Frame[6], TextAttr);
- WriteCharAt (2, h, w - 2, Frame[7], TextAttr);
- WriteCharAt (w, h, 1, Frame[8], TextAttr);
- SetPCCharSet (False);
- Attr := TextAttr;
- if TitleInverse then
- begin
- Color := GetTextColor;
- TextColor (GetTextBackground);
- TextBackground (Color)
- end;
- WriteStrAt ((w - Length (Title)) div 2 + 1, 1, Title, TextAttr);
- TextAttr := Attr
- end;
- function GetKey (TimeOut: Integer) = Key: TKey; forward;
- procedure ClosePopUpWindow;
- begin
- PanelDelete (GetActivePanel);
- PanelDelete (GetActivePanel)
- end;
- function PopUpConfirm (XSize, YSize: Integer; const Msg: String): Boolean;
- var
- ax, ay: Integer;
- Key: TKey;
- SSize: TPoint;
- begin
- repeat
- SSize := ScreenSize;
- ax := (SSize.x - XSize - 4) div 2 + 1;
- ay := (SSize.y - YSize - 4) div 2 + 1;
- PanelNew (ax, ay, ax + XSize + 3, ay + YSize + 1, False);
- TextBackground (Black);
- TextColor (Yellow);
- SetControlChars (True);
- FrameWin ('', DoubleFrame, False);
- NormalCursor;
- PanelNew (ax + 2, ay + 1, ax + XSize + 2, ay + YSize, False);
- ClrScr;
- Write (Msg);
- Key := GetKey (-1);
- if Key = kbScreenSizeChanged then ClosePopUpWindow
- until Key <> kbScreenSizeChanged;
- PopUpConfirm := not (Key in [kbEsc, kbAltEsc])
- end;
- procedure MainDraw;
- begin
- WriteLn ('3, F3 : Open a window');
- WriteLn ('4, F4 : Close window');
- WriteLn ('5, F5 : Previous window');
- WriteLn ('6, F6 : Next window');
- WriteLn ('7, F7 : Move window');
- WriteLn ('8, F8 : Resize window');
- Write ('q, Esc: Quit')
- end;
- procedure StatusDraw;
- const
- YesNo: array [Boolean] of String [3] = ('No', 'Yes');
- SimulateBlockCursorIDs: array [TSimulateBlockCursorKind] of String [8] = ('Off', 'Blinking', 'Static');
- CursorShapeIDs: array [TCursorShape] of String [7] = ('Ignored', 'Hidden', 'Normal', 'Fat', 'Block');
- var
- SSize: TPoint;
- begin
- WriteLn ('You can change some of the following');
- WriteLn ('settings by pressing the key shown');
- WriteLn ('in parentheses. Naturally, color and');
- WriteLn ('changing the cursor shape or screen');
- WriteLn ('size does not work on all terminals.');
- WriteLn;
- WriteLn ('XCurses version: ', YesNo[XCRT]);
- WriteLn ('CRTSavePreviousScreen: ', YesNo[CRTSavePreviousScreenWorks]);
- WriteLn ('(M)onochrome: ', YesNo[IsMonochrome]);
- SSize := ScreenSize;
- WriteLn ('Screen (C)olumns: ', SSize.x);
- WriteLn ('Screen (L)ines: ', SSize.y);
- WriteLn ('(R)estore screen size');
- WriteLn ('(B)reak checking: ', YesNo[CheckBreak]);
- WriteLn ('(S)crolling: ', YesNo[ScrollState]);
- WriteLn ('S(i)mulated block cursor: ', SimulateBlockCursorIDs[SimulateBlockCursorKind]);
- Write ('C(u)rsor shape: ', CursorShapeIDs[CursorShape]);
- GotoXY (36, WhereY)
- end;
- procedure RedrawAll; forward;
- procedure CheckScreenSize; forward;
- procedure StatusKey (Key: TKey);
- var SSize, NewSize: TPoint;
- begin
- case LoCase (Key2Char (Key)) of
- 'm': begin
- SetMonochrome (not IsMonochrome);
- RedrawAll
- end;
- 'c': begin
- SSize := ScreenSize;
- if SSize.x > 40 then
- NewSize.x := 40
- else
- NewSize.x := 80;
- if SSize.y > 25 then
- NewSize.y := 50
- else
- NewSize.y := 25;
- SetScreenSize (NewSize.x, NewSize.y);
- CheckScreenSize
- end;
- 'l': begin
- SSize := ScreenSize;
- if SSize.x > 40 then
- NewSize.x := 80
- else
- NewSize.x := 40;
- if SSize.y > 25 then
- NewSize.y := 25
- else
- NewSize.y := 50;
- SetScreenSize (NewSize.x, NewSize.y);
- CheckScreenSize
- end;
- 'r': begin
- SetScreenSize (OrigScreenSize.x, OrigScreenSize.y);
- CheckScreenSize
- end;
- 'b': CheckBreak := not CheckBreak;
- 's': ScrollState := not ScrollState;
- 'i': if SimulateBlockCursorKind = High (SimulateBlockCursorKind) then
- SimulateBlockCursorKind := Low (SimulateBlockCursorKind)
- else
- Inc (SimulateBlockCursorKind);
- 'u': case CursorShape of
- CursorNormal: CursorShape := CursorBlock;
- CursorFat,
- CursorBlock : CursorShape := CursorHidden;
- else CursorShape := CursorNormal
- end;
- end;
- ClrScr;
- StatusDraw
- end;
- procedure TextAttrDemo;
- var f, b, y, x1, y1, x2, y2, Fill, n1, n2, n3: Integer;
- begin
- GetWindow (x1, y1, x2, y2);
- Window (x1 - 1, y1, x2, y2);
- TextColor (White);
- TextBackground (Blue);
- ClrScr;
- SetScroll (False);
- Fill := GetXMax - 32;
- for y := 1 to GetYMax do
- begin
- GotoXY (1, y);
- b := (y - 1) mod 16;
- n1 := 0;
- for f := 0 to 15 do
- begin
- TextAttr := f + 16 * b;
- n2 := (Fill * (1 + 2 * f) + 16) div 32;
- n3 := (Fill * (2 + 2 * f) + 16) div 32;
- Write ('' : n2 - n1, NumericBaseDigitsUpper[b], NumericBaseDigitsUpper[f], '' : n3 - n2);
- n1 := n3
- end
- end
- end;
- procedure CharSetDemo (UsePCCharSet: Boolean);
- var h, l, y, x1, y1, x2, y2, Fill, n1, n2: Integer;
- begin
- GetWindow (x1, y1, x2, y2);
- Window (x1 - 1, y1, x2, y2);
- ClrScr;
- SetScroll (False);
- SetPCCharSet (UsePCCharSet);
- SetControlChars (False);
- Fill := GetXMax - 35;
- for y := 1 to GetYMax do
- begin
- GotoXY (1, y);
- h := (y - 2) mod 16;
- n1 := (Fill + 9) div 18;
- if y = 1 then
- Write ('' : 3 + n1)
- else
- Write (16 * h : 3 + n1);
- for l := 0 to 15 do
- begin
- n2 := (Fill * (2 + l) + 9) div 18;
- if y = 1 then
- Write ('' : n2 - n1, l : 2)
- else
- Write ('' : n2 - n1 + 1, Chr (16 * h + l));
- n1 := n2
- end
- end
- end;
- procedure NormalCharSetDemo;
- begin
- CharSetDemo (False)
- end;
- procedure PCCharSetDemo;
- begin
- CharSetDemo (True)
- end;
- procedure FKeyDemoDraw;
- var x1, y1, x2, y2: Integer;
- begin
- GetWindow (x1, y1, x2, y2);
- Window (x1, y1, x2 - 1, y2);
- ClrScr;
- SetScroll (False);
- WriteLn ('You can type the following keys');
- WriteLn ('(function keys if present on the');
- WriteLn ('terminal, letters as alternatives):');
- GotoXY (1, 4);
- WriteLn ('S, Left : left (wrap-around)');
- WriteLn ('D, Right : right (wrap-around)');
- WriteLn ('E, Up : up (wrap-around)');
- WriteLn ('X, Down : down (wrap-around)');
- WriteLn ('A, Home : go to first column');
- WriteLn ('F, End : go to last column');
- WriteLn ('R, Page Up : go to first line');
- WriteLn ('C, Page Down: go to last line');
- WriteLn ('Y, Ctrl-PgUp: first column and line');
- GotoXY (1, 13);
- WriteLn ('B, Ctrl-PgDn: last column and line');
- WriteLn ('Z, Ctrl-Home: clear screen');
- WriteLn ('N, Ctrl-End : clear to end of line');
- WriteLn ('V, Insert : insert a line');
- WriteLn ('T, Delete : delete a line');
- WriteLn ('# : beep');
- WriteLn ('* : flash');
- WriteLn ('Tab, Enter, Backspace, other');
- WriteLn (' normal characters: write text')
- end;
- procedure FKeyDemoKey (Key: TKey);
- const TabSize = 8;
- var
- ch: Char;
- NewX: Integer;
- begin
- case LoCaseKey (Key) of
- Ord ('s'), kbLeft : if WhereX = 1 then GotoXY (GetXMax, WhereY) else GotoXY (WhereX - 1, WhereY);
- Ord ('d'), kbRight : if WhereX = GetXMax then GotoXY (1, WhereY) else GotoXY (WhereX + 1, WhereY);
- Ord ('e'), kbUp : if WhereY = 1 then GotoXY (WhereX, GetYMax) else GotoXY (WhereX, WhereY - 1);
- Ord ('x'), kbDown : if WhereY = GetYMax then GotoXY (WhereX, 1) else GotoXY (WhereX, WhereY + 1);
- Ord ('a'), kbHome : Write (chCR);
- Ord ('f'), kbEnd : GotoXY (GetXMax, WhereY);
- Ord ('r'), kbPgUp : GotoXY (WhereX, 1);
- Ord ('c'), kbPgDn : GotoXY (WhereX, GetYMax);
- Ord ('y'), kbCtrlPgUp: GotoXY (1, 1);
- Ord ('b'), kbCtrlPgDn: GotoXY (GetXMax, GetYMax);
- Ord ('z'), kbCtrlHome: ClrScr;
- Ord ('n'), kbCtrlEnd : ClrEOL;
- Ord ('v'), kbIns : InsLine;
- Ord ('t'), kbDel : DelLine;
- Ord ('#') : Beep;
- Ord ('*') : Flash;
- kbTab : begin
- NewX := ((WhereX - 1) div TabSize + 1) * TabSize + 1;
- if NewX <= GetXMax then GotoXY (NewX, WhereY) else WriteLn
- end;
- kbCR : WriteLn;
- kbBkSp : Write (chBkSp, ' ', chBkSp);
- else ch := Key2Char (Key);
- if ch <> #0 then Write (ch)
- end
- end;
- procedure KeyDemoDraw;
- begin
- WriteLn ('Press some keys ...')
- end;
- procedure KeyDemoKey (Key: TKey);
- var ch: Char;
- begin
- ch := Key2Char (Key);
- if ch <> #0 then
- begin
- Write ('Normal key');
- if IsPrintable (ch) then Write (' `', ch, '''');
- WriteLn (', ASCII #', Ord (ch))
- end
- else
- WriteLn ('Special key ', Ord (Key2Scan (Key)))
- end;
- procedure IOSelectPeriodical;
- var
- CurrentTime: TimeStamp;
- s: String (8);
- i: Integer;
- begin
- GetTimeStamp (CurrentTime);
- with CurrentTime do
- WriteStr (s, Hour : 2, ':', Minute : 2, ':', Second : 2);
- for i := 1 to Length (s) do
- if s[i] = ' ' then s[i] := '0';
- GotoXY (1, 12);
- Write ('The time is: ', s)
- end;
- procedure IOSelectDraw;
- begin
- WriteLn ('IOSelect is a way to handle I/O from');
- WriteLn ('or to several places simultaneously,');
- WriteLn ('without having to use threads or');
- WriteLn ('signal/interrupt handlers or waste');
- WriteLn ('CPU time with busy waiting.');
- WriteLn;
- WriteLn ('This demo shows how IOSelect works');
- WriteLn ('in connection with CRT. It displays');
- WriteLn ('a clock, but still reacts to user');
- WriteLn ('input immediately.');
- IOSelectPeriodical
- end;
- procedure ModifierPeriodical;
- const
- Pressed: array [Boolean] of String [8] = ('Released', 'Pressed');
- ModifierNames: array [1 .. 7] of record
- Modifier: Integer;
- Name: String (17)
- end =
- ((shLeftShift, 'Left Shift'),
- (shRightShift, 'Right Shift'),
- (shLeftCtrl, 'Left Control'),
- (shRightCtrl, 'Right Control'),
- (shAlt, 'Alt (left)'),
- (shAltGr, 'AltGr (right Alt)'),
- (shExtra, 'Extra'));
- var
- ShiftState, i: Integer;
- begin
- ShiftState := GetShiftState;
- for i := 1 to 7 do
- with ModifierNames[i] do
- begin
- GotoXY (1, 4 + i);
- ClrEOL;
- Write (Name, ':');
- GotoXY (20, WhereY);
- Write (Pressed[(ShiftState and Modifier) <> 0])
- end
- end;
- procedure ModifierDraw;
- begin
- WriteLn ('Modifier keys (NOTE: only');
- WriteLn ('available on some systems;');
- WriteLn ('X11: only after key press):');
- ModifierPeriodical
- end;
- procedure ChecksDraw;
- begin
- WriteLn ('(O)S shell');
- WriteLn ('OS shell with (C)learing');
- WriteLn ('(R)efresh check');
- Write ('(S)ound check')
- end;
- procedure ChecksKey (Key: TKey);
- var
- i, j: Integer;
- WasteTime: Real; attribute (volatile);
- procedure DoOSShell;
- var
- Result: Integer;
- Shell: TString;
- begin
- Shell := GetShellPath (Null);
- {$I-}
- Result := Execute (Shell);
- {$I+}
- if (InOutRes <> 0) or (Result <> 0) then
- begin
- ClrScr;
- if InOutRes <> 0 then
- WriteLn (GetIOErrorMessage, ' while trying to execute `', Shell, '''.')
- else
- WriteLn ('`', Shell, ''' returned status ', Result, '.');
- Write ('Any key to continue.');
- BlockCursor;
- Discard (GetKey (-1))
- end
- end;
- begin
- case LoCase (Key2Char (Key)) of
- 'o': begin
- if PopUpConfirm (36, 12, 'You will now get an OS shell. Unless' + NewLine +
- 'CRTDemo is running in its own (GUI)' + NewLine +
- 'window, the shell will run on the' + NewLine +
- 'same screen as CRTDemo which is not' + NewLine +
- 'cleared before the shell is started.' + NewLine +
- 'If possible, the screen contents are' + NewLine +
- 'restored to the state before CRTDemo' + NewLine +
- 'was started. After leaving the shell' + NewLine +
- 'in the usual way (usually by enter-' + NewLine +
- 'ing `exit''), you will get back to' + NewLine +
- 'the demo. <ESC> to abort, any other' + NewLine +
- 'key to start.') then
- begin
- RestoreTerminal (True);
- DoOSShell
- end;
- ClosePopUpWindow
- end;
- 'c': begin
- if PopUpConfirm (36, 9, 'You will now get an OS shell. Unless' + NewLine +
- 'CRTDemo is running in its own (GUI)' + NewLine +
- 'window, the screen will be cleared,' + NewLine +
- 'and the cursor will be moved to the' + NewLine +
- 'top before the shell is started.' + NewLine +
- 'After leaving the shell in the usual' + NewLine +
- 'way (usually by entering `exit''),' + NewLine +
- 'you will get back to the demo. <ESC>' + NewLine +
- 'to abort, any other key to start.') then
- begin
- RestoreTerminalClearCRT;
- DoOSShell
- end;
- ClosePopUpWindow
- end;
- 'r': begin
- if PopUpConfirm (36, 11, 'The program will now get busy with' + NewLine +
- 'some dummy computations. However,' + NewLine +
- 'CRT output in the form of dots will' + NewLine +
- 'still appear continuously one by one' + NewLine +
- '(rather than the whole line at once' + NewLine +
- 'in the end). While running, the test' + NewLine +
- 'cannot be interrupted. <ESC> to' + NewLine +
- 'abort, any other key to start.') then
- begin
- SetCRTUpdate (UpdateRegularly);
- BlockCursor;
- WriteLn;
- WriteLn;
- for i := 1 to GetXMax - 2 do
- begin
- Write ('.');
- for j := 1 to 400000 do WasteTime := Random
- end;
- SetCRTUpdate (UpdateInput);
- WriteLn;
- Write ('Press any key.');
- Discard (GetKey (-1))
- end;
- ClosePopUpWindow
- end;
- 's': begin
- if PopUpConfirm (32, 4, 'You will now hear some sounds if' + NewLine +
- 'supported (otherwise there will' + NewLine +
- 'just be a short pause). <ESC> to' + NewLine +
- 'abort, any other key to start.') then
- begin
- BlockCursor;
- for i := 0 to 7 do
- begin
- Sound (Round (440 * 2 ** (Round (i * 12 / 7 + 0.3) / 12)));
- if GetKey (400000) in [kbEsc, kbAltEsc] then Break
- end;
- NoSound
- end;
- ClosePopUpWindow
- end;
- end
- end;
- type
- PWindowList = ^TWindowList;
- TWindowList = record
- Next, Prev: PWindowList;
- Panel, FramePanel: TPanel;
- WindowType: Integer;
- x1, y1, xs, ys: Integer;
- State: (ws_None, ws_Moving, ws_Resizing);
- end;
- TKeyProc = procedure (Key: TKey);
- TProcedure = procedure;
- const
- MenuNameLength = 16;
- WindowTypes: array [0 .. 9] of record
- DrawProc,
- PeriodicalProc: procedure;
- KeyProc : TKeyProc;
- Name : String (MenuNameLength);
- Color,
- Background,
- MinSizeX,
- MinSizeY,
- PrefSizeX,
- PrefSizeY : Integer;
- RedrawAlways,
- WantCursor : Boolean
- end =
- ((MainDraw , nil , nil , 'CRT Demo' , LightGreen, Blue , 26, 7, 0, 0, False, False),
- (StatusDraw , nil , StatusKey , 'Status' , White , Red , 38, 16, 0, 0, True, True),
- (TextAttrDemo , nil , nil , 'Text Attributes' , White , Blue , 32, 16, 64, 16, False, False),
- (NormalCharSetDemo, nil , nil , 'Character Set' , Black , Green , 35, 17, 53, 17, False, False),
- (PCCharSetDemo , nil , nil , 'PC Character Set', Black , Brown , 35, 17, 53, 17, False, False),
- (KeyDemoDraw , nil , KeyDemoKey , 'Keys' , Blue , LightGray, 29, 5, -1, -1, False, True),
- (FKeyDemoDraw , nil , FKeyDemoKey, 'Function Keys' , Blue , LightGray, 37, 22, -1, -1, False, True),
- (ModifierDraw , ModifierPeriodical, nil , 'Modifier Keys' , Black , Cyan , 29, 11, 0, 0, True, False),
- (IOSelectDraw , IOSelectPeriodical, nil , 'IOSelect Demo' , White , Magenta , 38, 12, 0, 0, False, False),
- (ChecksDraw , nil , ChecksKey , 'Various Checks' , Black , Red , 26, 4, 0, 0, False, False));
- MenuMax = High (WindowTypes);
- MenuXSize = MenuNameLength + 4;
- MenuYSize = MenuMax + 2;
- var
- WindowList: PWindowList = nil;
- procedure RedrawFrame (p: PWindowList);
- begin
- with p^, WindowTypes[WindowType] do
- begin
- PanelActivate (FramePanel);
- Window (x1, y1, x1 + xs - 1, y1 + ys - 1);
- ClrScr;
- case State of
- ws_None : if p = WindowList then
- FrameWin (' ' + Name + ' ', DoubleFrame, True)
- else
- FrameWin (' ' + Name + ' ', SingleFrame, False);
- ws_Moving : FrameWin (' Move Window ', SingleFrame, True);
- ws_Resizing: FrameWin (' Resize Window ', SingleFrame, True);
- end
- end
- end;
- procedure DrawWindow (p: PWindowList);
- begin
- with p^, WindowTypes[WindowType] do
- begin
- RedrawFrame (p);
- PanelActivate (Panel);
- Window (x1 + 2, y1 + 1, x1 + xs - 2, y1 + ys - 2);
- ClrScr;
- DrawProc
- end
- end;
- procedure RedrawAll;
- var
- LastPanel: TPanel;
- p: PWindowList;
- x2, y2: Integer;
- begin
- LastPanel := GetActivePanel;
- PanelActivate (MainPanel);
- TextBackground (Blue);
- ClrScr;
- p := WindowList;
- if p <> nil then
- repeat
- with p^ do
- begin
- PanelActivate (FramePanel);
- GetWindow (x1, y1, x2, y2); { updated automatically by CRT }
- xs := x2 - x1 + 1;
- ys := y2 - y1 + 1
- end;
- DrawWindow (p);
- p := p^.Next
- until p = WindowList;
- PanelActivate (LastPanel)
- end;
- procedure CheckScreenSize;
- var
- LastPanel: TPanel;
- MinScreenSizeX, MinScreenSizeY, i: Integer;
- SSize: TPoint;
- begin
- LastPanel := GetActivePanel;
- PanelActivate (MainPanel);
- HideCursor;
- MinScreenSizeX := MenuXSize;
- MinScreenSizeY := MenuYSize;
- for i := Low (WindowTypes) to High (WindowTypes) do
- with WindowTypes[i] do
- begin
- MinScreenSizeX := Max (MinScreenSizeX, MinSizeX + 2);
- MinScreenSizeY := Max (MinScreenSizeY, MinSizeY + 2)
- end;
- SSize := ScreenSize;
- Window (1, 1, SSize.x, SSize.y);
- if (SSize.x < MinScreenSizeX) or (SSize.y < MinScreenSizeY) then
- begin
- NormVideo;
- ClrScr;
- RestoreTerminal (True);
- WriteLn (StdErr, 'Sorry, your screen is too small for this demo (', SSize.x, 'x', SSize.y, ').');
- WriteLn (StdErr, 'You need at least ', MinScreenSizeX, 'x', MinScreenSizeY, ' characters.');
- Halt (2)
- end;
- PanelActivate (LastPanel);
- RedrawAll
- end;
- procedure Die; attribute (noreturn);
- begin
- NoSound;
- RestoreTerminalClearCRT;
- WriteLn (StdErr, 'You''re trying to kill me. Since I have break checking turned off,');
- WriteLn (StdErr, 'I''m not dying, but I''ll do you a favour and terminate now.');
- Halt (3)
- end;
- function GetKey (TimeOut: Integer) = Key: TKey;
- var
- NeedSelect, SelectValue: Integer;
- SimulateBlockCursorCurrent: TSimulateBlockCursorKind;
- SelectInput: array [1 .. 1] of PAnyFile = (@Input);
- NextSelectTime: MicroSecondTimeType = 0; attribute (static);
- TimeOutTime: MicroSecondTimeType;
- LastPanel: TPanel;
- p: PWindowList;
- begin
- LastPanel := GetActivePanel;
- if TimeOut < 0 then
- TimeOutTime := High (TimeOutTime)
- else
- TimeOutTime := GetMicroSecondTime + TimeOut;
- NeedSelect := 0;
- if TimeOut >= 0 then
- Inc (NeedSelect);
- SimulateBlockCursorCurrent := SimulateBlockCursorKind;
- if SimulateBlockCursorCurrent <> bc_None then
- Inc (NeedSelect);
- p := WindowList;
- repeat
- if @WindowTypes[p^.WindowType].PeriodicalProc <> nil then
- Inc (NeedSelect);
- p := p^.Next
- until p = WindowList;
- p := WindowList;
- repeat
- with p^, WindowTypes[WindowType] do
- if RedrawAlways then
- begin
- PanelActivate (Panel);
- ClrScr;
- DrawProc
- end;
- p := p^.Next
- until p = WindowList;
- if NeedSelect <> 0 then
- repeat
- CRTUpdate;
- SelectValue := IOSelectRead (SelectInput, Max (0, Min (NextSelectTime, TimeOutTime) - GetMicroSecondTime));
- if SelectValue = 0 then
- begin
- case SimulateBlockCursorCurrent of
- bc_None : ;
- bc_Blink : SimulateBlockCursor;
- bc_Static: begin
- SimulateBlockCursor;
- SimulateBlockCursorCurrent := bc_None;
- Dec (NeedSelect)
- end
- end;
- NextSelectTime := GetMicroSecondTime + 120000;
- p := WindowList;
- repeat
- with p^, WindowTypes[WindowType] do
- if @PeriodicalProc <> nil then
- begin
- PanelActivate (Panel);
- PeriodicalProc
- end;
- p := p^.Next
- until p = WindowList
- end;
- until (NeedSelect = 0) or (SelectValue <> 0) or ((TimeOut >= 0) and (GetMicroSecondTime >= TimeOutTime));
- if NeedSelect = 0 then
- SelectValue := 1;
- if SelectValue = 0 then
- Key := 0
- else
- Key := ReadKeyWord;
- if SimulateBlockCursorKind <> bc_None then
- SimulateBlockCursorOff;
- if IsDeadlySignal (Key) then Die;
- if Key = kbScreenSizeChanged then CheckScreenSize;
- PanelActivate (LastPanel)
- end;
- function Menu = n: Integer;
- var
- i, ax, ay: Integer;
- Key: TKey;
- Done: Boolean;
- SSize: TPoint;
- begin
- n := 1;
- repeat
- SSize := ScreenSize;
- ax := (SSize.x - MenuXSize) div 2 + 1;
- ay := (SSize.y - MenuYSize) div 2 + 1;
- PanelNew (ax, ay, ax + MenuXSize - 1, ay + MenuYSize - 1, False);
- SetControlChars (True);
- TextColor (Blue);
- TextBackground (LightGray);
- FrameWin (' Select Window ', DoubleFrame, True);
- IgnoreCursor;
- PanelNew (ax + 1, ay + 1, ax + MenuXSize - 2, ay + MenuYSize - 2, False);
- ClrScr;
- TextColor (Black);
- SetScroll (False);
- Done := False;
- repeat
- for i := 1 to MenuMax do
- begin
- GotoXY (1, i);
- if i = n then
- TextBackground (Green)
- else
- TextBackground (LightGray);
- ClrEOL;
- Write (' ', WindowTypes[i].Name);
- ChangeTextAttr (2, i, 1, Red + $10 * GetTextBackground)
- end;
- Key := GetKey (-1);
- case LoCaseKey (Key) of
- kbUp : if n = 1 then n := MenuMax else Dec (n);
- kbDown : if n = MenuMax then n := 1 else Inc (n);
- kbHome,
- kbPgUp,
- kbCtrlPgUp,
- kbCtrlHome : n := 1;
- kbEnd,
- kbPgDn,
- kbCtrlPgDn,
- kbCtrlEnd : n := MenuMax;
- kbCR : Done := True;
- kbEsc, kbAltEsc : begin
- n := -1;
- Done := True
- end;
- Ord ('a') .. Ord ('z'): begin
- i := MenuMax;
- while (i > 0) and (LoCase (Key2Char (Key)) <> LoCase (WindowTypes[i].Name[1])) do Dec (i);
- if i > 0 then
- begin
- n := i;
- Done := True
- end
- end;
- end
- until Done or (Key = kbScreenSizeChanged);
- ClosePopUpWindow
- until Key <> kbScreenSizeChanged
- end;
- procedure NewWindow (WindowType, ax, ay: Integer);
- var
- p, LastWindow: PWindowList;
- MaxX1, MaxY1: Integer;
- SSize: TPoint;
- begin
- New (p);
- if WindowList = nil then
- begin
- p^.Prev := p;
- p^.Next := p
- end
- else
- begin
- p^.Prev := WindowList;
- p^.Next := WindowList^.Next;
- p^.Prev^.Next := p;
- p^.Next^.Prev := p;
- end;
- p^.WindowType := WindowType;
- with p^, WindowTypes[WindowType] do
- begin
- SSize := ScreenSize;
- if PrefSizeX > 0 then xs := PrefSizeX else xs := MinSizeX;
- if PrefSizeY > 0 then ys := PrefSizeY else ys := MinSizeY;
- xs := Min (xs + 2, SSize.x);
- ys := Min (ys + 2, SSize.y);
- MaxX1 := SSize.x - xs + 1;
- MaxY1 := SSize.y - ys + 1;
- if ax = 0 then x1 := Random (MaxX1) + 1 else x1 := Min (ax, MaxX1);
- if ay = 0 then y1 := Random (MaxY1) + 1 else y1 := Min (ay, MaxY1);
- if (ax = 0) and (PrefSizeX < 0) then Inc (xs, Random (SSize.x - x1 - xs + 2));
- if (ax = 0) and (PrefSizeY < 0) then Inc (ys, Random (SSize.y - y1 - ys + 2));
- State := ws_None;
- PanelNew (1, 1, 1, 1, False);
- FramePanel := GetActivePanel;
- SetControlChars (True);
- TextColor (Color);
- TextBackground (Background);
- PanelNew (1, 1, 1, 1, False);
- SetPCCharSet (False);
- Panel := GetActivePanel;
- end;
- LastWindow := WindowList;
- WindowList := p;
- if LastWindow <> nil then RedrawFrame (LastWindow);
- DrawWindow (p)
- end;
- procedure OpenWindow;
- var WindowType: Integer;
- begin
- WindowType := Menu;
- if WindowType >= 0 then NewWindow (WindowType, 0, 0)
- end;
- procedure NextWindow;
- var LastWindow: PWindowList;
- begin
- LastWindow := WindowList;
- WindowList := WindowList^.Next;
- PanelTop (WindowList^.FramePanel);
- PanelTop (WindowList^.Panel);
- RedrawFrame (LastWindow);
- RedrawFrame (WindowList)
- end;
- procedure PreviousWindow;
- var LastWindow: PWindowList;
- begin
- PanelMoveAbove (WindowList^.Panel, MainPanel);
- PanelMoveAbove (WindowList^.FramePanel, MainPanel);
- LastWindow := WindowList;
- WindowList := WindowList^.Prev;
- RedrawFrame (LastWindow);
- RedrawFrame (WindowList)
- end;
- procedure CloseWindow;
- var p: PWindowList;
- begin
- if WindowList^.WindowType <> 0 then
- begin
- p := WindowList;
- NextWindow;
- PanelDelete (p^.FramePanel);
- PanelDelete (p^.Panel);
- p^.Next^.Prev := p^.Prev;
- p^.Prev^.Next := p^.Next;
- Dispose (p)
- end
- end;
- procedure MoveWindow;
- var
- Done, Changed: Boolean;
- SSize: TPoint;
- begin
- with WindowList^ do
- begin
- Done := False;
- Changed := True;
- State := ws_Moving;
- repeat
- if Changed then DrawWindow (WindowList);
- Changed := True;
- case LoCaseKey (GetKey (-1)) of
- Ord ('s'), kbLeft : if x1 > 1 then Dec (x1);
- Ord ('d'), kbRight : if x1 + xs - 1 < ScreenSize.x then Inc (x1);
- Ord ('e'), kbUp : if y1 > 1 then Dec (y1);
- Ord ('x'), kbDown : if y1 + ys - 1 < ScreenSize.y then Inc (y1);
- Ord ('a'), kbHome : x1 := 1;
- Ord ('f'), kbEnd : x1 := ScreenSize.x - xs + 1;
- Ord ('r'), kbPgUp : y1 := 1;
- Ord ('c'), kbPgDn : y1 := ScreenSize.y - ys + 1;
- Ord ('y'), kbCtrlPgUp: begin
- x1 := 1;
- y1 := 1
- end;
- Ord ('b'), kbCtrlPgDn: begin
- SSize := ScreenSize;
- x1 := SSize.x - xs + 1;
- y1 := SSize.y - ys + 1
- end;
- kbCR,
- kbEsc, kbAltEsc : Done := True;
- else Changed := False
- end
- until Done;
- State := ws_None;
- DrawWindow (WindowList)
- end
- end;
- procedure ResizeWindow;
- var
- Done, Changed: Boolean;
- SSize: TPoint;
- begin
- with WindowList^, WindowTypes[WindowType] do
- begin
- Done := False;
- Changed := True;
- State := ws_Resizing;
- repeat
- if Changed then DrawWindow (WindowList);
- Changed := True;
- case LoCaseKey (GetKey (-1)) of
- Ord ('s'), kbLeft : if xs > MinSizeX + 2 then Dec (xs);
- Ord ('d'), kbRight : if x1 + xs - 1 < ScreenSize.x then Inc (xs);
- Ord ('e'), kbUp : if ys > MinSizeY + 2 then Dec (ys);
- Ord ('x'), kbDown : if y1 + ys - 1 < ScreenSize.y then Inc (ys);
- Ord ('a'), kbHome : xs := MinSizeX + 2;
- Ord ('f'), kbEnd : xs := ScreenSize.x - x1 + 1;
- Ord ('r'), kbPgUp : ys := MinSizeY + 2;
- Ord ('c'), kbPgDn : ys := ScreenSize.y - y1 + 1;
- Ord ('y'), kbCtrlPgUp: begin
- xs := MinSizeX + 2;
- ys := MinSizeY + 2
- end;
- Ord ('b'), kbCtrlPgDn: begin
- SSize := ScreenSize;
- xs := SSize.x - x1 + 1;
- ys := SSize.y - y1 + 1
- end;
- kbCR,
- kbEsc, kbAltEsc : Done := True;
- else Changed := False
- end
- until Done;
- State := ws_None;
- DrawWindow (WindowList)
- end
- end;
- procedure ActivateCursor;
- begin
- with WindowList^, WindowTypes[WindowType] do
- begin
- PanelActivate (Panel);
- if WantCursor then
- SetCursorShape (CursorShape)
- else
- HideCursor
- end;
- SetScroll (ScrollState)
- end;
- var
- Key: TKey;
- ScreenShot, Done: Boolean;
- begin
- ScreenShot := ParamStr (1) = '--screenshot';
- if ParamCount <> Ord (ScreenShot) then
- begin
- RestoreTerminal (True);
- WriteLn (StdErr, ParamStr (0), ': invalid argument `', ParamStr (Ord (ScreenShot) + 1), '''');
- Halt (1)
- end;
- CRTSavePreviousScreen (True);
- SetCRTUpdate (UpdateInput);
- MainPanel := GetActivePanel;
- CheckScreenSize;
- OrigScreenSize := ScreenSize;
- if ScreenShot then
- begin
- CursorShape := CursorBlock;
- NewWindow (6, 1, 1);
- NewWindow (2, 1, MaxInt);
- NewWindow (8, MaxInt, 1);
- NewWindow (5, 1, 27);
- KeyDemoKey (Ord ('f'));
- KeyDemoKey (246);
- KeyDemoKey (kbDown);
- NewWindow (3, MaxInt, 13);
- NewWindow (4, MaxInt, 31);
- NewWindow (7, MaxInt, MaxInt);
- NewWindow (9, MaxInt, 33);
- NewWindow (0, 1, 2);
- NewWindow (1, 1, 14);
- ActivateCursor;
- OpenWindow
- end
- else
- NewWindow (0, 3, 2);
- Done := False;
- repeat
- ActivateCursor;
- Key := GetKey (-1);
- case LoCaseKey (Key) of
- Ord ('3'), kbF3 : OpenWindow;
- Ord ('4'), kbF4 : CloseWindow;
- Ord ('5'), kbF5 : PreviousWindow;
- Ord ('6'), kbF6 : NextWindow;
- Ord ('7'), kbF7 : MoveWindow;
- Ord ('8'), kbF8 : ResizeWindow;
- Ord ('q'), kbEsc,
- kbAltEsc: Done := True;
- else
- if WindowList <> nil then
- with WindowList^, WindowTypes[WindowType] do
- if @KeyProc <> nil then
- begin
- TextColor (Color);
- TextBackground (Background);
- KeyProc (Key)
- end
- end
- until Done
- end.
|