Subroutine MTF.INPUT.B(orientation, menu.x.orig, menu.y.orig, menu.width, menu.choices, submenu.flag, menu.help, cursor.location, menu.mnemonic, input.code,menu.items) ****************************************************************************** * * Menu input function * * Module %M% Version %I% Date %H% * * (c) Copyright 1998 Ardent Software Inc. - All Rights Reserved * This is unpublished proprietary source code of Ardent Software Inc. * The copyright notice above does not evidence any actual or intended * publication of such source code. * ******************************************************************************* * * Maintenence log - insert most recent change descriptions at top * * Date.... GTAR# WHO Description........................................ * 10/14/98 23801 SAP Change copyrights. * 07/09/91 8502 DTM Fixed input of key * 05/13/91 8345 DTM Changed print to tprint * 2/7/91 7673 DTM Final changes for FCS * 8/30/90 7403 DTM Revised reverse video screen routines * 8/13/90 7366 DPB Changed the delay time for escape sequences. * 6/28/90 7236 DSC New MOTIF-like capability ******************************************************************************* * This subroutine manipulates the highlighted cursor location on an * MOTIF menu object which has already been painted on the terminal * screen, and accepting and interpreting user input for navigation * and other MOTIF standard commands. * Commands for HELP and for moving cursor are handled internally; * commands that require manipulation of menus (as opposed to within * this one menu) are passed back to the calling routine. * Arguments to the function are: * orientation - is the menu horizontal (menubar) or vertical. * * menu.x.orig - the x (horizontal) anchor point for the menu. * * menu.y.orig - the y (vertical) anchor point for the menu. * * menu.width - for vertical menus, the width of the menu; * for horizontal menus, a dynamic array of horizontal * start and end points. * * menu.choices - number of menu elements. * * submenu.flag - dynamic array, True for those elements of a * vertically oriented menu which have cascading sub-menus. * * menu.help - dynamic array of help messages for each * menu element respectively. * * cursor.location - the currently chosen element. This argument * is modified and passed back to the calling routine. * * menu.mnemonic - dynamic array of mnemonic letters for each * menu element respectively. * * input.code - the code corresponding to the user input which * caused return to the calling routine. * * menu.items - dynamic array of menu choices to paint on * screen * Mnemonics are translated to motion to the selected item followed by * a select. * If the orientation is HORIZONTAL this routine assumes the menu * is the top-level menu bar; otherwise the orientation is VERTICAL * and this routine assumes the menu is a second-level or deeper menu. * These choices, and the presence or absence of cascaders at a given * point determine which of the arrow keys are return events, motion * events, or errors. * Here are some arbitrary choices we've made in design: * - Motion in the direction of orientation will WRAP to first or last * item, no boundary problem, never land in title area (of 2nd level menu) * - Downward or Rightward motion will navigate To lower level menu * (this event will return to the calling routine for handling). * - Select ( per the Motif style guide) will navigate To lower * level menu. * - Left from a vertical menu is always a return -- it may mean return * to previous menu from a cascaded menu, or it may mean go to sibling * from a second level menu * - There is not a symmetric right functionality. Right arrow means * go to a cascading menu if there is one, but is an error if there * isn't one. There is no 'go to right sibling' functionality in * the calling driver. id = "%W%" $include UNIVERSE.INCLUDE MTF.INCL.H * Times to wait for more characters, and granularity interval equ DELAY.INTERVAL to 25 ;* 25 millisecond nap unit equ ESC.DELAY.TIME to 100 ;* Delay to determine if singleton Escape * Half-second. WORK: Is it enough? * DPB 8/13/90: Nope, too long! equ SEQ.DELAY.TIME to 75 ;* Delay for next char in sequence * Where should we put the start and end of the highlight bar? * This is the space for the Magic Cookie if it exists, otherwise the * driver has left blanks or brackets there. equ LEFT.COOKIE lit 'if orientation = VERTICAL then (menu.x.orig + 1) else (menu.width)' equ RIGHT.COOKIE lit 'if orientation = VERTICAL then (menu.x.orig + menu.width - 2) else (menu.width)' equ CUR.LINE lit 'if orientation = VERTICAL then (menu.y.orig + cursor.location) else (menu.y.orig)' equ WRITE.POS lit 'if orientation = VERTICAL then (menu.x.orig) else (menu.width)' * Standard strings to emphasize or de-emphasize the current selection * iv.begin and iv.end are from common, typically @(13) and @(14) * Modified EMPH.STRING and DE.EMPH.STRING to handle strange Magic Cookie * problem and the differences it caused on different terminals - DTM equ EMPH.STRING lit "@(RIGHT.COOKIE,CUR.LINE):iv.end:@(LEFT.COOKIE,CUR.LINE):iv.begin:@(WRITE.POS,CUR.LINE):menu.items:@(RIGHT.COOKIE,CUR.LINE):iv.end:@(LEFT.COOKIE,CUR.LINE):iv.begin" equ DE.EMPH.STRING lit "@(LEFT.COOKIE,CUR.LINE):iv.end:@(WRITE.POS,CUR.LINE):menu.items" * Here are error messages for bad navigation keys, and help messages equ BAD.NAV to UVREADMSG(075024,"") equ HELP.ERR.LUD to BAD.NAV:UVREADMSG(075025,"") ;* No cascade equ HELP.ERR.LRD to BAD.NAV:UVREADMSG(075026,"") ;* Menubar equ NO.HELP to UVREADMSG(075027,"") equ HELP.BAD.TOKEN to UVREADMSG(075028,"") equ HELP.ESCAPE to UVREADMSG(075029,"") equ ESCAPE.MUST.BE.ALONE to UVREADMSG(075030,"") mnemos="" * Initialization - always clear out help area on entry help.area.needs.clearing = 1 * Main loop: highlight current.selection, take an input token, * make appropriate action, de-highlight loop tprint EMPH.STRING: call *GET.TOKEN.B(DELAY.INTERVAL, SEQ.DELAY.TIME, ESC.DELAY.TIME, CNT.OF.ALPHA, mat alphastrings, mat alphacodes, ESCAPE, MNEMONIC, UNKNOWN, menu.choices, menu.mnemonic, left.over, input.code, mnemos) * Help area could have been used by a previous iteration or a pending Escape if help.area.needs.clearing then gosub clear.help * The current token to do is in input.code * Check for tokens which always return if input.code = SEL.ACTION or input.code = F.10 or input.code = ESCAPE or input.code = LEFT.ARROW or input.code = MNEMONIC or input.code = RIGHT.ARROW then goto exit.point * Check for tokens which always return when orientation is HORIZONTAL * (Calling routine must adjust current selection and sub-menus) if (orientation = HORIZONTAL) and (input.code = RIGHT.ARROW or input.code = LEFT.ARROW or input.code = DOWN.ARROW) then goto exit.point * Handle other tokens begin case * case input.code = RIGHT.ARROW * * Got to a cascading menu if one is there * if submenu.flag then goto exit.point * * Logic: we're not in menu-bar and there's no cascader to * * go to, thus error. * help.msg = HELP.ERR.LUD * gosub show.help case input.code = DOWN.ARROW tprint DE.EMPH.STRING: cursor.location += 1 if cursor.location > menu.choices then cursor.location = 1 case input.code = UP.ARROW if orientation = HORIZONTAL then help.msg = HELP.ERR.LRD gosub show.help end else tprint DE.EMPH.STRING: cursor.location -= 1 if cursor.location < 1 then cursor.location = menu.choices end case input.code = F.1 ;* HELP help.msg = menu.help if help.msg = "" then help.msg = NO.HELP gosub show.help case input.code = F.4 goto exit.point case input.code = UNKNOWN if mnemos = alphastrings(ESCAPE) then help.msg = ESCAPE.MUST.BE.ALONE * Of course that message will only flash, as it only occurs * when there is some other character in the type-ahead buffer, * but this Escape plus that character don't match anything. * Following might be overkill, but it * avoids printing non-printables else seq.mnemos = seq(mnemos) ;* register int if seq.mnemos > 32 and seq.mnemos <= 126 then help.msg = mnemos:HELP.BAD.TOKEN else if seq.mnemos > 127 then help.msg = "^?":HELP.BAD.TOKEN else help.msg = "^":char(seq.mnemos+32):HELP.BAD.TOKEN end end gosub show.help end case repeat ;* forever clear.help: * Always print Help at bottom line tprint @(0,LINES-1):@(-4): help.area.needs.clearing = 0 return show.help: tprint @(0,LINES-1):@(-4):help.msg: help.area.needs.clearing = 1 * WORK: Do we want a delay here, or just keep this up until next keystroke return exit.point: tprint DE.EMPH.STRING: if input.code = MNEMONIC then * Combines jump to here and select cursor.location = mnemos input.code = SEL.ACTION end return