1 { GPC demo program for the CRT unit.
3 Copyright (C) 1999-2006, 2013-2015 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.
32 var a_to_b
: integer; // 'to' should not be highlighted
39 TFrameChars
= array [1 .. 8] of Char;
40 TSimulateBlockCursorKind
= (bc_None
, bc_Blink
, bc_Static
);
43 SingleFrame
: TFrameChars
= (chCornerTLS
, chLineHS
, chCornerTRS
, chLineVS
, chLineVS
, chCornerBLS
, chLineHS
, chCornerBRS
);
44 DoubleFrame
: TFrameChars
= (chCornerTLD
, chLineHD
, chCornerTRD
, chLineVD
, chLineVD
, chCornerBLD
, chLineHD
, chCornerBRD
);
47 ScrollState
: Boolean = True;
48 SimulateBlockCursorKind
: TSimulateBlockCursorKind
= bc_None
;
49 CursorShape
: TCursorShape
= CursorNormal
;
51 OrigScreenSize
: TPoint
;
53 procedure FrameWin (const Title
: String; const Frame
: TFrameChars
; TitleInverse
: Boolean);
55 w
, h
, y
, Color
: Integer;
63 WriteCharAt (1, 1, 1, Frame
[1], TextAttr
);
64 WriteCharAt (2, 1, w
- 2, Frame
[2], TextAttr
);
65 WriteCharAt (w
, 1, 1, Frame
[3], TextAttr
);
66 for y
:= 2 to h
- 1 do
68 WriteCharAt (1, y
, 1, Frame
[4], TextAttr
);
69 WriteCharAt (w
, y
, 1, Frame
[5], TextAttr
)
71 WriteCharAt (1, h
, 1, Frame
[6], TextAttr
);
72 WriteCharAt (2, h
, w
- 2, Frame
[7], TextAttr
);
73 WriteCharAt (w
, h
, 1, Frame
[8], TextAttr
);
78 Color
:= GetTextColor
;
79 TextColor (GetTextBackground
);
80 TextBackground (Color
)
82 WriteStrAt ((w
- Length (Title
)) div 2 + 1, 1, Title
, TextAttr
);
86 function GetKey (TimeOut
: Integer) = Key
: TKey
; forward;
88 procedure ClosePopUpWindow
;
90 PanelDelete (GetActivePanel
);
91 PanelDelete (GetActivePanel
)
94 function PopUpConfirm (XSize
, YSize
: Integer; const Msg
: String): Boolean;
102 ax
:= (SSize
.x
- XSize
- 4) div 2 + 1;
103 ay
:= (SSize
.y
- YSize
- 4) div 2 + 1;
104 PanelNew (ax
, ay
, ax
+ XSize
+ 3, ay
+ YSize
+ 1, False);
105 TextBackground (Black
);
107 SetControlChars (True);
108 FrameWin ('', DoubleFrame
, False);
110 PanelNew (ax
+ 2, ay
+ 1, ax
+ XSize
+ 2, ay
+ YSize
, False);
114 if Key
= kbScreenSizeChanged
then ClosePopUpWindow
115 until Key
<> kbScreenSizeChanged
;
116 PopUpConfirm
:= not (Key
in [kbEsc
, kbAltEsc
])
121 WriteLn ('3, F3 : Open a window');
122 WriteLn ('4, F4 : Close window');
123 WriteLn ('5, F5 : Previous window');
124 WriteLn ('6, F6 : Next window');
125 WriteLn ('7, F7 : Move window');
126 WriteLn ('8, F8 : Resize window');
127 Write ('q, Esc: Quit')
130 procedure StatusDraw
;
132 YesNo
: array [Boolean] of String [3] = ('No', 'Yes');
133 SimulateBlockCursorIDs
: array [TSimulateBlockCursorKind
] of String [8] = ('Off', 'Blinking', 'Static');
134 CursorShapeIDs
: array [TCursorShape
] of String [7] = ('Ignored', 'Hidden', 'Normal', 'Fat', 'Block');
138 WriteLn ('You can change some of the following');
139 WriteLn ('settings by pressing the key shown');
140 WriteLn ('in parentheses. Naturally, color and');
141 WriteLn ('changing the cursor shape or screen');
142 WriteLn ('size does not work on all terminals.');
144 WriteLn ('XCurses version: ', YesNo
[XCRT
]);
145 WriteLn ('CRTSavePreviousScreen: ', YesNo
[CRTSavePreviousScreenWorks
]);
146 WriteLn ('(M)onochrome: ', YesNo
[IsMonochrome
]);
148 WriteLn ('Screen (C)olumns: ', SSize
.x
);
149 WriteLn ('Screen (L)ines: ', SSize
.y
);
150 WriteLn ('(R)estore screen size');
151 WriteLn ('(B)reak checking: ', YesNo
[CheckBreak
]);
152 WriteLn ('(S)crolling: ', YesNo
[ScrollState
]);
153 WriteLn ('S(i)mulated block cursor: ', SimulateBlockCursorIDs
[SimulateBlockCursorKind
]);
154 Write ('C(u)rsor shape: ', CursorShapeIDs
[CursorShape
]);
158 procedure RedrawAll
; forward;
159 procedure CheckScreenSize
; forward;
161 procedure StatusKey (Key
: TKey
);
162 var SSize
, NewSize
: TPoint
;
164 case LoCase (Key2Char (Key
)) of
166 SetMonochrome (not IsMonochrome
);
179 SetScreenSize (NewSize
.x
, NewSize
.y
);
192 SetScreenSize (NewSize
.x
, NewSize
.y
);
196 SetScreenSize (OrigScreenSize
.x
, OrigScreenSize
.y
);
199 'b': CheckBreak
:= not CheckBreak
;
200 's': ScrollState
:= not ScrollState
;
201 'i': if SimulateBlockCursorKind
= High (SimulateBlockCursorKind
) then
202 SimulateBlockCursorKind
:= Low (SimulateBlockCursorKind
)
204 Inc (SimulateBlockCursorKind
);
205 'u': case CursorShape
of
206 CursorNormal
: CursorShape
:= CursorBlock
;
208 CursorBlock
: CursorShape
:= CursorHidden
;
209 else CursorShape
:= CursorNormal
216 procedure TextAttrDemo
;
217 var f
, b
, y
, x1
, y1
, x2
, y2
, Fill
, n1
, n2
, n3
: Integer;
219 GetWindow (x1
, y1
, x2
, y2
);
220 Window (x1
- 1, y1
, x2
, y2
);
222 TextBackground (Blue
);
225 Fill
:= GetXMax
- 32;
226 for y
:= 1 to GetYMax
do
233 TextAttr
:= f
+ 16 * b
;
234 n2
:= (Fill
* (1 + 2 * f
) + 16) div 32;
235 n3
:= (Fill
* (2 + 2 * f
) + 16) div 32;
236 Write ('' : n2
- n1
, NumericBaseDigitsUpper
[b
], NumericBaseDigitsUpper
[f
], '' : n3
- n2
);
242 procedure CharSetDemo (UsePCCharSet
: Boolean);
243 var h
, l
, y
, x1
, y1
, x2
, y2
, Fill
, n1
, n2
: Integer;
245 GetWindow (x1
, y1
, x2
, y2
);
246 Window (x1
- 1, y1
, x2
, y2
);
249 SetPCCharSet (UsePCCharSet
);
250 SetControlChars (False);
251 Fill
:= GetXMax
- 35;
252 for y
:= 1 to GetYMax
do
256 n1
:= (Fill
+ 9) div 18;
260 Write (16 * h
: 3 + n1
);
263 n2
:= (Fill
* (2 + l
) + 9) div 18;
265 Write ('' : n2
- n1
, l
: 2)
267 Write ('' : n2
- n1
+ 1, Chr (16 * h
+ l
));
273 procedure NormalCharSetDemo
;
278 procedure PCCharSetDemo
;
283 procedure FKeyDemoDraw
;
284 var x1
, y1
, x2
, y2
: Integer;
286 GetWindow (x1
, y1
, x2
, y2
);
287 Window (x1
, y1
, x2
- 1, y2
);
290 WriteLn ('You can type the following keys');
291 WriteLn ('(function keys if present on the');
292 WriteLn ('terminal, letters as alternatives):');
294 WriteLn ('S, Left : left (wrap-around)');
295 WriteLn ('D, Right : right (wrap-around)');
296 WriteLn ('E, Up : up (wrap-around)');
297 WriteLn ('X, Down : down (wrap-around)');
298 WriteLn ('A, Home : go to first column');
299 WriteLn ('F, End : go to last column');
300 WriteLn ('R, Page Up : go to first line');
301 WriteLn ('C, Page Down: go to last line');
302 WriteLn ('Y, Ctrl-PgUp: first column and line');
304 WriteLn ('B, Ctrl-PgDn: last column and line');
305 WriteLn ('Z, Ctrl-Home: clear screen');
306 WriteLn ('N, Ctrl-End : clear to end of line');
307 WriteLn ('V, Insert : insert a line');
308 WriteLn ('T, Delete : delete a line');
309 WriteLn ('# : beep');
310 WriteLn ('* : flash');
311 WriteLn ('Tab, Enter, Backspace, other');
312 WriteLn (' normal characters: write text')
315 procedure FKeyDemoKey (Key
: TKey
);
321 case LoCaseKey (Key
) of
322 Ord ('s'), kbLeft
: if WhereX
= 1 then GotoXY (GetXMax
, WhereY
) else GotoXY (WhereX
- 1, WhereY
);
323 Ord ('d'), kbRight
: if WhereX
= GetXMax
then GotoXY (1, WhereY
) else GotoXY (WhereX
+ 1, WhereY
);
324 Ord ('e'), kbUp
: if WhereY
= 1 then GotoXY (WhereX
, GetYMax
) else GotoXY (WhereX
, WhereY
- 1);
325 Ord ('x'), kbDown
: if WhereY
= GetYMax
then GotoXY (WhereX
, 1) else GotoXY (WhereX
, WhereY
+ 1);
326 Ord ('a'), kbHome
: Write (chCR
);
327 Ord ('f'), kbEnd
: GotoXY (GetXMax
, WhereY
);
328 Ord ('r'), kbPgUp
: GotoXY (WhereX
, 1);
329 Ord ('c'), kbPgDn
: GotoXY (WhereX
, GetYMax
);
330 Ord ('y'), kbCtrlPgUp
: GotoXY (1, 1);
331 Ord ('b'), kbCtrlPgDn
: GotoXY (GetXMax
, GetYMax
);
332 Ord ('z'), kbCtrlHome
: ClrScr
;
333 Ord ('n'), kbCtrlEnd
: ClrEOL
;
334 Ord ('v'), kbIns
: InsLine
;
335 Ord ('t'), kbDel
: DelLine
;
339 NewX
:= ((WhereX
- 1) div TabSize
+ 1) * TabSize
+ 1;
340 if NewX
<= GetXMax
then GotoXY (NewX
, WhereY
) else WriteLn
343 kbBkSp
: Write (chBkSp
, ' ', chBkSp
);
344 else ch
:= Key2Char (Key
);
345 if ch
<> #0 then Write (ch
)
349 procedure KeyDemoDraw
;
351 WriteLn ('Press some keys ...')
354 procedure KeyDemoKey (Key
: TKey
);
357 ch
:= Key2Char (Key
);
360 Write ('Normal key');
361 if IsPrintable (ch
) then Write (' `', ch
, '''');
362 WriteLn (', ASCII #', Ord (ch
))
365 WriteLn ('Special key ', Ord (Key2Scan (Key
)))
368 procedure IOSelectPeriodical
;
370 CurrentTime
: TimeStamp
;
374 GetTimeStamp (CurrentTime
);
376 WriteStr (s
, Hour
: 2, ':', Minute
: 2, ':', Second
: 2);
377 for i
:= 1 to Length (s
) do
378 if s
[i
] = ' ' then s
[i
] := '0';
380 Write ('The time is: ', s
)
383 procedure IOSelectDraw
;
385 WriteLn ('IOSelect is a way to handle I/O from');
386 WriteLn ('or to several places simultaneously,');
387 WriteLn ('without having to use threads or');
388 WriteLn ('signal/interrupt handlers or waste');
389 WriteLn ('CPU time with busy waiting.');
391 WriteLn ('This demo shows how IOSelect works');
392 WriteLn ('in connection with CRT. It displays');
393 WriteLn ('a clock, but still reacts to user');
394 WriteLn ('input immediately.');
398 procedure ModifierPeriodical
;
400 Pressed
: array [Boolean] of String [8] = ('Released', 'Pressed');
401 ModifierNames
: array [1 .. 7] of record
405 ((shLeftShift
, 'Left Shift'),
406 (shRightShift
, 'Right Shift'),
407 (shLeftCtrl
, 'Left Control'),
408 (shRightCtrl
, 'Right Control'),
409 (shAlt
, 'Alt (left)'),
410 (shAltGr
, 'AltGr (right Alt)'),
413 ShiftState
, i
: Integer;
415 ShiftState
:= GetShiftState
;
417 with ModifierNames
[i
] do
423 Write (Pressed
[(ShiftState
and Modifier
) <> 0])
427 procedure ModifierDraw
;
429 WriteLn ('Modifier keys (NOTE: only');
430 WriteLn ('available on some systems;');
431 WriteLn ('X11: only after key press):');
435 procedure ChecksDraw
;
437 WriteLn ('(O)S shell');
438 WriteLn ('OS shell with (C)learing');
439 WriteLn ('(R)efresh check');
440 Write ('(S)ound check')
443 procedure ChecksKey (Key
: TKey
);
446 WasteTime
: Real; attribute (volatile
);
453 Shell
:= GetShellPath (Null
);
455 Result
:= Execute (Shell
);
457 if (InOutRes
<> 0) or (Result
<> 0) then
460 if InOutRes
<> 0 then
461 WriteLn (GetIOErrorMessage
, ' while trying to execute `', Shell
, '''.')
463 WriteLn ('`', Shell
, ''' returned status ', Result
, '.');
464 Write ('Any key to continue.');
466 Discard (GetKey (-1))
471 case LoCase (Key2Char (Key
)) of
473 if PopUpConfirm (36, 12, 'You will now get an OS shell. Unless' + NewLine
+
474 'CRTDemo is running in its own (GUI)' + NewLine
+
475 'window, the shell will run on the' + NewLine
+
476 'same screen as CRTDemo which is not' + NewLine
+
477 'cleared before the shell is started.' + NewLine
+
478 'If possible, the screen contents are' + NewLine
+
479 'restored to the state before CRTDemo' + NewLine
+
480 'was started. After leaving the shell' + NewLine
+
481 'in the usual way (usually by enter-' + NewLine
+
482 'ing `exit''), you will get back to' + NewLine
+
483 'the demo. <ESC> to abort, any other' + NewLine
+
484 'key to start.') then
486 RestoreTerminal (True);
492 if PopUpConfirm (36, 9, 'You will now get an OS shell. Unless' + NewLine
+
493 'CRTDemo is running in its own (GUI)' + NewLine
+
494 'window, the screen will be cleared,' + NewLine
+
495 'and the cursor will be moved to the' + NewLine
+
496 'top before the shell is started.' + NewLine
+
497 'After leaving the shell in the usual' + NewLine
+
498 'way (usually by entering `exit''),' + NewLine
+
499 'you will get back to the demo. <ESC>' + NewLine
+
500 'to abort, any other key to start.') then
502 RestoreTerminalClearCRT
;
508 if PopUpConfirm (36, 11, 'The program will now get busy with' + NewLine
+
509 'some dummy computations. However,' + NewLine
+
510 'CRT output in the form of dots will' + NewLine
+
511 'still appear continuously one by one' + NewLine
+
512 '(rather than the whole line at once' + NewLine
+
513 'in the end). While running, the test' + NewLine
+
514 'cannot be interrupted. <ESC> to' + NewLine
+
515 'abort, any other key to start.') then
517 SetCRTUpdate (UpdateRegularly
);
521 for i
:= 1 to GetXMax
- 2 do
524 for j
:= 1 to 400000 do WasteTime
:= Random
526 SetCRTUpdate (UpdateInput
);
528 Write ('Press any key.');
529 Discard (GetKey (-1))
534 if PopUpConfirm (32, 4, 'You will now hear some sounds if' + NewLine
+
535 'supported (otherwise there will' + NewLine
+
536 'just be a short pause). <ESC> to' + NewLine
+
537 'abort, any other key to start.') then
542 Sound (Round (440 * 2 ** (Round (i
* 12 / 7 + 0.3) / 12)));
543 if GetKey (400000) in [kbEsc
, kbAltEsc
] then Break
553 PWindowList
= ^TWindowList
;
555 Next
, Prev
: PWindowList
;
556 Panel
, FramePanel
: TPanel
;
558 x1
, y1
, xs
, ys
: Integer;
559 State
: (ws_None
, ws_Moving
, ws_Resizing
);
562 TKeyProc
= procedure (Key
: TKey
);
563 TProcedure
= procedure;
567 WindowTypes
: array [0 .. 9] of record
569 PeriodicalProc
: procedure;
571 Name
: String (MenuNameLength
);
581 ((MainDraw
, nil , nil , 'CRT Demo' , LightGreen
, Blue
, 26, 7, 0, 0, False, False),
582 (StatusDraw
, nil , StatusKey
, 'Status' , White
, Red
, 38, 16, 0, 0, True, True),
583 (TextAttrDemo
, nil , nil , 'Text Attributes' , White
, Blue
, 32, 16, 64, 16, False, False),
584 (NormalCharSetDemo
, nil , nil , 'Character Set' , Black
, Green
, 35, 17, 53, 17, False, False),
585 (PCCharSetDemo
, nil , nil , 'PC Character Set', Black
, Brown
, 35, 17, 53, 17, False, False),
586 (KeyDemoDraw
, nil , KeyDemoKey
, 'Keys' , Blue
, LightGray
, 29, 5, -1, -1, False, True),
587 (FKeyDemoDraw
, nil , FKeyDemoKey
, 'Function Keys' , Blue
, LightGray
, 37, 22, -1, -1, False, True),
588 (ModifierDraw
, ModifierPeriodical
, nil , 'Modifier Keys' , Black
, Cyan
, 29, 11, 0, 0, True, False),
589 (IOSelectDraw
, IOSelectPeriodical
, nil , 'IOSelect Demo' , White
, Magenta
, 38, 12, 0, 0, False, False),
590 (ChecksDraw
, nil , ChecksKey
, 'Various Checks' , Black
, Red
, 26, 4, 0, 0, False, False));
592 MenuMax
= High (WindowTypes
);
593 MenuXSize
= MenuNameLength
+ 4;
594 MenuYSize
= MenuMax
+ 2;
597 WindowList
: PWindowList
= nil;
599 procedure RedrawFrame (p
: PWindowList
);
601 with p
^, WindowTypes
[WindowType
] do
603 PanelActivate (FramePanel
);
604 Window (x1
, y1
, x1
+ xs
- 1, y1
+ ys
- 1);
607 ws_None
: if p
= WindowList
then
608 FrameWin (' ' + Name
+ ' ', DoubleFrame
, True)
610 FrameWin (' ' + Name
+ ' ', SingleFrame
, False);
611 ws_Moving
: FrameWin (' Move Window ', SingleFrame
, True);
612 ws_Resizing
: FrameWin (' Resize Window ', SingleFrame
, True);
617 procedure DrawWindow (p
: PWindowList
);
619 with p
^, WindowTypes
[WindowType
] do
622 PanelActivate (Panel
);
623 Window (x1
+ 2, y1
+ 1, x1
+ xs
- 2, y1
+ ys
- 2);
635 LastPanel
:= GetActivePanel
;
636 PanelActivate (MainPanel
);
637 TextBackground (Blue
);
644 PanelActivate (FramePanel
);
645 GetWindow (x1
, y1
, x2
, y2
); { updated automatically by CRT }
651 until p
= WindowList
;
652 PanelActivate (LastPanel
)
655 procedure CheckScreenSize
;
658 MinScreenSizeX
, MinScreenSizeY
, i
: Integer;
661 LastPanel
:= GetActivePanel
;
662 PanelActivate (MainPanel
);
664 MinScreenSizeX
:= MenuXSize
;
665 MinScreenSizeY
:= MenuYSize
;
666 for i
:= Low (WindowTypes
) to High (WindowTypes
) do
667 with WindowTypes
[i
] do
669 MinScreenSizeX
:= Max (MinScreenSizeX
, MinSizeX
+ 2);
670 MinScreenSizeY
:= Max (MinScreenSizeY
, MinSizeY
+ 2)
673 Window (1, 1, SSize
.x
, SSize
.y
);
674 if (SSize
.x
< MinScreenSizeX
) or (SSize
.y
< MinScreenSizeY
) then
678 RestoreTerminal (True);
679 WriteLn (StdErr
, 'Sorry, your screen is too small for this demo (', SSize
.x
, 'x', SSize
.y
, ').');
680 WriteLn (StdErr
, 'You need at least ', MinScreenSizeX
, 'x', MinScreenSizeY
, ' characters.');
683 PanelActivate (LastPanel
);
687 procedure Die
; attribute (noreturn
);
690 RestoreTerminalClearCRT
;
691 WriteLn (StdErr
, 'You''re trying to kill me. Since I have break checking turned off,');
692 WriteLn (StdErr
, 'I''m not dying, but I''ll do you a favor and terminate now.');
696 function GetKey (TimeOut
: Integer) = Key
: TKey
;
698 NeedSelect
, SelectValue
: Integer;
699 SimulateBlockCursorCurrent
: TSimulateBlockCursorKind
;
700 SelectInput
: array [1 .. 1] of PAnyFile
= (@Input
);
701 NextSelectTime
: MicroSecondTimeType
= 0; attribute (static
);
702 TimeOutTime
: MicroSecondTimeType
;
706 LastPanel
:= GetActivePanel
;
708 TimeOutTime
:= High (TimeOutTime
)
710 TimeOutTime
:= GetMicroSecondTime
+ TimeOut
;
714 SimulateBlockCursorCurrent
:= SimulateBlockCursorKind
;
715 if SimulateBlockCursorCurrent
<> bc_None
then
719 if @WindowTypes
[p
^.WindowType
].PeriodicalProc
<> nil then
722 until p
= WindowList
;
725 with p
^, WindowTypes
[WindowType
] do
728 PanelActivate (Panel
);
733 until p
= WindowList
;
734 if NeedSelect
<> 0 then
737 SelectValue
:= IOSelectRead (SelectInput
, Max (0, Min (NextSelectTime
, TimeOutTime
) - GetMicroSecondTime
));
738 if SelectValue
= 0 then
740 case SimulateBlockCursorCurrent
of
742 bc_Blink
: SimulateBlockCursor
;
745 SimulateBlockCursorCurrent
:= bc_None
;
749 NextSelectTime
:= GetMicroSecondTime
+ 120000;
752 with p
^, WindowTypes
[WindowType
] do
753 if @PeriodicalProc
<> nil then
755 PanelActivate (Panel
);
761 until (NeedSelect
= 0) or (SelectValue
<> 0) or ((TimeOut
>= 0) and (GetMicroSecondTime
>= TimeOutTime
));
762 if NeedSelect
= 0 then
764 if SelectValue
= 0 then
768 if SimulateBlockCursorKind
<> bc_None
then
769 SimulateBlockCursorOff
;
770 if IsDeadlySignal (Key
) then Die
;
771 if Key
= kbScreenSizeChanged
then CheckScreenSize
;
772 PanelActivate (LastPanel
)
775 function Menu
= n
: Integer;
785 ax
:= (SSize
.x
- MenuXSize
) div 2 + 1;
786 ay
:= (SSize
.y
- MenuYSize
) div 2 + 1;
787 PanelNew (ax
, ay
, ax
+ MenuXSize
- 1, ay
+ MenuYSize
- 1, False);
788 SetControlChars (True);
790 TextBackground (LightGray
);
791 FrameWin (' Select Window ', DoubleFrame
, True);
793 PanelNew (ax
+ 1, ay
+ 1, ax
+ MenuXSize
- 2, ay
+ MenuYSize
- 2, False);
799 for i
:= 1 to MenuMax
do
803 TextBackground (Green
)
805 TextBackground (LightGray
);
807 Write (' ', WindowTypes
[i
].Name
);
808 ChangeTextAttr (2, i
, 1, Red
+ $10 * GetTextBackground
)
811 case LoCaseKey (Key
) of
812 kbUp
: if n
= 1 then n
:= MenuMax
else Dec (n
);
813 kbDown
: if n
= MenuMax
then n
:= 1 else Inc (n
);
821 kbCtrlEnd
: n
:= MenuMax
;
823 kbEsc
, kbAltEsc
: begin
827 Ord ('a') .. Ord ('z'): begin
829 while (i
> 0) and (LoCase (Key2Char (Key
)) <> LoCase (WindowTypes
[i
].Name
[1])) do Dec (i
);
837 until Done
or (Key
= kbScreenSizeChanged
);
839 until Key
<> kbScreenSizeChanged
842 procedure NewWindow (WindowType
, ax
, ay
: Integer);
844 p
, LastWindow
: PWindowList
;
845 MaxX1
, MaxY1
: Integer;
849 if WindowList
= nil then
856 p
^.Prev
:= WindowList
;
857 p
^.Next
:= WindowList
^.Next
;
861 p
^.WindowType
:= WindowType
;
862 with p
^, WindowTypes
[WindowType
] do
865 if PrefSizeX
> 0 then xs
:= PrefSizeX
else xs
:= MinSizeX
;
866 if PrefSizeY
> 0 then ys
:= PrefSizeY
else ys
:= MinSizeY
;
867 xs
:= Min (xs
+ 2, SSize
.x
);
868 ys
:= Min (ys
+ 2, SSize
.y
);
869 MaxX1
:= SSize
.x
- xs
+ 1;
870 MaxY1
:= SSize
.y
- ys
+ 1;
871 if ax
= 0 then x1
:= Random (MaxX1
) + 1 else x1
:= Min (ax
, MaxX1
);
872 if ay
= 0 then y1
:= Random (MaxY1
) + 1 else y1
:= Min (ay
, MaxY1
);
873 if (ax
= 0) and (PrefSizeX
< 0) then Inc (xs
, Random (SSize
.x
- x1
- xs
+ 2));
874 if (ax
= 0) and (PrefSizeY
< 0) then Inc (ys
, Random (SSize
.y
- y1
- ys
+ 2));
876 PanelNew (1, 1, 1, 1, False);
877 FramePanel
:= GetActivePanel
;
878 SetControlChars (True);
880 TextBackground (Background
);
881 PanelNew (1, 1, 1, 1, False);
882 SetPCCharSet (False);
883 Panel
:= GetActivePanel
;
885 LastWindow
:= WindowList
;
887 if LastWindow
<> nil then RedrawFrame (LastWindow
);
891 procedure OpenWindow
;
892 var WindowType
: Integer;
895 if WindowType
>= 0 then NewWindow (WindowType
, 0, 0)
898 procedure NextWindow
;
899 var LastWindow
: PWindowList
;
901 LastWindow
:= WindowList
;
902 WindowList
:= WindowList
^.Next
;
903 PanelTop (WindowList
^.FramePanel
);
904 PanelTop (WindowList
^.Panel
);
905 RedrawFrame (LastWindow
);
906 RedrawFrame (WindowList
)
909 procedure PreviousWindow
;
910 var LastWindow
: PWindowList
;
912 PanelMoveAbove (WindowList
^.Panel
, MainPanel
);
913 PanelMoveAbove (WindowList
^.FramePanel
, MainPanel
);
914 LastWindow
:= WindowList
;
915 WindowList
:= WindowList
^.Prev
;
916 RedrawFrame (LastWindow
);
917 RedrawFrame (WindowList
)
920 procedure CloseWindow
;
923 if WindowList
^.WindowType
<> 0 then
927 PanelDelete (p
^.FramePanel
);
928 PanelDelete (p
^.Panel
);
929 p
^.Next
^.Prev
:= p
^.Prev
;
930 p
^.Prev
^.Next
:= p
^.Next
;
935 procedure MoveWindow
;
937 Done
, Changed
: Boolean;
946 if Changed
then DrawWindow (WindowList
);
948 case LoCaseKey (GetKey (-1)) of
949 Ord ('s'), kbLeft
: if x1
> 1 then Dec (x1
);
950 Ord ('d'), kbRight
: if x1
+ xs
- 1 < ScreenSize
.x
then Inc (x1
);
951 Ord ('e'), kbUp
: if y1
> 1 then Dec (y1
);
952 Ord ('x'), kbDown
: if y1
+ ys
- 1 < ScreenSize
.y
then Inc (y1
);
953 Ord ('a'), kbHome
: x1
:= 1;
954 Ord ('f'), kbEnd
: x1
:= ScreenSize
.x
- xs
+ 1;
955 Ord ('r'), kbPgUp
: y1
:= 1;
956 Ord ('c'), kbPgDn
: y1
:= ScreenSize
.y
- ys
+ 1;
957 Ord ('y'), kbCtrlPgUp
: begin
961 Ord ('b'), kbCtrlPgDn
: begin
963 x1
:= SSize
.x
- xs
+ 1;
964 y1
:= SSize
.y
- ys
+ 1
967 kbEsc
, kbAltEsc
: Done
:= True;
968 else Changed
:= False
972 DrawWindow (WindowList
)
976 procedure ResizeWindow
;
978 Done
, Changed
: Boolean;
981 with WindowList
^, WindowTypes
[WindowType
] do
985 State
:= ws_Resizing
;
987 if Changed
then DrawWindow (WindowList
);
989 case LoCaseKey (GetKey (-1)) of
990 Ord ('s'), kbLeft
: if xs
> MinSizeX
+ 2 then Dec (xs
);
991 Ord ('d'), kbRight
: if x1
+ xs
- 1 < ScreenSize
.x
then Inc (xs
);
992 Ord ('e'), kbUp
: if ys
> MinSizeY
+ 2 then Dec (ys
);
993 Ord ('x'), kbDown
: if y1
+ ys
- 1 < ScreenSize
.y
then Inc (ys
);
994 Ord ('a'), kbHome
: xs
:= MinSizeX
+ 2;
995 Ord ('f'), kbEnd
: xs
:= ScreenSize
.x
- x1
+ 1;
996 Ord ('r'), kbPgUp
: ys
:= MinSizeY
+ 2;
997 Ord ('c'), kbPgDn
: ys
:= ScreenSize
.y
- y1
+ 1;
998 Ord ('y'), kbCtrlPgUp
: begin
1002 Ord ('b'), kbCtrlPgDn
: begin
1003 SSize
:= ScreenSize
;
1004 xs
:= SSize
.x
- x1
+ 1;
1005 ys
:= SSize
.y
- y1
+ 1
1008 kbEsc
, kbAltEsc
: Done
:= True;
1009 else Changed
:= False
1013 DrawWindow (WindowList
)
1017 procedure ActivateCursor
;
1019 with WindowList
^, WindowTypes
[WindowType
] do
1021 PanelActivate (Panel
);
1023 SetCursorShape (CursorShape
)
1027 SetScroll (ScrollState
)
1032 ScreenShot
, Done
: Boolean;
1035 ScreenShot
:= ParamStr (1) = '--screenshot';
1036 if ParamCount
<> Ord (ScreenShot
) then
1038 RestoreTerminal (True);
1039 WriteLn (StdErr
, ParamStr (0), ': invalid argument `', ParamStr (Ord (ScreenShot
) + 1), '''');
1042 CRTSavePreviousScreen (True);
1043 SetCRTUpdate (UpdateInput
);
1044 MainPanel
:= GetActivePanel
;
1046 OrigScreenSize
:= ScreenSize
;
1049 CursorShape
:= CursorBlock
;
1050 NewWindow (6, 1, 1);
1051 NewWindow (2, 1, MaxInt
);
1052 NewWindow (8, MaxInt
, 1);
1053 NewWindow (5, 1, 27);
1054 KeyDemoKey (Ord ('f'));
1056 KeyDemoKey (kbDown
);
1057 NewWindow (3, MaxInt
, 13);
1058 NewWindow (4, MaxInt
, 31);
1059 NewWindow (7, MaxInt
, MaxInt
);
1060 NewWindow (9, MaxInt
, 33);
1061 NewWindow (0, 1, 2);
1062 NewWindow (1, 1, 14);
1067 NewWindow (0, 3, 2);
1072 case LoCaseKey (Key
) of
1073 Ord ('3'), kbF3
: OpenWindow
;
1074 Ord ('4'), kbF4
: CloseWindow
;
1075 Ord ('5'), kbF5
: PreviousWindow
;
1076 Ord ('6'), kbF6
: NextWindow
;
1077 Ord ('7'), kbF7
: MoveWindow
;
1078 Ord ('8'), kbF8
: ResizeWindow
;
1080 kbAltEsc
: Done
:= True;
1082 if WindowList
<> nil then
1083 with WindowList
^, WindowTypes
[WindowType
] do
1084 if @KeyProc
<> nil then
1087 TextBackground (Background
);