1 { GPC demo program for the CRT unit.
3 Copyright (C) 1999-2006, 2013 Free Software Foundation, Inc.
5 Author: Frank Heckenbach <frank@pascal.gnu.de>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation, version 3.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 As a special exception, if you incorporate even large parts of the
20 code of this demo program into another program with substantially
21 different functionality, this does not cause the other program to
22 be covered by the GNU General Public License. This exception does
23 not however invalidate any other reasons why it might be covered
24 by the GNU General Public License. }
28 (* second style of comment *)
29 // Free-pascal style comment.
30 var x
:Char = 12 /* 45; // This /* does not start a comment.
31 var x
:Char = (/ 4); // This (/ does not start a comment.
38 TFrameChars
= array [1 .. 8] of Char;
39 TSimulateBlockCursorKind
= (bc_None
, bc_Blink
, bc_Static
);
42 SingleFrame
: TFrameChars
= (chCornerTLS
, chLineHS
, chCornerTRS
, chLineVS
, chLineVS
, chCornerBLS
, chLineHS
, chCornerBRS
);
43 DoubleFrame
: TFrameChars
= (chCornerTLD
, chLineHD
, chCornerTRD
, chLineVD
, chLineVD
, chCornerBLD
, chLineHD
, chCornerBRD
);
46 ScrollState
: Boolean = True;
47 SimulateBlockCursorKind
: TSimulateBlockCursorKind
= bc_None
;
48 CursorShape
: TCursorShape
= CursorNormal
;
50 OrigScreenSize
: TPoint
;
52 procedure FrameWin (const Title
: String; const Frame
: TFrameChars
; TitleInverse
: Boolean);
54 w
, h
, y
, Color
: Integer;
62 WriteCharAt (1, 1, 1, Frame
[1], TextAttr
);
63 WriteCharAt (2, 1, w
- 2, Frame
[2], TextAttr
);
64 WriteCharAt (w
, 1, 1, Frame
[3], TextAttr
);
65 for y
:= 2 to h
- 1 do
67 WriteCharAt (1, y
, 1, Frame
[4], TextAttr
);
68 WriteCharAt (w
, y
, 1, Frame
[5], TextAttr
)
70 WriteCharAt (1, h
, 1, Frame
[6], TextAttr
);
71 WriteCharAt (2, h
, w
- 2, Frame
[7], TextAttr
);
72 WriteCharAt (w
, h
, 1, Frame
[8], TextAttr
);
77 Color
:= GetTextColor
;
78 TextColor (GetTextBackground
);
79 TextBackground (Color
)
81 WriteStrAt ((w
- Length (Title
)) div 2 + 1, 1, Title
, TextAttr
);
85 function GetKey (TimeOut
: Integer) = Key
: TKey
; forward;
87 procedure ClosePopUpWindow
;
89 PanelDelete (GetActivePanel
);
90 PanelDelete (GetActivePanel
)
93 function PopUpConfirm (XSize
, YSize
: Integer; const Msg
: String): Boolean;
101 ax
:= (SSize
.x
- XSize
- 4) div 2 + 1;
102 ay
:= (SSize
.y
- YSize
- 4) div 2 + 1;
103 PanelNew (ax
, ay
, ax
+ XSize
+ 3, ay
+ YSize
+ 1, False);
104 TextBackground (Black
);
106 SetControlChars (True);
107 FrameWin ('', DoubleFrame
, False);
109 PanelNew (ax
+ 2, ay
+ 1, ax
+ XSize
+ 2, ay
+ YSize
, False);
113 if Key
= kbScreenSizeChanged
then ClosePopUpWindow
114 until Key
<> kbScreenSizeChanged
;
115 PopUpConfirm
:= not (Key
in [kbEsc
, kbAltEsc
])
120 WriteLn ('3, F3 : Open a window');
121 WriteLn ('4, F4 : Close window');
122 WriteLn ('5, F5 : Previous window');
123 WriteLn ('6, F6 : Next window');
124 WriteLn ('7, F7 : Move window');
125 WriteLn ('8, F8 : Resize window');
126 Write ('q, Esc: Quit')
129 procedure StatusDraw
;
131 YesNo
: array [Boolean] of String [3] = ('No', 'Yes');
132 SimulateBlockCursorIDs
: array [TSimulateBlockCursorKind
] of String [8] = ('Off', 'Blinking', 'Static');
133 CursorShapeIDs
: array [TCursorShape
] of String [7] = ('Ignored', 'Hidden', 'Normal', 'Fat', 'Block');
137 WriteLn ('You can change some of the following');
138 WriteLn ('settings by pressing the key shown');
139 WriteLn ('in parentheses. Naturally, color and');
140 WriteLn ('changing the cursor shape or screen');
141 WriteLn ('size does not work on all terminals.');
143 WriteLn ('XCurses version: ', YesNo
[XCRT
]);
144 WriteLn ('CRTSavePreviousScreen: ', YesNo
[CRTSavePreviousScreenWorks
]);
145 WriteLn ('(M)onochrome: ', YesNo
[IsMonochrome
]);
147 WriteLn ('Screen (C)olumns: ', SSize
.x
);
148 WriteLn ('Screen (L)ines: ', SSize
.y
);
149 WriteLn ('(R)estore screen size');
150 WriteLn ('(B)reak checking: ', YesNo
[CheckBreak
]);
151 WriteLn ('(S)crolling: ', YesNo
[ScrollState
]);
152 WriteLn ('S(i)mulated block cursor: ', SimulateBlockCursorIDs
[SimulateBlockCursorKind
]);
153 Write ('C(u)rsor shape: ', CursorShapeIDs
[CursorShape
]);
157 procedure RedrawAll
; forward;
158 procedure CheckScreenSize
; forward;
160 procedure StatusKey (Key
: TKey
);
161 var SSize
, NewSize
: TPoint
;
163 case LoCase (Key2Char (Key
)) of
165 SetMonochrome (not IsMonochrome
);
178 SetScreenSize (NewSize
.x
, NewSize
.y
);
191 SetScreenSize (NewSize
.x
, NewSize
.y
);
195 SetScreenSize (OrigScreenSize
.x
, OrigScreenSize
.y
);
198 'b': CheckBreak
:= not CheckBreak
;
199 's': ScrollState
:= not ScrollState
;
200 'i': if SimulateBlockCursorKind
= High (SimulateBlockCursorKind
) then
201 SimulateBlockCursorKind
:= Low (SimulateBlockCursorKind
)
203 Inc (SimulateBlockCursorKind
);
204 'u': case CursorShape
of
205 CursorNormal
: CursorShape
:= CursorBlock
;
207 CursorBlock
: CursorShape
:= CursorHidden
;
208 else CursorShape
:= CursorNormal
215 procedure TextAttrDemo
;
216 var f
, b
, y
, x1
, y1
, x2
, y2
, Fill
, n1
, n2
, n3
: Integer;
218 GetWindow (x1
, y1
, x2
, y2
);
219 Window (x1
- 1, y1
, x2
, y2
);
221 TextBackground (Blue
);
224 Fill
:= GetXMax
- 32;
225 for y
:= 1 to GetYMax
do
232 TextAttr
:= f
+ 16 * b
;
233 n2
:= (Fill
* (1 + 2 * f
) + 16) div 32;
234 n3
:= (Fill
* (2 + 2 * f
) + 16) div 32;
235 Write ('' : n2
- n1
, NumericBaseDigitsUpper
[b
], NumericBaseDigitsUpper
[f
], '' : n3
- n2
);
241 procedure CharSetDemo (UsePCCharSet
: Boolean);
242 var h
, l
, y
, x1
, y1
, x2
, y2
, Fill
, n1
, n2
: Integer;
244 GetWindow (x1
, y1
, x2
, y2
);
245 Window (x1
- 1, y1
, x2
, y2
);
248 SetPCCharSet (UsePCCharSet
);
249 SetControlChars (False);
250 Fill
:= GetXMax
- 35;
251 for y
:= 1 to GetYMax
do
255 n1
:= (Fill
+ 9) div 18;
259 Write (16 * h
: 3 + n1
);
262 n2
:= (Fill
* (2 + l
) + 9) div 18;
264 Write ('' : n2
- n1
, l
: 2)
266 Write ('' : n2
- n1
+ 1, Chr (16 * h
+ l
));
272 procedure NormalCharSetDemo
;
277 procedure PCCharSetDemo
;
282 procedure FKeyDemoDraw
;
283 var x1
, y1
, x2
, y2
: Integer;
285 GetWindow (x1
, y1
, x2
, y2
);
286 Window (x1
, y1
, x2
- 1, y2
);
289 WriteLn ('You can type the following keys');
290 WriteLn ('(function keys if present on the');
291 WriteLn ('terminal, letters as alternatives):');
293 WriteLn ('S, Left : left (wrap-around)');
294 WriteLn ('D, Right : right (wrap-around)');
295 WriteLn ('E, Up : up (wrap-around)');
296 WriteLn ('X, Down : down (wrap-around)');
297 WriteLn ('A, Home : go to first column');
298 WriteLn ('F, End : go to last column');
299 WriteLn ('R, Page Up : go to first line');
300 WriteLn ('C, Page Down: go to last line');
301 WriteLn ('Y, Ctrl-PgUp: first column and line');
303 WriteLn ('B, Ctrl-PgDn: last column and line');
304 WriteLn ('Z, Ctrl-Home: clear screen');
305 WriteLn ('N, Ctrl-End : clear to end of line');
306 WriteLn ('V, Insert : insert a line');
307 WriteLn ('T, Delete : delete a line');
308 WriteLn ('# : beep');
309 WriteLn ('* : flash');
310 WriteLn ('Tab, Enter, Backspace, other');
311 WriteLn (' normal characters: write text')
314 procedure FKeyDemoKey (Key
: TKey
);
320 case LoCaseKey (Key
) of
321 Ord ('s'), kbLeft
: if WhereX
= 1 then GotoXY (GetXMax
, WhereY
) else GotoXY (WhereX
- 1, WhereY
);
322 Ord ('d'), kbRight
: if WhereX
= GetXMax
then GotoXY (1, WhereY
) else GotoXY (WhereX
+ 1, WhereY
);
323 Ord ('e'), kbUp
: if WhereY
= 1 then GotoXY (WhereX
, GetYMax
) else GotoXY (WhereX
, WhereY
- 1);
324 Ord ('x'), kbDown
: if WhereY
= GetYMax
then GotoXY (WhereX
, 1) else GotoXY (WhereX
, WhereY
+ 1);
325 Ord ('a'), kbHome
: Write (chCR
);
326 Ord ('f'), kbEnd
: GotoXY (GetXMax
, WhereY
);
327 Ord ('r'), kbPgUp
: GotoXY (WhereX
, 1);
328 Ord ('c'), kbPgDn
: GotoXY (WhereX
, GetYMax
);
329 Ord ('y'), kbCtrlPgUp
: GotoXY (1, 1);
330 Ord ('b'), kbCtrlPgDn
: GotoXY (GetXMax
, GetYMax
);
331 Ord ('z'), kbCtrlHome
: ClrScr
;
332 Ord ('n'), kbCtrlEnd
: ClrEOL
;
333 Ord ('v'), kbIns
: InsLine
;
334 Ord ('t'), kbDel
: DelLine
;
338 NewX
:= ((WhereX
- 1) div TabSize
+ 1) * TabSize
+ 1;
339 if NewX
<= GetXMax
then GotoXY (NewX
, WhereY
) else WriteLn
342 kbBkSp
: Write (chBkSp
, ' ', chBkSp
);
343 else ch
:= Key2Char (Key
);
344 if ch
<> #0 then Write (ch
)
348 procedure KeyDemoDraw
;
350 WriteLn ('Press some keys ...')
353 procedure KeyDemoKey (Key
: TKey
);
356 ch
:= Key2Char (Key
);
359 Write ('Normal key');
360 if IsPrintable (ch
) then Write (' `', ch
, '''');
361 WriteLn (', ASCII #', Ord (ch
))
364 WriteLn ('Special key ', Ord (Key2Scan (Key
)))
367 procedure IOSelectPeriodical
;
369 CurrentTime
: TimeStamp
;
373 GetTimeStamp (CurrentTime
);
375 WriteStr (s
, Hour
: 2, ':', Minute
: 2, ':', Second
: 2);
376 for i
:= 1 to Length (s
) do
377 if s
[i
] = ' ' then s
[i
] := '0';
379 Write ('The time is: ', s
)
382 procedure IOSelectDraw
;
384 WriteLn ('IOSelect is a way to handle I/O from');
385 WriteLn ('or to several places simultaneously,');
386 WriteLn ('without having to use threads or');
387 WriteLn ('signal/interrupt handlers or waste');
388 WriteLn ('CPU time with busy waiting.');
390 WriteLn ('This demo shows how IOSelect works');
391 WriteLn ('in connection with CRT. It displays');
392 WriteLn ('a clock, but still reacts to user');
393 WriteLn ('input immediately.');
397 procedure ModifierPeriodical
;
399 Pressed
: array [Boolean] of String [8] = ('Released', 'Pressed');
400 ModifierNames
: array [1 .. 7] of record
404 ((shLeftShift
, 'Left Shift'),
405 (shRightShift
, 'Right Shift'),
406 (shLeftCtrl
, 'Left Control'),
407 (shRightCtrl
, 'Right Control'),
408 (shAlt
, 'Alt (left)'),
409 (shAltGr
, 'AltGr (right Alt)'),
412 ShiftState
, i
: Integer;
414 ShiftState
:= GetShiftState
;
416 with ModifierNames
[i
] do
422 Write (Pressed
[(ShiftState
and Modifier
) <> 0])
426 procedure ModifierDraw
;
428 WriteLn ('Modifier keys (NOTE: only');
429 WriteLn ('available on some systems;');
430 WriteLn ('X11: only after key press):');
434 procedure ChecksDraw
;
436 WriteLn ('(O)S shell');
437 WriteLn ('OS shell with (C)learing');
438 WriteLn ('(R)efresh check');
439 Write ('(S)ound check')
442 procedure ChecksKey (Key
: TKey
);
445 WasteTime
: Real; attribute (volatile
);
452 Shell
:= GetShellPath (Null
);
454 Result
:= Execute (Shell
);
456 if (InOutRes
<> 0) or (Result
<> 0) then
459 if InOutRes
<> 0 then
460 WriteLn (GetIOErrorMessage
, ' while trying to execute `', Shell
, '''.')
462 WriteLn ('`', Shell
, ''' returned status ', Result
, '.');
463 Write ('Any key to continue.');
465 Discard (GetKey (-1))
470 case LoCase (Key2Char (Key
)) of
472 if PopUpConfirm (36, 12, 'You will now get an OS shell. Unless' + NewLine
+
473 'CRTDemo is running in its own (GUI)' + NewLine
+
474 'window, the shell will run on the' + NewLine
+
475 'same screen as CRTDemo which is not' + NewLine
+
476 'cleared before the shell is started.' + NewLine
+
477 'If possible, the screen contents are' + NewLine
+
478 'restored to the state before CRTDemo' + NewLine
+
479 'was started. After leaving the shell' + NewLine
+
480 'in the usual way (usually by enter-' + NewLine
+
481 'ing `exit''), you will get back to' + NewLine
+
482 'the demo. <ESC> to abort, any other' + NewLine
+
483 'key to start.') then
485 RestoreTerminal (True);
491 if PopUpConfirm (36, 9, 'You will now get an OS shell. Unless' + NewLine
+
492 'CRTDemo is running in its own (GUI)' + NewLine
+
493 'window, the screen will be cleared,' + NewLine
+
494 'and the cursor will be moved to the' + NewLine
+
495 'top before the shell is started.' + NewLine
+
496 'After leaving the shell in the usual' + NewLine
+
497 'way (usually by entering `exit''),' + NewLine
+
498 'you will get back to the demo. <ESC>' + NewLine
+
499 'to abort, any other key to start.') then
501 RestoreTerminalClearCRT
;
507 if PopUpConfirm (36, 11, 'The program will now get busy with' + NewLine
+
508 'some dummy computations. However,' + NewLine
+
509 'CRT output in the form of dots will' + NewLine
+
510 'still appear continuously one by one' + NewLine
+
511 '(rather than the whole line at once' + NewLine
+
512 'in the end). While running, the test' + NewLine
+
513 'cannot be interrupted. <ESC> to' + NewLine
+
514 'abort, any other key to start.') then
516 SetCRTUpdate (UpdateRegularly
);
520 for i
:= 1 to GetXMax
- 2 do
523 for j
:= 1 to 400000 do WasteTime
:= Random
525 SetCRTUpdate (UpdateInput
);
527 Write ('Press any key.');
528 Discard (GetKey (-1))
533 if PopUpConfirm (32, 4, 'You will now hear some sounds if' + NewLine
+
534 'supported (otherwise there will' + NewLine
+
535 'just be a short pause). <ESC> to' + NewLine
+
536 'abort, any other key to start.') then
541 Sound (Round (440 * 2 ** (Round (i
* 12 / 7 + 0.3) / 12)));
542 if GetKey (400000) in [kbEsc
, kbAltEsc
] then Break
552 PWindowList
= ^TWindowList
;
554 Next
, Prev
: PWindowList
;
555 Panel
, FramePanel
: TPanel
;
557 x1
, y1
, xs
, ys
: Integer;
558 State
: (ws_None
, ws_Moving
, ws_Resizing
);
561 TKeyProc
= procedure (Key
: TKey
);
562 TProcedure
= procedure;
566 WindowTypes
: array [0 .. 9] of record
568 PeriodicalProc
: procedure;
570 Name
: String (MenuNameLength
);
580 ((MainDraw
, nil , nil , 'CRT Demo' , LightGreen
, Blue
, 26, 7, 0, 0, False, False),
581 (StatusDraw
, nil , StatusKey
, 'Status' , White
, Red
, 38, 16, 0, 0, True, True),
582 (TextAttrDemo
, nil , nil , 'Text Attributes' , White
, Blue
, 32, 16, 64, 16, False, False),
583 (NormalCharSetDemo
, nil , nil , 'Character Set' , Black
, Green
, 35, 17, 53, 17, False, False),
584 (PCCharSetDemo
, nil , nil , 'PC Character Set', Black
, Brown
, 35, 17, 53, 17, False, False),
585 (KeyDemoDraw
, nil , KeyDemoKey
, 'Keys' , Blue
, LightGray
, 29, 5, -1, -1, False, True),
586 (FKeyDemoDraw
, nil , FKeyDemoKey
, 'Function Keys' , Blue
, LightGray
, 37, 22, -1, -1, False, True),
587 (ModifierDraw
, ModifierPeriodical
, nil , 'Modifier Keys' , Black
, Cyan
, 29, 11, 0, 0, True, False),
588 (IOSelectDraw
, IOSelectPeriodical
, nil , 'IOSelect Demo' , White
, Magenta
, 38, 12, 0, 0, False, False),
589 (ChecksDraw
, nil , ChecksKey
, 'Various Checks' , Black
, Red
, 26, 4, 0, 0, False, False));
591 MenuMax
= High (WindowTypes
);
592 MenuXSize
= MenuNameLength
+ 4;
593 MenuYSize
= MenuMax
+ 2;
596 WindowList
: PWindowList
= nil;
598 procedure RedrawFrame (p
: PWindowList
);
600 with p
^, WindowTypes
[WindowType
] do
602 PanelActivate (FramePanel
);
603 Window (x1
, y1
, x1
+ xs
- 1, y1
+ ys
- 1);
606 ws_None
: if p
= WindowList
then
607 FrameWin (' ' + Name
+ ' ', DoubleFrame
, True)
609 FrameWin (' ' + Name
+ ' ', SingleFrame
, False);
610 ws_Moving
: FrameWin (' Move Window ', SingleFrame
, True);
611 ws_Resizing
: FrameWin (' Resize Window ', SingleFrame
, True);
616 procedure DrawWindow (p
: PWindowList
);
618 with p
^, WindowTypes
[WindowType
] do
621 PanelActivate (Panel
);
622 Window (x1
+ 2, y1
+ 1, x1
+ xs
- 2, y1
+ ys
- 2);
634 LastPanel
:= GetActivePanel
;
635 PanelActivate (MainPanel
);
636 TextBackground (Blue
);
643 PanelActivate (FramePanel
);
644 GetWindow (x1
, y1
, x2
, y2
); { updated automatically by CRT }
650 until p
= WindowList
;
651 PanelActivate (LastPanel
)
654 procedure CheckScreenSize
;
657 MinScreenSizeX
, MinScreenSizeY
, i
: Integer;
660 LastPanel
:= GetActivePanel
;
661 PanelActivate (MainPanel
);
663 MinScreenSizeX
:= MenuXSize
;
664 MinScreenSizeY
:= MenuYSize
;
665 for i
:= Low (WindowTypes
) to High (WindowTypes
) do
666 with WindowTypes
[i
] do
668 MinScreenSizeX
:= Max (MinScreenSizeX
, MinSizeX
+ 2);
669 MinScreenSizeY
:= Max (MinScreenSizeY
, MinSizeY
+ 2)
672 Window (1, 1, SSize
.x
, SSize
.y
);
673 if (SSize
.x
< MinScreenSizeX
) or (SSize
.y
< MinScreenSizeY
) then
677 RestoreTerminal (True);
678 WriteLn (StdErr
, 'Sorry, your screen is too small for this demo (', SSize
.x
, 'x', SSize
.y
, ').');
679 WriteLn (StdErr
, 'You need at least ', MinScreenSizeX
, 'x', MinScreenSizeY
, ' characters.');
682 PanelActivate (LastPanel
);
686 procedure Die
; attribute (noreturn
);
689 RestoreTerminalClearCRT
;
690 WriteLn (StdErr
, 'You''re trying to kill me. Since I have break checking turned off,');
691 WriteLn (StdErr
, 'I''m not dying, but I''ll do you a favour and terminate now.');
695 function GetKey (TimeOut
: Integer) = Key
: TKey
;
697 NeedSelect
, SelectValue
: Integer;
698 SimulateBlockCursorCurrent
: TSimulateBlockCursorKind
;
699 SelectInput
: array [1 .. 1] of PAnyFile
= (@Input
);
700 NextSelectTime
: MicroSecondTimeType
= 0; attribute (static
);
701 TimeOutTime
: MicroSecondTimeType
;
705 LastPanel
:= GetActivePanel
;
707 TimeOutTime
:= High (TimeOutTime
)
709 TimeOutTime
:= GetMicroSecondTime
+ TimeOut
;
713 SimulateBlockCursorCurrent
:= SimulateBlockCursorKind
;
714 if SimulateBlockCursorCurrent
<> bc_None
then
718 if @WindowTypes
[p
^.WindowType
].PeriodicalProc
<> nil then
721 until p
= WindowList
;
724 with p
^, WindowTypes
[WindowType
] do
727 PanelActivate (Panel
);
732 until p
= WindowList
;
733 if NeedSelect
<> 0 then
736 SelectValue
:= IOSelectRead (SelectInput
, Max (0, Min (NextSelectTime
, TimeOutTime
) - GetMicroSecondTime
));
737 if SelectValue
= 0 then
739 case SimulateBlockCursorCurrent
of
741 bc_Blink
: SimulateBlockCursor
;
744 SimulateBlockCursorCurrent
:= bc_None
;
748 NextSelectTime
:= GetMicroSecondTime
+ 120000;
751 with p
^, WindowTypes
[WindowType
] do
752 if @PeriodicalProc
<> nil then
754 PanelActivate (Panel
);
760 until (NeedSelect
= 0) or (SelectValue
<> 0) or ((TimeOut
>= 0) and (GetMicroSecondTime
>= TimeOutTime
));
761 if NeedSelect
= 0 then
763 if SelectValue
= 0 then
767 if SimulateBlockCursorKind
<> bc_None
then
768 SimulateBlockCursorOff
;
769 if IsDeadlySignal (Key
) then Die
;
770 if Key
= kbScreenSizeChanged
then CheckScreenSize
;
771 PanelActivate (LastPanel
)
774 function Menu
= n
: Integer;
784 ax
:= (SSize
.x
- MenuXSize
) div 2 + 1;
785 ay
:= (SSize
.y
- MenuYSize
) div 2 + 1;
786 PanelNew (ax
, ay
, ax
+ MenuXSize
- 1, ay
+ MenuYSize
- 1, False);
787 SetControlChars (True);
789 TextBackground (LightGray
);
790 FrameWin (' Select Window ', DoubleFrame
, True);
792 PanelNew (ax
+ 1, ay
+ 1, ax
+ MenuXSize
- 2, ay
+ MenuYSize
- 2, False);
798 for i
:= 1 to MenuMax
do
802 TextBackground (Green
)
804 TextBackground (LightGray
);
806 Write (' ', WindowTypes
[i
].Name
);
807 ChangeTextAttr (2, i
, 1, Red
+ $10 * GetTextBackground
)
810 case LoCaseKey (Key
) of
811 kbUp
: if n
= 1 then n
:= MenuMax
else Dec (n
);
812 kbDown
: if n
= MenuMax
then n
:= 1 else Inc (n
);
820 kbCtrlEnd
: n
:= MenuMax
;
822 kbEsc
, kbAltEsc
: begin
826 Ord ('a') .. Ord ('z'): begin
828 while (i
> 0) and (LoCase (Key2Char (Key
)) <> LoCase (WindowTypes
[i
].Name
[1])) do Dec (i
);
836 until Done
or (Key
= kbScreenSizeChanged
);
838 until Key
<> kbScreenSizeChanged
841 procedure NewWindow (WindowType
, ax
, ay
: Integer);
843 p
, LastWindow
: PWindowList
;
844 MaxX1
, MaxY1
: Integer;
848 if WindowList
= nil then
855 p
^.Prev
:= WindowList
;
856 p
^.Next
:= WindowList
^.Next
;
860 p
^.WindowType
:= WindowType
;
861 with p
^, WindowTypes
[WindowType
] do
864 if PrefSizeX
> 0 then xs
:= PrefSizeX
else xs
:= MinSizeX
;
865 if PrefSizeY
> 0 then ys
:= PrefSizeY
else ys
:= MinSizeY
;
866 xs
:= Min (xs
+ 2, SSize
.x
);
867 ys
:= Min (ys
+ 2, SSize
.y
);
868 MaxX1
:= SSize
.x
- xs
+ 1;
869 MaxY1
:= SSize
.y
- ys
+ 1;
870 if ax
= 0 then x1
:= Random (MaxX1
) + 1 else x1
:= Min (ax
, MaxX1
);
871 if ay
= 0 then y1
:= Random (MaxY1
) + 1 else y1
:= Min (ay
, MaxY1
);
872 if (ax
= 0) and (PrefSizeX
< 0) then Inc (xs
, Random (SSize
.x
- x1
- xs
+ 2));
873 if (ax
= 0) and (PrefSizeY
< 0) then Inc (ys
, Random (SSize
.y
- y1
- ys
+ 2));
875 PanelNew (1, 1, 1, 1, False);
876 FramePanel
:= GetActivePanel
;
877 SetControlChars (True);
879 TextBackground (Background
);
880 PanelNew (1, 1, 1, 1, False);
881 SetPCCharSet (False);
882 Panel
:= GetActivePanel
;
884 LastWindow
:= WindowList
;
886 if LastWindow
<> nil then RedrawFrame (LastWindow
);
890 procedure OpenWindow
;
891 var WindowType
: Integer;
894 if WindowType
>= 0 then NewWindow (WindowType
, 0, 0)
897 procedure NextWindow
;
898 var LastWindow
: PWindowList
;
900 LastWindow
:= WindowList
;
901 WindowList
:= WindowList
^.Next
;
902 PanelTop (WindowList
^.FramePanel
);
903 PanelTop (WindowList
^.Panel
);
904 RedrawFrame (LastWindow
);
905 RedrawFrame (WindowList
)
908 procedure PreviousWindow
;
909 var LastWindow
: PWindowList
;
911 PanelMoveAbove (WindowList
^.Panel
, MainPanel
);
912 PanelMoveAbove (WindowList
^.FramePanel
, MainPanel
);
913 LastWindow
:= WindowList
;
914 WindowList
:= WindowList
^.Prev
;
915 RedrawFrame (LastWindow
);
916 RedrawFrame (WindowList
)
919 procedure CloseWindow
;
922 if WindowList
^.WindowType
<> 0 then
926 PanelDelete (p
^.FramePanel
);
927 PanelDelete (p
^.Panel
);
928 p
^.Next
^.Prev
:= p
^.Prev
;
929 p
^.Prev
^.Next
:= p
^.Next
;
934 procedure MoveWindow
;
936 Done
, Changed
: Boolean;
945 if Changed
then DrawWindow (WindowList
);
947 case LoCaseKey (GetKey (-1)) of
948 Ord ('s'), kbLeft
: if x1
> 1 then Dec (x1
);
949 Ord ('d'), kbRight
: if x1
+ xs
- 1 < ScreenSize
.x
then Inc (x1
);
950 Ord ('e'), kbUp
: if y1
> 1 then Dec (y1
);
951 Ord ('x'), kbDown
: if y1
+ ys
- 1 < ScreenSize
.y
then Inc (y1
);
952 Ord ('a'), kbHome
: x1
:= 1;
953 Ord ('f'), kbEnd
: x1
:= ScreenSize
.x
- xs
+ 1;
954 Ord ('r'), kbPgUp
: y1
:= 1;
955 Ord ('c'), kbPgDn
: y1
:= ScreenSize
.y
- ys
+ 1;
956 Ord ('y'), kbCtrlPgUp
: begin
960 Ord ('b'), kbCtrlPgDn
: begin
962 x1
:= SSize
.x
- xs
+ 1;
963 y1
:= SSize
.y
- ys
+ 1
966 kbEsc
, kbAltEsc
: Done
:= True;
967 else Changed
:= False
971 DrawWindow (WindowList
)
975 procedure ResizeWindow
;
977 Done
, Changed
: Boolean;
980 with WindowList
^, WindowTypes
[WindowType
] do
984 State
:= ws_Resizing
;
986 if Changed
then DrawWindow (WindowList
);
988 case LoCaseKey (GetKey (-1)) of
989 Ord ('s'), kbLeft
: if xs
> MinSizeX
+ 2 then Dec (xs
);
990 Ord ('d'), kbRight
: if x1
+ xs
- 1 < ScreenSize
.x
then Inc (xs
);
991 Ord ('e'), kbUp
: if ys
> MinSizeY
+ 2 then Dec (ys
);
992 Ord ('x'), kbDown
: if y1
+ ys
- 1 < ScreenSize
.y
then Inc (ys
);
993 Ord ('a'), kbHome
: xs
:= MinSizeX
+ 2;
994 Ord ('f'), kbEnd
: xs
:= ScreenSize
.x
- x1
+ 1;
995 Ord ('r'), kbPgUp
: ys
:= MinSizeY
+ 2;
996 Ord ('c'), kbPgDn
: ys
:= ScreenSize
.y
- y1
+ 1;
997 Ord ('y'), kbCtrlPgUp
: begin
1001 Ord ('b'), kbCtrlPgDn
: begin
1002 SSize
:= ScreenSize
;
1003 xs
:= SSize
.x
- x1
+ 1;
1004 ys
:= SSize
.y
- y1
+ 1
1007 kbEsc
, kbAltEsc
: Done
:= True;
1008 else Changed
:= False
1012 DrawWindow (WindowList
)
1016 procedure ActivateCursor
;
1018 with WindowList
^, WindowTypes
[WindowType
] do
1020 PanelActivate (Panel
);
1022 SetCursorShape (CursorShape
)
1026 SetScroll (ScrollState
)
1031 ScreenShot
, Done
: Boolean;
1034 ScreenShot
:= ParamStr (1) = '--screenshot';
1035 if ParamCount
<> Ord (ScreenShot
) then
1037 RestoreTerminal (True);
1038 WriteLn (StdErr
, ParamStr (0), ': invalid argument `', ParamStr (Ord (ScreenShot
) + 1), '''');
1041 CRTSavePreviousScreen (True);
1042 SetCRTUpdate (UpdateInput
);
1043 MainPanel
:= GetActivePanel
;
1045 OrigScreenSize
:= ScreenSize
;
1048 CursorShape
:= CursorBlock
;
1049 NewWindow (6, 1, 1);
1050 NewWindow (2, 1, MaxInt
);
1051 NewWindow (8, MaxInt
, 1);
1052 NewWindow (5, 1, 27);
1053 KeyDemoKey (Ord ('f'));
1055 KeyDemoKey (kbDown
);
1056 NewWindow (3, MaxInt
, 13);
1057 NewWindow (4, MaxInt
, 31);
1058 NewWindow (7, MaxInt
, MaxInt
);
1059 NewWindow (9, MaxInt
, 33);
1060 NewWindow (0, 1, 2);
1061 NewWindow (1, 1, 14);
1066 NewWindow (0, 3, 2);
1071 case LoCaseKey (Key
) of
1072 Ord ('3'), kbF3
: OpenWindow
;
1073 Ord ('4'), kbF4
: CloseWindow
;
1074 Ord ('5'), kbF5
: PreviousWindow
;
1075 Ord ('6'), kbF6
: NextWindow
;
1076 Ord ('7'), kbF7
: MoveWindow
;
1077 Ord ('8'), kbF8
: ResizeWindow
;
1079 kbAltEsc
: Done
:= True;
1081 if WindowList
<> nil then
1082 with WindowList
^, WindowTypes
[WindowType
] do
1083 if @KeyProc
<> nil then
1086 TextBackground (Background
);