{***********************************************************************}
{									}
{ UNIT_MNU Menu Management Functions					}
{									}
{ This unit implements the POWER TOOLS PLUS menu management routines.	}
{ These routines provide the capability to create, display, modify,	}
{ read, remove and destroy moving highlight bar menus.	Menus can be	}
{ defined as vertical, horizontal, grid, or Lotus-style.		}
{									}
{									}
{  _KNOACTION_MNU  No action (may have motion)		     (constant) }
{  _KTRANSMIT_MNU  Transmit menu on this key		     (constant) }
{  _KABORT_MNU	   Transmit menu with error code	     (constant) }
{  _KBEEP_MNU	   Beep on this key			     (constant) }
{  _KDISABLE_MNU   Ignore this key			     (constant) }
{									}
{  _MDEFAULT_MNU   Default options only 		     (constant) }
{  _MREMOVE_MNU    Remove menu upon transmit		     (constant) }
{  _MKEEP_HIGHLIGHT_MNU 						}
{		   Leave highlight bar on transmit	     (constant) }
{  _MBEEP_ON_TRANSMIT_MNU						}
{		   Beep upon transmit			     (constant) }
{  _MBEEP_UNKNOWN_MNU							}
{		   Beep all unknown keystrokes		     (constant) }
{  _MTRANSMIT_UNKNOWN_MNU						}
{		   Transmit on unknown keystroke	     (constant) }
{  _MTRANSMIT_ALL_MNU							}
{		   Transmit on any keystroke		     (constant) }
{  _MCURSORON_MNU  Leave cursor on			     (constant) }
{  _MTRANSMIT_MNU  Transmit menu immediately		     (constant) }
{									}
{  _MENUSTRLEN_MNU String length for _MenuString	     (constant) }
{									}
{  _Menu	   Menu descriptor record		     (type)	}
{  _MenuPtr	   Pointer to a _Menu			     (type)	}
{  _Item	   Menu-item descriptor record		     (type)	}
{  _ItemPtr	   Pointer to an _Item			     (type)	}
{  _Key 	   Keystroke descriptor record		     (type)	}
{  _KeyPtr	   Pointer to a _Key			     (type)	}
{  _MenuString	   Menu-item string			     (type)	}
{  _MenuMotion	   Motions assigned to the _Motion field     (type)	}
{  _MError	   The possible values for _MenuError	     (type)	}
{  _MenuDefs	   Default menu definition record	     (type)	}
{									}
{  _MenuError	   Most recent menu error		     (variable) }
{  _MenuDefaults   Default menu definition		     (variable) }
{  _KnownPitch	   Tone for known keys			     (variable) }
{  _KnownDelay	   Duration of tone			     (variable) }
{  _UnknownPitch   Tone for unknown keys		     (variable) }
{  _UnknownDelay   Duration of tone			     (variable) }
{  _TransmitPitch  Tone at menu transmission		     (variable) }
{  _TransmitDelay  Duration of tone			     (variable) }
{									}
{ __MakeMnu	   Construct a menu descriptor record			}
{ __BuildMnu	   Create window, menu, items, keys with defaults	}
{ __AttchMnu	   Attach a menu to a window descriptor 		}
{ __ZapMnu	   Delete a menu descriptor				}
{ __ItemMnu	   Define a menu-item for a particular menu		}
{ __LItemMnu	   Define a Lotus-style menu item			}
{ __DelItMnu	   Delete a menu item					}
{ __RetItMnu	   Return a pointer to a menu item			}
{ __KeyMnu	   Define the keystrokes associated with a menu 	}
{ __DelKyMnu	   Delete a menu keystroke				}
{ __DefKyMnu	   Add a key to the linked list of default keys 	}
{ __DelDKMnu	   Delete a key from the linked list of default keys	}
{ __DispMnu	   Display a menu					}
{ __RemMnu	   Remove the a menu from the screen			}
{ __ReadMnu	   Return a menu selection				}
{									}
{ Version 4.00 (C)Copyright Blaise Computing Inc. 1987			}
{_______________________________________________________________________}

Unit Unit_Mnu;

interface

uses DOS,			       { Turbo Pascal DOS unit		}
     CRT,			       { Turbo Pascal CRT unit		}
     Unit_Sup,			       { POWER TOOLS PLUS Support  unit }
     Unit_Scn,			       { POWER TOOLS PLUS Screen   unit }
     Unit_Win,			       { POWER TOOLS PLUS Window   unit }
     Unit_Key;			       { POWER TOOLS PLUS Keyboard unit }


  const 			       { Menu keystroke actions 	}
    _KNOACTION_MNU	 = $00;        { No action (may have motion)	}
    _KTRANSMIT_MNU	 = $01;        { Transmit menu on this key	}
    _KABORT_MNU 	 = $02;        { Transmit menu with error code	}
    _KBEEP_MNU		 = $04;        { Beep on this key		}
    _KDISABLE_MNU	 = $08;        { Ignore this key		}

				       { __ReadMnu options:		}
    _MDEFAULT_MNU	 = $00;        { Do nothing special		}
    _MREMOVE_MNU	 = $01;        { Remove menu upon transmit	}
    _MKEEP_HIGHLIGHT_MNU = $02;        { Leave highlight bar on trans	}
    _MBEEP_TRANSMIT_MNU  = $04;        { Beep upon transmit		}
    _MBEEP_UNKNOWN_MNU	 = $08;        { Beep all unknown keystrokes	}
    _MTRANSMIT_UNKNOWN_MNU	       { Transmit upon unknown keystr	}
			 = $10;
    _MTRANSMIT_ALL_MNU	 = $20;        { Transmit on any keystroke	}
    _MCURSORON_MNU	 = $40;        { Leave cursor on		}
    _MTRANSMIT_MNU	 = $80;        { Transmit menu immediately	}

    _MENUSTRLEN_MNU	 = 80;	       { String length for _MenuString	}

  type
    _MenuString  = string[_MENUSTRLEN_MNU];

    _MenuMotion  = (_NoMove,	       { Do not move			}
		    _Up,	       { Upward in the same column	}
		    _Down,	       { Downward in the same column	}
		    _Right,	       { To the right on the same row	}
		    _Left,	       { To the left on the same row	}
		    _Next,	       { To the next item in the list	}
		    _Previous,	       { To the previous item		}
		    _First,	       { To the first item in the list	}
		    _Last,	       { To the last item in the list	}
		    _NextCh,	       { Next highlighted character item}
		    _Goto);	       { To the a specific item 	}

    _MError	 = (_NoError,	       { No error encountered yet	}
		    _InvalidMenu,      { Invalid menu structure 	}
		    _InvalidItem,      { Invalid item structure 	}
		    _InvalidKey,       { Invalid key structure		}
		    _InvalidWindow,    { No window attached to menu	}
		    _NoMenuItems,      { No items; menu cannot be read	}
		    _NoMenuExit);      { No keystroke transmits/aborts	}

    _ItemPtr	 = ^_Item;
    _Item	 = record		     { Menu item descriptor	}
		     _ISig	 : char;     { Signature byte		}
		     _Len	 : byte;     { Length of the menu item	}
		     _LDescCol	 : byte;     { Coordinates of optional	}
		     _LDescRow	 : byte;     { Lotus-style description	}
		     _LDescLen	 : byte;     { Long description length	}
		     _HiChPos	 : byte;     { Highlighted char position}
		     _HiChFore	 : byte;     { Attribute of highlighted }
		     _HiChBack	 : byte;     { character in menu item.	}
		     _Protect	 : boolean;  { Protected item		}
		     _Active	 : boolean;  { Visible item		}
		     _ItemStrPtr : pointer;  { Pointer to item string	}
		     _LDescPtr	 : pointer;  { Lotus description string }
		     _PrevItem	 : _ItemPtr; { List pointers		}
		     _NextItem	 : _ItemPtr;
		     case integer of	     { Coordinates within the	}
		       0  : (_ColRow   : word);  { menu window. 	}
		       1  : (_Row      : byte;
			     _Col      : byte)
		   end;

    _KeyPtr	 = ^_Key;
    _Key	 = record
		     _KSig     : char;	     { Signature byte		}
		     _Action   : byte;
		     _Motion   : _MenuMotion;
		     _KeyItem  : _ItemPtr;
		     _NextKey  : _KeyPtr;
		     _KChSc    : _KeySeq;
		   end;

    _MenuPtr	 = ^_Menu;
    _Menu	 = record		      { Menu descriptor 	}
		     _MSig	: char;       { Signature byte		}
		     _MWinPtr	: _WindowPtr; { Pointer to its window	}
		     _MItemsPtr : _ItemPtr;   { Pointer to _Item list	}
		     _MITailPtr : _ItemPtr;   { Pointer to last item	}
		     _MLastPtr	: _ItemPtr;   { Last position of bar	}
		     _MKeysPtr	: _KeyPtr;    { Pointer to _Key list	}
		     _BarFore	: byte;       { Highlight bar attribute }
		     _BarBack	: byte;
		     _LDescFore : byte;       { Lotus-type description	}
		     _LDescBack : byte;       {   attribute		}
		     _ProtFore	: byte;       { Protected attribute	}
		     _ProtBack	: byte;
		   end;

    _MenuDefs	 = record		      { __BuildMnu defaults	}
		     _DBorType	: byte;       { Window border type	}
		     _DBorFore	: byte;       { Border attribute	}
		     _DBorBack	: byte;
		     _DWinFore	: byte;       { Window attribute	}
		     _DWinBack	: byte;
		     _DBarFore	: byte;       { Highlight bar attribute }
		     _DBarBack	: byte;
		     _DProtFore : byte;       { Protected item attribute}
		     _DProtBack : byte;
		     _DHiFore	: byte;       { Highlighted character	}
		     _DHiBack	: byte;       { attribute		}
		     _DHorizOfs : byte;       { Item spacing		}
		     _DMStrLen	: byte;       { Max item string length	}
		     _DTitlePos : Unit_Win._WinTitlePos;
		     _DHighlight: boolean;    { Highlight first char?	}
		     _DAltXmit	: boolean     { Transmit with alt/char? }
		   end;

  var
    _MenuError	    : _MError;
    _MenuDefaults   : _MenuDefs;
    _KnownPitch     : word;
    _KnownDelay     : word;
    _UnknownPitch   : word;
    _UnknownDelay   : word;
    _TransmitPitch  : word;
    _TransmitDelay  : word;

  function __MakeMnu (WindowPtr : _WindowPtr;
		    BFore,BBack,
		    LFore,LBack,
		    PFore,PBack : byte) : _MenuPtr;
  function __BuildMnu(X1,Y1,X2,Y2 : byte;
			    Title : string;
			    MDefs : _MenuDefs;
			  TextPtr : pointer;
			TextItems : byte) : _MenuPtr;
  function __AttchMnu(MenuPtr : _MenuPtr;
		    WindowPtr : _WindowPtr) : boolean;
  function __ZapMnu  (var MenuPtr : _MenuPtr) : boolean;
  function __ItemMnu (MenuPtr : _MenuPtr;
		      Col,Row,
		      HiChPos,
	    HiChFore,HiChBack : byte;
		      Protect : boolean;
		     MenuItem : _MenuString) : _ItemPtr;
  function __LItemMnu(MenuPtr : _MenuPtr;
		     Col,Row,
		LDescCol,LDescRow,
		      HiChPos,
	    HiChFore,HiChBack : byte;
		      Protect : boolean;
		     MenuItem : _MenuString;
		       LDescr : string) : _ItemPtr;
  function __DelItMnu(MenuPtr : _MenuPtr; Col,Row : byte) : boolean;
  function __RetItMnu(MenuPtr : _MenuPtr; Col,Row : byte) :_ItemPtr;
  function __KeyMnu  (MenuPtr : _MenuPtr;
		      ItemPtr : _ItemPtr;
			  Key : _Keys;
		       Action : byte;
		       Motion : _MenuMotion) : _KeyPtr;
  function __DelKyMnu(MenuPtr : _MenuPtr; Key : _Keys) : boolean;
  function __DefKyMnu(Key : _Keys;
		   Action : byte;
		   Motion : _MenuMotion) : _KeyPtr;
  function __DelDKMnu(Key : _Keys) : boolean;
  function __DispMnu (MenuPtr : _MenuPtr) : boolean;
  function __RemMnu  (MenuPtr : _MenuPtr) : boolean;
  function __ReadMnu (MenuPtr : _MenuPtr;
		    FirstItem : _ItemPtr;
		      Options : word;
		      var Key : _Keys) : _ItemPtr;

implementation

  const
				       { Signature bytes for		}
    ITEMSIG_ = 'I';		       { _Item records, 		}
    MENUSIG_ = 'M';		       { _Menu records, and		}
    KEYSIG_  = 'K';		       { _Key records.			}

  var
    DefaultKeyPtr_  : _KeyPtr;	       { Head of default keys list.	}

{$I utlmnu.imp	}
{$I makemnu.imp }
{$I buildmnu.imp}
{$I attchmnu.imp}
{$I zapmnu.imp	}
{$I itemmnu.imp }
{$I litemmnu.imp}
{$I delitmnu.imp}
{$I retitmnu.imp}
{$I keymnu.imp	}
{$I delkymnu.imp}
{$I defkymnu.imp}
{$I deldkmnu.imp}
{$I dispmnu.imp }
{$I remmnu.imp	}
{$I readmnu.imp }

  type
    KeyDefaults = record
		     DAction  : byte;
		     DMotion  : _MenuMotion;
		     DKey     : _Keys
		   end;

  { The following typed constant array defines the initial default	}
  { key definitions which become active when __ReadMnu is called.  The	}
  { unit initialization code stores these definitions in a linked list	}
  { on the heap.  You can modify the default list with the function	}
  { __DefKyMnu (add default key definitions) and __DelDKMnu (delete	}
  { default key definitions).						}

  const

    NUMKEYS = 17;

    InitKeys : array[1..NUMKEYS] of KeyDefaults =
					   ((DAction : _KNOACTION_MNU;
					     DMotion : _Up;
					     DKey    : _Key_up	     ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Up;
					     DKey    : _Key_pad_up   ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Down;
					     DKey    : _Key_down     ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Down;
					     DKey    : _Key_pad_down ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Right;
					     DKey    : _Key_right    ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Right;
					     DKey    : _Key_pad_right),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Left;
					     DKey    : _Key_left     ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Left;
					     DKey    : _Key_pad_left ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _First;
					     DKey    : _Key_Home     ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _First;
					     DKey    : _Key_pad_Home ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Last;
					     DKey    : _Key_End      ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Last;
					     DKey    : _Key_pad_End  ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Next;
					     DKey    : _Key_Tab      ),
					    (DAction : _KNOACTION_MNU;
					     DMotion : _Previous;
					     DKey    : _Key_s_Tab    ),
					    (DAction : _KABORT_MNU;
					     DMotion : _NoMove;
					     DKey    : _Key_Esc      ),
					    (DAction : _KTRANSMIT_MNU;
					     DMotion : _NoMove;
					     DKey    : _Key_Enter    ),
					    (DAction : _KTRANSMIT_MNU;
					     DMotion : _NoMove;
					     DKey    : _Key_pad_Enter));

  var
    TempPtr : _KeyPtr;
    LastPtr : _KeyPtr;
    I	    : word;

  begin {Initialization}

    { Load the default key definitions into a linked list, which is	}
    { copied into the linked list of key definitions for every menu	}
    { created with __MakeMnu or __BuildMnu.				}

    _MenuError	   := _NoError;
    DefaultKeyPtr_ := NIL;	       { Default key list root		}
    for I := 1 to NUMKEYS do
      with InitKeys[I] do
	TempPtr := __DefKyMnu(DKey,DAction,DMotion);

    _KnownPitch    := 110;	       { All times are in milliseconds	}
    _KnownDelay    := 20;
    _UnknownPitch  := 880;
    _UnknownDelay  := 100;
    _TransmitPitch := 440;
    _TransmitDelay := 150;

    { Define _MenuDefaults, so it may be used with __BuildMnu.		}

    with _MenuDefaults do
      begin
	if (Unit_Scn._CurDevice = _MONO) then
	   begin
	     _DBorFore	  := Black;	{ Reverse video border		}
	     _DBorBack	  := LightGray;
	     _DWinFore	  := LightGray; { Normal video window		}
	     _DWinBack	  := Black;
	     _DBarFore	  := Black;	{ Reverse video highlight bar	}
	     _DBarBack	  := LightGray;
	     _DProtFore   := LightGray; { Protected same as unprotected }
	     _DProtBack   := Black;	{ no highlighted character.	}
	     _DHiFore	  := White;	{ Intense white for highlighted }
	     _DHiBack	  := Black	{ characters.			}
	   end
	else
	   begin
	     _DBorFore	  := Black;	{ Reverse video border		}
	     _DBorBack	  := LightGray;
	     _DWinFore	  := Yellow;
	     _DWinBack	  := Blue;
	     _DBarFore	  := White;
	     _DBarBack	  := Red;
	     _DProtFore   := LightGray;
	     _DProtBack   := Blue;
	     _DHiFore	  := White;
	     _DHiBack	  := Blue
	   end;

	_DBorType    := 0;		{ Single line border		}
	_DHorizOfs   := 0;		{ Vertical style		}
	_DMStrLen    := _MENUSTRLEN_MNU;{ Max item length		}
	_DTitlePos   := _TopCenter;	{ Top centered title		}
	_DHighLight  := TRUE;		{ Highlight the first character }
	_DAltXmit    := TRUE		{ Choose item and transmit on	}
      end				{ Alt key combinations		}

  end.	{Initialization}
