home *** CD-ROM | disk | FTP | other *** search
-
- { Program: General Interface Utilities
- Module: Menu Generator
- File: MENU.INC
- System: Turbo Pascal - Version 3, Generic MSDOS
- Version: 2.0 10/12/85
- Author: Michael H. Hughes [75766,1455]
-
- This material is hereby placed in the Public Domain
- Please give credit where credit is due }
-
-
- { This module contains the function "menu" which generates a very nice
- kind of menu display. This general type of menu has been common on Wang
- equipment for years, but has not caught on elsewhere. It is a neater and
- quicker menu than most of the common types.
-
- Pass the function a list of descriptive lines and it will display them
- on the screen along with a heading and instructions. A pointer is displayed
- beside the first line of the list, and that line is highlighted. Press
- a key (usually the space-bar) and the pointer will drop one line down the
- list. Another key (backspace) will move the pointer back up the list.
- Pressing any character key will cause the routine to search for a line
- beginning with that character. If found, the pointer will be positioned
- on that line. Another key (RETURN/ENTER/EXEC) will cause the routine to
- exit and return the number of the selected line. Another key (CANCEL/ESC)
- can be used as a "cancel" and will return a zero.
-
- The list is passed as an array of strings of length 30 with up to 40
- elements. The array may contain less than 40 elements, however.
- Note the use of a typeless parameter and an absolute address to pass an
- array of uknown length to the routine. The routine will position the
- list on the screen automatically, using two columns if necessary.
-
- The routine requires a single-keystroke input routine which does not echo
- to the screen or require a return/enter to respond. This routine must
- also return a unique value for any function keys used.
-
- The display will look better if the cursor is turned off. If this can't
- be done, move it out of the way while waiting for input. Note the ANSI
- code for this function in the "display header" section. This will work
- on IBM systems using the ANSI.SYS driver. Otherwise, a BIOS call will
- be required.
-
- The existing set-up is for IBM PC, but is easily changed for other
- systems. }
-
-
-
- { "keyin" checks to see if there is a character in the keyboard buffer
- and returns its numeric value if there is. Otherwise it returns a
- zero immediately. It does not wait for a character, or echo it to
- the screen. Note the machine dependent section for handling function
- keys; it can simply be eliminated in most cases. This routine can be
- placed inside "menu" if desired. }
-
- Function keyin: Byte;
- Var ch: Char;
- Begin
- keyin:=0;
- If keypressed Then
- Begin
- Read(KBD,ch);
- keyin:=ord(ch);
-
- { The next 5 lines handle function keys on the Wang PC;
- delete them or modify as required on other systems
- If ch = chr(31) Then
- Begin
- Read(KBD,ch);
- keyin:=ord(ch)
- End }
-
- End
- End;
-
-
- { "menu" generates the menu display, allows the operator to select the desired
- pick, and returns the number of the picked choice. It returns a zero if
- the "cancel" key is pressed.
-
- The parameter "number" specifies the number of choices on the menu, not
- counting the heading item, which is considered item zero.
-
- The parameter "data" is an array of strings containing number+1 elements,
- each with a maximum length of 30 characters. The first element contains
- the header line. Note that the number of elements in the array is
- undefined; it is up to the programmer to insure that "number" contains the
- correct value, and the elements of the array are defined as String[30]. }
-
-
- Function menu(number: Integer; Var data): Integer;
-
- Const llen=80; { screen line length }
- slen=20; { maximum number of items in one column }
- maxnumber=40; { maximum size of list array }
-
- { The following constants describe the values returned by "keyin"
- for the various keys used to control the display. }
-
- uplistkey = 8; { BACKSPACE }
- downlistkey = 32; { SPACE BAR }
-
-
- { For IBM PC and others use the following }
- cancelkey = 27; { ESC }
- executekey = 13; { RETURN/ENTER }
-
- (* { The Following values are for Wang PC only }
- cancelkey = 224; { CANCEL }
- executekey = 197; { EXECUTE } *)
-
-
- { The following constants specify graphic characters which are used
- to mark selected and non-selected items on the menu. }
-
- { Use these for IBM PC and video compatibles }
- menupointer = $FE;
- menumarker = $1C;
-
- (* { Use these values for Wang PC }
- menupointer = $87;
- menumarker = $85; *)
-
- (* { Use these for ASCII systems
- menupointer = $3E;
- menumarker = $2D; } *)
-
- Type listtype=Array[0..maxnumber] Of String[30]; {Dummy type for menu list}
- Var list: listtype Absolute data; { Dummy variable }
- posn, len, margin, vmargin, maxlen: Integer;{ Positioning variables }
- count, chval, cnumber: Integer; { Position counters }
- pointer, marker: String[3]; { Graphic markers }
- ch: Char; { Temporary }
-
- Begin
- pointer:=' '; pointer[2]:=chr(menupointer); { Create graphic markers }
- marker:=' '; marker[2]:=chr(menumarker);
-
- { Display Heading }
- ClrScr; NormVideo;
- write(chr(27),'[5h'); { ANSI cursor-off command; modify as required }
- gotoxy(39-length(list[0]) Div 2,1);
- write(list[0]); { Title line }
- { Insert any additional header line(s) here }
- LowVideo;
-
- { Compute positioning parameters for single or double column }
- If number > maxnumber Then number:=maxnumber;
- If number <= slen Then len:=number Else len:=slen;
- If number > slen Then margin:=0
- Else
- Begin
- maxlen:=0;
- For count:=1 to number Do
- If length(list[count]) > maxlen Then maxlen:=length(list[count]);
- margin:=39-((maxlen+2) Div 2)
- End;
- If number < slen Then vmargin:=(slen-number) Div 2
- Else vmargin:=(slen-(number Div 2)) Div 2;
- vmargin:=vmargin+3;
- If number > slen Then cnumber:=number Div 2
- Else cnumber:=number;
-
- { Display list }
- For posn:=1 To cnumber Do
- Begin
- gotoxy(margin,posn+vmargin);
- write(marker,list[posn]);
- If ((number) > slen) And ((posn+cnumber) < number) Then
- Begin
- gotoxy(36,posn+vmargin);
- write(marker,list[posn+cnumber])
- End;
- writeln
- End;
-
- { Display Instructions; modify as required }
- gotoxy(1,24); LowVideo;
- writeln('Press SPACE or BACKSPACE or First Letter of Line to Select');
- write('Press ENTER to run your choice, ESC for previous function');
-
- { Pick menu }
- posn:=1;
- Repeat
- { Display current pick }
- gotoxy(((posn-1) Div cnumber)*40+margin,
- ((posn-1) Mod cnumber)+1+vmargin);
- NormVideo;
- write(pointer,list[posn]);
- { Get Keyboard and clear current pick }
- Repeat chval:=keyin Until chval <> 0;
- gotoxy(((posn-1) Div cnumber)*40+margin,
- ((posn-1) Mod cnumber)+1+vmargin);
- LowVideo;
- If chval <> executekey Then write(marker,list[posn]);
-
- { Determine new Pick }
- If chval = executekey Then menu:=posn
- Else If chval = cancelkey Then menu:=0
- Else If chval = uplistkey Then
- If posn > 1 Then posn:=posn-1
- Else posn:=number
- Else If chval = downlistkey Then
- If posn < (number) Then posn:=posn+1
- Else posn:=1
- Else { Check for first character of line }
- Begin
- count:=posn;
- ch:=UpCase(chr(chval));
- Repeat
- count:=succ(count);
- If count > number Then count:=1
- Until (count = posn) Or (ch = UpCase(copy(list[count],1,1)));
- posn:=count
- End
- Until (chval = executekey) Or (chval = cancelkey)
- End;
-
-
-
-
- { The following program shows the use of "menu" as a basic program loader.
- The typed constants are used to set up the menu, and can be changed to
- provide any desired choice. The program list is simply in the same order as
- the descriptive lines. Lines[0] defines the menu heading while progs[0] is
- the program to be loaded if the "cancel" key is pressed. }
-
-
- Const maxlines = 4; { number of lines in menu }
-
- lines: Array[0..maxlines] Of String[30] =
- ('General Business Menu',
- 'Accounts Receivable',
- 'Accounts Payable',
- 'Payroll',
- 'General Ledger');
-
- progs: Array[0..maxlines] Of String[30] = { list of programs to load }
- ('MAINMENU.COM',
- 'AR.COM',
- 'AP.COM',
- 'PA.COM',
- 'GL.COM');
-
- Var nextprog: File;
-
- Begin { Main Program }
- assign(nextprog,progs[menu(maxlines,lines)]);
- execute(nextprog)
- End.