! Scrolled Menu ! Customization possibilities: ! Menu_HSCROLL is by default set to 8. ! Menu_Activate_With_SPACE_TOO ! When defined, SPACE, in addition to RETURN, activates ! the selected item. ! Menu_DrawLine ! When defined, the specified function is called instead of the ! default Menu_MenuDrawLine routine when no menudrawline parameter ! is specified. ! Menu_GetTMP ! When defined, it is used as the function to obtain temporary ! storage used by built-in _MenuDrawLine uses. This is in effect ! only when Menu_UseMenuDrawLine is set. ! Menu_Bleep ! When defined, it is used as the function to bleep. Otherwise, ! this package uses its own implementation. Constant KEY_UP 129; Constant KEY_DOWN 130; Constant KEY_LEFT 131; Constant KEY_RIGHT 132; Constant KEY_RETURN 13; Default Menu_HSCROLL 8; #IFNDEF Menu_Bleep; [ Menu__Bleep; @sound_effect 1; ]; Constant Menu_Bleep Menu__Bleep; #ENDIF; #IFNDEF Menu_GetTmp; Array Menu__TMP -> 512; [ Menu__GetTMP; return Menu_TMP; ]; Constant Menu_GetTMP Menu__GetTMP; #ENDIF; #IFNDEF Menu_DrawLine; ! At coordinate (x y), draw str starting from ofs'th character. ! Allocated screen width for this string is w; blank the rest. ! hlt tells whether the item is highlighted or not. [ Menu__DrawLine y x str ofs w hlt tmp len j; @set_cursor y x; if (hlt) { print (char) '>'; style reverse; } else print (char) ' '; if (str) { tmp = _GetTMP(); len = str.print_to_array(tmp); for (j = ofs+2: (j < len+2) && x+(j-(ofs+2))+1 <= w && (tmp->j ~= 13): j++) print (char) tmp->j; } else j = ofs+2; if (hlt) style roman; while ((x+((j++)-(ofs+2))+1) <= w) print (char) ' '; ]; Constant Menu_DrawLine Menu__DrawLine; #ENDIF; ! Draws a menu, interacts with the user, and returns the ! selected menu item number. ! ! menufunc should be a function which: ! - menufunc(0) returns the number of menu items, ! - menufunc(n) for 1 < n < menufunc(0) returns 0 or a non-zero value, ! - menufunc(n) for 1 == n or menufunc(0) == 0 returns a value. ! menudrawline is passed the value returned from menufunc to draw ! a line for the corresponding menu item. ! The menu is drawn at (x y), with dimension (w h). ! The initial selection is set to sel, which defaults to 1. ! The menu items are drawn one per line. The menu supports ! horizontal and vertical scrolling. ! The user navigates the menu with UP/DOWN key to change highlights, ! and RET key to make selection. If the number of items in the menu ! is more than h, then the menu scrolls as needed. The items ! menufunc() returns 0 are displayed as blank lines, and cannot be ! selected. [ Menu menufunc x y w h sel menudrawline ow om num_menu j osel t; if (~~x) { x = 1; y = 2; h = (0->$20)-1; w = (0->$21); } if (~~menudrawline) menudrawline = Menu_DrawLine; num_menu = menufunc(0); osel = 0; om = 1; if (sel == 0) sel = 1; while ((sel <= num_menu) && (menufunc(sel) == 0)) sel++; ow = 0; if (om + h <= sel) om = sel - h; while (1) { if (osel <= 0) { for (j = om: (j <= num_menu) && (j-om) < h: j++) menudrawline(j-om+y, x, menufunc(j), ow, w, sel==j); while (((j++)-om) < h) menudrawline(j-om+y, x, "", ow, w, 0); } else { menudrawline(osel-om+y, x, menufunc(osel), ow, w, 0); menudrawline(sel-om+y, x, menufunc(sel), ow, w, 1); } osel = sel; #IFDEF Menu_DEBUG; @set_cursor 1 1; print " H ", h, " N ", num_menu, " OM ", om, " S ", sel, " "; #ENDIF; t = y + sel - om; @set_cursor t x; switch (Menu_GetKey()) { KEY_LEFT: if (0 <= ow - Menu_HSCROLL) { ow = ow - Menu_HSCROLL; osel = 0; } else Menu_Bleep(); KEY_RIGHT: ow = ow + Menu_HSCROLL; osel = 0; KEY_UP: while ((0 < --sel) && menufunc(sel) == 0) ; if (sel < 1) { sel = osel; Menu_Bleep(); } else if (sel-om < 0) { om = sel; osel = 0; } KEY_DOWN: while ((++sel <= num_menu) && menufunc(sel) == 0) ; if (num_menu < sel) { sel = osel; Menu_Bleep(); } else if (h <= sel-om) { om = sel-h+1; osel = 0; } #IFDEF Menu_Activate_With_SPACE_TOO; ' ', KEY_RETURN: #IFNOT; KEY_RETURN: #ENDIF; return sel; } } ]; [ Menu_GetKey j; @read_char 1 j; switch (j) { 'h', 'w': return KEY_LEFT; 'l', 'e': return KEY_RIGHT; 'k', 'n': return KEY_UP; 'j', 's': return KEY_DOWN; default: return j; } ];