\begindata{text,537620288} \textdsversion{12} \template{default} \define{italic menu:[Font,Italic] attr:[FontFace Italic Int Set]} \define{bold menu:[Font,Bold] attr:[FontFace Bold Int Set]} \define{chapter menu:[Title,Chapter] attr:[Justification LeftJustified Point 0] attr:[FontFace Bold Int Set] attr:[FontSize PreviousFontSize Point 4]} \define{section menu:[Title,Section] attr:[Justification LeftJustified Point 0] attr:[FontFace Bold Int Set] attr:[FontSize PreviousFontSize Point 2]} \define{subsection menu:[Title,Subsection] attr:[Justification LeftJustified Point 0] attr:[FontFace Bold Int Set]} \define{paragraph menu:[Title,Paragraph] attr:[Justification LeftJustified Point 0] attr:[FontFace Italic Int Set]} \define{bigger menu:[Font,Bigger] attr:[FontSize PreviousFontSize Point 2]} \define{indent menu:[Region,Indent] attr:[LeftMargin LeftMargin Inch 32768] attr:[RightMargin RightMargin Inch 32768]} \define{typewriter menu:[Font,Typewriter] attr:[FontFace FixedFace Int Set] attr:[FontFamily AndyType Int 0]} \define{display menu:[Region,Display] attr:[LeftMargin LeftMargin Inch 32768] attr:[RightMargin RightMargin Inch 32768] attr:[Justification LeftJustified Point 0]} \define{example menu:[Region,Example] attr:[LeftMargin LeftMargin Inch 32768] attr:[Justification LeftJustified Point 0] attr:[FontFace FixedFace Int Set] attr:[FontFamily AndyType Int 0]} \define{description menu:[Region,Description] attr:[LeftMargin LeftMargin Inch 32768] attr:[Indent LeftEdge Inch -32768]} \define{quotation menu:[Region,Quotation] attr:[LeftMargin LeftMargin Inch 32768] attr:[RightMargin RightMargin Inch 32768] attr:[FontFace Italic Int Set]} \define{subscript menu:[Font~1,Subscript~31] attr:[Script PreviousScriptMovement Point 2] attr:[FontSize PreviousFontSize Point -2]} \define{superscript menu:[Font~1,Superscript~30] attr:[Script PreviousScriptMovement Point -6] attr:[FontSize PreviousFontSize Point -2]} \define{smaller menu:[Font,Smaller] attr:[FontSize PreviousFontSize Point -2]} \define{heading menu:[Title,Heading] attr:[LeftMargin LeftMargin Inch -13107] attr:[Justification LeftJustified Point 0] attr:[FontFace Bold Int Set]} \define{majorheading menu:[Title,MajorHeading] attr:[Justification Centered Point 0] attr:[FontSize PreviousFontSize Point 4]} \define{formatnote menu:[Region,FormatNote] attr:[Flags PassThru Int Set]} \define{subheading menu:[Title,Subheading] attr:[Justification LeftJustified Point 0] attr:[FontFace Bold Int Set]} \define{center menu:[Justify,Center] attr:[Justification Centered Point 0]} \define{flushleft menu:[Justify,FlushLeft] attr:[Justification LeftJustified Point 0]} \define{flushright menu:[Justify,FlushRight] attr:[Justification RightJustified Point 0]} \define{leftindent menu:[Region,LeftIndent] attr:[LeftMargin LeftMargin Inch 32768]} \majorheading{C Panel and Menus Handling Package } \center{Author - Larry K. Raper Menu Code by Mark Chance Unix Support by Mike Sclafani Version 2.0 (C) Copyright IBM Corporation 1986, 1987, 1988 Program Property of IBM \smaller{\smaller{$Disclaimer: Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice, this permission notice, and the following disclaimer appear in supporting documentation, and that the names of IBM, Carnegie Mellon University, and other copyright holders, not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. IBM, CARNEGIE MELLON UNIVERSITY, AND THE OTHER COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL IBM, CARNEGIE MELLON UNIVERSITY, OR ANY OTHER COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. $}}} \heading{Abstract } This package supports monochrome, color, and B/W displays via the standard PC BIOS Int 0x10 Video Interface. Also supported are terminals with cursor movement capability via the curses/termcap interface on Unix systems. Provides high level definition of input and output screens for easy user manipulation. Also provides programmer-friendly mechanisms for defining hierarchic menus in the style of Lotus 1-2-3. The normal sequence of the panel handler calls is 1. InitPanels (once) 2. SaveVideoEnv (once) 3. DrawPanel (as needed) 4. GetKey (once) 5. RestoreVideoEnv (once) The normal sequence of the menu handler calls is 1. InitMenus (once) 2. SetBaseMenu (once) 3. MenuInput (as needed) The keytab provided to GetKey is presumed to contain an exit key. \heading{General Panel Data Structures} There are several useful definitions provided in the panel input/output package. To use these your program must #include "panel.h". \subheading{PANEL} This is the fundamental output structure. struct \{ char prow, pcol, Starting row, column of panel. (0,0) is upper left. pattr, Panel attribute from list of field attribute values plen; Number of characters for input. Zero for an output panel. char *pdata; Panel text data \}; A panel array ends in (0,0,0,0,NULL). Example: \example{ PANEL login_boilerplate2[] = \{ 19, 3, RVIDEO, 0, "F1", 19, 6, NORMAL, 0, "Login", 19, 13, RVIDEO, 0, "F2", 19, 16, NORMAL, 0, "Logout", 19, 27, RVIDEO, 0, "PgDn", 19, 32, NORMAL, 0, "Display other sessions", 19, 60, RVIDEO, 0, "Esc", 19, 64, NORMAL, 0, "Return to DOS", 0, 0, 0, 0, NULL \}; PANEL PCSERVER_lines[] = \{ 14, 3, NORMAL, 0, "Root Directory ", 16, 8, NORMAL, 0, "PC Drive ", 0, 0, 0, 0, NULL \}; PANEL *PanelArray[] = \{ login_boilerplate1, login_boilerplate2, PCSERVER_lines, No_PCSERVER_lines, login_data, NULL\};} \subheading{FIELD } A field is the fundamental input structure. Each field consists of one or more extents for input and one prompt that will be shown when the field has the input focus. struct field \{ struct field *freturn; Next field on 'return' key struct field *fup; 'up' struct field *fdown; 'down' struct field *fleft; 'left' struct field *fright; 'right' XTENT *flocation; Field location ending in a zero-triplet unsigned char fattr; Video attribute of field char ftype; Type of data in field char *fdata; Data to display in field PRMPT *fprompt; Prompt to show when in field void (*fmodifyhandler)(); Function to call when field is modified void (*fentryhandler)(); Function to call on entry void (*fexithandler)(); Function to call on exit \}; \subheading{XTENT} An extent is one segment of a field. Generally extents do not cross lines. struct \{ unsigned char xrow, xcol, xlen; Row, column, and length vector \}; \subheading{PRMPT} A prompt is the text shown at the bottom of the screen when the user moves the cursor into a new field. typedef struct \{ char plen; Prompt length char *pdata; Prompt text \} PRMPT; Example: \example{PRMPT toprompt = \{0, "Enter the names of people to send the message to" \}; XTENT to_xtents[] = \{ 1, 4, TOCC_FIELD_LEN, 2, 4, TOCC_FIELD_LEN, 3, 4, TOCC_FIELD_LEN, 0, 0, 0 \}; char to_data[1+TOCC_FIELD_LEN*3]; PRMPT subprompt =\{0, "Enter the subject of your message" \}; XTENT subj_xtents[] = \{ 4, 9, SUBJ_FIELD_LEN, 0, 0, 0 \}; char subj_data[1+SUBJ_FIELD_LEN]; PRMPT ccprompt = \{0, "Enter the names of people to receive copies of your message" \}; XTENT cc_xtents[] = \{ 5, 4, TOCC_FIELD_LEN, 6, 4, TOCC_FIELD_LEN, 7, 4, TOCC_FIELD_LEN, 0, 0, 0 \}; char cc_data[1+ TOCC_FIELD_LEN*3]; PRMPT boprompt = \{0, "Enter the text of your message" \}; FIELD entry_fields[] = \{ /\italic{*0:To:*/} &entry_fields[1], &entry_fields[3], &entry_fields[1], &entry_fields[1], &entry_fields[1], to_xtents, NORMAL, FTYPE_ASC, to_data, &toprompt, SetSavethepage, (int (*)()) NULL, (int (*)())NULL, /\italic{*1:Su:*/} &entry_fields[2], &entry_fields[0], &entry_fields[2], &entry_fields[2], &entry_fields[2], subj_xtents, NORMAL, FTYPE_ASC, subj_data, &subprompt, SetSavethepage, (int (*)()) NULL, (int (*)())NULL, /\italic{*2:CC:*/} &entry_fields[3], &entry_fields[1], &entry_fields[3], &entry_fields[3], &entry_fields[3], cc_xtents, NORMAL, FTYPE_ASC, cc_data, &ccprompt, SetSavethepage, (int (*)()) NULL, (int (*)())NULL, /\italic{*3:bod*/} &entry_fields[0], &entry_fields[2], &entry_fields[0], &entry_fields[0], &entry_fields[0], (XTENT *) NULL, NORMAL, FTYPE_SCR, NIL, &boprompt, SetSavethepage, (int (*)()) NULL, EntryPageDnKey, NULL_FIELD \}; FIELD *FieldArray[] = \{ entry_fields, (FIELD *) NULL, \};} \subheading{Field attribute values} NORMAL Normal on all displays HILITE Hilite on all displays RVIDEO Reverse Video BLINKH Blink + HILITE REGDIF RVIDEO unless B/W adapter NORMCE Same as NORMAL, unless color NORMCI Same as NORMAL, unless color HILITC Same as HILITE, unless color RVIDHI Reverse Video + HILITE WHTBLU While on blue, or normal INVISI Invisible RINVIS Reverse Video & invisible data UNDERN Normal underline UNDERH Hilited underline \subheading{Field type values} FTYPE_ASC character string FTYPE_INT integer FTYPE_YN yes or no FTYPE_SEL cursor selection field FTYPE_WRD word (without blanks) FTYPE_SCR automatic scroll field \subheading{KEYTAB} This structure allows you to build tables which define how to treat special keys. The key codes are defined in keycodes.h which contains definitions for both the PC and terminals. struct \{ int scan_code; FIELD *(*keyhandler)(); \}; Example \example{ KEYTAB login_keys[] = \{ KEYCODE_F1, NewLogin, /* F1 */ KEYCODE_F2, NewLogout, /* F2 */ KEYCODE_PAGE_DOWN, NewPriorSession, /* PgDn */ KEYCODE_PAGE_UP, NewNextSession, /* PgUp */ KEYCODE_ESCAPE, EscapeKey, /* Esc */ 0, 0\}; FIELD *EscapeKey (curfield) FIELD *curfield; \{ RestoreVideoEnv (&vp, PANEL_NOCLEAR, 22); longjmp (endpanel1, -1); \} } \subheading{VIDEOPARMS} This structure holds the state of the system's video parameters. Generally you will not need to change these. struct \{ unsigned char palette; unsigned char page; unsigned char attr; unsigned char mode; unsigned char columns; \}; Example \example{VIDEOPARMS vp; SaveVideoEnv(&vp, 1); ... RestoreVideoEnv( &vp, PANEL_CLEAR, 0);} \heading{Menu Creation Data Structures (lmenus.h)} The package provides data and constant definitions for the 1-2-3 style menus enhancements. Your program must #include "lmenus.h". \subheading{MKEYTAB } This structure is just like KEYTAB except that the handling functions return integers instead of field pointers. struct \{ int scan_code; Key code int (*keyhandler)(); Handling function \} MKEYTAB; \subheading{MENU_OPTS } This structure defines one menu option. It consists of the one word description and a prompt to be displayed when the option is highlighted. struct \{ char *Option; Option word PRMPT prompt; Description of option \} MENU_OPTS; \subheading{MENU_TREE } This structure provides the definition of the menu hierarchy. The first element is an index into an array of menu options, the second is a pointer to a sub-menu. (Currently the nesting has only been tested to a level of 3 deep. struct \{ int this; MENU_TREE *submenu; \} ; Example: \example{MENU_OPTS vui_menus[] = \{ #define OPT_D_READ 0 "Read", \{0, "Display the list of messages in the highlighted folder"\}, #define OPT_D_ADD 1 "Create", \{0, "Create a new folder"\}, ....... NIL, \{0, NIL\}, \} MENU_TREE bb_menu[] = \{ OPT_D_READ, (MENU_TREE *)NIL, OPT_S_POST, (MENU_TREE *)NIL, OPT_D_INFO, d_info_menu, OPT_D_SUBSCR, d_subscr_menu, NULL_MENU \}; MENU_TREE d_info_menu[] = \{ OPT_D_BRIEF, (MENU_TREE *)NIL, OPT_D_LONG, (MENU_TREE *)NIL, NULL_MENU \};} The OPT_* constants can be used in the calling program to process the various options that are entered by the user. \heading{Function Calls for Paneling} To use the functions listed in this section you must compile and link in the panelp.c module. \subheading{InitPanels }This procedure fills in the length fields in panel and field arrays to agree with the corresponding constant strings. Some minimal consistency checking is also performed. \example{ InitPanels (p, f) PANEL *p[]; FIELD *f[];} \subheading{SaveVideoEnv }This routine should be called early in your program to allow you to exit and return the machine to the state is was prior to running your program. \example{ SaveVideoEnv (vp) VIDEOPARMS *vp;} \subheading{RestoreVideoEnv} This routine should be called just before your program exits. \example{ RestoreVideoEnv (vp, clear, cursor_row) VIDEOPARMS *vp; int clear; int cursor_row;} \subheading{ShowString }This routine allows you to put a text string on the screen. Generally there are higher-level routines that are preferred. Attr is one of the Field Attribute Values. \example{ ShowString (data, row, col, len, attr) char *data; unsigned char row, col, len, attr;} \subheading{ShowCursor} This routine redisplays the field currently with input focus. (At one time this field was displayed in reverse video, but it was considered too harsh for data entry especially when red is used as the background color, plus it takes a while to paint the screen reverse over slow terminals.) \example{ ShowCursor();} \subheading{EraseCursor} This routine removes highlighting from the current field. \example{ EraseCursor();} \subheading{ShowPrompt }This routine displays a prompt. Again, there are higher-level routines that are preferred. \example{ShowPrompt(msg) PRMPT *msg; } \subheading{DrawPanel} This routine displays a panel on the screen. \example{ DrawPanel (panel, inputfield, clear) PANEL *panel; An array of panels FIELD *inputfield; First field (may be NULL) int clear; Flag to indicate clearing the screen} For the \italic{clear} argument use either of the two constants: \leftindent{PANEL_CLEAR PANEL_NOCLEAR} \subheading{ShowMsg} \example{ ShowMsg (msg) PRMPT *msg;} \subheading{ErrorBeep} \example{ ErrorBeep();} \subheading{ShowError} \example{ ShowError (msg) PRMPT *msg;} \subheading{ClearError } \example{ClearError(); } \subheading{ClearLine }\example{ClearLine(line_no) int line_no; } \subheading{ClearScreen }\example{ClearScreen(); } \subheading{RedrawScreen }This routine is only be needed in a Unix terminal environment. \example{RedrawScreen(); } \subheading{UpdateScreen }This routine is only be needed in a Unix terminal environment. \subheading{ }\example{UpdateScreen(); } \subheading{GetCurrentField} \example{ FIELD *GetCurrentField ();} \subheading{SetCurrentField} This routine causes \italic{newfield} to become the current field. The exit handler on the current field is called, its highlighting removed and the entry handler of the new field is called and it is highlighted. \example{ SetCurrentField (newfield, prompt) FIELD *newfield; int prompt;} \subheading{RestoreCurrentField} This routine changes the current field, but does not update the screen or call any of the entry or exit handlers. \example{ RestoreCurrentField (curfield) FIELD *curfield;} \subheading{GetKey} Wait for the user to press a key, then process the value. \example{ GetKey (keytable) KEYTAB *keytable;} \subheading{GetFromUser }Use this routine to get an arbitrary string from the user. \example{GetFromUser(row, col, length, default, field_type, return_str) int row, col, length; char *default, field_type, *return_str; } \subheading{GetNUser }Use this routine to get a number within a specified range from the user. \example{GetNUser(row, col, length, min, max, val_out) int row, col, length, min, max, *val_out; } \subheading{GetSUser }This routine gets a string from the user using the default locations for input and output. \example{GetSUser(msg, prompt, default, str_out) char *msg, *prompt, *default, *str_out; } \subheading{GetStringFromUser }Another version with fewer options. \example{GetStringFromUser(prompt, output, length) char *prompt, *output; int length; } \subheading{GetBooleanFromUser }This routine asks the user a yes/no question and returns a boolean value. \example{GetBooleanFromUser(msg, default) char *msg, default; } \subheading{ConfirmUser }This routine displays the message and waits for the user to press return. \example{ConfirmUser(msg) char *msg; } \subheading{KeyHit }This routine returns a true value if a key has been pressed. \example{KeyHit(); } \subheading{KeyIn }This routine waits for the user to press a key and returns that value. When possible use GetKey. \example{KeyIn(); } \subheading{SetCursorPosn } \example{SetCursorPosn(); } \subheading{CursorOff }This routine turns the flashing cursor off or moves it out of the way on terminals that can't turn off the cursor. \example{CursorOff(); } \subheading{CursorOn }This routine turns the cursor on and displays it at the current input location. \example{CursorOn(); }\heading{Function Calls for Menu bars } To use the functions listed in this section you must compile and link in the lmenus.c module. \subheading{InitMenus }Initialize a set of menus by determining the length of each prompt and inserting that value into the data structure. This lets you avoid having to count the length of character strings. \example{InitMenus(menu_opt) MENU_OPTS *menu_opt; } \subheading{SetBaseMenu }This lets the panelling code know what array you are using. The menu trees contain indices into this array. \example{SetBaseMenu(menu) MENU_OPTS *menu; } \subheading{ShowMenu }Display a specified menu. \example{ShowMenu(menu_tree, current_option) MENU_TREE menu_tree[]; int current_option; } \subheading{EraseMenuCursor }Turn off the highlighting of a menu option. Typically you will call this routine before beginning to process a menu option. \example{EraseMenuCursor(); } \subheading{ShowMenuCursor }Call this routine to indicate that processing has finished and you are ready for input again. \example{ShowMenuCursor(); } \subheading{MenuInput }Display a menu, handle keys according to the table and return a value. The previous option is stored in last_opt_p. \example{MenuInput( menu_tree, keytable, last_opt_p) MENU_TREE menu_tree[]; MKEYTAB *keytable; int *last_opt_p; } \subheading{ClearPrompt }Erase the menu prompt. \example{ClearPrompt(); } \heading{Program Sample} \example{ ShowPanel () \{ FIELD *first_field; InitPanels (PanelArray, FieldArray); SaveVideoEnv (&vp); if (*p_hostname == 0) first_field = &login_fields[HOSIDX]; else first_field = &login_fields[USEIDX]; DrawPanel (login_boilerplate1, NULL, PANEL_CLEAR); DrawPanel (login_boilerplate2, NULL, PANEL_NOCLEAR); DrawPanel (login_data, first_field, PANEL_NOCLEAR); int i; if ((i = setjmp (endpanel1)) != 0) \{ /* Note: because of setjmp */ StripInput (); /* no register variables may */ ExitKey (); /* be used in this function. */ \} GetKey (login_keys); \} MainMenu () \{ quit = FALSE; while (!quit) \{ if (reshow) \{ DrawPanel(intro, NIL, PANEL_CLEAR); ShowBar(); reshow=FALSE; \} opt = MenuInput(main_menu, f1_keys, &last_opt); if (opt<0) \{ /* They pressed escape */ if (!GetBooleanFromUser("Do you really want to quit now?", FALSE)) return(0); \} switch (opt) \{ case OPT_G_MAIL: ..... \} \} \} } \heading{Implementer's Notes: } Aside from the files mentioned above: (panel.h, panelp.c, lmenus.h, lmenus.c, keycodes.h) there is a file that contains screen manipulation routines that are machine specific, panelmach.c. \enddata{text,537620288}