1
{ $Id: menus.pas,v 1.24 2005/02/14 17:13:18 peter Exp $ }
2
{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
4
{ System independent GRAPHICAL clone of MENUS.PAS }
6
{ Interface Copyright (c) 1992 Borland International }
8
{ Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer }
9
{ ldeboer@attglobal.net - primary e-mail addr }
10
{ ldeboer@starwon.com.au - backup e-mail addr }
12
{****************[ THIS CODE IS FREEWARE ]*****************}
14
{ This sourcecode is released for the purpose to }
15
{ promote the pascal language on all platforms. You may }
16
{ redistribute it and/or modify with the following }
19
{ This SOURCE CODE is distributed "AS IS" WITHOUT }
20
{ WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR }
21
{ ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED. }
23
{*****************[ SUPPORTED PLATFORMS ]******************}
25
{ Only Free Pascal Compiler supported }
27
{**********************************************************}
31
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
33
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
35
{====Include file to sort compiler platform out =====================}
37
{====================================================================}
39
{==== Compiler directives ===========================================}
41
{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
42
{$F-} { Near calls are okay }
43
{$A+} { Word Align Data }
44
{$B-} { Allow short circuit boolean evaluations }
45
{$O+} { This unit may be overlaid }
46
{$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
47
{$P-} { Normal string variables }
48
{$N-} { No 80x87 code generation }
49
{$E+} { Emulation is on }
52
{$X+} { Extended syntax is ok }
53
{$R-} { Disable range checking }
54
{$S-} { Disable Stack Checking }
55
{$I-} { Disable IO Checking }
56
{$Q-} { Disable Overflow Checking }
57
{$V-} { Turn off strict VAR strings }
58
{====================================================================}
61
{$IFDEF OS_WINDOWS} { WIN/NT CODE }
62
{$IFNDEF PPC_SPEED} { NON SPEED COMPILER }
63
{$IFDEF PPC_FPC} { FPC WINDOWS COMPILER }
64
Windows, { Standard unit }
65
{$ELSE} { OTHER COMPILERS }
66
WinTypes,WinProcs, { Standard units }
68
{$ELSE} { SPEEDSOFT COMPILER }
69
WinBase, WinDef, { Standard units }
73
objects, drivers, views, fvconsts; { GFV standard units }
75
{***************************************************************************}
77
{***************************************************************************}
79
{---------------------------------------------------------------------------}
81
{---------------------------------------------------------------------------}
83
CMenuView = #2#3#4#5#6#7; { Menu colours }
84
CStatusLine = #2#3#4#5#6#7; { Statusline colours }
86
{***************************************************************************}
87
{ RECORD DEFINITIONS }
88
{***************************************************************************}
90
TMenuStr = String[31]; { Menu string }
92
PMenu = ^TMenu; { Pointer to menu }
94
{---------------------------------------------------------------------------}
96
{---------------------------------------------------------------------------}
97
PMenuItem = ^TMenuItem;
99
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
101
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
103
Next: PMenuItem; { Next menu item }
104
Name: PString; { Menu item name }
105
Command: Word; { Menu item command }
106
Disabled: Boolean; { Menu item state }
107
KeyCode: Word; { Menu item keycode }
108
HelpCtx: Word; { Menu item help ctx }
114
{---------------------------------------------------------------------------}
116
{---------------------------------------------------------------------------}
118
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
120
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
122
Items: PMenuItem; { Menu item list }
123
Default: PMenuItem; { Default menu }
126
{---------------------------------------------------------------------------}
127
{ TStatusItem RECORD }
128
{---------------------------------------------------------------------------}
130
PStatusItem = ^TStatusItem;
132
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
134
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
136
Next: PStatusItem; { Next status item }
137
Text: PString; { Text of status item }
138
KeyCode: Word; { Keycode of item }
139
Command: Word; { Command of item }
142
{---------------------------------------------------------------------------}
143
{ TStatusDef RECORD }
144
{---------------------------------------------------------------------------}
146
PStatusDef = ^TStatusDef;
148
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
150
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
152
Next: PStatusDef; { Next status defined }
153
Min, Max: Word; { Range of item }
154
Items: PStatusItem; { Item list }
157
{***************************************************************************}
158
{ OBJECT DEFINITIONS }
159
{***************************************************************************}
161
{---------------------------------------------------------------------------}
162
{ TMenuView OBJECT - MENU VIEW ANCESTOR OBJECT }
163
{---------------------------------------------------------------------------}
165
PMenuView = ^TMenuView;
166
TMenuView = OBJECT (TView)
167
ParentMenu: PMenuView; { Parent menu }
168
Menu : PMenu; { Menu item list }
169
Current : PMenuItem; { Current menu item }
170
OldItem : PMenuItem; { Old item for draws }
171
CONSTRUCTOR Init (Var Bounds: TRect);
172
CONSTRUCTOR Load (Var S: TStream);
173
FUNCTION Execute: Word; Virtual;
174
FUNCTION GetHelpCtx: Word; Virtual;
175
FUNCTION GetPalette: PPalette; Virtual;
176
FUNCTION FindItem (Ch: Char): PMenuItem;
177
FUNCTION HotKey (KeyCode: Word): PMenuItem;
178
FUNCTION NewSubView (Var Bounds: TRect; AMenu: PMenu;
179
AParentMenu: PMenuView): PMenuView; Virtual;
180
PROCEDURE Store (Var S: TStream);
181
PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
182
PROCEDURE GetItemRect (Item: PMenuItem; Var R: TRect); Virtual;
184
PROCEDURE GetItemRectX (Item: PMenuItem; Var R: TRect); Virtual;
187
{---------------------------------------------------------------------------}
188
{ TMenuBar OBJECT - MENU BAR OBJECT }
189
{---------------------------------------------------------------------------}
191
TMenuBar = OBJECT (TMenuView)
192
CONSTRUCTOR Init (Var Bounds: TRect; AMenu: PMenu);
193
DESTRUCTOR Done; Virtual;
194
PROCEDURE Draw; Virtual;
196
PROCEDURE GetItemRectX (Item: PMenuItem; Var R: TRect); Virtual;
198
PMenuBar = ^TMenuBar;
200
{---------------------------------------------------------------------------}
201
{ TMenuBox OBJECT - BOXED MENU OBJECT }
202
{---------------------------------------------------------------------------}
204
TMenuBox = OBJECT (TMenuView)
205
CONSTRUCTOR Init (Var Bounds: TRect; AMenu: PMenu;
206
AParentMenu: PMenuView);
207
PROCEDURE Draw; Virtual;
209
PROCEDURE GetItemRectX (Item: PMenuItem; Var R: TRect); Virtual;
211
PMenuBox = ^TMenuBox;
213
{---------------------------------------------------------------------------}
214
{ TMenuPopUp OBJECT - POPUP MENU OBJECT }
215
{---------------------------------------------------------------------------}
217
TMenuPopup = OBJECT (TMenuBox)
218
CONSTRUCTOR Init (Var Bounds: TRect; AMenu: PMenu);
219
DESTRUCTOR Done; Virtual;
220
PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
222
PMenuPopup = ^TMenuPopup;
224
{---------------------------------------------------------------------------}
225
{ TStatusLine OBJECT - STATUS LINE OBJECT }
226
{---------------------------------------------------------------------------}
228
TStatusLine = OBJECT (TView)
229
Items: PStatusItem; { Status line items }
230
Defs : PStatusDef; { Status line default }
231
CONSTRUCTOR Init (Var Bounds: TRect; ADefs: PStatusDef);
232
CONSTRUCTOR Load (Var S: TStream);
233
DESTRUCTOR Done; Virtual;
234
FUNCTION GetPalette: PPalette; Virtual;
235
FUNCTION Hint (AHelpCtx: Word): String; Virtual;
236
PROCEDURE Draw; Virtual;
237
PROCEDURE Update; Virtual;
238
PROCEDURE Store (Var S: TStream);
239
PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
242
PROCEDURE DrawSelect (Selected: PStatusItem);
244
PStatusLine = ^TStatusLine;
246
{***************************************************************************}
247
{ INTERFACE ROUTINES }
248
{***************************************************************************}
250
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
251
{ MENU INTERFACE ROUTINES }
252
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
254
{-NewMenu------------------------------------------------------------
255
Allocates and returns a pointer to a new TMenu record. Sets the Items
256
and Default fields of the record to the value given by the parameter.
257
An error creating will return a nil pointer.
259
---------------------------------------------------------------------}
260
FUNCTION NewMenu (Items: PMenuItem): PMenu;
262
{-DisposeMenu--------------------------------------------------------
263
Disposes of all the elements of the specified menu (and all submenus).
265
---------------------------------------------------------------------}
266
PROCEDURE DisposeMenu (Menu: PMenu);
268
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
269
{ MENU ITEM ROUTINES }
270
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
272
{-NewLine------------------------------------------------------------
273
Allocates and returns a pointer to a new TMenuItem record that
274
represents a separator line in a menu box.
275
An error creating will return a nil pointer.
277
---------------------------------------------------------------------}
278
FUNCTION NewLine (Next: PMenuItem): PMenuItem;
280
{-NewItem------------------------------------------------------------
281
Allocates and returns a pointer to a new TMenuItem record that
282
represents a menu item (using NewStr to allocate the Name and Param).
283
An error creating will return a nil pointer.
285
---------------------------------------------------------------------}
286
FUNCTION NewItem (Name, Param: TMenuStr; KeyCode: Word; Command: Word;
287
AHelpCtx: Word; Next: PMenuItem): PMenuItem;
289
{-NewSubMenu---------------------------------------------------------
290
Allocates and returns a pointer to a new TMenuItem record, which
291
represents a submenu (using NewStr to allocate the Name).
292
An error creating will return a nil pointer.
294
---------------------------------------------------------------------}
295
FUNCTION NewSubMenu (Name: TMenuStr; AHelpCtx: Word; SubMenu: PMenu;
296
Next: PMenuItem): PMenuItem;
298
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
299
{ STATUS INTERFACE ROUTINES }
300
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
302
{-NewStatusDef-------------------------------------------------------
303
Allocates and returns a pointer to a new TStatusDef record initialized
304
with the given parameter values. Calls to NewStatusDef can be nested.
305
An error creating will return a nil pointer.
307
---------------------------------------------------------------------}
308
FUNCTION NewStatusDef (AMin, AMax: Word; AItems: PStatusItem;
309
ANext: PStatusDef): PStatusDef;
311
{-NewStatusKey-------------------------------------------------------
312
Allocates and returns a pointer to a new TStatusItem record initialized
313
with the given parameter values (using NewStr to allocate the Text).
314
An error in creating will return a nil pointer.
316
---------------------------------------------------------------------}
317
FUNCTION NewStatusKey (AText: String; AKeyCode: Word; ACommand: Word;
318
ANext: PStatusItem): PStatusItem;
320
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
321
{ OBJECT REGISTER ROUTINES }
322
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
323
{-RegisterMenus-------------------------------------------------------
324
Calls RegisterType for each of the object types defined in this unit.
326
---------------------------------------------------------------------}
327
PROCEDURE RegisterMenus;
329
{***************************************************************************}
330
{ OBJECT REGISTRATION }
331
{***************************************************************************}
333
{---------------------------------------------------------------------------}
334
{ TMenuBar STREAM REGISTRATION }
335
{---------------------------------------------------------------------------}
337
RMenuBar: TStreamRec = (
338
ObjType: idMenuBar; { Register id = 40 }
339
{$IFDEF BP_VMTLink} { BP style VMT link }
340
VmtLink: Ofs(TypeOf(TMenuBar)^);
341
{$ELSE} { Alt style VMT link }
342
VmtLink: TypeOf(TMenuBar);
344
Load: @TMenuBar.Load; { Object load method }
345
Store: @TMenuBar.Store { Object store method }
348
{---------------------------------------------------------------------------}
349
{ TMenuBox STREAM REGISTRATION }
350
{---------------------------------------------------------------------------}
352
RMenuBox: TStreamRec = (
353
ObjType: idMenuBox; { Register id = 41 }
354
{$IFDEF BP_VMTLink} { BP style VMT link }
355
VmtLink: Ofs(TypeOf(TMenuBox)^);
356
{$ELSE} { Alt style VMT link }
357
VmtLink: TypeOf(TMenuBox);
359
Load: @TMenuBox.Load; { Object load method }
360
Store: @TMenuBox.Store { Object store method }
363
{---------------------------------------------------------------------------}
364
{ TStatusLine STREAM REGISTRATION }
365
{---------------------------------------------------------------------------}
367
RStatusLine: TStreamRec = (
368
ObjType: 42; { Register id = 42 }
369
{$IFDEF BP_VMTLink} { BP style VMT link }
370
VmtLink: Ofs(TypeOf(TStatusLine)^);
371
{$ELSE} { Alt style VMT link }
372
VmtLink: TypeOf(TStatusLine);
374
Load: @TStatusLine.Load; { Object load method }
375
Store: @TStatusLine.Store { Object store method }
378
{---------------------------------------------------------------------------}
379
{ TMenuPopup STREAM REGISTRATION }
380
{---------------------------------------------------------------------------}
382
RMenuPopup: TStreamRec = (
383
ObjType: 43; { Register id = 43 }
384
{$IFDEF BP_VMTLink} { BP style VMT link }
385
VmtLink: Ofs(TypeOf(TMenuPopup)^);
386
{$ELSE} { Alt style VMT link }
387
VmtLink: TypeOf(TMenuPopup);
389
Load: @TMenuPopup.Load; { Object load method }
390
Store: @TMenuPopup.Store { Object store method }
393
{***************************************************************************}
394
{ INITIALIZED PUBLIC VARIABLES }
395
{***************************************************************************}
397
{---------------------------------------------------------------------------}
398
{ INITIALIZED PUBLIC VARIABLES }
399
{---------------------------------------------------------------------------}
401
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
403
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
408
SubMenuChar : array[boolean] of char = ('>',#16);
409
{ SubMenuChar is the character displayed at right of submenu }
411
{***************************************************************************}
413
{***************************************************************************}
415
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
416
{ TMenuView OBJECT METHODS }
417
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
419
{--TMenuView----------------------------------------------------------------}
420
{ Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
421
{---------------------------------------------------------------------------}
422
CONSTRUCTOR TMenuView.Init (Var Bounds: TRect);
424
Inherited Init(Bounds); { Call ancestor }
425
EventMask := EventMask OR evBroadcast; { See broadcast events }
428
{--TMenuView----------------------------------------------------------------}
429
{ Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB }
430
{---------------------------------------------------------------------------}
431
CONSTRUCTOR TMenuView.Load (Var S: TStream);
433
FUNCTION DoLoadMenu: PMenu;
434
VAR Tok: Byte; Item: PMenuItem; Last: ^PMenuItem; Menu: PMenu;
436
New(Menu); { Create new menu }
437
Last := @Menu^.Items; { Start on first item }
438
Item := Nil; { Clear pointer }
439
S.Read(Tok, SizeOf(Tok)); { Read token }
440
While (Tok <> 0) Do Begin
441
New(Item); { Create new item }
442
Last^ := Item; { First part of chain }
443
If (Item <> Nil) Then Begin { Check item valid }
444
Last := @Item^.Next; { Complete chain }
446
Name := S.ReadStr; { Read menu name }
447
S.Read(Command, SizeOf(Command)); { Menu item command }
448
S.Read(Disabled, SizeOf(Disabled)); { Menu item state }
449
S.Read(KeyCode, SizeOf(KeyCode)); { Menu item keycode }
450
S.Read(HelpCtx, SizeOf(HelpCtx)); { Menu item help ctx }
451
If (Name <> Nil) Then
454
SubMenu := DoLoadMenu() { Load submenu }
456
SubMenu := DoLoadMenu { Load submenu }
458
Else Param := S.ReadStr; { Read param string }
461
S.Read(Tok, SizeOf(Tok)); { Read token }
463
Last^ := Nil; { List complete }
464
Menu^.Default := Menu^.Items; { Set menu default }
465
DoLoadMenu := Menu; { Return menu }
469
Inherited Load(S); { Call ancestor }
470
Menu := DoLoadMenu; { Load menu items }
473
{--TMenuView----------------------------------------------------------------}
474
{ Execute -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB }
475
{---------------------------------------------------------------------------}
476
FUNCTION TMenuView.Execute: Word;
477
TYPE MenuAction = (DoNothing, DoSelect, DoReturn);
478
VAR AutoSelect: Boolean; Action: MenuAction; Ch: Char; Res: Word; R: TRect;
479
ItemShown, P: PMenuItem; Target: PMenuView; E: TEvent; MouseActive: Boolean;
481
PROCEDURE TrackMouse;
482
VAR Mouse: TPoint; R: TRect;
484
Mouse.X := E.Where.X - Origin.X; { Local x position }
485
Mouse.Y := E.Where.Y - oRigin.Y; { Local y position }
486
Current := Menu^.Items; { Start with current }
487
While (Current <> Nil) Do Begin
488
GetItemRectX(Current, R); { Get item rectangle }
489
If R.Contains(Mouse) Then Begin { Contains mouse }
490
MouseActive := True; { Return true }
493
Current := Current^.Next; { Try next item }
497
PROCEDURE TrackKey (FindNext: Boolean);
501
Current := Current^.Next; { Move to next item }
502
If (Current = Nil) Then
503
Current := Menu^.Items; { Return first menu }
509
P := Current; { Start on current }
510
If (P = Menu^.Items) Then P := Nil; { Check if at start }
511
Repeat NextItem Until Current^.Next = P; { Prev item found }
515
If (Current <> Nil) Then { Current view valid }
517
If FindNext Then NextItem Else PrevItem; { Find next/prev item }
518
Until (Current^.Name <> Nil); { Until we have name }
521
FUNCTION MouseInOwner: Boolean;
522
VAR Mouse: TPoint; R: TRect;
524
MouseInOwner := False; { Preset false }
525
If (ParentMenu <> Nil) AND (ParentMenu^.Size.Y = 1)
526
Then Begin { Valid parent menu }
527
Mouse.X := E.Where.X - ParentMenu^.Origin.X;{ Local x position }
528
Mouse.Y := E.Where.Y - ParentMenu^.Origin.Y;{ Local y position }
529
ParentMenu^.GetItemRectX(ParentMenu^.Current,R);{ Get item rect }
530
MouseInOwner := R.Contains(Mouse); { Return result }
534
FUNCTION MouseInMenus: Boolean;
537
P := ParentMenu; { Parent menu }
538
While (P <> Nil) AND NOT P^.MouseInView(E.Where)
539
Do P := P^.ParentMenu; { Check next menu }
540
MouseInMenus := (P <> Nil); { Return result }
543
FUNCTION TopMenu: PMenuView;
546
P := @Self; { Start with self }
547
While (P^.ParentMenu <> Nil) Do
548
P := P^.ParentMenu; { Check next menu }
549
TopMenu := P; { Top menu }
553
AutoSelect := False; { Clear select flag }
554
MouseActive := False; { Clear mouse flag }
555
Res := 0; { Clear result }
556
ItemShown := Nil; { Clear item pointer }
557
If (Menu <> Nil) Then Current := Menu^.Default { Set current item }
558
Else Current := Nil; { No menu = no current }
560
Action := DoNothing; { Clear action flag }
561
GetEvent(E); { Get next event }
563
evMouseDown: If MouseInView(E.Where) { Mouse in us }
564
OR MouseInOwner Then Begin { Mouse in owner area }
565
TrackMouse; { Track the mouse }
566
If (Size.Y = 1) Then AutoSelect := True; { Set select flag }
567
End Else Action := DoReturn; { Set return action }
569
TrackMouse; { Track the mouse }
570
If MouseInOwner Then { Mouse in owner }
571
Current := Menu^.Default { Set as current }
572
Else If (Current <> Nil) AND
573
(Current^.Name <> Nil) Then
574
Action := DoSelect { Set select action }
575
Else If MouseActive OR MouseInView(E.Where)
576
Then Action := DoReturn { Set return action }
578
Current := Menu^.Default; { Set current item }
579
If (Current = Nil) Then
580
Current := Menu^.Items; { Select first item }
581
Action := DoNothing; { Do nothing action }
584
evMouseMove: If (E.Buttons <> 0) Then Begin { Mouse moved }
585
TrackMouse; { Track the mouse }
586
If NOT (MouseInView(E.Where) OR MouseInOwner)
587
AND MouseInMenus Then Action := DoReturn; { Set return action }
590
Case CtrlToArrow(E.KeyCode) Of { Check arrow keys }
591
kbUp, kbDown: If (Size.Y <> 1) Then
592
TrackKey(CtrlToArrow(E.KeyCode) = kbDown){ Track keyboard }
593
Else If (E.KeyCode = kbDown) Then { Down arrow }
594
AutoSelect := True; { Select item }
595
kbLeft, kbRight: If (ParentMenu = Nil) Then
596
TrackKey(CtrlToArrow(E.KeyCode)=kbRight) { Track keyboard }
597
Else Action := DoReturn; { Set return action }
598
kbHome, kbEnd: If (Size.Y <> 1) Then Begin
599
Current := Menu^.Items; { Set to first item }
600
If (E.KeyCode = kbEnd) Then { If the 'end' key }
601
TrackKey(False); { Move to last item }
604
If Size.Y = 1 Then AutoSelect := True; { Select item }
605
Action := DoSelect; { Return the item }
608
Action := DoReturn; { Set return action }
609
If (ParentMenu = Nil) OR
610
(ParentMenu^.Size.Y <> 1) Then { Check parent }
611
ClearEvent(E); { Kill the event }
613
Else Target := @Self; { Set target as self }
614
Ch := GetAltChar(E.KeyCode);
615
If (Ch = #0) Then Ch := E.CharCode Else
616
Target := TopMenu; { Target is top menu }
617
P := Target^.FindItem(Ch); { Check for item }
618
If (P = Nil) Then Begin
619
P := TopMenu^.HotKey(E.KeyCode); { Check for hot key }
620
If (P <> Nil) AND { Item valid }
621
CommandEnabled(P^.Command) Then Begin { Command enabled }
622
Res := P^.Command; { Set return command }
623
Action := DoReturn; { Set return action }
625
End Else If Target = @Self Then Begin
626
If Size.Y = 1 Then AutoSelect := True; { Set auto select }
627
Action := DoSelect; { Select item }
628
Current := P; { Set current item }
629
End Else If (ParentMenu <> Target) OR
630
(ParentMenu^.Current <> P) Then { Item different }
631
Action := DoReturn; { Set return action }
633
evCommand: If (E.Command = cmMenu) Then Begin { Menu command }
634
AutoSelect := False; { Dont select item }
635
If (ParentMenu <> Nil) Then
636
Action := DoReturn; { Set return action }
637
End Else Action := DoReturn; { Set return action }
639
If (ItemShown <> Current) Then Begin { New current item }
640
OldItem := ItemShown; { Hold old item }
641
ItemShown := Current; { Hold new item }
642
DrawView; { Redraw the items }
643
OldItem := Nil; { Clear old item }
645
If (Action = DoSelect) OR ((Action = DoNothing)
646
AND AutoSelect) Then { Item is selecting }
647
If (Current <> Nil) Then With Current^ Do { Current item valid }
648
If (Name <> Nil) Then { Item has a name }
649
If (Command = 0) Then Begin { Has no command }
650
If (E.What AND (evMouseDown+evMouseMove) <> 0)
651
Then PutEvent(E); { Put event on queue }
652
GetItemRectX(Current, R); { Get area of item }
653
R.A.X := R.A.X + Origin.X; { Left start point }
654
R.A.Y := R.B.Y + Origin.Y;{ Top start point }
655
R.B.X := Owner^.Size.X; { X screen area left }
656
R.B.Y := Owner^.Size.Y; { Y screen area left }
657
Target := TopMenu^.NewSubView(R, SubMenu,
658
@Self); { Create drop menu }
659
Res := Owner^.ExecView(Target); { Execute dropped view }
660
Dispose(Target, Done); { Dispose drop view }
661
End Else If Action = DoSelect Then
662
Res := Command; { Return result }
663
If (Res <> 0) AND CommandEnabled(Res) { Check command }
665
Action := DoReturn; { Return command }
666
ClearEvent(E); { Clear the event }
667
End Else Res := 0; { Clear result }
668
Until (Action = DoReturn);
669
If (E.What <> evNothing) Then
670
If (ParentMenu <> Nil) OR (E.What = evCommand) { Check event type }
671
Then PutEvent(E); { Put event on queue }
672
If (Current <> Nil) Then Begin
673
Menu^.Default := Current; { Set new default }
674
Current := Nil; { Clear current }
675
DrawView; { Redraw the view }
677
Execute := Res; { Return result }
680
{--TMenuView----------------------------------------------------------------}
681
{ GetHelpCtx -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
682
{---------------------------------------------------------------------------}
683
FUNCTION TMenuView.GetHelpCtx: Word;
686
C := @Self; { Start at self }
687
While (C <> Nil) AND ((C^.Current = Nil) OR
688
(C^.Current^.HelpCtx = hcNoContext) OR { Has no context }
689
(C^.Current^.Name = Nil)) Do C := C^.ParentMenu; { Parent menu context }
690
If (C<>Nil) Then GetHelpCtx := C^.Current^.HelpCtx { Current context }
691
Else GetHelpCtx := hcNoContext; { No help context }
694
{--TMenuView----------------------------------------------------------------}
695
{ GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
696
{---------------------------------------------------------------------------}
697
FUNCTION TMenuView.GetPalette: PPalette;
698
{$IFDEF PPC_DELPHI3} { DELPHI3+ COMPILER }
699
CONST P: String = CMenuView; { Possible huge string }
700
{$ELSE} { OTHER COMPILERS }
701
CONST P: String[Length(CMenuView)] = CMenuView; { Always normal string }
704
GetPalette := @P; { Return palette }
707
{--TMenuView----------------------------------------------------------------}
708
{ FindItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
709
{---------------------------------------------------------------------------}
710
FUNCTION TMenuView.FindItem (Ch: Char): PMenuItem;
711
VAR I: Integer; P: PMenuItem;
713
Ch := UpCase(Ch); { Upper case of char }
714
P := Menu^.Items; { First menu item }
715
While (P <> Nil) Do Begin { While item valid }
716
If (P^.Name <> Nil) AND (NOT P^.Disabled) { Valid enabled cmd }
718
I := Pos('~', P^.Name^); { Scan for highlight }
719
If (I <> 0) AND (Ch = UpCase(P^.Name^[I+1])) { Hotkey char found }
721
FindItem := P; { Return item }
725
P := P^.Next; { Next item }
727
FindItem := Nil; { No item found }
730
{--TMenuView----------------------------------------------------------------}
731
{ HotKey -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
732
{---------------------------------------------------------------------------}
733
FUNCTION TMenuView.HotKey (KeyCode: Word): PMenuItem;
735
FUNCTION FindHotKey (P: PMenuItem): PMenuItem;
738
While (P <> Nil) Do Begin { While item valid }
739
If (P^.Name <> Nil) Then { If valid name }
740
If (P^.Command = 0) Then Begin { Valid command }
741
T := FindHotKey(P^.SubMenu^.Items); { Search for hot key }
742
If (T <> Nil) Then Begin
743
FindHotKey := T; { Return hotkey }
746
End Else If NOT P^.Disabled AND { Hotkey is enabled }
747
(P^.KeyCode <> kbNoKey) AND { Valid keycode }
748
(P^.KeyCode = KeyCode) Then Begin { Key matches request }
749
FindHotKey := P; { Return hotkey code }
752
P := P^.Next; { Next item }
754
FindHotKey := Nil; { No item found }
758
HotKey := FindHotKey(Menu^.Items); { Hot key function }
761
{--TMenuView----------------------------------------------------------------}
762
{ NewSubView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
763
{---------------------------------------------------------------------------}
764
FUNCTION TMenuView.NewSubView (Var Bounds: TRect; AMenu: PMenu;
765
AParentMenu: PMenuView): PMenuView;
767
NewSubView := New(PMenuBox, Init(Bounds, AMenu,
768
AParentMenu)); { Create a menu box }
771
{--TMenuView----------------------------------------------------------------}
772
{ Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
773
{---------------------------------------------------------------------------}
774
PROCEDURE TMenuView.Store (Var S: TStream);
776
PROCEDURE DoStoreMenu (Menu: PMenu);
777
VAR Item: PMenuItem; Tok: Byte;
779
Tok := $FF; { Preset max count }
780
Item := Menu^.Items; { Start first item }
781
While (Item <> Nil) Do Begin
783
S.Write(Tok, SizeOf(Tok)); { Write tok value }
784
S.WriteStr(Name); { Write item name }
785
S.Write(Command, SizeOf(Command)); { Menu item command }
786
S.Write(Disabled, SizeOf(Disabled)); { Menu item state }
787
S.Write(KeyCode, SizeOf(KeyCode)); { Menu item keycode }
788
S.Write(HelpCtx, SizeOf(HelpCtx)); { Menu item help ctx }
789
If (Name <> Nil) Then
790
If Command = 0 Then DoStoreMenu(SubMenu)
791
Else S.WriteStr(Param); { Write parameter }
793
Item := Item^.Next; { Next item }
795
Tok := 0; { Clear tok count }
796
S.Write(Tok, SizeOf(Tok)); { Write tok value }
800
TView.Store(S); { TView.Store called }
801
DoStoreMenu(Menu); { Store menu items }
804
{--TMenuView----------------------------------------------------------------}
805
{ HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
806
{---------------------------------------------------------------------------}
807
PROCEDURE TMenuView.HandleEvent (Var Event: TEvent);
808
VAR CallDraw: Boolean; P: PMenuItem;
810
PROCEDURE UpdateMenu (Menu: PMenu);
811
VAR P: PMenuItem; CommandState: Boolean;
813
P := Menu^.Items; { Start on first item }
814
While (P <> Nil) Do Begin
815
If (P^.Name <> Nil) Then { Valid name }
816
If (P^.Command = 0) Then UpdateMenu(P^.SubMenu){ Update menu }
818
CommandState := CommandEnabled(P^.Command); { Menu item state }
819
If (P^.Disabled = CommandState) Then Begin
820
P^.Disabled := NOT CommandState; { Disable item }
821
CallDraw := True; { Must draw }
824
P := P^.Next; { Next item }
830
PutEvent(Event); { Put event on queue }
831
Event.Command := Owner^.ExecView(@Self); { Execute view }
832
If (Event.Command <> 0) AND
833
CommandEnabled(Event.Command) Then Begin
834
Event.What := evCommand; { Command event }
835
Event.InfoPtr := Nil; { Clear info ptr }
836
PutEvent(Event); { Put event on queue }
838
ClearEvent(Event); { Clear the event }
842
If (Menu <> Nil) Then
844
evMouseDown: DoSelect; { Select menu item }
846
If (FindItem(GetAltChar(Event.KeyCode)) <> Nil)
847
Then DoSelect Else Begin { Select menu item }
848
P := HotKey(Event.KeyCode); { Check for hotkey }
850
(CommandEnabled(P^.Command)) Then Begin
851
Event.What := evCommand; { Command event }
852
Event.Command := P^.Command; { Set command event }
853
Event.InfoPtr := Nil; { Clear info ptr }
854
PutEvent(Event); { Put event on queue }
855
ClearEvent(Event); { Clear the event }
859
If Event.Command = cmMenu Then DoSelect; { Select menu item }
861
If (Event.Command = cmCommandSetChanged) { Commands changed }
863
CallDraw := False; { Preset no redraw }
864
UpdateMenu(Menu); { Update menu }
865
If CallDraw Then DrawView; { Redraw if needed }
870
{--TMenuView----------------------------------------------------------------}
871
{ GetItemRectX -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
872
{---------------------------------------------------------------------------}
873
PROCEDURE TMenuView.GetItemRectX (Item: PMenuItem; Var R: TRect);
874
BEGIN { Abstract method }
877
{--TMenuView----------------------------------------------------------------}
878
{ GetItemRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
879
{---------------------------------------------------------------------------}
880
PROCEDURE TMenuView.GetItemRect (Item: PMenuItem; Var R: TRect);
882
GetItemRectX(Item,R);
885
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
886
{ TMenuBar OBJECT METHODS }
887
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
889
{--TMenuBar-----------------------------------------------------------------}
890
{ Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
891
{---------------------------------------------------------------------------}
892
CONSTRUCTOR TMenuBar.Init (Var Bounds: TRect; AMenu: PMenu);
894
Inherited Init(Bounds); { Call ancestor }
895
GrowMode := gfGrowHiX; { Set grow mode }
896
Menu := AMenu; { Hold menu item }
897
Options := Options OR ofPreProcess; { Preprocessing view }
900
{--TMenuBar-----------------------------------------------------------------}
901
{ Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
902
{---------------------------------------------------------------------------}
903
DESTRUCTOR TMenuBar.Done;
905
If (Menu <> Nil) Then DisposeMenu(Menu); { Dispose menu items }
906
Inherited Done; { Call ancestor }
909
{--TMenuBar-----------------------------------------------------------------}
910
{ DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
911
{---------------------------------------------------------------------------}
912
PROCEDURE TMenuBar.Draw;
913
VAR I, J, CNormal, CSelect, CNormDisabled, CSelDisabled, Color: Word;
914
P: PMenuItem; B: TDrawBuffer;
916
CNormal := GetColor($0301); { Normal colour }
917
CSelect := GetColor($0604); { Select colour }
918
CNormDisabled := GetColor($0202); { Disabled colour }
919
CSelDisabled := GetColor($0505); { Select disabled }
920
MoveChar(B, ' ', Byte(CNormal), Size.X); { Empty bar }
921
If (Menu <> Nil) Then Begin { Valid menu }
922
I := 0; { Set start position }
923
P := Menu^.Items; { First item }
924
While (P <> Nil) Do Begin
925
If (P^.Name <> Nil) Then Begin { Name valid }
926
If P^.Disabled Then Begin
927
If (P = Current) Then Color := CSelDisabled{ Select disabled }
928
Else Color := CNormDisabled { Normal disabled }
930
If (P = Current) Then Color := CSelect { Select colour }
931
Else Color := CNormal; { Normal colour }
933
J := CStrLen(P^.Name^); { Length of string }
934
MoveChar(B[I], ' ', Byte(Color), 1);
935
MoveCStr(B[I+1], P^.Name^, Color); { Name to buffer }
936
MoveChar(B[I+1+J], ' ', Byte(Color), 1);
937
Inc(I, J+2); { Advance position }
939
P := P^.Next; { Next item }
942
WriteBuf(0, 0, Size.X, 1, B); { Write the string }
945
{--TMenuBar-----------------------------------------------------------------}
946
{ GetItemRectX -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB }
947
{---------------------------------------------------------------------------}
948
PROCEDURE TMenuBar.GetItemRectX (Item: PMenuItem; Var R: TRect);
949
VAR I: Integer; P: PMenuItem;
951
I := 0; { Preset to zero }
952
R.Assign(0, 0, 0, 1); { Initial rect size }
953
P := Menu^.Items; { First item }
954
While (P <> Nil) Do Begin { While valid item }
955
R.A.X := I; { Move area along }
956
If (P^.Name <> Nil) Then Begin { Valid name }
957
R.B.X := R.A.X+CTextWidth(' ' + P^.Name^ + ' ');{ Add text width }
958
I := I + CStrLen(P^.Name^) + 2; { Add item length }
959
End Else R.B.X := R.A.X;
960
If (P = Item) Then break; { Requested item found }
961
P := P^.Next; { Next item }
965
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
966
{ TMenuBox OBJECT METHODS }
967
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
969
{--TMenuBox-----------------------------------------------------------------}
970
{ Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
971
{---------------------------------------------------------------------------}
972
CONSTRUCTOR TMenuBox.Init (Var Bounds: TRect; AMenu: PMenu;
973
AParentMenu: PMenuView);
974
VAR W, H, L: Integer; S: String; P: PMenuItem; R: TRect;
976
W := 0; { Clear initial width }
977
H := 2; { Set initial height }
978
If (AMenu <> Nil) Then Begin { Valid menu }
979
P := AMenu^.Items; { Start on first item }
980
While (P <> Nil) Do Begin { If item valid }
981
If (P^.Name <> Nil) Then Begin { Check for name }
982
S := ' ' + P^.Name^ + ' '; { Transfer string }
983
If (P^.Command <> 0) AND (P^.Param <> Nil)
984
Then S := S + ' - ' + P^.Param^; { Add any parameter }
986
L := CTextWidth(S); { Width of string }
987
If (L > W) Then W := L; { Hold maximum }
988
Inc(H); { Inc count of items }
989
P := P^.Next; { Move to next item }
992
W := 5 + W; { Longest text width }
993
R.Copy(Bounds); { Copy the bounds }
994
If (R.A.X + W < R.B.X) Then R.B.X := R.A.X + W { Shorten if possible }
995
Else R.A.X := R.B.X - W; { Insufficent space }
997
If (R.A.Y + H < R.B.Y) Then R.B.Y := R.A.Y + H { Shorten if possible }
998
Else R.A.Y := R.B.Y - H; { Insufficent height }
999
Inherited Init(R); { Call ancestor }
1000
State := State OR sfShadow; { Set shadow state }
1001
Options := Options OR ofFramed or ofPreProcess; { View pre processes }
1002
Menu := AMenu; { Hold menu }
1003
ParentMenu := AParentMenu; { Hold parent }
1006
{--TMenuBox-----------------------------------------------------------------}
1007
{ Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1008
{---------------------------------------------------------------------------}
1009
PROCEDURE TMenuBox.Draw;
1010
VAR CNormal, CSelect, CSelectDisabled, CDisabled, Color: Word; Index, Y: Integer;
1011
S: String; P: PMenuItem; B: TDrawBuffer;
1013
FrameLineType = (UpperLine,NormalLine,SeparationLine,LowerLine);
1014
FrameLineChars = Array[0..2] of char;
1016
FrameLines : Array[FrameLineType] of FrameLineChars =
1017
('�Ŀ','� �','�Ĵ','���');
1018
Procedure CreateBorder(LineType : FrameLineType);
1020
MoveChar(B, ' ', CNormal, 1);
1021
MoveChar(B[1], FrameLines[LineType][0], CNormal, 1);
1022
MoveChar(B[2], FrameLines[LineType][1], Color, Size.X-4);
1023
MoveChar(B[Size.X-2], FrameLines[LineType][2], CNormal, 1);
1024
MoveChar(B[Size.X-1], ' ', CNormal, 1);
1029
CNormal := GetColor($0301); { Normal colour }
1030
CSelect := GetColor($0604); { Selected colour }
1031
CDisabled := GetColor($0202); { Disabled colour }
1032
CSelectDisabled := GetColor($0505); { Selected, but disabled }
1033
Color := CNormal; { Normal colour }
1034
CreateBorder(UpperLine);
1035
WriteBuf(0, 0, Size.X, 1, B); { Write the line }
1037
If (Menu <> Nil) Then Begin { We have a menu }
1038
P := Menu^.Items; { Start on first }
1039
While (P <> Nil) Do Begin { Valid menu item }
1040
Color := CNormal; { Normal colour }
1041
If (P^.Name <> Nil) Then Begin { Item has text }
1044
if (P = Current) then
1045
Color := CSelectDisabled
1047
Color := CDisabled; { Is item disabled }
1050
If (P = Current) Then Color := CSelect; { Select colour }
1051
CreateBorder(NormalLine);
1053
S := ' ' + P^.Name^ + ' '; { Menu string }
1054
MoveCStr(B[Index], S, Color); { Transfer string }
1055
if P^.Command = 0 then
1056
MoveChar(B[Size.X - 4],SubMenuChar[LowAscii],
1057
Byte(Color), 1) else
1058
If (P^.Command <> 0) AND(P^.Param <> Nil) Then
1060
MoveCStr(B[Size.X - 3 - Length(P^.Param^)], P^.Param^, Color); { Add param chars }
1061
S := S + ' - ' + P^.Param^; { Add to string }
1063
If (OldItem = Nil) OR (OldItem = P) OR
1065
Begin { We need to fix draw }
1066
WriteBuf(0, Y, Size.X, 1, B); { Write the whole line }
1068
End Else Begin { no text NewLine }
1069
Color := CNormal; { Normal colour }
1070
CreateBorder(SeparationLine);
1071
WriteBuf(0, Y, Size.X, 1, B); { Write the line }
1073
Inc(Y); { Next line down }
1074
P := P^.Next; { fetch next item }
1077
Color := CNormal; { Normal colour }
1078
CreateBorder(LowerLine);
1079
WriteBuf(0, Size.Y-1, Size.X, 1, B); { Write the line }
1083
{--TMenuBox-----------------------------------------------------------------}
1084
{ GetItemRectX -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1085
{---------------------------------------------------------------------------}
1086
PROCEDURE TMenuBox.GetItemRectX (Item: PMenuItem; Var R: TRect);
1087
VAR X, Y: Integer; P: PMenuItem;
1089
Y := 1; { Initial y position }
1090
P := Menu^.Items; { Initial item }
1091
While (P <> Item) Do Begin { Valid item }
1092
Inc(Y); { Inc position }
1093
P := P^.Next; { Next item }
1095
X := 2; { Left/Right margin }
1096
R.Assign(X, Y, Size.X - X, Y + 1); { Assign area }
1099
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1100
{ TMenuPopUp OBJECT METHODS }
1101
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1103
{--TMenuPopUp---------------------------------------------------------------}
1104
{ Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
1105
{---------------------------------------------------------------------------}
1106
CONSTRUCTOR TMenuPopup.Init (Var Bounds: TRect; AMenu: PMenu);
1108
Inherited Init(Bounds, AMenu, Nil); { Call ancestor }
1111
{--TMenuPopUp---------------------------------------------------------------}
1112
{ Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
1113
{---------------------------------------------------------------------------}
1114
DESTRUCTOR TMenuPopup.Done;
1116
If (Menu <> Nil) Then DisposeMenu(Menu); { Dispose menu items }
1117
Inherited Done; { Call ancestor }
1120
{--TMenuPopUp---------------------------------------------------------------}
1121
{ HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
1122
{---------------------------------------------------------------------------}
1123
PROCEDURE TMenuPopup.HandleEvent (Var Event: TEvent);
1128
P := FindItem(GetCtrlChar(Event.KeyCode)); { Find the item }
1129
If (P = Nil) Then P := HotKey(Event.KeyCode);{ Try hot key }
1130
If (P <> Nil) AND (CommandEnabled(P^.Command))
1131
Then Begin { Command valid }
1132
Event.What := evCommand; { Command event }
1133
Event.Command := P^.Command; { Set command value }
1134
Event.InfoPtr := Nil; { Clear info ptr }
1135
PutEvent(Event); { Put event on queue }
1136
ClearEvent(Event); { Clear the event }
1137
End Else If (GetAltChar(Event.KeyCode) <> #0)
1138
Then ClearEvent(Event); { Clear the event }
1141
Inherited HandleEvent(Event); { Call ancestor }
1144
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1145
{ TStatusLine OBJECT METHODS }
1146
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1148
{--TStatusLine--------------------------------------------------------------}
1149
{ Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1150
{---------------------------------------------------------------------------}
1151
CONSTRUCTOR TStatusLine.Init (Var Bounds: TRect; ADefs: PStatusDef);
1153
Inherited Init(Bounds); { Call ancestor }
1154
Options := Options OR ofPreProcess; { Pre processing view }
1155
EventMask := EventMask OR evBroadcast; { See broadcasts }
1156
GrowMode := gfGrowLoY + gfGrowHiX + gfGrowHiY; { Set grow modes }
1157
Defs := ADefs; { Set default items }
1158
FindItems; { Find the items }
1161
{--TStatusLine--------------------------------------------------------------}
1162
{ Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1163
{---------------------------------------------------------------------------}
1164
CONSTRUCTOR TStatusLine.Load (Var S: TStream);
1166
FUNCTION DoLoadStatusItems: PStatusItem;
1167
VAR Count: Integer; Cur, First: PStatusItem; Last: ^PStatusItem;
1169
Cur := Nil; { Preset nil }
1170
Last := @First; { Start on first item }
1171
S.Read(Count, SizeOf(Count)); { Read count }
1172
While (Count > 0) Do Begin
1173
New(Cur); { New status item }
1174
Last^ := Cur; { First chain part }
1175
If (Cur <> Nil) Then Begin { Check pointer valid }
1176
Last := @Cur^.Next; { Chain complete }
1177
Cur^.Text := S.ReadStr; { Read item text }
1178
S.Read(Cur^.KeyCode, SizeOf(Cur^.KeyCode)); { Keycode of item }
1179
S.Read(Cur^.Command, SizeOf(Cur^.Command)); { Command of item }
1181
Dec(Count); { One item loaded }
1183
Last^ := Nil; { Now chain end }
1184
DoLoadStatusItems := First; { Return the list }
1187
FUNCTION DoLoadStatusDefs: PStatusDef;
1188
VAR Count: Integer; Cur, First: PStatusDef; Last: ^PStatusDef;
1190
Last := @First; { Start on first }
1191
S.Read(Count, SizeOf(Count)); { Read item count }
1192
While (Count > 0) Do Begin
1193
New(Cur); { New status def }
1194
Last^ := Cur; { First part of chain }
1195
If (Cur <> Nil) Then Begin { Check pointer valid }
1196
Last := @Cur^.Next; { Chain complete }
1197
S.Read(Cur^.Min, SizeOf(Cur^.Min)); { Read min data }
1198
S.Read(Cur^.Max, SizeOf(Cur^.Max)); { Read max data }
1199
Cur^.Items := DoLoadStatusItems; { Set pointer }
1201
Dec(Count); { One item loaded }
1203
Last^ := Nil; { Now chain ends }
1204
DoLoadStatusDefs := First; { Return item list }
1208
Inherited Load(S); { Call ancestor }
1209
Defs := DoLoadStatusDefs; { Retreive items }
1210
FindItems; { Find the items }
1213
{--TStatusLine--------------------------------------------------------------}
1214
{ Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1215
{---------------------------------------------------------------------------}
1216
DESTRUCTOR TStatusLine.Done;
1219
PROCEDURE DisposeItems (Item: PStatusItem);
1222
While (Item <> Nil) Do Begin { Item to dispose }
1223
T := Item; { Hold pointer }
1224
Item := Item^.Next; { Move down chain }
1225
DisposeStr(T^.Text); { Dispose string }
1226
Dispose(T); { Dispose item }
1231
While (Defs <> Nil) Do Begin
1232
T := Defs; { Hold pointer }
1233
Defs := Defs^.Next; { Move down chain }
1234
DisposeItems(T^.Items); { Dispose the item }
1235
Dispose(T); { Dispose status item }
1237
Inherited Done; { Call ancestor }
1241
{--TStatusLine--------------------------------------------------------------}
1242
{ GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1243
{---------------------------------------------------------------------------}
1244
FUNCTION TStatusLine.GetPalette: PPalette;
1245
{$IFDEF PPC_DELPHI3} { DELPHI3+ COMPILER }
1246
CONST P: String = CStatusLine; { Possible huge string }
1247
{$ELSE} { OTHER COMPILERS }
1248
CONST P: String[Length(CStatusLine)] = CStatusLine; { Always normal string }
1251
GetPalette := @P; { Return palette }
1254
{--TStatusLine--------------------------------------------------------------}
1255
{ Hint -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1256
{---------------------------------------------------------------------------}
1257
FUNCTION TStatusLine.Hint (AHelpCtx: Word): String;
1259
Hint := ''; { Return nothing }
1262
{--TStatusLine--------------------------------------------------------------}
1263
{ Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1264
{---------------------------------------------------------------------------}
1265
PROCEDURE TStatusLine.Draw;
1267
DrawSelect(Nil); { Call draw select }
1270
{--TStatusLine--------------------------------------------------------------}
1271
{ Update -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
1272
{---------------------------------------------------------------------------}
1273
PROCEDURE TStatusLine.Update;
1274
VAR H: Word; P: PView;
1276
P := TopView; { Get topmost view }
1277
If (P <> Nil) Then H := P^.GetHelpCtx Else { Top views context }
1278
H := hcNoContext; { No context }
1279
If (HelpCtx <> H) Then Begin { Differs from last }
1280
HelpCtx := H; { Hold new context }
1281
FindItems; { Find the item }
1282
DrawView; { Redraw the view }
1286
{--TStatusLine--------------------------------------------------------------}
1287
{ Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1288
{---------------------------------------------------------------------------}
1289
PROCEDURE TStatusLine.Store (Var S: TStream);
1291
PROCEDURE DoStoreStatusItems (Cur: PStatusItem);
1292
VAR Count: Integer; T: PStatusItem;
1294
Count := 0; { Clear count }
1295
T := Cur; { Start on current }
1296
While (T <> Nil) Do Begin
1297
Inc(Count); { Count items }
1298
T := T^.Next; { Next item }
1300
S.Write(Count, SizeOf(Count)); { Write item count }
1301
While (Cur <> Nil) Do Begin
1302
S.WriteStr(Cur^.Text); { Store item text }
1303
S.Write(Cur^.KeyCode, SizeOf(Cur^.KeyCode)); { Keycode of item }
1304
S.Write(Cur^.Command, SizeOf(Cur^.Command)); { Command of item }
1305
Cur := Cur^.Next; { Move to next item }
1309
PROCEDURE DoStoreStatusDefs (Cur: PStatusDef);
1310
VAR Count: Integer; T: PStatusDef;
1312
Count := 0; { Clear count }
1313
T := Cur; { Current status item }
1314
While (T <> Nil) Do Begin
1315
Inc(Count); { Count items }
1316
T := T^.Next { Next item }
1318
S.Write(Count, 2); { Write item count }
1319
While (Cur <> Nil) Do Begin
1321
S.Write(Cur^.Min, 2); { Write min data }
1322
S.Write(Cur^.Max, 2); { Write max data }
1323
DoStoreStatusItems(Items); { Store the items }
1325
Cur := Cur^.Next; { Next status item }
1330
TView.Store(S); { TView.Store called }
1331
DoStoreStatusDefs(Defs); { Store status items }
1334
{--TStatusLine--------------------------------------------------------------}
1335
{ HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1336
{---------------------------------------------------------------------------}
1337
PROCEDURE TStatusLine.HandleEvent (Var Event: TEvent);
1338
VAR Mouse: TPoint; T, Tt: PStatusItem;
1340
FUNCTION ItemMouseIsIn: PStatusItem;
1341
VAR X, Xi: Word; T: PStatusItem;
1343
ItemMouseIsIn := Nil; { Preset fail }
1344
If (Mouse.Y < 0) OR (Mouse.Y > 1) { Outside view height }
1345
Then Exit; { Not in view exit }
1346
X := 0; { Zero x position }
1347
T := Items; { Start at first item }
1348
While (T <> Nil) Do Begin { While item valid }
1349
If (T^.Text <> Nil) Then Begin { Check valid text }
1350
Xi := X; { Hold initial x value }
1351
X := Xi + CTextWidth(' ' + T^.Text^ + ' '); { Add text width }
1352
If (Mouse.X >= Xi) AND (Mouse.X < X)
1354
ItemMouseIsIn := T; { Selected item }
1358
T := T^.Next; { Next item }
1363
Inherited HandleEvent(Event); { Call ancestor }
1366
T := Nil; { Preset ptr to nil }
1368
Mouse.X := Event.Where.X - Origin.X; { Local x position }
1369
Mouse.Y := Event.Where.Y - Origin.Y; { Local y position }
1370
Tt := ItemMouseIsIn; { Find selected item }
1371
If (T <> Tt) Then { Item has changed }
1372
DrawSelect(Tt); { Draw new item }
1373
T := Tt { Transfer item }
1374
Until NOT MouseEvent(Event, evMouseMove); { Mouse stopped moving }
1375
If (T <> Nil) AND CommandEnabled(T^.Command) { Check cmd enabled }
1377
Event.What := evCommand; { Command event }
1378
Event.Command := T^.Command; { Set command value }
1379
Event.InfoPtr := Nil; { No info ptr }
1380
PutEvent(Event); { Put event on queue }
1382
ClearEvent(Event); { Clear the event }
1383
DrawSelect(Nil); { Clear the highlight }
1385
evKeyDown: Begin { Key down event }
1386
T := Items; { Start on first item }
1387
While (T <> Nil) Do Begin { For each valid item }
1388
If (Event.KeyCode = T^.KeyCode) AND { Check for hot key }
1389
CommandEnabled(T^.Command) Then Begin { Check cmd enabled }
1390
Event.What := evCommand; { Change to command }
1391
Event.Command := T^.Command; { Set command value }
1392
Event.InfoPtr := Nil; { Clear info ptr }
1395
T := T^.Next; { Next item }
1399
If (Event.Command = cmCommandSetChanged) Then { Command set change }
1400
DrawView; { Redraw view }
1404
{***************************************************************************}
1405
{ TStatusLine OBJECT PRIVATE METHODS }
1406
{***************************************************************************}
1408
{--TStatusLine--------------------------------------------------------------}
1409
{ FindItems -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1410
{---------------------------------------------------------------------------}
1411
PROCEDURE TStatusLine.FindItems;
1414
P := Defs; { First status item }
1415
While (P <> Nil) AND ((HelpCtx < P^.Min) OR
1416
(HelpCtx > P^.Max)) Do P := P^.Next; { Find status item }
1417
If (P = Nil) Then Items := Nil Else
1418
Items := P^.Items; { Return found item }
1421
{--TStatusLine--------------------------------------------------------------}
1422
{ DrawSelect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB }
1423
{---------------------------------------------------------------------------}
1424
PROCEDURE TStatusLine.DrawSelect (Selected: PStatusItem);
1425
VAR I, L: Integer; Color, CSelect, CNormal, CSelDisabled, CNormDisabled: Word;
1426
HintBuf: String; B: TDrawBuffer; T: PStatusItem;
1428
CNormal := GetColor($0301); { Normal colour }
1429
CSelect := GetColor($0604); { Select colour }
1430
CNormDisabled := GetColor($0202); { Disabled colour }
1431
CSelDisabled := GetColor($0505); { Select disabled }
1432
MoveChar(B, ' ', Byte(CNormal), Size.X); { Clear the buffer }
1433
T := Items; { First item }
1434
I := 0; { Clear the count }
1436
While (T <> Nil) Do Begin { While valid item }
1437
If (T^.Text <> Nil) Then Begin { While valid text }
1438
L := CStrLen(' '+T^.Text^+' '); { Text length }
1439
If CommandEnabled(T^.Command) Then Begin { Command enabled }
1440
If T = Selected Then Color := CSelect { Selected colour }
1441
Else Color := CNormal { Normal colour }
1443
If T = Selected Then Color := CSelDisabled { Selected disabled }
1444
Else Color := CNormDisabled; { Disabled colour }
1445
MoveCStr(B[I], ' '+T^.Text^+' ', Color); { Move text to buf }
1446
Inc(I, L); { Advance position }
1448
T := T^.Next; { Next item }
1450
HintBuf := Hint(HelpCtx); { Get hint string }
1451
If (HintBuf <> '') Then Begin { Hint present }
1452
{$IFNDEF OS_WINDOWS}
1453
MoveChar(B[I], #179, Byte(CNormal), 1); { '|' char to buffer }
1455
MoveChar(B[I], #166, Byte(CNormal), 1); { '|' char to buffer }
1457
Inc(I, 2); { Move along }
1458
MoveStr(B[I], HintBuf, Byte(CNormal)); { Move hint to buffer }
1459
I := I + Length(HintBuf); { Hint length }
1461
WriteLine(0, 0, Size.X, 1, B); { Write the buffer }
1464
{***************************************************************************}
1465
{ INTERFACE ROUTINES }
1466
{***************************************************************************}
1468
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1469
{ MENU INTERFACE ROUTINES }
1470
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1472
{---------------------------------------------------------------------------}
1473
{ NewMenu -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB }
1474
{---------------------------------------------------------------------------}
1475
FUNCTION NewMenu (Items: PMenuItem): PMenu;
1478
New(P); { Create new menu }
1479
FillChar(P^,sizeof(TMenu),0);
1480
If (P <> Nil) Then Begin { Check valid pointer }
1481
P^.Items := Items; { Hold item list }
1482
P^.Default := Items; { Set default item }
1484
NewMenu := P; { Return menu }
1487
{---------------------------------------------------------------------------}
1488
{ DisposeMenu -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB }
1489
{---------------------------------------------------------------------------}
1490
PROCEDURE DisposeMenu (Menu: PMenu);
1491
VAR P, Q: PMenuItem;
1493
If (Menu <> Nil) Then Begin { Valid menu item }
1494
P := Menu^.Items; { First item in list }
1495
While (P <> Nil) Do Begin { Item is valid }
1496
If (P^.Name <> Nil) Then Begin { Valid name pointer }
1497
DisposeStr(P^.Name); { Dispose of name }
1498
If (P^.Command <> 0) Then
1499
DisposeStr(P^.Param) Else { Dispose parameter }
1500
DisposeMenu(P^.SubMenu); { Dispose submenu }
1502
Q := P; { Hold pointer }
1503
P := P^.Next; { Move to next item }
1504
Dispose(Q); { Dispose of item }
1506
Dispose(Menu); { Dispose of menu }
1510
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1511
{ MENU ITEM ROUTINES }
1512
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1514
{---------------------------------------------------------------------------}
1515
{ NewLine -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB }
1516
{---------------------------------------------------------------------------}
1517
FUNCTION NewLine (Next: PMenuItem): PMenuItem;
1520
New(P); { Allocate memory }
1521
FillChar(P^,sizeof(TMenuItem),0);
1522
If (P <> Nil) Then Begin { Check valid pointer }
1523
P^.Next := Next; { Hold next menu item }
1525
NewLine := P; { Return new line }
1528
{---------------------------------------------------------------------------}
1529
{ NewItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB }
1530
{---------------------------------------------------------------------------}
1531
FUNCTION NewItem (Name, Param: TMenuStr; KeyCode: Word; Command: Word;
1532
AHelpCtx: Word; Next: PMenuItem): PMenuItem;
1533
VAR P: PMenuItem; R: TRect; T: PView;
1535
If (Name <> '') AND (Command <> 0) Then Begin
1536
New(P); { Allocate memory }
1537
FillChar(P^,sizeof(TMenuItem),0);
1538
If (P <> Nil) Then Begin { Check valid pointer }
1539
P^.Next := Next; { Hold next item }
1540
P^.Name := NewStr(Name); { Hold item name }
1541
P^.Command := Command; { Hold item command }
1542
R.Assign(1, 1, 10, 10); { Random assignment }
1543
T := New(PView, Init(R)); { Create a view }
1544
If (T <> Nil) Then Begin
1545
P^.Disabled := NOT T^.CommandEnabled(Command);
1546
Dispose(T, Done); { Dispose of view }
1547
End Else P^.Disabled := True;
1548
P^.KeyCode := KeyCode; { Hold item keycode }
1549
P^.HelpCtx := AHelpCtx; { Hold help context }
1550
P^.Param := NewStr(Param); { Hold parameter }
1552
NewItem := P; { Return item }
1553
End Else NewItem := Next; { Move forward }
1556
{---------------------------------------------------------------------------}
1557
{ NewSubMenu -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB }
1558
{---------------------------------------------------------------------------}
1559
FUNCTION NewSubMenu (Name: TMenuStr; AHelpCtx: Word; SubMenu: PMenu;
1560
Next: PMenuItem): PMenuItem;
1563
If (Name <> '') AND (SubMenu <> Nil) Then Begin
1564
New(P); { Allocate memory }
1565
FillChar(P^,sizeof(TMenuItem),0);
1566
If (P <> Nil) Then Begin { Check valid pointer }
1567
P^.Next := Next; { Hold next item }
1568
P^.Name := NewStr(Name); { Hold submenu name }
1569
P^.HelpCtx := AHelpCtx; { Set help context }
1570
P^.SubMenu := SubMenu; { Hold next submenu }
1572
NewSubMenu := P; { Return submenu }
1573
End Else NewSubMenu := Next; { Return next item }
1576
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1577
{ STATUS INTERFACE ROUTINES }
1578
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1580
{---------------------------------------------------------------------------}
1581
{ NewStatusDef -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
1582
{---------------------------------------------------------------------------}
1583
FUNCTION NewStatusDef (AMin, AMax: Word; AItems: PStatusItem;
1584
ANext:PStatusDef): PStatusDef;
1587
New(T); { Allocate memory }
1588
If (T <> Nil) Then Begin { Check valid pointer }
1589
T^.Next := ANext; { Set next item }
1590
T^.Min := AMin; { Hold min value }
1591
T^.Max := AMax; { Hold max value }
1592
T^.Items := AItems; { Hold item list }
1594
NewStatusDef := T; { Return status }
1597
{---------------------------------------------------------------------------}
1598
{ NewStatusKey -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
1599
{---------------------------------------------------------------------------}
1600
FUNCTION NewStatusKey (AText: String; AKeyCode: Word; ACommand: Word;
1601
ANext: PStatusItem): PStatusItem;
1604
New(T); { Allocate memory }
1605
If (T <> Nil) Then Begin { Check valid pointer }
1606
T^.Text := NewStr(AText); { Hold text string }
1607
T^.KeyCode := AKeyCode; { Hold keycode }
1608
T^.Command := ACommand; { Hold command }
1609
T^.Next := ANext; { Pointer to next }
1611
NewStatusKey := T; { Return status item }
1614
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1615
{ OBJECT REGISTER ROUTINES }
1616
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
1618
{---------------------------------------------------------------------------}
1619
{ RegisterMenus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB }
1620
{---------------------------------------------------------------------------}
1621
PROCEDURE RegisterMenus;
1623
RegisterType(RMenuBar); { Register bar menu }
1624
RegisterType(RMenuBox); { Register menu box }
1625
RegisterType(RStatusLine); { Register status line }
1626
RegisterType(RMenuPopup); { Register popup menu }
1632
Revision 1.24 2005/02/14 17:13:18 peter