From unet.unet.umn.edu!fin Sat May 4 03:31:13 1991 Status: RO X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] [nil "Thu" "2" "May" "1991" "21:02:42" "+0300" "\"Craig A. Finseth\"" "fin@unet.unet.umn.edu" nil "660" "alamanac, part 1 of 2" "^Date:" nil nil "5"]) Received: from funet.fi ([128.214.1.1]) by nic.funet.fi with SMTP id <80721>; Sat, 4 May 1991 03:30:58 +0300 Received: from mail.unet.umn.edu by funet.fi with SMTP; Thu, 2 May 91 21:03:36 +0300 Received: from norge.unet.umn.edu by mail.unet.umn.edu (5.61/1.14) id AA07982; Thu, 2 May 91 12:57:59 -0500 Message-Id: <9105021802.AA19322@unet.unet.umn.edu> Received: by unet.unet.umn.edu; Thu, 2 May 91 13:02:42 -0500 Date: Thu, 2 May 1991 21:02:42 +0300 From: "Craig A. Finseth" To: luosto@nic.funet.fi Subject: alamanac, part 1 of 2 >From uc!norge.unet.umn.edu!fin Mon Apr 15 11:30:54 CDT 1991 Article 7515 of comp.sys.handhelds: Path: uc!norge.unet.umn.edu!fin >From: fin@norge.unet.umn.edu (Craig A. Finseth) Newsgroups: comp.sys.handhelds Subject: 48SX/S Browse (use with Astronomy and Alamanc routines) Message-ID: <3897@uc.msc.umn.edu> Date: 15 Apr 91 16:30:07 GMT Sender: news@uc.msc.umn.edu Organization: Univ Netw Serv, Univ of Minn Lines: 646 This is a general-purpose browser. It is in two parts: - the browser - a small test routine Craig A. Finseth fin@unet.umn.edu [CAF13] University Networking Services +1 612 624 3375 desk University of Minnesota +1 612 625 0006 problems 130 Lind Hall, 207 Church St SE +1 612 626 1002 FAX Minneapolis MN 55455-0134, U.S.A. ====================================================================== The HP-48SX Browser Instructions and Commented Listing Version 1.1, 23 May 1990 Copyright (c) 1990 by Jeff Brown, free for personal non-commercial use. Formatted for monofont (e.g. Courier type for Postscript/Macintosh users) Contents: Purpose of the Browser Parts of the Browser Display Browser Keys Applications of the Browser How to Use the Browser Advanced Use of the Browser Technical Details of the Browser Areas for Improvement Browser Commented Listing Browser Variables Browser Downloadable Listing PURPOSE OF THE BROWSER The browser provides a clean, intuitive way for users to browse the contents of a list and select an item. If you have used the catalog function of the Solver or Plotter, you have already used a kind of browser. The browser is not an application. It is a user interface tool to be used by your applications. At about 1,800 bytes, it is small enough to be used even in 32K machines. The Browser is a simple to incorporate but powerful programming tool. Your users will find it an intuitive and convenient way to choose from among data items or options. Your program calls the browser with a message and a list on the stack. The browser displays your message and list to the user. It manages keys and the display, permitting the user to scroll and page through the list until he finds the appropriate item. When the user selects an item, the browser returns its current state, the selected item and the item's position to the stack. Using the results from a browse, you can change or edit items at the user's request or choose different execution paths. Since the browser returns its state, you can accept the user's choice, take action and return the user to browsing where he last left off. This permits some fairly flashy applications. The browser is very simple to operate but it can be used in so many ways, it takes a bit of explaining. If you wish to just give it a try, skip to the 'How to Use the Browser' section. PARTS OF THE BROWSER DISPLAY Description Example HP-48 display Display Line Used ----------------- ---------------------- ----------------- Prompt message -> Select a company: Line 1 -> Apple | Compaq List pane --| >Hewlett-Packard Lines 2-6 | IBM -> Zenith Scroll bar -> <--------####--------> Line 7 The prompt message is your message to the user indicating what is being browsed and what you expect the user to do. The list pane is a scrolling window onto your list. There is always a current item in the window. This item is displayed with a cursor in front of it. The scroll bar graphically represents the location of the list pane within the list. A block of box characters (called a 'thumb') representing the pane moves along the scroll bar as the user scrolls through the list. The size of the thumb represents the portion of the list visible in the pane. The larger the list, the smaller the thumb. Note: the box characters of the thumb are represented here as '#' since there is no ASCII box character. BROWSER KEYS Prefix Key Function ----------- ---------- --------------------------------------- Up arrow scroll up one item Left-shift Up arrow scroll up one page (five items) Right-shift Up arrow go to top of list Down arrow scroll down one item Left-shift Down arrow scroll down one page (five items) Right-shift Down arrow go to bottom of list Enter accept current item Backspace cancel browsing without choosing The left arrow key functions identically to the up arrow and the right arrow key functions identically to the down arrow. APPLICATIONS OF THE BROWSER - Address or phone number lists - Inspectors that let the user delve into the structure of objects. - Presentation of program options For a good real-live application of the browser, refer to the Almanac program and Astronomy Directory by Craig Finseth and Lauren Nelson. HOW TO USE THE BROWSER The browser takes two arguments from the stack. The simplest way to call the browser is to put the following arguments on the stack: Level 2: your message to the user (string) Level 1: the list to be browsed (list or name) The browser will take care of the user interaction and return the following results to the stack: Level 2: state of the browser (list) Level 1: acceptance information (a list) consisting of: - item selected (type depends on the object), - position of the item in the list (real number), - 0 if user cancelled or keycode (51.1) if user accepted (real number) Example: Peter Palmer, proprietor of Palmer's Polygonal Pies, wishes to record customer orders using his trusty HP-48SX. Since pie names are long and descriptive, it would be best to select the pies from a list. To build a program which takes orders, Peter stores the available types of pies in a variable: { "Triangular Treacle" "Raspberry Rhombus" "Pentagonal Plum" "Hexagon Hash" "Strawberry Septagon" "Octagonal Orange Mousse" "Nonpareil Nonagon" "Decagonal Delight"} 'pies' STO Next, he writes a little program that takes pie orders. A fragment that gets the user's choice of pie looks like this: "Select a Pie:" pies BROWSE 1 GET This invokes the browser: Select a pie: >Triangular Treacle Raspberry Rhombus Pentagonal Praline Hexagon Hash Strawberry Septagon ##############-------> After the user chooses a pie, the 1 GET retrieves the description of the user's chosen pie. Peter's program could also add the choice to an order list or use the position of the choice (2 GET) to look up pricing information from a price list. ADVANCED USE OF THE BROWSER If you wish to have the browser start at a particular position in the list or if you need to specially format your list items for display, there is an alternate way to call the browser: Level 2: a list consisting of: - Your message (string) - Current item in list (real number) - Lines off-screen above the list pane (real number) - Procedure used to format your list items (program) Level 1: the list to be browsed (list or name) The list in level 2 is the same format as that returned to level 2 when the browser ends. This is a brief run-down of its parts: 1) Your message to the user 2) The current item (the list position pointed to by the cursor). 3) The lines off-screen tells the browser how far down in the list its window should start (if the current item is not visible in this area, the list pane will be moved far enough in the appropriate direction to include it). 4) The browser will run your program object on each list item prior to displaying it. Your program object should take an item (extracted from your list by the browser and placed in level 1) and format it for display by the browser. The browser will call this code every time it draws an item in the display so keep it fast and simple. This approach is very powerful because you can start the browser in any position and format its items any way you like. The list is returned to you (updated to match the user's actions) when the browser ends. This enables you to take the user's response, carry out appropriate actions and return to browsing the list in the same position the user left off. One use of this is to browse hierarchically, that is, browse a list of lists, returning to the proper place every time the user pops up a level. To do this, just keep a list containing your list path and a matching list containing browser state lists. When the users pops up a level, just discard the last item in each list and call the browser with the new last item. For example a program for selecting people to receive mailings might work like this: Select a company: Apple Compaq >Hewlett-Packard User selects company, presses enter IBM Zenith ###################### Select a division: Boise >Corvallis Phoenix User selects division, presses enter Palo Alto Santa Clara <-###############----> Select an Employee: Sanders, John Terpack, Daniel Vogel, Eric User selects employee (presses enter) West, Carmen (repeat as needed then press backspace) >Wickes, William <-------------------#> Select a division: Boise >Corvallis Phoenix User is returned to the division browser Palo Alto (with list pane and current item unchanged) Santa Clara <-###############----> TECHNICAL DETAILS OF THE BROWSER The original version of the browser was a collection of three main program objects and about two dozen state variables and key handling objects. To eliminate the need for a separate browser directory, I have compressed the whole thing into a single program object (with considerable loss of readability). The browser has four logical parts: Browse - sets things up for browsing MainLoop - waits for key events and hands them off to handlers. DrawView - draws the browser after key events change it. Key handlers - interpret the meaning of various keys. BROWSE This initialization code is run when the browser is called. It extracts the input parameters and puts them in temporary variables. It also calculates the size of the thumb. When Browse finishes setup, it flows into the main loop. MAINLOOP The main loop is wrapped around the DrawView procedure and the key handlers. It loops, drawing the browser and handling keys until the user accepts an item or aborts the browsing process. DRAWVIEW DrawView checks the current state of the browser and uses one of three methods to draw the browser's visible parts on the screen. If the list pane is above the current item (the user scrolled down) it redraws the pane from the bottom up. If the list pane is below the current item (the user scrolled up) it redraws the pane from the top down. If the current and previous items are both in the pane (the user moved the cursor within the visible region) only the current and previous items are redrawn. Originally, I simply drew the lines of the browser from the top down, every time. Performance was so slow that when scrolling down, the display gave the impression that it was scrolling up. This came about because the user pressed the down arrow key but saw the top lines of the display changing first. To remedy this, I determine which way the user scrolled and redraw the lines from that direction. This gives a satisfying sense of scrolling in the proper direction. To further improve performance, DrawView checks to see if the cursor has moved out of or into the visible region. If it has not, only the previous item and the current item are redrawn. This cuts drawing time in half. I decided to implement the scroll bar fairly early in development. Browsing a large list can be disorienting. People need to know where they are in a list and how much progress they are making with each keystroke. They use the cursor keys differently in large lists than they do in small lists so constant visual feedback is very valuable. AREAS FOR IMPROVEMENT Speed is not as snappy as it ought to be. Limited redraws take about 0.8 seconds, full redraws take 1.5 seconds. The code needs to run about four times faster. An assembly language version would improve this. Since my Saturn assembly skills are a bit rusty, I will leave this to others for the time being. I have not tried bit-wise scrolling of the list pane. It is conceivable that this might be faster than re-drawing the entire pane on some occasions. The scroll bar is a bit cheesy in that it is horizontal and the list is displayed vertically. This was a practical necessity since there isn't enough vertical resolution to do it vertically. Ideally, I would do a vertical bit-mapped scroll bar. This would have enough resolution (48 pixels) for the job. Again, assembly language might be the only practical solution. Originally, I planned to take a menu key list and display it so you could add user-defined features to the browser, but this was torpedoed by HP's method of handling menus. There is no supported way to display a menu and retain program control. A program must halt for the menu to appear. In short, I can't display your menu and give you back keycodes when the user presses menu keys. To further exacerbate matters, I can't get rid of the potentially confusing menus already displayed or use the extra line for more items. Ideas, anyone? I may do some experimentation with binary searches on ordered lists. This would permit an 'alpha mode' for the browser so users could press a letter key and instantly jump to that part of the list. Some applications may want several items from a single browse. Features to permit selection of multiple items (by creating contiguous or non-contiguous selections) before accepting would be useful if user interface issues could be resolved. Features for range selection and Cut/Copy/Paste would be great for interactive list editing. This would be a dream for editing programs. BROWSER COMMENTED LISTING /* browse L2: msg | {msg c brOS fmtP} L1: list | name of list */ \<< "by Jeff Brown (612) 646-2478" DROP "v1.1" DROP DUP IF TYPE 6 == THEN /* if it is a name, get its value */ EVAL END DUP /* list */ SIZE /* listL */ DUP 5 MIN /* brL */ DUP2 158 CHR /* loop to build thumb */ \-> l b t \<< "" 1 b l / 22 * 0 RND FOR i t + NEXT \>> /* thumb */ "\<---------------------\->" /* scrB */ 6 ROLL DUP IF TYPE 5 == THEN LIST\-> DROP /* msg c brOS fmtP */ ELSE 1 0 \<< \>> {} END 3 PICK /* p */ \<<220 0.125 BEEP\>> /* eBeep */ 134 CHR /* cursChr */ 1 /* full */ 1 /* continue */ 1 /* j */ CLLCD \-> list listL brL thumb scrB msg c brOS fmtP p eBeep cursChr full continue j \<< Msg 1 DISP WHILE continue 1 == REPEAT /* drawView */ 1 DUP 'j' STO brL /* loop limits */ CASE c brOs s THEN /* user moved above pane */ c 1 - 'brOs' STO 1 'full' STO END c brOs brL + > THEN /* user moved below pane */ DROP2 c brL - 'brOs' STO 1 'full' STO brL 1 -1 'j' STO /* set new loop limits */ END END IF full 1 == THEN /* full redraw is needed */ 0 'full' STO FOR i IF i c brOs - = THEN " " list brOs i + GET fmtP EVAL \->STR + i 1 + DISP ELSE cursChr list brOs i + GET fmtP EVAL \->STR + i 1 + DISP END J STEP c 'p' STO scrB brOs listL / 22 * .5 + 0 RND thumb REPL 7 DISP ELSE DROP2 " " list p GET fmtP EVAL \->STR + p brOs - 1 + DISP cursChr list c GET fmtP EVAL \->STR + c brOs - 1 + DISP END 3 FREEZE /* mainLoop */ 0 WAIT \-> k \<< IF k FP .3 > THEN k .3 - 'k' STO END CASE k IP DUP 35 == SWAP 36 == OR THEN /* a down key*/ IF c listL == THEN eBeep EVAL ELSE listL /* bottom of list */ c DUP DUP 'p' STO brL + listL MIN /* page dn/last item */ SWAP 1 + /* item down */ k FP 10 * ROLL 'c' STO DROP2 /* choose by keycode */ END END k IP DUP 25 == SWAP 34 == OR THEN /* an up key */ IF c 1 == THEN eBeep EVAL ELSE 1 /* top of list */ c DUP DUP 'p' STO brL - 1 MAX /* page up/1st item */ SWAP 1 - /* item up */ k FP 10 * ROLL /* choose by keycode */ 'c' STO DROP2 END END k 51.1 == THEN /* enter */ list c GET c 0 'continue' STO END k 15.1 == THEN /* cancel */ 0 DUP 'continue' STO END END \>> END {} msg + c + brOS + fmtP + 3 ROLLD \>> BROWSER VARIABLES continue boolean Should waitLoop continue? full boolean Should drawView do entire pane? cursChr char The cursor character brL integer Length (in lines) of list pane brOs integer Items above list pane c integer Position of current item in list p integer Position of previous item in list msg string The prompt message listL integer Number of items in List list list The list being browsed scrB sring 22 character image of the scroll bar thumb string The text image for the thumb j integer Loop increment value (-1 or 1) BROWSER DOWNLOADABLE LISTING Checksum: #3e2h Size: 1751 ------------------------------------------------------------ %%HP: T(3)A(D)F(.); \<< "v1.1" DROP DUP IF DTAG TYPE 6 == THEN EVAL END DUP SIZE DUP 5 MIN DUP2 158 CHR \-> l b t \<< "" 1 b l / 22 * 0 RND FOR i t + NEXT \>> "\<---------------------\->" 6 ROLL DUP IF DTAG TYPE 5 == THEN LIST\-> DROP ELSE 1 0 \<< \>> END 3 PICK \<< 220 .125 BEEP \>> 134 CHR 1 1 1 CLLCD \-> list listL brL thumb scrB msg c brOs fmtP p eBeep cursChr full continue j \<< msg 1 DISP WHILE continue 1 == REPEAT 1 DUP 'j' STO brL CASE c brOs \<= THEN c 1 - 'brOs' STO 1 'full' STO END c brOs brL + > THEN DROP2 c brL - 'brOs' STO 1 'full' STO brL 1 -1 'j' STO END END IF full 1 == THEN 0 'full' STO FOR i IF i c brOs - \=/ THEN " " list brOs i + GET fmtP EVAL \->STR + i 1 + DISP ELSE cursChr list brOs i + GET fmtP EVAL \->STR + i 1 + DISP END j STEP c 'p' STO scrB brOs listL / 22 * .5 + 0 RND thumb REPL 7 DISP ELSE DROP2 " " list p GET fmtP EVAL \->STR + p brOs - 1 + DISP cursChr list c GET fmtP EVAL \->STR + c brOs - 1 + DISP END 3 FREEZE 0 WAIT \-> k \<< IF k FP .3 > THEN k .3 - 'k' STO END CASE k IP DUP 35 == SWAP 36 == OR THEN IF c listL == THEN eBeep EVAL ELSE listL c DUP DUP 'p' STO brL + listL MIN SWAP 1 + k FP 10 * ROLL 'c' STO DROP2 END END k IP DUP 25 == SWAP 34 == OR THEN IF c 1 == THEN eBeep EVAL ELSE 1 c DUP DUP 'p' STO brL - 1 MAX SWAP 1 - k FP 10 * ROLL 'c' STO DROP2 END END k 51.1 == THEN list c GET c k 0 'continue' STO END k 55.1 == THEN "" 0 DUP DUP 'continue' STO END END \>> END { } msg + c + brOs + fmtP + 4 ROLLD 3 \->LIST \>> \>> ====================================================================== Written by: Jeff Brown When: 10 May 1990 Test program for the browser. Checksum: #14095d Size: 64.5 ------------------------------------------------------------ %%HP: T(3)A(D)F(.); \<< "Select an item:" VARS DUP + DUP + BROWSE \>>