📄 echo-area.c
字号:
NODE *temp; temp = message_buffer_to_node (); add_gcable_pointer (temp->contents); name_internal_node (temp, compwin_name); possible_completions_output_node = temp; } /* Find a suitable window for displaying the completions output. First choice is an existing window showing completions output. If there is only one window, and it is large, make another (smaller) window, and use that one. Otherwise, use the caller's window. */ { WINDOW *compwin; compwin = get_internal_info_window (compwin_name); if (!compwin) { /* If we can split the window to display most of the completion items, then do so. */ if (calling_window->height > (count * 2) && calling_window->height / 2 >= WINDOW_MIN_SIZE) { int start, pagetop;#ifdef SPLIT_BEFORE_ACTIVE int end;#endif active_window = calling_window; /* Perhaps we can scroll this window on redisplay. */ start = calling_window->first_row; pagetop = calling_window->pagetop; compwin = window_make_window (possible_completions_output_node); active_window = the_echo_area; window_change_window_height (compwin, -(compwin->height - (count + 2))); window_adjust_pagetop (calling_window); remember_calling_window (calling_window);#if defined (SPLIT_BEFORE_ACTIVE) /* If the pagetop hasn't changed, scrolling the calling window is a reasonable thing to do. */ if (pagetop == calling_window->pagetop) { end = start + calling_window->height; display_scroll_display (start, end, calling_window->prev->height + 1); }#else /* !SPLIT_BEFORE_ACTIVE */ /* If the pagetop has changed, set the new pagetop here. */ if (pagetop != calling_window->pagetop) { int newtop = calling_window->pagetop; calling_window->pagetop = pagetop; set_window_pagetop (calling_window, newtop); }#endif /* !SPLIT_BEFORE_ACTIVE */ echo_area_completions_window = compwin; remember_window_and_node (compwin, compwin->node); } else compwin = calling_window; } if (compwin->node != possible_completions_output_node) { window_set_node_of_window (compwin, possible_completions_output_node); remember_window_and_node (compwin, compwin->node); } display_update_display (windows); } }}DECLARE_INFO_COMMAND (ea_complete, _("Insert completion")){ if (!echo_area_completion_items) { ea_insert (window, count, key); return; } /* If KEY is SPC, and we are not forcing completion to take place, simply insert the key. */ if (!echo_area_must_complete_p && key == SPC) { ea_insert (window, count, key); return; } if (ea_last_executed_command == ea_complete) { /* If the keypress is a SPC character, and we have already tried completing once, and there are several completions, then check the batch of completions to see if any continue with a space. If there are some, insert the space character and continue. */ if (key == SPC && completions_found_index > 1) { register int i, offset; offset = input_line_end - input_line_beg; for (i = 0; i < completions_found_index; i++) if (completions_found[i]->label[offset] == ' ') break; if (completions_found[i]) ea_insert (window, 1, ' '); else { ea_possible_completions (window, count, key); return; } } else { ea_possible_completions (window, count, key); return; } } input_line_point = input_line_end; build_completions (); if (!completions_found_index) terminal_ring_bell (); else if (LCD_completion->label[0] == '\0') ea_possible_completions (window, count, key); else { register int i; input_line_point = input_line_end = input_line_beg; for (i = 0; LCD_completion->label[i]; i++) ea_insert (window, 1, LCD_completion->label[i]); }}/* Utility REFERENCE used to store possible LCD. */static REFERENCE LCD_reference = { (char *)NULL, (char *)NULL, (char *)NULL };static void remove_completion_duplicates ();/* Variables which remember the state of the most recent call to build_completions (). */static char *last_completion_request = (char *)NULL;static REFERENCE **last_completion_items = (REFERENCE **)NULL;/* How to tell the completion builder to reset internal state. */static voidcompletions_must_be_rebuilt (){ maybe_free (last_completion_request); last_completion_request = (char *)NULL; last_completion_items = (REFERENCE **)NULL;}/* Build a list of possible completions from echo_area_completion_items, and the contents of input_line. */static voidbuild_completions (){ register int i, len; register REFERENCE *entry; char *request; int informed_of_lengthy_job = 0; /* If there are no items to complete over, exit immediately. */ if (!echo_area_completion_items) { completions_found_index = 0; LCD_completion = (REFERENCE *)NULL; return; } /* Check to see if this call to build completions is the same as the last call to build completions. */ len = input_line_end - input_line_beg; request = (char *)xmalloc (1 + len); strncpy (request, &input_line[input_line_beg], len); request[len] = '\0'; if (last_completion_request && last_completion_items && last_completion_items == echo_area_completion_items && (strcmp (last_completion_request, request) == 0)) { free (request); return; } maybe_free (last_completion_request); last_completion_request = request; last_completion_items = echo_area_completion_items; /* Always start at the beginning of the list. */ completions_found_index = 0; LCD_completion = (REFERENCE *)NULL; for (i = 0; (entry = echo_area_completion_items[i]); i++) { if (strncasecmp (request, entry->label, len) == 0) add_pointer_to_array (entry, completions_found_index, completions_found, completions_found_slots, 20, REFERENCE *); if (!informed_of_lengthy_job && completions_found_index > 100) { informed_of_lengthy_job = 1; window_message_in_echo_area (_("Building completions...")); } } if (!completions_found_index) return; /* Sort and prune duplicate entries from the completions array. */ remove_completion_duplicates (); /* If there is only one completion, just return that. */ if (completions_found_index == 1) { LCD_completion = completions_found[0]; return; } /* Find the least common denominator. */ { long shortest = 100000; for (i = 1; i < completions_found_index; i++) { register int j; int c1, c2; for (j = 0; (c1 = info_tolower (completions_found[i - 1]->label[j])) && (c2 = info_tolower (completions_found[i]->label[j])); j++) if (c1 != c2) break; if (shortest > j) shortest = j; } maybe_free (LCD_reference.label); LCD_reference.label = (char *)xmalloc (1 + shortest); strncpy (LCD_reference.label, completions_found[0]->label, shortest); LCD_reference.label[shortest] = '\0'; LCD_completion = &LCD_reference; } if (informed_of_lengthy_job) echo_area_initialize_node ();}/* Function called by qsort. */static intcompare_references (entry1, entry2) REFERENCE **entry1, **entry2;{ return (strcasecmp ((*entry1)->label, (*entry2)->label));}/* Prune duplicate entries from COMPLETIONS_FOUND. */static voidremove_completion_duplicates (){ register int i, j; REFERENCE **temp; int newlen; if (!completions_found_index) return; /* Sort the items. */ qsort (completions_found, completions_found_index, sizeof (REFERENCE *), compare_references); for (i = 0, newlen = 1; i < completions_found_index - 1; i++) { if (strcmp (completions_found[i]->label, completions_found[i + 1]->label) == 0) completions_found[i] = (REFERENCE *)NULL; else newlen++; } /* We have marked all the dead slots. It is faster to copy the live slots twice than to prune the dead slots one by one. */ temp = (REFERENCE **)xmalloc ((1 + newlen) * sizeof (REFERENCE *)); for (i = 0, j = 0; i < completions_found_index; i++) if (completions_found[i]) temp[j++] = completions_found[i]; for (i = 0; i < newlen; i++) completions_found[i] = temp[i]; completions_found[i] = (REFERENCE *)NULL; completions_found_index = newlen; free (temp);}/* Scroll the "other" window. If there is a window showing completions, scroll that one, otherwise scroll the window which was active on entering the read function. */DECLARE_INFO_COMMAND (ea_scroll_completions_window, _("Scroll the completions window")){ WINDOW *compwin; int old_pagetop; compwin = get_internal_info_window (compwin_name); if (!compwin) compwin = calling_window; old_pagetop = compwin->pagetop; /* Let info_scroll_forward () do the work, and print any messages that need to be displayed. */ info_scroll_forward (compwin, count, key);}/* Function which gets called when an Info window is deleted while the echo area is active. WINDOW is the window which has just been deleted. */voidecho_area_inform_of_deleted_window (window) WINDOW *window;{ /* If this is the calling_window, forget what we remembered about it. */ if (window == calling_window) { if (active_window != the_echo_area) remember_calling_window (active_window); else remember_calling_window (windows); } /* If this window was the echo_area_completions_window, then notice that the window has been deleted. */ if (window == echo_area_completions_window) echo_area_completions_window = (WINDOW *)NULL;}/* **************************************************************** *//* *//* Pushing and Popping the Echo Area *//* *//* **************************************************************** *//* Push and Pop the echo area. */typedef struct { char *line; char *prompt; REFERENCE **comp_items; int point, beg, end; int must_complete; NODE node; WINDOW *compwin;} PUSHED_EA;static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL;static int pushed_echo_areas_index = 0;static int pushed_echo_areas_slots = 0;/* Pushing the echo_area has a side effect of zeroing the completion_items. */static voidpush_echo_area (){ PUSHED_EA *pushed; pushed = (PUSHED_EA *)xmalloc (sizeof (PUSHED_EA)); pushed->line = xstrdup (input_line); pushed->prompt = input_line_prompt; pushed->point = input_line_point; pushed->beg = input_line_beg; pushed->end = input_line_end; pushed->node = input_line_node; pushed->comp_items = echo_area_completion_items; pushed->must_complete = echo_area_must_complete_p; pushed->compwin = echo_area_completions_window; add_pointer_to_array (pushed, pushed_echo_areas_index, pushed_echo_areas, pushed_echo_areas_slots, 4, PUSHED_EA *); echo_area_completion_items = (REFERENCE **)NULL;}static voidpop_echo_area (){ PUSHED_EA *popped; popped = pushed_echo_areas[--pushed_echo_areas_index]; strcpy (input_line, popped->line); free (popped->line); input_line_prompt = popped->prompt; input_line_point = popped->point; input_line_beg = popped->beg; input_line_end = popped->end; input_line_node = popped->node; echo_area_completion_items = popped->comp_items; echo_area_must_complete_p = popped->must_complete; echo_area_completions_window = popped->compwin; completions_must_be_rebuilt (); /* If the completion window no longer exists, forget about it. */ if (echo_area_completions_window) { register WINDOW *win; for (win = windows; win; win = win->next) if (echo_area_completions_window == win) break; /* If the window wasn't found, then it has already been deleted. */ if (!win) echo_area_completions_window = (WINDOW *)NULL; } free (popped);}/* Returns non-zero if any of the prior stacked calls to read in the echo area produced a completions window. */static intecho_area_stack_contains_completions_p (){ register int i; for (i = 0; i < pushed_echo_areas_index; i++) if (pushed_echo_areas[i]->compwin) return (1); return (0);}/* **************************************************************** *//* *//* Error Messages While Reading in Echo Area *//* *//* **************************************************************** */#if defined (HAVE_SYS_TIME_H)# include <sys/time.h># define HAVE_STRUCT_TIMEVAL#endif /* HAVE_SYS_TIME_H */static voidpause_or_input (){#if defined (FD_SET) struct timeval timer; fd_set readfds; int ready; FD_ZERO (&readfds); FD_SET (fileno (stdin), &readfds); timer.tv_sec = 2; timer.tv_usec = 750; ready = select (fileno (stdin) + 1, &readfds, (fd_set *) NULL, (fd_set *) NULL, &timer);#endif /* FD_SET */}/* Print MESSAGE right after the end of the current line, and wait for input or 2.75 seconds, whichever comes first. Then flush the informational message that was printed. */voidinform_in_echo_area (message) char *message;{ register int i; char *text; text = xstrdup (message); for (i = 0; text[i] && text[i] != '\n'; i++); text[i] = '\0'; echo_area_initialize_node (); sprintf (&input_line[input_line_end], "%s[%s]\n", echo_area_is_active ? " ": "", text); free (text); the_echo_area->point = input_line_point; display_update_one_window (the_echo_area); display_cursor_at_point (active_window); fflush (stdout); pause_or_input (); echo_area_initialize_node ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -