diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/HTFWriter.c | 2 | ||||
-rw-r--r-- | src/LYCurses.c | 10 | ||||
-rw-r--r-- | src/LYForms.c | 1059 | ||||
-rw-r--r-- | src/LYOptions.c | 975 | ||||
-rw-r--r-- | src/LYOptions.h | 2 | ||||
-rw-r--r-- | src/LYStrings.c | 1139 | ||||
-rw-r--r-- | src/LYStrings.h | 25 | ||||
-rw-r--r-- | src/LYUtils.c | 21 |
8 files changed, 1150 insertions, 2083 deletions
diff --git a/src/HTFWriter.c b/src/HTFWriter.c index 653c2a9f..b765e520 100644 --- a/src/HTFWriter.c +++ b/src/HTFWriter.c @@ -749,7 +749,7 @@ PUBLIC HTStream* HTSaveToFile ARGS3( _statusline(CANNOT_DISPLAY_FILE_D_OR_C); } - while (c != 'D' && c != 'C') { + while (c != 'D' && c != 'C' && c != 7) { c = LYgetch_single(); #ifdef VMS /* diff --git a/src/LYCurses.c b/src/LYCurses.c index 6991981d..040df6a5 100644 --- a/src/LYCurses.c +++ b/src/LYCurses.c @@ -1332,7 +1332,7 @@ PUBLIC void LYpaddstr ARGS3( CONST char *, the_string) { width -= strlen(the_string); - waddstr(the_window, the_string); + LYwaddstr(the_window, the_string); while (width-- > 0) waddstr(the_window, " "); } @@ -1429,11 +1429,13 @@ PUBLIC void LYwaddnstr ARGS3( CONST char *, s, size_t, len) { - if (len != 0) { + while (len > 0) { char temp[MAX_LINE]; - memcpy(temp, s, len); - temp[len] = 0; + size_t use = (len >= MAX_LINE) ? MAX_LINE - 1 : len; + memcpy(temp, s, use); + temp[use] = 0; waddstr(w, temp); + len -= use; } } diff --git a/src/LYForms.c b/src/LYForms.c index 1795b306..b9a5b314 100644 --- a/src/LYForms.c +++ b/src/LYForms.c @@ -30,15 +30,34 @@ PRIVATE int form_getstr PARAMS(( struct link * form_link, BOOLEAN use_last_tfpos, BOOLEAN redraw_only)); -PRIVATE int popup_options PARAMS(( - int cur_selection, - OptionType * list, - int ly, - int lx, - int width, - int i_length, - int disabled)); +/* + * Returns an array of pointers to the given list + */ +PRIVATE char ** options_list ARGS1( + OptionType *, opt_ptr) +{ + char **result = 0; + size_t len; + int pass; + OptionType *tmp_ptr; + + for (pass = 0; pass < 2; pass++) { + for (tmp_ptr = opt_ptr, len = 0; tmp_ptr != 0; tmp_ptr = tmp_ptr->next) { + if (pass != 0) + result[len] = tmp_ptr->name; + len++; + } + if (pass == 0) { + len++; + result = typecallocn(char *, len); + } else { + result[len] = 0; + } + } + + return result; +} PUBLIC int change_form_link_ex ARGS8( struct link *, form_link, @@ -54,13 +73,15 @@ PUBLIC int change_form_link_ex ARGS8( int newdoc_changed = 0; int c = DO_NOTHING; int OrigNumValue; + char **my_data = 0; - /* - * If there is no form to perform action on, don't do anything. - */ - if (form == NULL) { - return(c); - } + /* + * If there is no form to perform action on, don't do anything. + */ + if (form == NULL) { + return(c); + } + my_data = options_list(form->select_list); /* * Move to the link position. @@ -81,7 +102,7 @@ PUBLIC int change_form_link_ex ARGS8( break; case F_OPTION_LIST_TYPE: - if (!form->select_list) { + if (form->select_list == 0) { HTAlert(BAD_HTML_NO_POPUP); c = DO_NOTHING; break; @@ -89,9 +110,15 @@ PUBLIC int change_form_link_ex ARGS8( if (form->disabled == YES) { int dummy; - dummy = popup_options(form->num_value, form->select_list, - form_link->ly, form_link->lx, form->size, - form->size_l, form->disabled); + dummy = LYhandlePopupList(form->num_value, + form_link->ly, + form_link->lx, + (CONST char **)my_data, + form->size, + form->size_l, + form->disabled, + FALSE, + FALSE); #if CTRL_W_HACK != DO_NOTHING if (!enable_scrollback) c = CTRL_W_HACK; /* CTRL-W refresh without clearok */ @@ -101,10 +128,15 @@ PUBLIC int change_form_link_ex ARGS8( break; } OrigNumValue = form->num_value; - form->num_value = popup_options(form->num_value, form->select_list, - form_link->ly, form_link->lx, form->size, - form->size_l, form->disabled); - + form->num_value = LYhandlePopupList(form->num_value, + form_link->ly, + form_link->lx, + (CONST char **)my_data, + form->size, + form->size_l, + form->disabled, + FALSE, + FALSE); { OptionType * opt_ptr = form->select_list; int i; @@ -313,6 +345,7 @@ PUBLIC int change_form_link_ex ARGS8( LYforce_no_cache = FALSE; reloading = FALSE; } + FREE(my_data); return(c); } @@ -791,988 +824,6 @@ breakfor: } /* -** This function prompts for an option or page number. -** If a 'g' or 'p' suffix is included, that will be -** loaded into c. Otherwise, c is zeroed. - FM & LE -*/ -PRIVATE int get_popup_option_number ARGS2( - int *, c, - int *, rel) -{ - char temp[120]; - char *p = temp; - int num; - - /* - * Load the c argument into the prompt buffer. - */ - temp[0] = (char) *c; - temp[1] = '\0'; - _statusline(SELECT_OPTION_NUMBER); - - /* - * Get the number, possibly with a suffix, from the user. - */ - if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 || *temp == 0) { - HTInfoMsg(CANCELLED); - *c = '\0'; - *rel = '\0'; - return(0); - } - - *rel = '\0'; - num = atoi(p); - while ( isdigit(*p) ) - ++p; - switch ( *p ) { - case '+': case '-': - /* 123+ or 123- */ - *rel = *p++; *c = *p; - break; - default: - *c = *p++; - *rel = *p; - break; - case 0: - break; - } - - /* - * If we had a 'g' or 'p' suffix, load it into c. - * Otherwise, zero c. Then return the number. - */ - if ( *p == 'g' || *p == 'G' ) { - *c = 'g'; - } else if (*p == 'p' || *p == 'P' ) { - *c = 'p'; - } else { - *c = '\0'; - } - if ( *rel != '+' && *rel != '-' ) - *rel = 0; - return num; -} - -PRIVATE void draw_option ARGS5( - WINDOW *, win, - int, entry, - int, width, - BOOL, reversed, - OptionType *, opt_ptr) -{ -#ifdef USE_SLANG - if (reversed) - SLsmg_set_color(2); - SLsmg_gotorc(win->top_y + entry, win->left_x + 2); - SLsmg_write_nstring(opt_ptr->name, win->width); - if (reversed) - SLsmg_set_color(0); -#else - wmove(win, entry, 2); - if (reversed) - wstart_reverse(win); - LYpaddstr(win, width, opt_ptr->name); - if (reversed) - wstop_reverse(win); -#endif /* USE_SLANG */ -} - -PRIVATE int popup_options ARGS7( - int, cur_selection, - OptionType *, list, - int, ly, - int, lx, - int, width, - int, i_length, - int, disabled) -{ - /* - * Revamped to handle within-tag VALUE's, if present, - * and to position the popup window appropriately, - * taking the user_mode setting into account. -- FM - */ - int c = 0, cmd = 0, i = 0, j = 0, rel = 0; - int orig_selection = cur_selection; - WINDOW * form_window; - int num_options = 0, top, bottom, length = -1; - OptionType * opt_ptr = list; - int window_offset = 0; - int lines_to_show; - int npages; - static char prev_target[512]; /* Search string buffer */ - static char prev_target_buffer[512]; /* Next search buffer */ - static BOOL first = TRUE; - char *cp; - int ch = 0, recall; - int QueryTotal; - int QueryNum; - BOOLEAN FirstRecall = TRUE; - OptionType * tmp_ptr; - BOOLEAN ReDraw = FALSE; - int number; - - /* - * Initialize the search string buffer. - FM - */ - if (first) { - *prev_target_buffer = '\0'; - first = FALSE; - } - *prev_target = '\0'; - QueryTotal = (search_queries ? HTList_count(search_queries) : 0); - recall = ((QueryTotal >= 1) ? RECALL : NORECALL); - QueryNum = QueryTotal; - - /* - * Set lines_to_show based on the user_mode global. - */ - if (user_mode == NOVICE_MODE) - lines_to_show = LYlines-4; - else - lines_to_show = LYlines-2; - - /* - * Counting the number of options to be displayed. - * num_options ranges 0...n - */ - for (; opt_ptr->next; num_options++, opt_ptr = opt_ptr->next) - ; /* null body */ - - /* - * Let's assume for the sake of sanity that ly is the number - * corresponding to the line the selection box is on. - * Let's also assume that cur_selection is the number of the - * item that should be initially selected, as 0 beign the - * first item. - * So what we have, is the top equal to the current screen line - * subtracting the cur_selection + 1 (the one must be for the - * top line we will draw in a box). If the top goes under 0, - * consider it 0. - */ - top = ly - (cur_selection + 1); - if (top < 0) - top = 0; - - /* - * Check and see if we need to put the i_length parameter up to - * the number of real options. - */ - if (!i_length) { - i_length = num_options; - } else { - /* - * Otherwise, it is really one number too high. - */ - i_length--; - } - - /* - * The bottom is the value of the top plus the number of options - * to view plus 3 (one for the top line, one for the bottom line, - * and one to offset the 0 counted in the num_options). - */ - bottom = top + i_length + 3; - - /* - * Hmm... If the bottom goes beyond the number of lines available, - */ - if (bottom > lines_to_show) { - /* - * Position the window at the top if we have more - * options than will fit in the window. - */ - if (i_length+3 > lines_to_show) { - top = 0; - bottom = top + i_length+3; - if (bottom > lines_to_show) - bottom = lines_to_show + 1; - } else { - /* - * Try to position the window so that the selected option will - * appear where the selection box currently is positioned. - * It could end up too high, at this point, but we'll move it - * down latter, if that has happened. - */ - top = (lines_to_show + 1) - (i_length + 3); - bottom = (lines_to_show + 1); - } - } - - /* - * This is really fun, when the length is 4, it means 0-4, or 5. - */ - length = (bottom - top) - 2; - - /* - * Move the window down if it's too high. - */ - if (bottom < ly + 2) { - bottom = ly + 2; - if (bottom > lines_to_show + 1) - bottom = lines_to_show + 1; - top = bottom - length - 2; - } - - /* - * Set up the overall window, including the boxing characters ('*'), - * if it all fits. Otherwise, set up the widest window possible. - FM - */ - if (width + 4 > LYcols) { - lx = 1; - width = LYcols - 5; /* avoids a crash? - kw */ - } - if ((form_window = LYstartPopup(top, lx, bottom - top, width)) == 0) - return(orig_selection); - - /* - * Set up the window_offset for options. - * cur_selection ranges from 0...n - * length ranges from 0...m - */ - if (cur_selection >= length) { - window_offset = cur_selection - length + 1; - } - - /* - * Compute the number of popup window pages. - FM - */ - npages = ((num_options + 1) > length) ? - (((num_options + 1) + (length - 1))/(length)) - : 1; -/* - * OH! I LOVE GOTOs! hack hack hack - * 07-11-94 GAB - * MORE hack hack hack - * 09-05-94 FM - */ -redraw: - opt_ptr = list; - - /* - * Display the boxed options. - */ - for (i = 0; i <= num_options; i++, opt_ptr = opt_ptr->next) { - if (i >= window_offset && i - window_offset < length) { - draw_option(form_window, ((i + 1) - window_offset), width, FALSE, opt_ptr); - } - } - LYbox(form_window, TRUE); - opt_ptr = NULL; - - /* - * Loop on user input. - */ - while (cmd != LYK_ACTIVATE) { - int row = ((i + 1) - window_offset); - - /* - * Unreverse cur selection. - */ - if (opt_ptr != NULL) { - draw_option(form_window, row, width, FALSE, opt_ptr); - } - - opt_ptr = list; - - for (i = 0; i < cur_selection; i++, opt_ptr = opt_ptr->next) - ; /* null body */ - row = ((i + 1) - window_offset); - - draw_option(form_window, row, width, TRUE, opt_ptr); - LYstowCursor(form_window, row, 1); - - c = LYgetch_choice(); - if (c == 7) { /* Control-C or Control-G */ - cmd = LYK_QUIT; -#ifndef USE_SLANG - } else if (c == MOUSE_KEY) { - if ((cmd = fancy_mouse(form_window, row, &cur_selection)) < 0) - goto redraw; - if (cmd == LYK_ACTIVATE) - break; -#endif - } else { - cmd = LKC_TO_LAC(keymap,c); - } -#ifdef VMS - if (HadVMSInterrupt) { - HadVMSInterrupt = FALSE; - cmd = LYK_QUIT; - } -#endif /* VMS */ - - switch(cmd) { - case LYK_F_LINK_NUM: - c = '\0'; - /* FALLTHRU */ - case LYK_1: /* FALLTHRU */ - case LYK_2: /* FALLTHRU */ - case LYK_3: /* FALLTHRU */ - case LYK_4: /* FALLTHRU */ - case LYK_5: /* FALLTHRU */ - case LYK_6: /* FALLTHRU */ - case LYK_7: /* FALLTHRU */ - case LYK_8: /* FALLTHRU */ - case LYK_9: - /* - * Get a number from the user, possibly with - * a 'g' or 'p' suffix (which will be loaded - * into c). - FM & LE - */ - number = get_popup_option_number((int *)&c,(int *)&rel); - - /* handle + or - suffix */ - CTRACE((tfp,"got popup option number %d, ",number)); - CTRACE((tfp,"rel='%c', c='%c', cur_selection=%d\n", - rel,c,cur_selection)); - if ( c == 'p' ) { - int curpage = ((cur_selection + 1) > length) ? - (((cur_selection + 1) + (length - 1))/(length)) - : 1; - CTRACE((tfp," curpage=%d\n",curpage)); - if ( rel == '+' ) - number = curpage + number; - else if ( rel == '-' ) - number = curpage - number; - } else if ( rel == '+' ) { - number = cur_selection + number + 1; - } else if ( rel == '-' ) { - number = cur_selection - number + 1; - } - if ( rel ) CTRACE((tfp,"new number=%d\n",number)); - /* - * Check for a 'p' suffix. - FM - */ - if (c == 'p') { - /* - * Treat 1 or less as the first page. - FM - */ - if (number <= 1) { - if (window_offset == 0) { - HTUserMsg(ALREADY_AT_OPTION_BEGIN); - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - break; - } - window_offset = 0; - cur_selection = 0; - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - goto redraw; - } - - /* - * Treat a number equal to or greater than the - * number of pages as the last page. - FM - */ - if (number >= npages) { - if (window_offset >= ((num_options - length) + 1)) { - HTUserMsg(ALREADY_AT_OPTION_END); - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - break; - } - window_offset = ((npages - 1) * length); - if (window_offset > (num_options - length)) { - window_offset = (num_options - length + 1); - } - if (cur_selection < window_offset) - cur_selection = window_offset; - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - goto redraw; - } - - /* - * We want an intermediate page. - FM - */ - if (((number - 1) * length) == window_offset) { - char *msg = 0; - HTSprintf0(&msg, ALREADY_AT_OPTION_PAGE, number); - HTUserMsg(msg); - FREE(msg); - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - break; - } - cur_selection = window_offset = ((number - 1) * length); - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - goto redraw; - - } - - /* - * Check for a positive number, which signifies - * that an option should be sought. - FM - */ - if (number > 0) { - /* - * Decrement the number so as to correspond - * with our cur_selection values. - FM - */ - number--; - - /* - * If the number is in range and had no legal - * suffix, select the indicated option. - FM - */ - if (number <= num_options && c == '\0') { - cur_selection = number; - cmd = LYK_ACTIVATE; - break; - } - - /* - * Verify that we had a 'g' suffix, - * and act on the number. - FM - */ - if (c == 'g') { - if (cur_selection == number) { - /* - * The option already is current. - FM - */ - char *msg = 0; - HTSprintf0(&msg, OPTION_ALREADY_CURRENT, (number + 1)); - HTUserMsg(msg); - FREE(msg); - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - break; - } - - if (number <= num_options) { - /* - * The number is in range and had a 'g' - * suffix, so make it the current option, - * scrolling if needed. - FM - */ - j = (number - cur_selection); - cur_selection = number; - if ((j > 0) && - (cur_selection - window_offset) >= length) { - window_offset += j; - if (window_offset > (num_options - length + 1)) - window_offset = (num_options - length + 1); - } else if ((cur_selection - window_offset) < 0) { - window_offset -= abs(j); - if (window_offset < 0) - window_offset = 0; - } - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - goto redraw; - } - - /* - * Not in range. - FM - */ - HTUserMsg(BAD_OPTION_NUM_ENTERED); - } - } - - /* - * Restore the popup statusline. - FM - */ - if (disabled) { - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - } else { - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - } - break; - - case LYK_PREV_LINK: - case LYK_LPOS_PREV_LINK: - case LYK_FASTBACKW_LINK: - case LYK_UP_LINK: - - if (cur_selection > 0) - cur_selection--; - - /* - * Scroll the window up if necessary. - */ - if ((cur_selection - window_offset) < 0) { - window_offset--; - goto redraw; - } - break; - - case LYK_NEXT_LINK: - case LYK_LPOS_NEXT_LINK: - case LYK_FASTFORW_LINK: - case LYK_DOWN_LINK: - if (cur_selection < num_options) - cur_selection++; - - /* - * Scroll the window down if necessary - */ - if ((cur_selection - window_offset) >= length) { - window_offset++; - goto redraw; - } - break; - - case LYK_NEXT_PAGE: - /* - * Okay, are we on the last page of the list? - * If not then, - */ - if (window_offset != (num_options - length + 1)) { - /* - * Modify the current selection to not be a - * coordinate in the list, but a coordinate - * on the item selected in the window. - */ - cur_selection -= window_offset; - - /* - * Page down the proper length for the list. - * If simply to far, back up. - */ - window_offset += length; - if (window_offset > (num_options - length)) { - window_offset = (num_options - length + 1); - } - - /* - * Readjust the current selection to be a - * list coordinate rather than window. - * Redraw this thing. - */ - cur_selection += window_offset; - goto redraw; - } - else if (cur_selection < num_options) { - /* - * Already on last page of the list so just - * redraw it with the last item selected. - */ - cur_selection = num_options; - } - break; - - case LYK_PREV_PAGE: - /* - * Are we on the first page of the list? - * If not then, - */ - if (window_offset != 0) { - /* - * Modify the current selection to not be a - * list coordinate, but a window coordinate. - */ - cur_selection -= window_offset; - - /* - * Page up the proper length. - * If too far, back up. - */ - window_offset -= length; - if (window_offset < 0) { - window_offset = 0; - } - - /* - * Readjust the current selection. - */ - cur_selection += window_offset; - goto redraw; - } else if (cur_selection > 0) { - /* - * Already on the first page so just - * back up to the first item. - */ - cur_selection = 0; - } - break; - - case LYK_HOME: - cur_selection = 0; - if (window_offset > 0) { - window_offset = 0; - goto redraw; - } - break; - - case LYK_END: - cur_selection = num_options; - if (window_offset != (num_options - length + 1)) { - window_offset = (num_options - length + 1); - goto redraw; - } - break; - - case LYK_DOWN_TWO: - cur_selection += 2; - if (cur_selection > num_options) - cur_selection = num_options; - - /* - * Scroll the window down if necessary. - */ - if ((cur_selection - window_offset) >= length) { - window_offset += 2; - if (window_offset > (num_options - length + 1)) - window_offset = (num_options - length + 1); - goto redraw; - } - break; - - case LYK_UP_TWO: - cur_selection -= 2; - if (cur_selection < 0) - cur_selection = 0; - - /* - * Scroll the window up if necessary. - */ - if ((cur_selection - window_offset) < 0) { - window_offset -= 2; - if (window_offset < 0) - window_offset = 0; - goto redraw; - } - break; - - case LYK_DOWN_HALF: - cur_selection += (length/2); - if (cur_selection > num_options) - cur_selection = num_options; - - /* - * Scroll the window down if necessary. - */ - if ((cur_selection - window_offset) >= length) { - window_offset += (length/2); - if (window_offset > (num_options - length + 1)) - window_offset = (num_options - length + 1); - goto redraw; - } - break; - - case LYK_UP_HALF: - cur_selection -= (length/2); - if (cur_selection < 0) - cur_selection = 0; - - /* - * Scroll the window up if necessary. - */ - if ((cur_selection - window_offset) < 0) { - window_offset -= (length/2); - if (window_offset < 0) - window_offset = 0; - goto redraw; - } - break; - - case LYK_REFRESH: - lynx_force_repaint(); - refresh(); - break; - - case LYK_NEXT: - if (recall && *prev_target_buffer == '\0') { - /* - * We got a 'n'ext command with no prior query - * specified within the popup window. See if - * one was entered when the popup was retracted, - * and if so, assume that's what's wanted. Note - * that it will become the default within popups, - * unless another is entered within a popup. If - * the within popup default is to be changed at - * that point, use WHEREIS ('/') and enter it, - * or the up- or down-arrow keys to seek any of - * the previously entered queries, regardless of - * whether they were entered within or outside - * of a popup window. - FM - */ - if ((cp = (char *)HTList_objectAt(search_queries, - 0)) != NULL) { - LYstrncpy(prev_target_buffer, cp, sizeof(prev_target_buffer)); - QueryNum = 0; - FirstRecall = FALSE; - } - } - strcpy(prev_target, prev_target_buffer); - /* FALLTHRU */ - case LYK_WHEREIS: - if (*prev_target == '\0' ) { - _statusline(ENTER_WHEREIS_QUERY); - if ((ch = LYgetstr(prev_target, VISIBLE, - sizeof(prev_target_buffer), - recall)) < 0) { - /* - * User cancelled the search via ^G. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - } - -check_recall: - if (*prev_target == '\0' && - !(recall && (ch == UPARROW || ch == DNARROW))) { - /* - * No entry. Simply break. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - - if (recall && ch == UPARROW) { - if (FirstRecall) { - /* - * Use the current string or - * last query in the list. - FM - */ - FirstRecall = FALSE; - if (*prev_target_buffer) { - for (QueryNum = (QueryTotal - 1); - QueryNum > 0; QueryNum--) { - if ((cp = (char *)HTList_objectAt( - search_queries, - QueryNum)) != NULL && - !strcmp(prev_target_buffer, cp)) { - break; - } - } - } else { - QueryNum = 0; - } - } else { - /* - * Go back to the previous query in the list. - FM - */ - QueryNum++; - } - if (QueryNum >= QueryTotal) { - /* - * Roll around to the last query in the list. - FM - */ - QueryNum = 0; - } - if ((cp = (char *)HTList_objectAt(search_queries, - QueryNum)) != NULL) { - LYstrncpy(prev_target, cp, sizeof(prev_target)-1); - if (*prev_target_buffer && - !strcmp(prev_target_buffer, prev_target)) { - _statusline(EDIT_CURRENT_QUERY); - } else if ((*prev_target_buffer && QueryTotal == 2) || - (!(*prev_target_buffer) && - QueryTotal == 1)) { - _statusline(EDIT_THE_PREV_QUERY); - } else { - _statusline(EDIT_A_PREV_QUERY); - } - if ((ch = LYgetstr(prev_target, VISIBLE, - sizeof(prev_target_buffer), recall)) < 0) { - /* - * User cancelled the search via ^G. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - goto check_recall; - } - } else if (recall && ch == DNARROW) { - if (FirstRecall) { - /* - * Use the current string or - * first query in the list. - FM - */ - FirstRecall = FALSE; - if (*prev_target_buffer) { - for (QueryNum = 0; - QueryNum < (QueryTotal - 1); QueryNum++) { - if ((cp = (char *)HTList_objectAt( - search_queries, - QueryNum)) != NULL && - !strcmp(prev_target_buffer, cp)) { - break; - } - } - } else { - QueryNum = (QueryTotal - 1); - } - } else { - /* - * Advance to the next query in the list. - FM - */ - QueryNum--; - } - if (QueryNum < 0) { - /* - * Roll around to the first query in the list. - FM - */ - QueryNum = (QueryTotal - 1); - } - if ((cp = (char *)HTList_objectAt(search_queries, - QueryNum)) != NULL) { - LYstrncpy(prev_target, cp, sizeof(prev_target)-1); - if (*prev_target_buffer && - !strcmp(prev_target_buffer, prev_target)) { - _statusline(EDIT_CURRENT_QUERY); - } else if ((*prev_target_buffer && - QueryTotal == 2) || - (!(*prev_target_buffer) && - QueryTotal == 1)) { - _statusline(EDIT_THE_PREV_QUERY); - } else { - _statusline(EDIT_A_PREV_QUERY); - } - if ((ch = LYgetstr(prev_target, VISIBLE, - sizeof(prev_target_buffer), - recall)) < 0) { - /* - * User cancelled the search via ^G. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - goto check_recall; - } - } - /* - * Replace the search string buffer with the new target. - FM - */ - strcpy(prev_target_buffer, prev_target); - HTAddSearchQuery(prev_target_buffer); - - /* - * Start search at the next option. - FM - */ - for (j = 1, tmp_ptr = opt_ptr->next; - tmp_ptr != NULL; tmp_ptr = tmp_ptr->next, j++) { - if (case_sensitive) { - if (strstr(tmp_ptr->name, prev_target_buffer) != NULL) - break; - } else { - if (LYstrstr(tmp_ptr->name, prev_target_buffer) != NULL) - break; - } - } - if (tmp_ptr != NULL) { - /* - * We have a hit, so make that option the current. - FM - */ - cur_selection += j; - /* - * Scroll the window down if necessary. - */ - if ((cur_selection - window_offset) >= length) { - window_offset += j; - if (window_offset > (num_options - length + 1)) - window_offset = (num_options - length + 1); - ReDraw = TRUE; - } - goto restore_popup_statusline; - } - - /* - * If we started at the beginning, it can't be present. - FM - */ - if (cur_selection == 0) { - HTUserMsg2(STRING_NOT_FOUND, prev_target_buffer); - goto restore_popup_statusline; - } - - /* - * Search from the beginning to the current option. - FM - */ - for (j = 0, tmp_ptr = list; - j < cur_selection; tmp_ptr = tmp_ptr->next, j++) { - if (case_sensitive) { - if (strstr(tmp_ptr->name, prev_target_buffer) != NULL) - break; - } else { - if (LYstrstr(tmp_ptr->name, prev_target_buffer) != NULL) - break; - } - } - if (j < cur_selection) { - /* - * We have a hit, so make that option the current. - FM - */ - j = (cur_selection - j); - cur_selection -= j; - /* - * Scroll the window up if necessary. - */ - if ((cur_selection - window_offset) < 0) { - window_offset -= j; - if (window_offset < 0) - window_offset = 0; - ReDraw = TRUE; - } - goto restore_popup_statusline; - } - - /* - * Didn't find it in the preceding options either. - FM - */ - HTUserMsg2(STRING_NOT_FOUND, prev_target_buffer); - -restore_popup_statusline: - /* - * Restore the popup statusline and - * reset the search variables. - FM - */ - if (disabled) - _statusline(FORM_LINK_OPTION_LIST_UNM_MSG); - else - _statusline(FORM_LINK_OPTION_LIST_MESSAGE); - *prev_target = '\0'; - QueryTotal = (search_queries ? HTList_count(search_queries) - : 0); - recall = ((QueryTotal >= 1) ? RECALL : NORECALL); - QueryNum = QueryTotal; - if (ReDraw == TRUE) { - ReDraw = FALSE; - goto redraw; - } - break; - - case LYK_QUIT: - case LYK_ABORT: - case LYK_PREV_DOC: - cur_selection = orig_selection; - cmd = LYK_ACTIVATE; /* to exit */ - break; - } - } - LYstopPopup(); - - return(disabled ? orig_selection : cur_selection); -} - -/* * Display statusline info tailored for the current form field. */ PUBLIC void show_formlink_statusline ARGS2( diff --git a/src/LYOptions.c b/src/LYOptions.c index 9beb653f..1ce2d238 100644 --- a/src/LYOptions.c +++ b/src/LYOptions.c @@ -176,17 +176,17 @@ PRIVATE int boolean_choice PARAMS(( #define C_VERBOSE_IMAGES (B_VERBOSE_IMAGES + 21) /* a kludge to add assume_charset only in ADVANCED mode... */ -#define L_Bool_A (use_assume_charset ? L_BOOL_A + 1 : L_BOOL_A) -#define L_Bool_B (use_assume_charset ? L_BOOL_B + 1 : L_BOOL_B) -#define L_Exec (use_assume_charset ? L_EXEC + 1 : L_EXEC) -#define L_Rawmode (use_assume_charset ? L_RAWMODE + 1 : L_RAWMODE) -#define L_Charset (use_assume_charset ? L_CHARSET + 1 : L_CHARSET) -#define L_Color (use_assume_charset ? L_COLOR + 1 : L_COLOR) -#define L_Keypad (use_assume_charset ? L_KEYPAD + 1 : L_KEYPAD) -#define L_Lineed (use_assume_charset ? L_LINEED + 1 : L_LINEED) -#define L_Layout (use_assume_charset ? L_LAYOUT + 1 : L_LAYOUT) -#define L_Dired (use_assume_charset ? L_DIRED + 1 : L_DIRED) -#define L_User_Mode (use_assume_charset ? L_USER_MODE + 1 : L_USER_MODE) +#define L_Bool_A (use_assume_charset ? L_BOOL_A + 1 : L_BOOL_A) +#define L_Bool_B (use_assume_charset ? L_BOOL_B + 1 : L_BOOL_B) +#define L_Exec (use_assume_charset ? L_EXEC + 1 : L_EXEC) +#define L_Rawmode (use_assume_charset ? L_RAWMODE + 1 : L_RAWMODE) +#define L_Charset (use_assume_charset ? L_CHARSET + 1 : L_CHARSET) +#define L_Color (use_assume_charset ? L_COLOR + 1 : L_COLOR) +#define L_Keypad (use_assume_charset ? L_KEYPAD + 1 : L_KEYPAD) +#define L_Lineed (use_assume_charset ? L_LINEED + 1 : L_LINEED) +#define L_Layout (use_assume_charset ? L_LAYOUT + 1 : L_LAYOUT) +#define L_Dired (use_assume_charset ? L_DIRED + 1 : L_DIRED) +#define L_User_Mode (use_assume_charset ? L_USER_MODE + 1 : L_USER_MODE) #define L_User_Agent (use_assume_charset ? L_USER_AGENT + 1 : L_USER_AGENT) #define LPAREN '(' @@ -2116,84 +2116,6 @@ draw_bookmark_list: } #if !defined(NO_OPTION_MENU) || (defined(USE_MOUSE) && (defined(NCURSES) || defined(PDCURSES))) -/* -** This function prompts for a choice or page number. -** If a 'g' or 'p' suffix is included, that will be -** loaded into c. Otherwise, c is zeroed. - FM -*/ -PRIVATE int get_popup_choice_number ARGS1( - int *, c) -{ - char temp[120]; - - /* - * Load the c argument into the prompt buffer. - */ - temp[0] = (char) *c; - temp[1] = '\0'; - _statusline(OPTION_CHOICE_NUMBER); - - /* - * Get the number, possibly with a suffix, from the user. - */ - if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 || - *temp == 0 || term_options) { - HTInfoMsg(CANCELLED); - *c = '\0'; - term_options = FALSE; - return(0); - } - - /* - * If we had a 'g' or 'p' suffix, load it into c. - * Otherwise, zero c. Then return the number. - */ - if (strchr(temp, 'g') != NULL || strchr(temp, 'G') != NULL) { - *c = 'g'; - } else if (strchr(temp, 'p') != NULL || strchr(temp, 'P') != NULL) { - *c = 'p'; - } else { - *c = '\0'; - } - return(atoi(temp)); -} - -#define FormatChoiceNum(dst, choice, value) \ - sprintf(dst, "%s%d: %.500s", \ - ((num_choices > 8 && choice < 9) ? \ - " " : ""), \ - (choice + 1), value) - -PRIVATE void draw_option ARGS7( - WINDOW *, win, - int, entry, - int, width, - BOOLEAN, reverse, - int, num_choices, - int, number, - CONST char *, value) -{ - char Cnum[64]; - - FormatChoiceNum(Cnum, number, ""); -#ifdef USE_SLANG - SLsmg_gotorc(win->top_y + entry, (win->left_x + 2)); - addstr(Cnum); - if (reverse) - SLsmg_set_color(2); - LYaddnstr(value, width); - if (reverse) - SLsmg_set_color(0); -#else - wmove(win, entry, 2); - waddstr(win, Cnum); - if (reverse) - wstart_reverse(win); - LYpaddstr(win, width, value); - if (reverse) - wstop_reverse(win); -#endif /* USE_SLANG */ -} /* * This function offers the choices for values of an @@ -2212,868 +2134,39 @@ PUBLIC int popup_choice ARGS7( int, disabled, BOOLEAN, for_mouse) { - int ly = line; - int lx = (column >= 0 ? column : (COL_OPTION_VALUES - 1)); - int c = 0, cmd = 0, i = 0, j = 0; - int orig_choice = cur_choice; - WINDOW * form_window; - int num_choices = 0, top, bottom, length = -1; - unsigned width = 0; - CONST char ** Cptr = choices; - int window_offset = 0; - int DisplayLines = (LYlines - 2); - char Cnum[64]; - int Lnum; - int npages; - static char prev_target[512]; /* Search string buffer */ - static char prev_target_buffer[512]; /* Next search buffer */ - static BOOL first = TRUE; - char *cp; - int ch = 0, recall; - int QueryTotal; - int QueryNum; - BOOLEAN FirstRecall = TRUE; - BOOLEAN ReDraw = FALSE; - int number; - char buffer[512]; - char *popup_status_msg = NULL; - - /* - * Initialize the search string buffer. - FM - */ - if (first) { - *prev_target_buffer = '\0'; - first = FALSE; - } - *prev_target = '\0'; - QueryTotal = (search_queries ? HTList_count(search_queries) : 0); - recall = ((QueryTotal >= 1) ? RECALL : NORECALL); - QueryNum = QueryTotal; - - /* - * Count the number of choices to be displayed, where - * num_choices ranges from 0 to n, and set width to the - * longest choice string length. Also set Lnum to the - * length for the highest choice number, then decrement - * num_choices so as to be zero-based. The window width - * will be based on the sum of width and Lnum. - FM - */ - for (num_choices = 0; Cptr[num_choices] != NULL; num_choices++) { - if (strlen(Cptr[num_choices]) > width) { - width = strlen(Cptr[num_choices]); - } - } - sprintf(Cnum, "%d: ", num_choices); - Lnum = strlen(Cnum); - num_choices--; - - /* - * Let's assume for the sake of sanity that ly is the number - * corresponding to the line the option is on. - * Let's also assume that cur_choice is the number of the - * choice that should be initially selected, with 0 being - * the first choice. - * So what we have, is the top equal to the current screen line - * subtracting the cur_choice + 1 (the one must be for the top - * line we will draw in a box). If the top goes under 0, then - * consider it 0. - */ - top = ly - (cur_choice + 1); - if (top < 0) - top = 0; - - /* - * Check and see if we need to put the i_length parameter up to - * the number of real choices. - */ - if (i_length < 1) { - i_length = num_choices; - } else { - /* - * Otherwise, it is really one number too high. - */ - i_length--; - } - - /* - * The bottom is the value of the top plus the number of choices - * to view plus 3 (one for the top line, one for the bottom line, - * and one to offset the 0 counted in the num_choices). - */ - bottom = top + i_length + 3; - - if (for_mouse && user_mode == NOVICE_MODE && DisplayLines > 2) - DisplayLines--; - /* - * Hmm... If the bottom goes beyond the number of lines available, - */ - if (bottom > DisplayLines) { - /* - * Position the window at the top if we have more - * choices than will fit in the window. - */ - if ((i_length + 3) > DisplayLines) { - top = 0; - bottom = (top + (i_length + 3)); - if (bottom > DisplayLines) - bottom = (DisplayLines + 1); - } else { - /* - * Try to position the window so that the selected choice will - * appear where the choice box currently is positioned. - * It could end up too high, at this point, but we'll move it - * down latter, if that has happened. - */ - top = (DisplayLines + 1) - (i_length + 3); - bottom = (DisplayLines + 1); - } - } - - /* - * This is really fun, when the length is 4, it means 0 to 4, or 5. - */ - length = (bottom - top) - 2; - - /* - * Move the window down if it's too high. - */ - if (bottom < ly + 2) { - bottom = ly + 2; - if (bottom > DisplayLines + 1) - bottom = DisplayLines + 1; - top = bottom - length - 2; - } - - if (for_mouse) { - /* shift horizontally to lie within screen width, if possible */ - if (Lnum + (int)width + 4 < LYcols) { - if (lx - 1 + (Lnum + (int)width + 4) > LYcols) - lx = LYcols + 1 - (Lnum + width + 4); - else if (lx <= 0) - lx = 1; - } - } - - /* - * Set up the overall window, including the boxing characters ('*'), - * if it all fits. Otherwise, set up the widest window possible. - FM - */ - if ((form_window = LYstartPopup(top, lx, bottom - top, Lnum + width)) == 0) - return(orig_choice); - - /* - * Clear the command line and write - * the popup statusline. - FM - */ - move((LYlines - 2), 0); - clrtoeol(); - if (disabled) { - StrAllocCopy(popup_status_msg, CHOICE_LIST_UNM_MSG); - } else if (!for_mouse) { - StrAllocCopy(popup_status_msg, CHOICE_LIST_MESSAGE); -#if defined(USE_MOUSE) && (defined(NCURSES) || defined(PDCURSES)) - } else { - StrAllocCopy(popup_status_msg, gettext( - "Left mouse button or return to select, arrow keys to scroll.")); -#endif - } - _statusline(popup_status_msg); - - /* - * Set up the window_offset for choices. - * cur_choice ranges from 0...n - * length ranges from 0...m - */ - if (cur_choice >= length) { - window_offset = cur_choice - length + 1; - } - - /* - * Compute the number of popup window pages. - FM - */ - npages = ((num_choices + 1) > length) ? - (((num_choices + 1) + (length - 1))/(length)) - : 1; -/* - * OH! I LOVE GOTOs! hack hack hack - */ -redraw: - Cptr = choices; + if (column < 0) + column = (COL_OPTION_VALUES - 1); - /* - * Display the boxed choices. - */ - for (i = 0; i <= num_choices; i++) { - if (i >= window_offset && i - window_offset < length) { - draw_option (form_window, ((i + 1) - window_offset), width, FALSE, - num_choices, i, Cptr[i]); - } - } - LYbox(form_window, FALSE); - Cptr = NULL; - - /* - * Loop on user input. - */ - while (cmd != LYK_ACTIVATE) { - int row = ((i + 1) - window_offset); - - /* - * Unreverse cur choice. - */ - if (Cptr != NULL) { - draw_option (form_window, row, width, FALSE, - num_choices, i, Cptr[i]); - } - Cptr = choices; - i = cur_choice; - row = ((i + 1) - window_offset); - draw_option (form_window, row, width, TRUE, - num_choices, i, Cptr[i]); - LYstowCursor(form_window, row, 1); - - term_options = FALSE; - c = LYgetch_choice(); - if (term_options || c == 7) { - cmd = LYK_QUIT; -#ifndef USE_SLANG - } else if (c == MOUSE_KEY) { - if ((cmd = fancy_mouse(form_window, row, &cur_choice)) < 0) - goto redraw; - if (cmd == LYK_ACTIVATE) - break; -#endif - } else { - cmd = LKC_TO_LAC(keymap,c); - } -#ifdef VMS - if (HadVMSInterrupt) { - HadVMSInterrupt = FALSE; - cmd = LYK_QUIT; - } -#endif /* VMS */ - - switch(cmd) { - case LYK_F_LINK_NUM: - c = '\0'; - /* FALLTHRU */ - case LYK_1: /* FALLTHRU */ - case LYK_2: /* FALLTHRU */ - case LYK_3: /* FALLTHRU */ - case LYK_4: /* FALLTHRU */ - case LYK_5: /* FALLTHRU */ - case LYK_6: /* FALLTHRU */ - case LYK_7: /* FALLTHRU */ - case LYK_8: /* FALLTHRU */ - case LYK_9: - /* - * Get a number from the user, possibly with - * a 'g' or 'p' suffix (which will be loaded - * into c). - FM & LE - */ - number = get_popup_choice_number((int *)&c); - - /* - * Check for a 'p' suffix. - FM - */ - if (c == 'p') { - /* - * Treat 1 or less as the first page. - FM - */ - if (number <= 1) { - if (window_offset == 0) { - HTUserMsg(ALREADY_AT_CHOICE_BEGIN); - _statusline(popup_status_msg); - break; - } - window_offset = 0; - cur_choice = 0; - _statusline(popup_status_msg); - goto redraw; - } - - /* - * Treat a number equal to or greater than the - * number of pages as the last page. - FM - */ - if (number >= npages) { - if (window_offset >= ((num_choices - length) + 1)) { - HTUserMsg(ALREADY_AT_CHOICE_END); - _statusline(popup_status_msg); - break; - } - window_offset = ((npages - 1) * length); - if (window_offset > (num_choices - length)) { - window_offset = (num_choices - length + 1); - } - if (cur_choice < window_offset) - cur_choice = window_offset; - _statusline(popup_status_msg); - goto redraw; - } - - /* - * We want an intermediate page. - FM - */ - if (((number - 1) * length) == window_offset) { - sprintf(buffer, ALREADY_AT_CHOICE_PAGE, number); - HTUserMsg(buffer); - _statusline(popup_status_msg); - break; - } - cur_choice = window_offset = ((number - 1) * length); - _statusline(popup_status_msg); - goto redraw; - - } - - /* - * Check for a positive number, which signifies - * that a choice should be sought. - FM - */ - if (number > 0) { - /* - * Decrement the number so as to correspond - * with our cur_choice values. - FM - */ - number--; - - /* - * If the number is in range and had no legal - * suffix, select the indicated choice. - FM - */ - if (number <= num_choices && c == '\0') { - cur_choice = number; - cmd = LYK_ACTIVATE; - break; - } - - /* - * Verify that we had a 'g' suffix, - * and act on the number. - FM - */ - if (c == 'g') { - if (cur_choice == number) { - /* - * The choice already is current. - FM - */ - sprintf(buffer, - CHOICE_ALREADY_CURRENT, (number + 1)); - HTUserMsg(buffer); - _statusline(popup_status_msg); - break; - } - - if (number <= num_choices) { - /* - * The number is in range and had a 'g' - * suffix, so make it the current choice, - * scrolling if needed. - FM - */ - j = (number - cur_choice); - cur_choice = number; - if ((j > 0) && - (cur_choice - window_offset) >= length) { - window_offset += j; - if (window_offset > (num_choices - length + 1)) - window_offset = (num_choices - length + 1); - } else if ((cur_choice - window_offset) < 0) { - window_offset -= abs(j); - if (window_offset < 0) - window_offset = 0; - } - _statusline(popup_status_msg); - goto redraw; - } - - /* - * Not in range. - FM - */ - HTUserMsg(BAD_CHOICE_NUM_ENTERED); - } - } - - /* - * Restore the popup statusline. - FM - */ - _statusline(popup_status_msg); - break; - - case LYK_PREV_LINK: - case LYK_LPOS_PREV_LINK: - case LYK_UP_LINK: - - if (cur_choice > 0) - cur_choice--; - - /* - * Scroll the window up if necessary. - */ - if ((cur_choice - window_offset) < 0) { - window_offset--; - goto redraw; - } - break; - - case LYK_NEXT_LINK: - case LYK_LPOS_NEXT_LINK: - case LYK_DOWN_LINK: - if (cur_choice < num_choices) - cur_choice++; - - /* - * Scroll the window down if necessary - */ - if ((cur_choice - window_offset) >= length) { - window_offset++; - goto redraw; - } - break; - - case LYK_NEXT_PAGE: - /* - * Okay, are we on the last page of the choices list? - * If not then, - */ - if (window_offset != (num_choices - length + 1)) { - /* - * Modify the current choice to not be a - * coordinate in the list, but a coordinate - * on the item selected in the window. - */ - cur_choice -= window_offset; - - /* - * Page down the proper length for the list. - * If simply to far, back up. - */ - window_offset += length; - if (window_offset > (num_choices - length)) { - window_offset = (num_choices - length + 1); - } - - /* - * Readjust the current choice to be a choice - * list coordinate rather than window. - * Redraw this thing. - */ - cur_choice += window_offset; - goto redraw; - } - else if (cur_choice < num_choices) { - /* - * Already on last page of the choice list so - * just redraw it with the last item selected. - */ - cur_choice = num_choices; - } - break; - - case LYK_PREV_PAGE: - /* - * Are we on the first page of the choice list? - * If not then, - */ - if (window_offset != 0) { - /* - * Modify the current choice to not be a choice - * list coordinate, but a window coordinate. - */ - cur_choice -= window_offset; - - /* - * Page up the proper length. - * If too far, back up. - */ - window_offset -= length; - if (window_offset < 0) { - window_offset = 0; - } - - /* - * Readjust the current choice. - */ - cur_choice += window_offset; - goto redraw; - } else if (cur_choice > 0) { - /* - * Already on the first page so just - * back up to the first item. - */ - cur_choice = 0; - } - break; - - case LYK_HOME: - cur_choice = 0; - if (window_offset > 0) { - window_offset = 0; - goto redraw; - } - break; - - case LYK_END: - cur_choice = num_choices; - if (window_offset != (num_choices - length + 1)) { - window_offset = (num_choices - length + 1); - goto redraw; - } - break; - - case LYK_DOWN_TWO: - cur_choice += 2; - if (cur_choice > num_choices) - cur_choice = num_choices; - - /* - * Scroll the window down if necessary. - */ - if ((cur_choice - window_offset) >= length) { - window_offset += 2; - if (window_offset > (num_choices - length + 1)) - window_offset = (num_choices - length + 1); - goto redraw; - } - break; - - case LYK_UP_TWO: - cur_choice -= 2; - if (cur_choice < 0) - cur_choice = 0; - - /* - * Scroll the window up if necessary. - */ - if ((cur_choice - window_offset) < 0) { - window_offset -= 2; - if (window_offset < 0) - window_offset = 0; - goto redraw; - } - break; - - case LYK_DOWN_HALF: - cur_choice += (length/2); - if (cur_choice > num_choices) - cur_choice = num_choices; - - /* - * Scroll the window down if necessary. - */ - if ((cur_choice - window_offset) >= length) { - window_offset += (length/2); - if (window_offset > (num_choices - length + 1)) - window_offset = (num_choices - length + 1); - goto redraw; - } - break; - - case LYK_UP_HALF: - cur_choice -= (length/2); - if (cur_choice < 0) - cur_choice = 0; - - /* - * Scroll the window up if necessary. - */ - if ((cur_choice - window_offset) < 0) { - window_offset -= (length/2); - if (window_offset < 0) - window_offset = 0; - goto redraw; - } - break; - - case LYK_REFRESH: - lynx_force_repaint(); - refresh(); - break; - - case LYK_NEXT: - if (recall && *prev_target_buffer == '\0') { - /* - * We got a 'n'ext command with no prior query - * specified within the popup window. See if - * one was entered when the popup was retracted, - * and if so, assume that's what's wanted. Note - * that it will become the default within popups, - * unless another is entered within a popup. If - * the within popup default is to be changed at - * that point, use WHEREIS ('/') and enter it, - * or the up- or down-arrow keys to seek any of - * the previously entered queries, regardless of - * whether they were entered within or outside - * of a popup window. - FM - */ - if ((cp = (char *)HTList_objectAt(search_queries, - 0)) != NULL) { - LYstrncpy(prev_target_buffer, cp, sizeof(prev_target_buffer) - 1); - QueryNum = 0; - FirstRecall = FALSE; - } - } - strcpy(prev_target, prev_target_buffer); - /* FALLTHRU */ - case LYK_WHEREIS: - if (*prev_target == '\0' ) { - _statusline(ENTER_WHEREIS_QUERY); - if ((ch = LYgetstr(prev_target, VISIBLE, - sizeof(prev_target_buffer), - recall)) < 0) { - /* - * User cancelled the search via ^G. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - } - -check_recall: - if (*prev_target == '\0' && - !(recall && (ch == UPARROW || ch == DNARROW))) { - /* - * No entry. Simply break. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - - if (recall && ch == UPARROW) { - if (FirstRecall) { - /* - * Use the current string or - * last query in the list. - FM - */ - FirstRecall = FALSE; - if (*prev_target_buffer) { - for (QueryNum = (QueryTotal - 1); - QueryNum > 0; QueryNum--) { - if ((cp = (char *)HTList_objectAt( - search_queries, - QueryNum)) != NULL && - !strcmp(prev_target_buffer, cp)) { - break; - } - } - } else { - QueryNum = 0; - } - } else { - /* - * Go back to the previous query in the list. - FM - */ - QueryNum++; - } - if (QueryNum >= QueryTotal) - /* - * Roll around to the last query in the list. - FM - */ - QueryNum = 0; - if ((cp = (char *)HTList_objectAt(search_queries, - QueryNum)) != NULL) { - LYstrncpy(prev_target, cp, sizeof(prev_target) - 1); - if (*prev_target_buffer && - !strcmp(prev_target_buffer, prev_target)) { - _statusline(EDIT_CURRENT_QUERY); - } else if ((*prev_target_buffer && QueryTotal == 2) || - (!(*prev_target_buffer) && - QueryTotal == 1)) { - _statusline(EDIT_THE_PREV_QUERY); - } else { - _statusline(EDIT_A_PREV_QUERY); - } - if ((ch = LYgetstr(prev_target, VISIBLE, - sizeof(prev_target_buffer), recall)) < 0) { - /* - * User cancelled the search via ^G. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - goto check_recall; - } - } else if (recall && ch == DNARROW) { - if (FirstRecall) { - /* - * Use the current string or - * first query in the list. - FM - */ - FirstRecall = FALSE; - if (*prev_target_buffer) { - for (QueryNum = 0; - QueryNum < (QueryTotal - 1); QueryNum++) { - if ((cp = (char *)HTList_objectAt( - search_queries, - QueryNum)) != NULL && - !strcmp(prev_target_buffer, cp)) { - break; - } - } - } else { - QueryNum = (QueryTotal - 1); - } - } else { - /* - * Advance to the next query in the list. - FM - */ - QueryNum--; - } - if (QueryNum < 0) - /* - * Roll around to the first query in the list. - FM - */ - QueryNum = (QueryTotal - 1); - if ((cp = (char *)HTList_objectAt(search_queries, - QueryNum)) != NULL) { - LYstrncpy(prev_target, cp, sizeof(prev_target) - 1); - if (*prev_target_buffer && - !strcmp(prev_target_buffer, prev_target)) { - _statusline(EDIT_CURRENT_QUERY); - } else if ((*prev_target_buffer && - QueryTotal == 2) || - (!(*prev_target_buffer) && - QueryTotal == 1)) { - _statusline(EDIT_THE_PREV_QUERY); - } else { - _statusline(EDIT_A_PREV_QUERY); - } - if ((ch = LYgetstr(prev_target, VISIBLE, - sizeof(prev_target_buffer), - recall)) < 0) { - /* - * User cancelled the search via ^G. - FM - */ - HTInfoMsg(CANCELLED); - goto restore_popup_statusline; - } - goto check_recall; - } - } - /* - * Replace the search string buffer with the new target. - FM - */ - strcpy(prev_target_buffer, prev_target); - HTAddSearchQuery(prev_target_buffer); - - /* - * Start search at the next choice. - FM - */ - for (j = 1; Cptr[i+j] != NULL; j++) { - FormatChoiceNum(buffer, (i + j), Cptr[i+j]); - if (case_sensitive) { - if (strstr(buffer, prev_target_buffer) != NULL) - break; - } else { - if (LYstrstr(buffer, prev_target_buffer) != NULL) - break; - } - } - if (Cptr[i+j] != NULL) { - /* - * We have a hit, so make that choice the current. - FM - */ - cur_choice += j; - /* - * Scroll the window down if necessary. - */ - if ((cur_choice - window_offset) >= length) { - window_offset += j; - if (window_offset > (num_choices - length + 1)) - window_offset = (num_choices - length + 1); - ReDraw = TRUE; - } - goto restore_popup_statusline; - } - - /* - * If we started at the beginning, it can't be present. - FM - */ - if (cur_choice == 0) { - HTUserMsg2(STRING_NOT_FOUND, prev_target_buffer); - goto restore_popup_statusline; - } - - /* - * Search from the beginning to the current choice. - FM - */ - for (j = 0; j < cur_choice; j++) { - FormatChoiceNum(buffer, (j + 1), Cptr[j]); - if (case_sensitive) { - if (strstr(buffer, prev_target_buffer) != NULL) - break; - } else { - if (LYstrstr(buffer, prev_target_buffer) != NULL) - break; - } - } - if (j < cur_choice) { - /* - * We have a hit, so make that choice the current. - FM - */ - j = (cur_choice - j); - cur_choice -= j; - /* - * Scroll the window up if necessary. - */ - if ((cur_choice - window_offset) < 0) { - window_offset -= j; - if (window_offset < 0) - window_offset = 0; - ReDraw = TRUE; - } - goto restore_popup_statusline; - } - - /* - * Didn't find it in the preceding choices either. - FM - */ - HTUserMsg2(STRING_NOT_FOUND, prev_target_buffer); - -restore_popup_statusline: - /* - * Restore the popup statusline and - * reset the search variables. - FM - */ - _statusline(popup_status_msg); - *prev_target = '\0'; - QueryTotal = (search_queries ? HTList_count(search_queries) - : 0); - recall = ((QueryTotal >= 1) ? RECALL : NORECALL); - QueryNum = QueryTotal; - if (ReDraw == TRUE) { - ReDraw = FALSE; - goto redraw; - } - break; - - case LYK_QUIT: - case LYK_ABORT: - case LYK_PREV_DOC: - cur_choice = orig_choice; - term_options = TRUE; - if (!for_mouse) { - HTUserMsg(CANCELLED); - } - cmd = LYK_ACTIVATE; /* to exit */ - break; + term_options = FALSE; + cur_choice = LYhandlePopupList(cur_choice, + line, + column, + (CONST char **)choices, + -1, + i_length, + disabled, + for_mouse, + TRUE); + switch (cur_choice) { + case LYK_QUIT: + case LYK_ABORT: + case LYK_PREV_DOC: + term_options = TRUE; + if (!for_mouse) { + HTUserMsg(CANCELLED); } + break; } - FREE(popup_status_msg); - LYstopPopup(); if (disabled || term_options) { _statusline(""); - return(orig_choice); - } else { - if (!for_mouse) { - _statusline(VALUE_ACCEPTED); - } - return(cur_choice); + } else if (!for_mouse) { + _statusline(VALUE_ACCEPTED); } + return(cur_choice); } #endif /* !NO_OPTION_MENU */ - #ifndef NO_OPTION_FORMS /* diff --git a/src/LYOptions.h b/src/LYOptions.h index 17242f80..ba486999 100644 --- a/src/LYOptions.h +++ b/src/LYOptions.h @@ -2,6 +2,7 @@ #define LYOPTIONS_H #include <LYStructs.h> +#include <LYStrings.h> extern BOOLEAN term_options; /* for LYgetstr() */ @@ -14,6 +15,7 @@ extern int popup_choice PARAMS(( int length, int disabled, BOOLEAN mouse)); + #define LYChoosePopup(cur, line, column, choices, length, disabled, mouse) \ popup_choice(cur, line, column, (CONST char **)choices, length, disabled, mouse) diff --git a/src/LYStrings.c b/src/LYStrings.c index f163a791..dfaecfc4 100644 --- a/src/LYStrings.c +++ b/src/LYStrings.c @@ -706,9 +706,10 @@ PRIVATE WINDOW *my_subwindow; PUBLIC void LYsubwindow ARGS1(WINDOW *, param) { - if ((my_subwindow = param) != 0) { + if (param != 0) { + my_subwindow = param; #if defined(NCURSES) || defined(PDCURSES) - keypad(param, TRUE); + keypad(my_subwindow, TRUE); #if defined(HAVE_GETBKGD) /* not defined in ncurses 1.8.7 */ wbkgd(my_subwindow, getbkgd(stdscr)); wbkgdset(my_subwindow, getbkgd(stdscr)); @@ -718,6 +719,7 @@ PUBLIC void LYsubwindow ARGS1(WINDOW *, param) } else { touchwin(stdscr); delwin(my_subwindow); + my_subwindow = 0; } } #endif @@ -1407,7 +1409,7 @@ PRIVATE int LYmouse_menu ARGS4(int, x, int, y, int, atlink, int, code) : TABLESIZE(actions)), FALSE, TRUE); /* - * popup_choice() in LYOptions.c wasn't really meant to be used + * LYhandlePopupList() wasn't really meant to be used * outside of old-style Options menu processing. One result of * mis-using it here is that we have to deal with side-effects * regarding SIGINT signal handler and the term_options global @@ -3084,6 +3086,70 @@ PUBLIC int LYEdit1 ARGS4( return(0); } +/* +** This function prompts for a choice or page number. +** If a 'g' or 'p' suffix is included, that will be +** loaded into c. Otherwise, c is zeroed. - FM & LE +*/ +PUBLIC int get_popup_number ARGS3( + char *, msg, + int *, c, + int *, rel) +{ + char temp[120]; + char *p = temp; + int num; + + /* + * Load the c argument into the prompt buffer. + */ + temp[0] = (char) *c; + temp[1] = '\0'; + _statusline(msg); + + /* + * Get the number, possibly with a suffix, from the user. + */ + if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 || *temp == 0) { + HTInfoMsg(CANCELLED); + *c = '\0'; + *rel = '\0'; + return(0); + } + + *rel = '\0'; + num = atoi(p); + while ( isdigit(*p) ) + ++p; + switch ( *p ) { + case '+': case '-': + /* 123+ or 123- */ + *rel = *p++; *c = *p; + break; + default: + *c = *p++; + *rel = *p; + break; + case 0: + break; + } + + /* + * If we had a 'g' or 'p' suffix, load it into c. + * Otherwise, zero c. Then return the number. + */ + if ( *p == 'g' || *p == 'G' ) { + *c = 'g'; + } else if (*p == 'p' || *p == 'P' ) { + *c = 'p'; + } else { + *c = '\0'; + } + if ( *rel != '+' && *rel != '-' ) + *rel = 0; + return num; +} + PUBLIC void LYRefreshEdit ARGS1( EDREC *, edit) @@ -3319,24 +3385,43 @@ PRIVATE char **sortedList ARGS2( BOOL, ignorecase) { unsigned count = HTList_count(list); - unsigned n = 0; + unsigned j = 0; + unsigned k, jk; char **result = calloc(count + 1, sizeof(char *)); if (result == 0) outofmem(__FILE__, "sortedList"); while (!HTList_isEmpty(list)) - result[n++] = HTList_nextObject(list); + result[j++] = HTList_nextObject(list); + if (count > 1) { qsort((char *)result, count, sizeof(*result), ignorecase ? caselessCmpList : normalCmpList); + + /* remove duplicate entries from the sorted index */ + for (j = 0; result[j] != 0; j++) { + k = j; + while (result[k] != 0 + && !strcmp(result[j], result[k])) { + k++; + } + k--; + if (j != k) { + for (jk = j; ; jk++) { + result[jk] = result[jk + k - j]; + if (result[jk] == 0) + break; + } + } + } } return result; } -PRIVATE int lengthOfList ARGS1( - char **, list) +PUBLIC int LYarrayLength ARGS1( + CONST char **, list) { int result = 0; @@ -3345,8 +3430,8 @@ PRIVATE int lengthOfList ARGS1( return result; } -PRIVATE int widestInList ARGS1( - char **, list) +PUBLIC int LYarrayWidth ARGS1( + CONST char **, list) { int result = 0; int check; @@ -3359,22 +3444,60 @@ PRIVATE int widestInList ARGS1( return result; } -PRIVATE void draw_option ARGS5( - WINDOW *, win, - int, entry, - int, width, - BOOL, reversed, - char *, value) +PRIVATE void FormatChoiceNum ARGS4( + char *, dst, + int, num_choices, + int, choice, + CONST char *, value) +{ + if (num_choices >= 0) { + int digits = (num_choices > 9) ? 2 : 1; + sprintf(dst, "%*d: %.*s", + digits, (choice + 1), + MAX_LINE - 9 - digits, value); + } else { + LYstrncpy(dst, value, MAX_LINE-1); + } +} + +PRIVATE unsigned options_width ARGS1( + CONST char **, list) +{ + unsigned width = 0; + int count = 0; + + while (list[count] != 0) { + if (strlen(list[count]) > width) { + width = strlen(list[count]); + } + count++; + } + return width; +} + +PRIVATE void draw_option ARGS7( + WINDOW *, win, + int, entry, + int, width, + BOOL, reversed, + int, num_choices, + int, number, + CONST char *, value) { + char Cnum[MAX_LINE]; + + FormatChoiceNum(Cnum, num_choices, number, ""); #ifdef USE_SLANG + SLsmg_gotorc(win->top_y + entry, (win->left_x + 2)); + addstr(Cnum); if (reversed) SLsmg_set_color(2); - SLsmg_gotorc(win->top_y + entry, win->left_x + 2); - SLsmg_write_nstring(value, win->width); + SLsmg_write_nstring((char *)value, win->width); if (reversed) SLsmg_set_color(0); #else wmove(win, entry, 2); + waddstr(win, Cnum); if (reversed) wstart_reverse(win); LYpaddstr(win, width, value); @@ -3383,130 +3506,455 @@ PRIVATE void draw_option ARGS5( #endif /* USE_SLANG */ } -PRIVATE int LYgetMenuKeycode ARGS3( - WINDOW *, win, - int, row, - int *, cur_selectionp) +/* + * This function offers the choices for values of an + * option via a popup window which functions like + * that for selection of options in a form. - FM + * + * Also used for mouse popups with ncurses; this is indicated + * by for_mouse. + */ +PUBLIC int LYhandlePopupList ARGS9( + int, cur_choice, + int, ly, + int, lx, + CONST char **, choices, + int, width, + int, i_length, + int, disabled, + BOOLEAN, for_mouse, + BOOLEAN, numbered) { - int cmd; - int c = LYgetch_choice(); + int c = 0, cmd = 0, i = 0, j = 0, rel = 0; + int orig_choice = cur_choice; + WINDOW * form_window; + int num_choices = 0; + int max_choices = 0; + int top, bottom, length = -1; + int window_offset = 0; + int lines_to_show; + char Cnum[64]; + int Lnum; + int npages; + static char prev_target[MAX_LINE]; /* Search string buffer */ + static char prev_target_buffer[MAX_LINE]; /* Next search buffer */ + static BOOL first = TRUE; + char *cp; + int ch = 0, recall; + int QueryTotal; + int QueryNum; + BOOLEAN FirstRecall = TRUE; + BOOLEAN ReDraw = FALSE; + int number; + char buffer[MAX_LINE]; + char *popup_status_msg = NULL; + CONST char **Cptr = NULL; - if (c == 7) { /* Control-C or Control-G */ - cmd = LYK_QUIT; -#ifndef USE_SLANG - } else if (c == MOUSE_KEY) { - cmd = fancy_mouse(win, row, cur_selectionp); -#endif + /* + * Initialize the search string buffer. - FM + */ + if (first) { + *prev_target_buffer = '\0'; + first = FALSE; + } + *prev_target = '\0'; + QueryTotal = (search_queries ? HTList_count(search_queries) : 0); + recall = ((QueryTotal >= 1) ? RECALL : NORECALL); + QueryNum = QueryTotal; + + /* + * Count the number of choices to be displayed, where + * num_choices ranges from 0 to n, and set width to the + * longest choice string length. Also set Lnum to the + * length for the highest choice number, then decrement + * num_choices so as to be zero-based. The window width + * will be based on the sum of width and Lnum. - FM + */ + num_choices = LYarrayLength(choices) - 1; + if (width <= 0) + width = options_width(choices); + if (numbered) { + sprintf(Cnum, "%d: ", num_choices); + Lnum = strlen(Cnum); + max_choices = num_choices; } else { - cmd = LKC_TO_LAC(keymap,c); + Lnum = 0; + max_choices = -1; } -#ifdef VMS - if (HadVMSInterrupt) { - HadVMSInterrupt = FALSE; - cmd = LYK_QUIT; + + /* + * Let's assume for the sake of sanity that ly is the number + * corresponding to the line the choice is on. + * Let's also assume that cur_choice is the number of the + * item that should be initially selected, as 0 being the + * first item. + * So what we have, is the top equal to the current screen line + * subtracting the cur_choice + 1 (the one must be for the + * top line we will draw in a box). If the top goes under 0, + * consider it 0. + */ + top = ly - (cur_choice + 1); + if (top < 0) + top = 0; + + /* + * Check and see if we need to put the i_length parameter up to + * the number of real choices. + */ + if (i_length < 1) { + i_length = num_choices; + } else { + /* + * Otherwise, it is really one number too high. + */ + i_length--; } -#endif /* VMS */ - return cmd; -} -PRIVATE void completeFromPopup ARGS2( - EditFieldData *, edit, - char **, data) -{ - WINDOW *win; - int top; - int lx = 2; - int width = widestInList(data); - int num_options = lengthOfList(data); - int height = num_options + 2; - int i, row, length; - int cmd = LYK_UNKNOWN; - int window_offset = 0; - int cur_selection = 0; - int old_selection = -1; - int old_y, old_x; + /* + * The bottom is the value of the top plus the number of options + * to view plus 3 (one for the top line, one for the bottom line, + * and one to offset the 0 counted in the num_choices). + */ + bottom = top + i_length + 3; -#ifdef USE_SLANG - old_y = SLsmg_get_row(); - old_x = SLsmg_get_column(); -#else - getyx(stdscr, old_y, old_x); -#endif + /* + * Set lines_to_show based on the user_mode global. + */ + if (user_mode == NOVICE_MODE) + lines_to_show = LYlines-4; + else + lines_to_show = LYlines-2; - if (height > LYlines - 2) - height = LYlines - 2; - length = height - 2; - top = LYlines - height - 1; + if (for_mouse && user_mode == NOVICE_MODE && lines_to_show > 2) + lines_to_show--; - while (cur_selection < num_options - && strcasecomp(data[cur_selection], edit->buffer) < 0) - cur_selection++; - if (cur_selection + 1 - window_offset >= length) { - window_offset = cur_selection + 1 - length; + /* + * Hmm... If the bottom goes beyond the number of lines available, + */ + if (bottom > lines_to_show) { + /* + * Position the window at the top if we have more + * choices than will fit in the window. + */ + if ((i_length + 3) > lines_to_show) { + top = 0; + bottom = (top + (i_length + 3)); + if (bottom > lines_to_show) + bottom = (lines_to_show + 1); + } else { + /* + * Try to position the window so that the selected choice will + * appear where the selection box currently is positioned. + * It could end up too high, at this point, but we'll move it + * down latter, if that has happened. + */ + top = (lines_to_show + 1) - (i_length + 3); + bottom = (lines_to_show + 1); + } } - /* construct a popup window */ - if ((win = LYstartPopup(top, lx, height, width)) != 0) { - /* handle events in the popup window */ -redraw: - LYbox(win, FALSE); - for (i = 0; i < num_options; i++) { - row = ((i + 1) - window_offset); - if (row >= 1 && row <= length) - draw_option(win, row, width, FALSE, data[i]); + /* + * This is really fun, when the length is 4, it means 0 to 4, or 5. + */ + length = (bottom - top) - 2; + + /* + * Move the window down if it's too high. + */ + if (bottom < ly + 2) { + bottom = ly + 2; + if (bottom > lines_to_show + 1) + bottom = lines_to_show + 1; + top = bottom - length - 2; + } + + if (for_mouse) { + /* shift horizontally to lie within screen width, if possible */ + if (Lnum + (int)width + 4 < LYcols) { + if (lx - 1 + (Lnum + (int)width + 4) > LYcols) + lx = LYcols + 1 - (Lnum + width + 4); + else if (lx <= 0) + lx = 1; } - old_selection = -1; + } - while (cmd != LYK_ACTIVATE) { + /* + * Set up the overall window, including the boxing characters ('*'), + * if it all fits. Otherwise, set up the widest window possible. - FM + */ + if ((form_window = LYstartPopup(top, lx, bottom - top, Lnum + width)) == 0) + return(orig_choice); - if (old_selection >= 0 - && old_selection != cur_selection) { - row = ((old_selection + 1) - window_offset); - draw_option(win, row, width, FALSE, data[old_selection]); - } - old_selection = cur_selection; + /* + * Clear the command line and write + * the popup statusline. - FM + */ + move((LYlines - 2), 0); + clrtoeol(); + if (disabled) { + popup_status_msg = CHOICE_LIST_UNM_MSG; + } else if (!for_mouse) { + popup_status_msg = CHOICE_LIST_MESSAGE; +#if defined(USE_MOUSE) && (defined(NCURSES) || defined(PDCURSES)) + } else { + popup_status_msg = gettext( + "Left mouse button or return to select, arrow keys to scroll."); +#endif + } + _statusline(popup_status_msg); - row = ((cur_selection + 1) - window_offset); - draw_option(win, row, width, TRUE, data[cur_selection]); - LYstowCursor(win, row, 1); - cmd = LYgetMenuKeycode(win, row, &cur_selection); + /* + * Set up the window_offset for choices. + * cur_choice ranges from 0...n + * length ranges from 0...m + */ + if (cur_choice >= length) { + window_offset = cur_choice - length + 1; + } - /* FIXME: this whole switch statement should be integrated with - * the redundant logic in LYForms.c and LYOptions.c (there's no - * point in having multiple copies of code that scroll through - * a popup menu). - */ - switch (cmd) { - case -1: + /* + * Compute the number of popup window pages. - FM + */ + npages = ((num_choices + 1) > length) ? + (((num_choices + 1) + (length - 1))/(length)) + : 1; +/* + * OH! I LOVE GOTOs! hack hack hack + */ +redraw: + + /* + * Display the boxed choices. + */ + for (i = 0; i <= num_choices; i++) { + if (i >= window_offset && i - window_offset < length) { + draw_option (form_window, ((i + 1) - window_offset), width, FALSE, + max_choices, i, choices[i]); + } + } + LYbox(form_window, !numbered); + Cptr = NULL; + + /* + * Loop on user input. + */ + while (cmd != LYK_ACTIVATE) { + int row = ((i + 1) - window_offset); + + /* + * Unreverse cur choice. + */ + if (Cptr != NULL) { + draw_option (form_window, row, width, FALSE, + max_choices, i, Cptr[i]); + } + Cptr = choices; + i = cur_choice; + row = ((cur_choice + 1) - window_offset); + draw_option (form_window, row, width, TRUE, + max_choices, cur_choice, Cptr[cur_choice]); + LYstowCursor(form_window, row, 1); + + c = LYgetch_choice(); + if (term_options || c == 7) { /* Control-C or Control-G */ + cmd = LYK_QUIT; +#ifndef USE_SLANG + } else if (c == MOUSE_KEY) { + if ((cmd = fancy_mouse(form_window, row, &cur_choice)) < 0) goto redraw; + if (cmd == LYK_ACTIVATE) + break; +#endif + } else { + cmd = LKC_TO_LAC(keymap,c); + } +#ifdef VMS + if (HadVMSInterrupt) { + HadVMSInterrupt = FALSE; + cmd = LYK_QUIT; + } +#endif /* VMS */ - case LYK_HOME: - cur_selection = 0; - if (window_offset > 0) { - window_offset = 0; - goto redraw; + switch(cmd) { + case LYK_F_LINK_NUM: + c = '\0'; + /* FALLTHRU */ + case LYK_1: /* FALLTHRU */ + case LYK_2: /* FALLTHRU */ + case LYK_3: /* FALLTHRU */ + case LYK_4: /* FALLTHRU */ + case LYK_5: /* FALLTHRU */ + case LYK_6: /* FALLTHRU */ + case LYK_7: /* FALLTHRU */ + case LYK_8: /* FALLTHRU */ + case LYK_9: + /* + * Get a number from the user, possibly with + * a 'g' or 'p' suffix (which will be loaded + * into c). - FM & LE + */ + number = get_popup_number(SELECT_OPTION_NUMBER, &c, &rel); + + /* handle + or - suffix */ + CTRACE((tfp,"got popup option number %d, ",number)); + CTRACE((tfp,"rel='%c', c='%c', cur_choice=%d\n", + rel, c, cur_choice)); + if ( c == 'p' ) { + int curpage = ((cur_choice + 1) > length) ? + (((cur_choice + 1) + (length - 1))/(length)) + : 1; + CTRACE((tfp," curpage=%d\n",curpage)); + if ( rel == '+' ) + number = curpage + number; + else if ( rel == '-' ) + number = curpage - number; + } else if ( rel == '+' ) { + number = cur_choice + number + 1; + } else if ( rel == '-' ) { + number = cur_choice - number + 1; } - break; + if ( rel ) CTRACE((tfp,"new number=%d\n",number)); + /* + * Check for a 'p' suffix. - FM + */ + if (c == 'p') { + /* + * Treat 1 or less as the first page. - FM + */ + if (number <= 1) { + if (window_offset == 0) { + HTUserMsg(ALREADY_AT_OPTION_BEGIN); + _statusline(popup_status_msg); + break; + } + window_offset = 0; + cur_choice = 0; + _statusline(popup_status_msg); + goto redraw; + } - case LYK_END: - cur_selection = num_options - 1; - if (window_offset != (num_options - length)) { - window_offset = (num_options - length); + /* + * Treat a number equal to or greater than the + * number of pages as the last page. - FM + */ + if (number >= npages) { + if (window_offset >= ((num_choices - length) + 1)) { + HTUserMsg(ALREADY_AT_OPTION_END); + _statusline(popup_status_msg); + break; + } + window_offset = ((npages - 1) * length); + if (window_offset > (num_choices - length)) { + window_offset = (num_choices - length + 1); + } + if (cur_choice < window_offset) + cur_choice = window_offset; + _statusline(popup_status_msg); + goto redraw; + } + + /* + * We want an intermediate page. - FM + */ + if (((number - 1) * length) == window_offset) { + char *msg = 0; + HTSprintf0(&msg, ALREADY_AT_OPTION_PAGE, number); + HTUserMsg(msg); + FREE(msg); + _statusline(popup_status_msg); + break; + } + cur_choice = window_offset = ((number - 1) * length); + _statusline(popup_status_msg); goto redraw; + + } + + /* + * Check for a positive number, which signifies + * that a choice should be sought. - FM + */ + if (number > 0) { + /* + * Decrement the number so as to correspond + * with our cur_choice values. - FM + */ + number--; + + /* + * If the number is in range and had no legal + * suffix, select the indicated choice. - FM + */ + if (number <= num_choices && c == '\0') { + cur_choice = number; + cmd = LYK_ACTIVATE; + break; + } + + /* + * Verify that we had a 'g' suffix, + * and act on the number. - FM + */ + if (c == 'g') { + if (cur_choice == number) { + /* + * The choice already is current. - FM + */ + char *msg = 0; + HTSprintf0(&msg, OPTION_ALREADY_CURRENT, (number + 1)); + HTUserMsg(msg); + FREE(msg); + _statusline(popup_status_msg); + break; + } + + if (number <= num_choices) { + /* + * The number is in range and had a 'g' + * suffix, so make it the current option, + * scrolling if needed. - FM + */ + j = (number - cur_choice); + cur_choice = number; + if ((j > 0) && + (cur_choice - window_offset) >= length) { + window_offset += j; + if (window_offset > (num_choices - length + 1)) + window_offset = (num_choices - length + 1); + } else if ((cur_choice - window_offset) < 0) { + window_offset -= abs(j); + if (window_offset < 0) + window_offset = 0; + } + _statusline(popup_status_msg); + goto redraw; + } + + /* + * Not in range. - FM + */ + HTUserMsg(BAD_OPTION_NUM_ENTERED); + } } + + /* + * Restore the popup statusline. - FM + */ + _statusline(popup_status_msg); break; case LYK_PREV_LINK: case LYK_LPOS_PREV_LINK: case LYK_FASTBACKW_LINK: case LYK_UP_LINK: - if (cur_selection > 0) - cur_selection--; + + if (cur_choice > 0) + cur_choice--; /* * Scroll the window up if necessary. */ - if ((cur_selection - window_offset) < 0) { + if ((cur_choice - window_offset) < 0) { window_offset--; goto redraw; } @@ -3516,35 +3964,447 @@ redraw: case LYK_LPOS_NEXT_LINK: case LYK_FASTFORW_LINK: case LYK_DOWN_LINK: - if (cur_selection < num_options - 1) - cur_selection++; + if (cur_choice < num_choices) + cur_choice++; + /* * Scroll the window down if necessary */ - if ((cur_selection - window_offset) >= length) { + if ((cur_choice - window_offset) >= length) { window_offset++; goto redraw; } break; + case LYK_NEXT_PAGE: + /* + * Okay, are we on the last page of the list? + * If not then, + */ + if (window_offset != (num_choices - length + 1)) { + /* + * Modify the current choice to not be a + * coordinate in the list, but a coordinate + * on the item selected in the window. + */ + cur_choice -= window_offset; + + /* + * Page down the proper length for the list. + * If simply to far, back up. + */ + window_offset += length; + if (window_offset > (num_choices - length)) { + window_offset = (num_choices - length + 1); + } + + /* + * Readjust the current selection to be a + * list coordinate rather than window. + * Redraw this thing. + */ + cur_choice += window_offset; + goto redraw; + } + else if (cur_choice < num_choices) { + /* + * Already on last page of the list so just + * redraw it with the last item selected. + */ + cur_choice = num_choices; + } + break; + + case LYK_PREV_PAGE: + /* + * Are we on the first page of the list? + * If not then, + */ + if (window_offset != 0) { + /* + * Modify the current selection to not be a + * list coordinate, but a window coordinate. + */ + cur_choice -= window_offset; + + /* + * Page up the proper length. + * If too far, back up. + */ + window_offset -= length; + if (window_offset < 0) { + window_offset = 0; + } + + /* + * Readjust the current choice. + */ + cur_choice += window_offset; + goto redraw; + } else if (cur_choice > 0) { + /* + * Already on the first page so just + * back up to the first item. + */ + cur_choice = 0; + } + break; + + case LYK_HOME: + cur_choice = 0; + if (window_offset > 0) { + window_offset = 0; + goto redraw; + } + break; + + case LYK_END: + cur_choice = num_choices; + if (window_offset != (num_choices - length + 1)) { + window_offset = (num_choices - length + 1); + goto redraw; + } + break; + + case LYK_DOWN_TWO: + cur_choice += 2; + if (cur_choice > num_choices) + cur_choice = num_choices; + + /* + * Scroll the window down if necessary. + */ + if ((cur_choice - window_offset) >= length) { + window_offset += 2; + if (window_offset > (num_choices - length + 1)) + window_offset = (num_choices - length + 1); + goto redraw; + } + break; + + case LYK_UP_TWO: + cur_choice -= 2; + if (cur_choice < 0) + cur_choice = 0; + + /* + * Scroll the window up if necessary. + */ + if ((cur_choice - window_offset) < 0) { + window_offset -= 2; + if (window_offset < 0) + window_offset = 0; + goto redraw; + } + break; + + case LYK_DOWN_HALF: + cur_choice += (length/2); + if (cur_choice > num_choices) + cur_choice = num_choices; + + /* + * Scroll the window down if necessary. + */ + if ((cur_choice - window_offset) >= length) { + window_offset += (length/2); + if (window_offset > (num_choices - length + 1)) + window_offset = (num_choices - length + 1); + goto redraw; + } + break; + + case LYK_UP_HALF: + cur_choice -= (length/2); + if (cur_choice < 0) + cur_choice = 0; + + /* + * Scroll the window up if necessary. + */ + if ((cur_choice - window_offset) < 0) { + window_offset -= (length/2); + if (window_offset < 0) + window_offset = 0; + goto redraw; + } + break; + + case LYK_REFRESH: + lynx_force_repaint(); + refresh(); + break; + + case LYK_NEXT: + if (recall && *prev_target_buffer == '\0') { + /* + * We got a 'n'ext command with no prior query + * specified within the popup window. See if + * one was entered when the popup was retracted, + * and if so, assume that's what's wanted. Note + * that it will become the default within popups, + * unless another is entered within a popup. If + * the within popup default is to be changed at + * that point, use WHEREIS ('/') and enter it, + * or the up- or down-arrow keys to seek any of + * the previously entered queries, regardless of + * whether they were entered within or outside + * of a popup window. - FM + */ + if ((cp = (char *)HTList_objectAt(search_queries, + 0)) != NULL) { + LYstrncpy(prev_target_buffer, cp, sizeof(prev_target_buffer)); + QueryNum = 0; + FirstRecall = FALSE; + } + } + strcpy(prev_target, prev_target_buffer); + /* FALLTHRU */ + case LYK_WHEREIS: + if (*prev_target == '\0' ) { + _statusline(ENTER_WHEREIS_QUERY); + if ((ch = LYgetstr(prev_target, VISIBLE, + sizeof(prev_target_buffer), + recall)) < 0) { + /* + * User cancelled the search via ^G. - FM + */ + HTInfoMsg(CANCELLED); + goto restore_popup_statusline; + } + } + +check_recall: + if (*prev_target == '\0' && + !(recall && (ch == UPARROW || ch == DNARROW))) { + /* + * No entry. Simply break. - FM + */ + HTInfoMsg(CANCELLED); + goto restore_popup_statusline; + } + + if (recall && ch == UPARROW) { + if (FirstRecall) { + /* + * Use the current string or + * last query in the list. - FM + */ + FirstRecall = FALSE; + if (*prev_target_buffer) { + for (QueryNum = (QueryTotal - 1); + QueryNum > 0; QueryNum--) { + if ((cp = (char *)HTList_objectAt( + search_queries, + QueryNum)) != NULL && + !strcmp(prev_target_buffer, cp)) { + break; + } + } + } else { + QueryNum = 0; + } + } else { + /* + * Go back to the previous query in the list. - FM + */ + QueryNum++; + } + if (QueryNum >= QueryTotal) { + /* + * Roll around to the last query in the list. - FM + */ + QueryNum = 0; + } + if ((cp = (char *)HTList_objectAt(search_queries, + QueryNum)) != NULL) { + LYstrncpy(prev_target, cp, sizeof(prev_target) - 1); + if (*prev_target_buffer && + !strcmp(prev_target_buffer, prev_target)) { + _statusline(EDIT_CURRENT_QUERY); + } else if ((*prev_target_buffer && QueryTotal == 2) || + (!(*prev_target_buffer) && + QueryTotal == 1)) { + _statusline(EDIT_THE_PREV_QUERY); + } else { + _statusline(EDIT_A_PREV_QUERY); + } + if ((ch = LYgetstr(prev_target, VISIBLE, + sizeof(prev_target_buffer), recall)) < 0) { + /* + * User cancelled the search via ^G. - FM + */ + HTInfoMsg(CANCELLED); + goto restore_popup_statusline; + } + goto check_recall; + } + } else if (recall && ch == DNARROW) { + if (FirstRecall) { + /* + * Use the current string or + * first query in the list. - FM + */ + FirstRecall = FALSE; + if (*prev_target_buffer) { + for (QueryNum = 0; + QueryNum < (QueryTotal - 1); QueryNum++) { + if ((cp = (char *)HTList_objectAt( + search_queries, + QueryNum)) != NULL && + !strcmp(prev_target_buffer, cp)) { + break; + } + } + } else { + QueryNum = (QueryTotal - 1); + } + } else { + /* + * Advance to the next query in the list. - FM + */ + QueryNum--; + } + if (QueryNum < 0) { + /* + * Roll around to the first query in the list. - FM + */ + QueryNum = (QueryTotal - 1); + } + if ((cp = (char *)HTList_objectAt(search_queries, + QueryNum)) != NULL) { + LYstrncpy(prev_target, cp, sizeof(prev_target) - 1); + if (*prev_target_buffer && + !strcmp(prev_target_buffer, prev_target)) { + _statusline(EDIT_CURRENT_QUERY); + } else if ((*prev_target_buffer && + QueryTotal == 2) || + (!(*prev_target_buffer) && + QueryTotal == 1)) { + _statusline(EDIT_THE_PREV_QUERY); + } else { + _statusline(EDIT_A_PREV_QUERY); + } + if ((ch = LYgetstr(prev_target, VISIBLE, + sizeof(prev_target_buffer), + recall)) < 0) { + /* + * User cancelled the search via ^G. - FM + */ + HTInfoMsg(CANCELLED); + goto restore_popup_statusline; + } + goto check_recall; + } + } + /* + * Replace the search string buffer with the new target. - FM + */ + strcpy(prev_target_buffer, prev_target); + HTAddSearchQuery(prev_target_buffer); + + /* + * Start search at the next choice. - FM + */ + for (j = 1; Cptr[i+j] != NULL; j++) { + FormatChoiceNum(buffer, max_choices, (i + j), Cptr[i+j]); + if (case_sensitive) { + if (strstr(buffer, prev_target_buffer) != NULL) + break; + } else { + if (LYstrstr(buffer, prev_target_buffer) != NULL) + break; + } + } + if (Cptr[i+j] != NULL) { + /* + * We have a hit, so make that choice the current. - FM + */ + cur_choice += j; + /* + * Scroll the window down if necessary. + */ + if ((cur_choice - window_offset) >= length) { + window_offset += j; + if (window_offset > (num_choices - length + 1)) + window_offset = (num_choices - length + 1); + ReDraw = TRUE; + } + goto restore_popup_statusline; + } + + /* + * If we started at the beginning, it can't be present. - FM + */ + if (cur_choice == 0) { + HTUserMsg2(STRING_NOT_FOUND, prev_target_buffer); + goto restore_popup_statusline; + } + + /* + * Search from the beginning to the current choice. - FM + */ + for (j = 0; j < cur_choice; j++) { + FormatChoiceNum(buffer, max_choices, (j + 1), Cptr[j]); + if (case_sensitive) { + if (strstr(buffer, prev_target_buffer) != NULL) + break; + } else { + if (LYstrstr(buffer, prev_target_buffer) != NULL) + break; + } + } + if (j < cur_choice) { + /* + * We have a hit, so make that choice the current. - FM + */ + j = (cur_choice - j); + cur_choice -= j; + /* + * Scroll the window up if necessary. + */ + if ((cur_choice - window_offset) < 0) { + window_offset -= j; + if (window_offset < 0) + window_offset = 0; + ReDraw = TRUE; + } + goto restore_popup_statusline; + } + + /* + * Didn't find it in the preceding choices either. - FM + */ + HTUserMsg2(STRING_NOT_FOUND, prev_target_buffer); + +restore_popup_statusline: + /* + * Restore the popup statusline and + * reset the search variables. - FM + */ + _statusline(popup_status_msg); + *prev_target = '\0'; + QueryTotal = (search_queries ? HTList_count(search_queries) + : 0); + recall = ((QueryTotal >= 1) ? RECALL : NORECALL); + QueryNum = QueryTotal; + if (ReDraw == TRUE) { + ReDraw = FALSE; + goto redraw; + } + break; + case LYK_QUIT: case LYK_ABORT: case LYK_PREV_DOC: - cur_selection = -1; + cur_choice = orig_choice; cmd = LYK_ACTIVATE; /* to exit */ break; - } } - LYstopPopup(); } - if (cur_selection >= 0) - reinsertEdit(edit, data[cur_selection]); + LYstopPopup(); -#ifdef USE_SLANG - SLsmg_gotorc(old_y, old_x); -#else - wmove(stdscr, old_y, old_x); -#endif + return(disabled ? orig_choice : cur_choice); } #define CurModif MyEdit.current_modifiers @@ -3649,7 +4509,40 @@ again: HTList *list = whichRecall(recall); if (!HTList_isEmpty(list)) { char **data = sortedList(list, recall == RECALL_CMD); - completeFromPopup(&MyEdit, data); + int old_y, old_x; + int cur_choice = 0; + int num_options = LYarrayLength((CONST char **)data); + + while (cur_choice < num_options + && strcasecomp(data[cur_choice], MyEdit.buffer) < 0) + cur_choice++; +#ifdef USE_SLANG + old_y = SLsmg_get_row(); + old_x = SLsmg_get_column(); +#else + getyx(stdscr, old_y, old_x); +#endif + + cur_choice = LYhandlePopupList( + cur_choice, + 0, + old_x, + (CONST char **)data, + -1, + -1, + FALSE, + FALSE, + TRUE); + if (cur_choice >= 0) { + if (recall == RECALL_CMD) + _statusline(": "); + reinsertEdit(&MyEdit, data[cur_choice]); + } +#ifdef USE_SLANG + SLsmg_gotorc(old_y, old_x); +#else + wmove(stdscr, old_y, old_x); +#endif FREE(data); } } else { diff --git a/src/LYStrings.h b/src/LYStrings.h index 1d2f9131..5df1d16d 100644 --- a/src/LYStrings.h +++ b/src/LYStrings.h @@ -24,6 +24,12 @@ extern char * LYstrncpy PARAMS(( CONST char * src, int n)); extern void ena_csi PARAMS((BOOLEAN flag)); +extern int get_popup_number PARAMS(( + char * msg, + int * c, + int * rel)); +extern int LYarrayLength PARAMS((CONST char ** list)); +extern int LYarrayWidth PARAMS((CONST char ** list)); extern int LYgetch NOPARAMS; extern int LYgetch_choice NOPARAMS; extern int LYgetch_input NOPARAMS; @@ -305,6 +311,16 @@ extern int LYEdit1 PARAMS(( BOOL maxMessage)); extern void LYOpenCloset NOPARAMS; extern void LYCloseCloset NOPARAMS; +extern int LYhandlePopupList PARAMS(( + int cur_choice, + int ly, + int lx, + CONST char ** choices, + int width, + int i_length, + int disabled, + BOOLEAN for_mouse, + BOOLEAN numbered)); extern int current_lineedit; extern char * LYLineeditNames[]; @@ -313,15 +329,6 @@ extern CONST char * LYLineeditHelpURLs[]; extern CONST char * LYLineeditHelpURL NOPARAMS; -#if 0 /* NOT USED, use function instead - kw */ -/* Push a character through the lineedit machinery */ -#ifdef NOT_ASCII /* S/390 -- gil -- 2080 */ -#define EditBinding(c) (LYLineEditors[current_lineedit][(c)<256 ? TOASCII(c) : c]) -#else /* NOT_ASCII */ -#define EditBinding(c) (LYLineEditors[current_lineedit][c]) -#endif /* NOT_ASCII */ -#endif /* 0 */ - #define LYLineEdit(e,c,m) LYEdit1(e,c,EditBinding(c)&~LYE_DF,m) /* Dummy initializer for LYEditmap.c */ diff --git a/src/LYUtils.c b/src/LYUtils.c index 896ff407..6334f935 100644 --- a/src/LYUtils.c +++ b/src/LYUtils.c @@ -2066,7 +2066,12 @@ PUBLIC void statusline ARGS1( if (text != NULL && text[0] != '\0') { #ifdef HAVE_UTF8_STATUSLINES - if (LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8) { + if ((LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8) || + (HTCJK != NOCJK)) { + refresh(); + } +#else + if (HTCJK != NOCJK) { refresh(); } #endif /* HAVE_UTF8_STATUSLINES */ @@ -4913,6 +4918,11 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( char *Fragment = NULL; BOOLEAN GotHost = FALSE; BOOLEAN Startup = (BOOL) (helpfilepath == NULL); +#ifdef INET6 + struct addrinfo hints, *res; + int error; +#endif /* INET6 */ + #ifdef _WINDOWS int hoststat; struct hostent *phost; /* Pointer to host - See netdb.h */ @@ -4989,7 +4999,16 @@ PUBLIC BOOLEAN LYExpandHostForURL ARGS3( fprintf(stdout, "%s '%s'%s\n", WWW_FIND_MESSAGE, host, FIRST_SEGMENT); } +#ifdef INET6 + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(host, "80", &hints, &res); + + if (!error && res) +#else if (LYGetHostByName(host) != NULL) +#endif /* INET6 */ { /* * Clear any residual interrupt. - FM |