/* Program Name : MENUNAVI.C */ /* Original Author : C. K. Hung */ /* Date : 12-JUL-1990 */ /* Program Description : */ /* : */ /* Revision History follows */ #include "global.h" #include "filer.h" #include "inquire.h" /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- **/ unsigned short int navigator(m, menu_choice_nop, number_of_choices) struct menutype m[]; int *menu_choice_nop; int number_of_choices; { char validitm[MAXCOMMANDSITEMNUM+1]; unsigned short int word_terminator_code = 0; int submenu_choice_no; struct menutype *p; char **q; char *c1, *c2; unsigned long status; char *cp; int timeout; c1 = validitm; for (q = m[*menu_choice_nop].item; *q; q++) for (c2 = *q; *c2; c2++) if (isupper (*c2) || *c2 == '-') { *c1++ = *c2; break; } *c1 = EOS; /* ** Submenu will not be displayed if the user types the option letter ** fast enough (before time-out). **/ timeout = 1; status = smg$read_keystroke ( &cntrl_info_block.keyboard_id, &word_terminator_code, 0, &timeout, 0, 0, 0); word_terminator_code = _toupper(word_terminator_code); cp = strchr(validitm, word_terminator_code); if (word_terminator_code == SMG$K_TRM_KP1) { /** Display help message **/ highlight_general_cmd( m[*menu_choice_nop], &cntrl_info_block.commands_display.id); } else if (status != SS$_TIMEOUT && word_terminator_code != '-' && (cp && !strchr(cp+1, word_terminator_code)) && word_terminator_code != SMG$K_TRM_CANCELLED) { /** Option letter was typed before timeout **/ highlight_general_cmd( m[*menu_choice_nop], &cntrl_info_block.commands_display.id); submenu_choice_no = cp - validitm; } else { if (cntrl_info_block.user_pref.display_clock) write_time(cntrl_info_block.commands_display.id); if (cp && word_terminator_code != '-') { /** Found a valid option letter **/ submenu_choice_no = cp - validitm; } else { submenu_choice_no = 0; while (!strcmp( *(m[*menu_choice_nop].item+submenu_choice_no), MENU_SEPARATOR)) { submenu_choice_no++; } } put_filer_pfs(FILER_PFS, cntrl_info_block.commands_display.id); do { highlight_general_cmd( m[*menu_choice_nop], &cntrl_info_block.commands_display.id); word_terminator_code = get_menu_choice(m[*menu_choice_nop], &submenu_choice_no); if (word_terminator_code == SMG$K_TRM_LEFT) { unhighlight_general_cmd( m[*menu_choice_nop], &cntrl_info_block.commands_display.id); if (--(*menu_choice_nop) < 0) *menu_choice_nop = number_of_choices-1; submenu_choice_no = 0; while (!strcmp( *(m[*menu_choice_nop].item+submenu_choice_no), MENU_SEPARATOR)) { submenu_choice_no++; } } else if (word_terminator_code == SMG$K_TRM_RIGHT) { unhighlight_general_cmd( m[*menu_choice_nop], &cntrl_info_block.commands_display.id); if (++(*menu_choice_nop) >= number_of_choices) *menu_choice_nop = 0; submenu_choice_no = 0; while (!strcmp( *(m[*menu_choice_nop].item+submenu_choice_no), MENU_SEPARATOR)) { submenu_choice_no++; } } } while (word_terminator_code == SMG$K_TRM_LEFT || word_terminator_code == SMG$K_TRM_RIGHT); put_filer_pfs(FILER_PFS, cntrl_info_block.commands_display.id); } if (word_terminator_code == SMG$K_TRM_KP0) { /** Command cancelled **/ signal_err("Command canceled by user", silence); } else if (word_terminator_code != SMG$K_TRM_KP1) { /** Execute the command **/ check_OK(smg$set_cursor_abs ( &cntrl_info_block.commands_display.id, &cntrl_info_block.commands_display.rows, &cntrl_info_block.commands_display.width)) (m[*menu_choice_nop].op[submenu_choice_no])( m[*menu_choice_nop].item[submenu_choice_no]); } else { /** Show a specific help message **/ switch (*menu_choice_nop) { case 0: filer_help("DX WINDOW_MENU"); break; case 1: filer_help("DX ACTION_MENU"); break; case 2: filer_help("DX EXECUTE_MENU"); break; case 3: filer_help("DX SORT_MENU"); break; case 4: filer_help("DX FILTER_MENU"); break; case 5: filer_help("DX OPTION_MENU"); break; case 6: filer_help("DX CUSTOMIZE_MENU"); break; default: ; } } unhighlight_general_cmd( m[*menu_choice_nop], &cntrl_info_block.commands_display.id); return word_terminator_code; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** tbs ** **-- */ unsigned short int get_menu_choice(submenu, choice_nop) struct menutype submenu; int *choice_nop; { char item[MAXCOMMANDSITEMLENGTH+1]; $DESCRIPTOR (item_descriptor, item); int i, j; char *c1, *c2; char validitm[MAXCOMMANDSITEMNUM+1]; char **p; unsigned short int word_terminator_code; struct display_tag submenu_items_display; submenu_items_display.rows = submenu_items_display.width = 0; c1 = validitm; for (p = submenu.item; *p; p++) { for (c2 = *p; *c2; c2++) if (isupper (*c2) || *c2 == '-') { *c1++ = *c2; break; } submenu_items_display.rows++; } *c1 = EOS; for (i = 0, p = submenu.item; *p && i < MAXCOMMANDSITEMNUM; i++, p++) submenu_items_display.width = max((int)submenu_items_display.width, (int)strlen(*p)); submenu_items_display.width += 4; check_OK(smg$create_virtual_display ( &submenu_items_display.rows, &submenu_items_display.width, &submenu_items_display.id, &SMG$M_BORDER, 0, 0)) create_submenu(submenu_items_display, submenu.item); select_from_submenu(submenu_items_display, submenu, choice_nop, validitm, &word_terminator_code); if (word_terminator_code == SMG$K_TRM_ENTER || word_terminator_code == SMG$K_TRM_CR) { word_terminator_code = (unsigned short int) (*(validitm+*choice_nop)); } check_OK(smg$delete_virtual_display ( &submenu_items_display.id)) return word_terminator_code; } /* **++ ** tbd **-- **/ int create_submenu(menu_display, items) struct display_tag menu_display; char **items; { char **p; char item[MAXCOMMANDSITEMLENGTH+1]; $DESCRIPTOR (item_descriptor, item); int i, j; char *c; char ch[1]; $DESCRIPTOR (ch_descriptor, ch); LENGTH(ch_descriptor) = 1; for (p = items, i = 1; *p; p++, i++) { if (!strcmp(*p, MENU_SEPARATOR)) { *item = ' '; memset (item+1, '-', menu_display.width-2); *(item+menu_display.width-1) = ' '; } else { sprintf(item, " %s", *p); for (j = strlen(item); j < menu_display.width; j++) { *(item+j) = ' '; } } LENGTH(item_descriptor) = menu_display.width; check_OK(smg$put_chars ( &menu_display.id, &item_descriptor, &i, &1, 0, 0, 0, 0)) for (c = *p, j = 3; *c; c++, j++) { if (isupper (*c)) { ch[0] = *c; check_OK(smg$put_chars ( &menu_display.id, &ch_descriptor, 0, &j, 0, &SMG$M_UNDERLINE, &SMG$M_BOLD, 0)) break; } } } return DX__NORMAL; } /* **++ ** tbd **-- **/ int select_from_submenu(menu_display, submenu, choice_nop, validitm, word_terminator_codep) struct display_tag menu_display; struct menutype submenu; int *choice_nop; char validitm[]; unsigned short int *word_terminator_codep; { char **p; char item[MAXCOMMANDSITEMLENGTH+1]; $DESCRIPTOR (item_descriptor, item); int i, j; char *c1, *c2; char *c, *d; long int start_row, start_col; char ch[1]; $DESCRIPTOR (ch_descriptor, ch); int prev_choice; int timeout; unsigned long status; LENGTH (ch_descriptor) = 1; p = submenu.item+*choice_nop; sprintf(item, " %s", *p); for (i = strlen(item); i < menu_display.width; i++) { *(item+i) = ' '; } i = *choice_nop+1; LENGTH(item_descriptor) = menu_display.width; check_OK(smg$put_chars ( &menu_display.id, &item_descriptor, &i, &1, 0, 0, &SMG$M_REVERSE, 0)) for (c1 = *p, j = 3; *c1; c1++, j++) { if (isupper (*c1)) { ch[0] = *c1; check_OK(smg$put_chars ( &menu_display.id, &ch_descriptor, 0, &j, 0, &SMG$M_REVERSE, &SMG$M_BOLD, 0)) break; } } check_OK(smg$set_cursor_abs ( &menu_display.id, &i, &1)) start_row = submenu.start_row+2; if (submenu.start_col + menu_display.width <= cntrl_info_block.pasteboard_width) { start_col = submenu.start_col + 1; } else { start_col = cntrl_info_block.pasteboard_width - menu_display.width; submenu.start_col = start_col - 1; } check_OK(smg$paste_virtual_display ( &menu_display.id, &cntrl_info_block.pasteboard_id, &start_row, &start_col, 0)) timeout = cntrl_info_block.user_pref.update_in_second? 1 : 60; do { do { status = smg$read_keystroke ( &cntrl_info_block.keyboard_id, word_terminator_codep, 0, &timeout, &menu_display.id, 0, 0); if (cntrl_info_block.user_pref.display_clock) write_time(cntrl_info_block.commands_display.id); } while (status == SS$_TIMEOUT || *word_terminator_codep == SMG$K_TRM_CANCELLED); *word_terminator_codep = _toupper(*word_terminator_codep); if ((c = strchr (validitm, *word_terminator_codep)) && !strchr (c+1, *word_terminator_codep) && *word_terminator_codep != '-') { /** Exact one submenu item matchs the options letter **/ *choice_nop = c - validitm; break; } if (((c = strchr(validitm+*choice_nop, *word_terminator_codep)) && *word_terminator_codep != '-') || *word_terminator_codep == SMG$K_TRM_KP5 || *word_terminator_codep == SMG$K_TRM_KP6 || *word_terminator_codep == SMG$K_TRM_UP || *word_terminator_codep == SMG$K_TRM_DOWN) { prev_choice = *choice_nop; /** Save old option number **/ /** Get new option number **/ if (*word_terminator_codep == SMG$K_TRM_KP5) { *choice_nop = 0; } else if (*word_terminator_codep == SMG$K_TRM_KP6) { *choice_nop = menu_display.rows-1; } else if (*word_terminator_codep == SMG$K_TRM_UP) { if (--(*choice_nop) < 0) { *choice_nop = menu_display.rows-1; } while (!strcmp ( *(submenu.item+*choice_nop), MENU_SEPARATOR)) { if (--(*choice_nop) < 0) { *choice_nop = menu_display.rows-1; } } } else if (*word_terminator_codep == SMG$K_TRM_DOWN) { if (++(*choice_nop) > menu_display.rows-1) { *choice_nop = 0; } while (!strcmp ( *(submenu.item+*choice_nop), MENU_SEPARATOR)) { if (++(*choice_nop) > menu_display.rows-1) { *choice_nop = 0; } } } else if (c == validitm+*choice_nop) { /** Current cursor is the option letter **/ if ((d = strchr (c+1, *word_terminator_codep))) { /* ** One or more submenu items with the option ** letter ahead **/ *choice_nop = d - validitm; if (!strchr (d+1, *word_terminator_codep)) { /* ** Only one submenu items with the option ** letter ahead **/ break; } } else { /* ** The cursor is the only current submenu item ** with the option letter **/ break; } } else { /** Current cusor is not the option letter **/ *choice_nop = c - validitm; if (!strchr (c+1, *word_terminator_codep)) { break; } } /** Un-highlight previous option **/ p = submenu.item + prev_choice; sprintf(item, " %s", *p); for (j = strlen(item); j < menu_display.width; j++) { *(item+j) = ' '; } i = prev_choice+1; LENGTH(item_descriptor) = menu_display.width; check_OK(smg$put_chars ( &menu_display.id, &item_descriptor, &i, &1, 0, 0, 0, 0)) for (c1 = *p, j = 3; *c1; c1++, j++) { if (isupper (*c1)) { ch[0] = *c1; check_OK(smg$put_chars ( &menu_display.id, &ch_descriptor, 0, &j, 0, &SMG$M_UNDERLINE, &SMG$M_BOLD, 0)) break; } } /** Highlight new option **/ p = submenu.item+*choice_nop; sprintf(item, " %s", *p); for (j = strlen(item); j < menu_display.width; j++) { *(item+j) = ' '; } i = *choice_nop+1; LENGTH(item_descriptor) = menu_display.width; check_OK(smg$put_chars ( &menu_display.id, &item_descriptor, &i, &1, 0, 0, &SMG$M_REVERSE, 0)) for (c1 = *p, j = 3; *c1; c1++, j++) { if (isupper (*c1)) { ch[0] = *c1; check_OK(smg$put_chars ( &menu_display.id, &ch_descriptor, 0, &j, 0, &SMG$M_REVERSE, &SMG$M_BOLD, 0)) break; } } check_OK(smg$set_cursor_abs ( &menu_display.id, &i, &1)) } else if (*word_terminator_codep != SMG$K_TRM_LEFT && *word_terminator_codep != SMG$K_TRM_RIGHT && *word_terminator_codep != SMG$K_TRM_KP0 && *word_terminator_codep != SMG$K_TRM_KP1 && *word_terminator_codep != SMG$K_TRM_ENTER && *word_terminator_codep != SMG$K_TRM_CR) { check_OK(smg$ring_bell ( &menu_display.id, &1)) } } while (*word_terminator_codep != SMG$K_TRM_KP0 && *word_terminator_codep != SMG$K_TRM_KP1 && *word_terminator_codep != SMG$K_TRM_CR && *word_terminator_codep != SMG$K_TRM_ENTER && *word_terminator_codep != SMG$K_TRM_LEFT && *word_terminator_codep != SMG$K_TRM_RIGHT); return DX__NORMAL; } /* ** HIGHLIGHT_GENERAL_CMD highlights the FILER command ** that was selected by the user **/ int highlight_general_cmd(m, cmds_display_idp) struct menutype m; unsigned long *cmds_display_idp; { char c[1]; $DESCRIPTOR (c_descriptor, c); int limit; int i; char *cp; unsigned long rendition_set = SMG$M_REVERSE+SMG$M_BOLD; LENGTH(c_descriptor) = 1; limit = m.start_col+strlen (m.itmstr); check_OK(smg$begin_display_update ( cmds_display_idp)) for (i = m.start_col, cp = m.itmstr; i < limit; i++, cp++) { if (! isupper((c[0] = *cp))) { check_OK(smg$put_chars ( cmds_display_idp, &c_descriptor, &(m.start_row), &i, 0, &SMG$M_REVERSE, 0, 0)) } else { check_OK(smg$put_chars ( cmds_display_idp, &c_descriptor, &(m.start_row), &i, 0, &rendition_set, 0, 0)) } } check_OK(smg$end_display_update ( cmds_display_idp)) return DX__NORMAL; } /* ** UNHIGHLIGHT_GENERAL_CMD un-highlights the FILER command ** after execution is completed **/ int unhighlight_general_cmd(m, cmds_display_idp) struct menutype m; unsigned long *cmds_display_idp; { char c[1]; $DESCRIPTOR (c_descriptor, c); int limit; int i; char *cp; LENGTH(c_descriptor) = 1; limit = m.start_col+strlen (m.itmstr); check_OK(smg$begin_display_update ( cmds_display_idp)) for (i = m.start_col, cp = m.itmstr; i < limit; i++, cp++) { if (! isupper((c[0] = *cp))) { check_OK(smg$put_chars ( cmds_display_idp, &c_descriptor, &(m.start_row), &i, 0, &SMG$M_NORMAL, 0, 0)) } else { check_OK(smg$put_chars ( cmds_display_idp, &c_descriptor, &(m.start_row), &i, 0, &SMG$M_UNDERLINE, &SMG$M_BOLD, 0)) } } check_OK(smg$end_display_update ( cmds_display_idp)) return DX__NORMAL; }