From comp.sys.handhelds Fri Feb  1 07:39:15 1991
Path: mentor.cc.purdue.edu!purdue!news.cs.indiana.edu!msi.umn.edu!noc.MR.NET!gacvx2.gac.edu!hhdist
From: HUBER@gacvx1.gac.edu (Tom Huber, Gustavus Adolphus College, (507) 933-7036)
Newsgroups: comp.sys.handhelds
Subject: RE: HP48SX: Full screen menu program, mark III
Message-ID: <A8AD50EC40003CF2@gacvx1.gac.edu>
Date: 31 Jan 91 23:22:00 GMT
Lines: 287

Michael Woodhams posted the program FSMENU, mark III
(Message-ID: <5816@idunno.Princeton.EDU>)

Michael has added several excellent features to the full screen menu
program.  There were, however, several typos in the posted programs.
Below are downloadable versions of the programs with the bugs (at least the
ones I found) fixed

(PS: I would recommend that you put KEYSIZE, UCLEAR and UMOD in your
HOME directory rather than in the FSMENU directory as recommended by
Michael otherwise it will be difficult to use UMOD from another directory)


	Tom Huber,   Physics Department 
	Gustavus Adolphus College,   St. Peter, MN  56082
	Bitnet: HUBER@GACVAX1   Internet: HUBER@GAC.EDU  (507)933-7036
	

Checksum: #B2F7h  Size:492.5  (Evaluated by 'KEYSIZE' BYTES)
KEYSIZE
%%HP: T(3)A(D)F(.);
{
  { 6 #20d #22d #42d #22d }
  { 6 #20d #22d #42d #22d }
  { 6 #20d #22d #42d #22d }
  { 6 #20d #22d #42d #22d }
  { 5 #42d #44d #64d #22d }
  { 5 #20d #24d #49d #27d }
  { 5 #20d #24d #49d #27d }
  { 5 #20d #24d #49d #27d }
}

Checksum: #7ED9h  Size:776
UCLEAR
%%HP: T(3)A(D)F(.);
\<<
 "Enter number of rows"		@ Get number of rows of keys and
 { V } INPUT OBJ\->		@ store it in local variable "n"
 \-> n
  \<<
   IF 'n<1 OR n>8 OR FP(n)\=/0' THEN
    KILL			@ quit if n is out of range
   END
   ERASE {#0d #0d} PVIEW	@ erase screen and display it
   1 n FOR row			@ for each row
    KEYSIZE row GET		@ get the list of key size parameters
    LIST\-> DROP		@ disassemble it into components
    \-> m e1 s2 e2 inc      	@ and store in local variables
				@ m=number of keys in this row
				@ e1=last pixel in the first key
				@ s2=first pixel in the second key
				@ e2=last pixel in the second key
				@ inc=distance between start of second and
                                @     third keys
     \<<
      1 m FOR col		@ for each key in the row
       IF 'col==1' THEN	@ if first row, then
        #0d e1			@ draw from pixel 0 to e1
       ELSE			@ else
        col 2 - inc *
        DUP s2 +		@ draw from s2+(col-2)*inc
        SWAP e2 +		@ to e2+(col-2)*inc
       END
       \-> x1 x2		@ put the left and right x-coordinates of
				@ the key into x1 and x2
        \<<
         row 1 - 8 * DUP 6 + FOR line
				@ for line = (row-1)*8 to (row-1)*8+6
				@ (for line=top pixel of key to bottom pixel)
          x1 line R\->B 2 \->LIST @ make coordinate list {x1 line}
          x2 line R\->B 2 \->LIST @ make coordinate list {x2 line}
          LINE			@ draw line between coordinates
         NEXT			@ next line
        \>>			@ end of x1, x2 local variable block
      NEXT			@ next col (i.e. next key in the row)
     \>>			@ end of m, e1, s2, e2, inc variable block
   NEXT				@ next row
   PICT {#8d #41d} "\Ga"	@ write alpha on the alpha shift key
   1 \->GROB GXOR		@ (even if fewer than 6 rows were requested)
   PICT {#7d #49d}
   GROB 7 5 4020F72444 GXOR     @ write left arrow on gold shift key
   PICT {#7d #57d}
   GROB 7 5 0102F71211 GXOR     @ write right arrow on blue shift key
   PICT {#0d #0d}		@ put PICT, {#0d #0d}, {#131d n*#8-#1}
   #131d n #8d * #1d - 2 \->LIST @ onto stack
   SUB				@ and extract the picture of the keyboard
                                @   from the graphics screen. (If there were
				@   not enough rows for the alpha and/or shift
				@   keys to be displayed, the alpha, left and
				@   right arrows that were drawn on the screen
				@   will be left behind at this stage
   { }				@ Now make the list of key definitions
				@ These braces will delimit the list of
				@   row information
   1 n FOR row			@ for each row
    { }				@ These braces will delimit the list of
				@   information for each key in the row
    1 KEYSIZE row GET 1 GET	@ get number of keys in the row from KEYSIZE
     FOR col			@ for each key in the row
     { { } } +			@ add an empty list to the row list 
				@ for each key in the row
    NEXT			@ next col
    1 \->LIST                   @ Imbed the row list in another set of braces
    +				@ add the row list to the master list
   NEXT				@ next row
  \>>                           @ end of n local variable block
\>>                             @ end of UCLEAR program

Checksum: #B2E9h  Size:1632
UMOD
%%HP: T(3)A(D)F(.);
\<<
 DUP RCL SIZE			@ find size (number of rows) of values variable
 \-> ugrob uvalues n		@ store names of variables in ugrob, uvalues
				@ and number of rows in n
  \<<
   ugrob RCL PICT STO		@ store keyboard picture in graphics screen
   {#0d #0d} PVIEW 		@ and display it
   0 WAIT			@ get a keystroke
   IF DUP n 1 + 10 * > THEN	@ if keystroke comes from a row after row n
    DROP ugrob uvalues KILL	@ restore stack and kill program
   END
   DUP 10 / IP			@ find row number of the key
   SWAP IP 10 MOD		@ and column number of the key
   \-> row col			@ store in local variables row, col
    \<<
     KEYSIZE row GET		@ get list for this row from KEYSIZE
     IF 'col==1' THEN		@ if this is the first key in the row
      2 GET #0d			@ the rightmost and leftmost pixels of the key
				@ are e1 (2nd element of list) and #0
     ELSE			@ if this is not the first key in the row
      LIST\-> DROP		@ disassemble the list
      col 2 - *			@ put inc*(col-2) on the stack
      SWAP OVER			@ stack contains:
				@ m e1 s2 inc*(col-2) e2 inc*(col-2)
      + ROT ROT +		@ stack contains:
				@ m e1 e2+inc*(col-2) s2+inc*(col-2)
      ROT DROP ROT DROP		@ stack contains:
				@ e2+inc*(col-2) s2+inc*(col-2)
				@ i.e. rightmost and leftmost pixels of the key
     END
     row 1 - 8 *		@ stack contains:
				@(rightmost pixel) (leftmost pixel) (top pixel)
     \-> x2 x1 y		@ store these in x2, x1, y
      \<<
       PICT			@ put PICT on stack for use later
       0			@ put a junk value on stack to drop inside loop
       DO
        DROP			@ drop junk value or previous bad label
	STD			@ put calc in std mode to display row and col
        row "," + col +
        " Label?" +		@ assemble prompt string
        { \Ga } INPUT		@ input label for key as a string
        1 \->GROB		@ turn it into a grob
       UNTIL
        DUP SIZE DROP		@ loop until x size of grob is smaller than key
        'x2-x1' EVAL \<=	@ ("\<=" means less than or equals. I may have
				@ the wrong code here.)
       END
       DUP SIZE DROP		@ get x size of grob on stack
       IF DUP #0d == THEN	@ if the label was a null string
        DROP DROP DROP		@ drop PICT, grob and grob size from stack,
				@ and leave keyboard picture unchanged
       ELSE
        y 'y+6' FOR line	@ for each row of pixels in the key
         x1 line R\->B 2 \->LIST @ make pixel coordinate {x1 line}
         x2 line R\->B 2 \->LIST @ make pixel coordinate {x2 line}
         LINE			@ draw a line between them
        NEXT			@ the key has now been erased
	'x1+x2+2' EVAL SWAP -	@ find x-coordinate to put grob at
        2 /			@ (x size of grob was already on stack)
	y #1d +			@ find y-coordinate to put grob at
        2 \->LIST SWAP GXOR     @ put label in keyboard picture
       END			@ end "if grob size = 0"
      \>>                       @ end of x2, x1, y local variable block
     PICT {#0d #0d} 
     #131d n #8d * 2 \->LIST    @ coordinates of lower right corner of picture
     SUB ugrob STO		@ extract picture from screen and store it
     uvalues RCL		@ get key values list
     DUP row GET		@ extract list for the row
     DO				@ loop until valid key input
      "C-constant object" 1 DISP @ display menu
      "L-library constant" 2 DISP
      "M-menu" 3 DISP
      "N-no change" 4 DISP
      "P-program name" 5 DISP
      "U-unit" 6 DISP
      0 WAIT IP			@ get (integer part of) key number
      CASE
       DUP 13 == THEN		@ "c" was pressed
        DROP			@ drop key number
        "Constant Object" { V }
        INPUT OBJ\->            @ input constant as string and make it object
        1 \->LIST		@ turn it into a one element list
        1			@ leave 1 on stack to indicate success
       END
       DUP 26 == THEN		@ if "l" pressed
        DROP			@ drop key number
        "Constant Name" 
        { \Ga } INPUT		@ input constant name as a string
        "\<< '" SWAP +          @ make string 
        "' CONST \>>" +		@ "\<< 'constantname' CONST \>>"
        OBJ\->			@ turn string into a program
        1 \->LIST		@ put program in a list
        1			@ indicate success
       END
       DUP 31 == THEN		@ if "m" pressed
        DROP			@ drop key number
        "\<< '"			@ start of program string
        "Graphic variable name" 
        { \Ga } INPUT + "' '" + @ get name of picture variable, add to string
        "Values variable name"
        { \Ga } INPUT +
        "' UMENU \>>" +		@ string contains
				@ "\<< 'grobname' 'valuename' UMENU \>>"
        OBJ\->			@ turn string into a program
        1 \->LIST		@ put program in a list
        1			@ indicate success
       END
       DUP 32 == THEN		@ if "n" pressed
        DROP			@ drop key number
        DUP col GET 1 \->LIST   @ get current value of key to stack
        1			@ indicate success
       END
       DUP 34 == THEN		@ if "p" pressed
        DROP			@ drop key number
        "Program name" { \Ga }
        INPUT "\<< "		@ get program name as a string
        SWAP + " \>>" + OBJ\->  @ make program \<< programname \>>
        1 \->LIST               @ put into a list
        1			@ indicate success
       END
        43 == THEN		@ if "u" pressed
        "Unit Name" { \Ga } INPUT @ get unit as a string
        \-> u
         \<<
          "\<< 1_" u + " * \>>"
          + OBJ\->		@ make program \<< 1_unit * \>>
          "\<< 1_" u + " CONVERT \>>"
          + OBJ\->		@ make program \<< 1_unit CONVERT \>>
          "\<< 1_" u + " / \>>"
          + OBJ\->		@ make program \<< 1_unit / \>>
          3 \->LIST		@ make a list of the three programs
         \>>
        1			@ indicate success
       END
       0			@ else indicate failure
      END			@ end of case statement
     UNTIL			@ loop again if 0 on stack
     END
     col SWAP PUT		@ put the object generated into row list
     row SWAP PUT		@ put the modified row list into main list
     uvalues STO		@ store in values variable
    \>>                         @ end of row, col local variable block
   ugrob uvalues		@ return variable names to stack
  \>>                           @ end of ugrob, uvalues, n local variable block
\>>                             @ end of program

Checksum: #42B7h  Size:263.5
UMENU
%%HP: T(3)A(D)F(.);
\<<
 \-> ugrob uvalues		@ store variable names in ugrob, uvalues
  \<<
   LCD\->			@ turn stack display into a picture
   {#0d #0d} ugrob RCL REPL	@ overwrite the top of picture with keyboard
   PICT STO			@ and store in graphics screen
   {#0d #0d} PVIEW		@ store composite keyboard/stack display
   0 WAIT			@ get keystroke
   IFERR			@ (keystroke might be from too low on keyboard)
    uvalues RCL 		@ put values list on stack
    OVER 10 / IP GET		@ extract row from this list (could give error)
    OVER 10 MOD GET		@ extract key from row list (should not give
				@ error)
   THEN				@ (does following if error)
    DROP DROP DROP KILL		@ return stack to pristine status and die
   END
   IFERR			@ (values list might not have defined response
				@ for a shifted key, or the key might never 
				@ have been defined by UMOD)
    SWAP FP 10 * GET 		@ extract program from key list
   THEN
    DROP DROP KILL		@ restore stack and die
   END
   EVAL				@ execute the program extracted from values
				@ list
  \>>				@ end of local variables list.
\>>

