📄 echo-area.c
字号:
then transpose the characters before point. */DECLARE_INFO_COMMAND (ea_transpose_chars, _("Transpose characters at point")){ /* Handle conditions that would make it impossible to transpose characters. */ if (!count || !input_line_point || (input_line_end - input_line_beg) < 2) return; while (count) { int t; if (input_line_point == input_line_end) { t = input_line[input_line_point - 1]; input_line[input_line_point - 1] = input_line[input_line_point - 2]; input_line[input_line_point - 2] = t; } else { t = input_line[input_line_point]; input_line[input_line_point] = input_line[input_line_point - 1]; input_line[input_line_point - 1] = t; if (count < 0 && input_line_point != input_line_beg) input_line_point--; else input_line_point++; } if (count < 0) count++; else count--; }}/* **************************************************************** *//* *//* Echo Area Killing and Yanking *//* *//* **************************************************************** */static char **kill_ring = (char **)NULL;static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */static int kill_ring_loc = 0; /* Location of current yank pointer. *//* The largest number of kills that we remember at one time. */static int max_retained_kills = 15;DECLARE_INFO_COMMAND (ea_yank, _("Yank back the contents of the last kill")){ register int i; register char *text; if (!kill_ring_index) { inform_in_echo_area (_("Kill ring is empty")); return; } text = kill_ring[kill_ring_loc]; for (i = 0; text[i]; i++) ea_insert (window, 1, text[i]);}/* If the last command was yank, or yank_pop, and the text just before point is identical to the current kill item, then delete that text from the line, rotate the index down, and yank back some other text. */DECLARE_INFO_COMMAND (ea_yank_pop, _("Yank back a previous kill")){ register int len; if (((ea_last_executed_command != ea_yank) && (ea_last_executed_command != ea_yank_pop)) || (kill_ring_index == 0)) return; len = strlen (kill_ring[kill_ring_loc]); /* Delete the last yanked item from the line. */ { register int i, counter; counter = input_line_end - input_line_point; for (i = input_line_point - len; counter; i++, counter--) input_line[i] = input_line[i + len]; input_line_end -= len; input_line_point -= len; } /* Get a previous kill, and yank that. */ kill_ring_loc--; if (kill_ring_loc < 0) kill_ring_loc = kill_ring_index - 1; ea_yank (window, count, key);}/* Delete the text from point to end of line. */DECLARE_INFO_COMMAND (ea_kill_line, _("Kill to the end of the line")){ if (count < 0) { ea_kill_text (input_line_point, input_line_beg); input_line_point = input_line_beg; } else ea_kill_text (input_line_point, input_line_end);}/* Delete the text from point to beg of line. */DECLARE_INFO_COMMAND (ea_backward_kill_line, _("Kill to the beginning of the line")){ if (count < 0) ea_kill_text (input_line_point, input_line_end); else { ea_kill_text (input_line_point, input_line_beg); input_line_point = input_line_beg; }}/* Delete from point to the end of the current word. */DECLARE_INFO_COMMAND (ea_kill_word, _("Kill the word following the cursor")){ int orig_point = input_line_point; if (count < 0) ea_backward_kill_word (window, -count, key); else { ea_forward_word (window, count, key); if (input_line_point != orig_point) ea_kill_text (orig_point, input_line_point); input_line_point = orig_point; }}/* Delete from point to the start of the current word. */DECLARE_INFO_COMMAND (ea_backward_kill_word, _("Kill the word preceding the cursor")){ int orig_point = input_line_point; if (count < 0) ea_kill_word (window, -count, key); else { ea_backward_word (window, count, key); if (input_line_point != orig_point) ea_kill_text (orig_point, input_line_point); }}/* The way to kill something. This appends or prepends to the last kill, if the last command was a kill command. If FROM is less than TO, then the killed text is appended to the most recent kill, otherwise it is prepended. If the last command was not a kill command, then a new slot is made for this kill. */static voidea_kill_text (from, to) int from, to;{ register int i, counter, distance; int killing_backwards, slot; char *killed_text; killing_backwards = (from > to); /* If killing backwards, reverse the values of FROM and TO. */ if (killing_backwards) { int temp = from; from = to; to = temp; } /* Remember the text that we are about to delete. */ distance = to - from; killed_text = (char *)xmalloc (1 + distance); strncpy (killed_text, &input_line[from], distance); killed_text[distance] = '\0'; /* Actually delete the text from the line. */ counter = input_line_end - to; for (i = from; counter; i++, counter--) input_line[i] = input_line[i + distance]; input_line_end -= distance; /* If the last command was a kill, append or prepend the killed text to the last command's killed text. */ if (echo_area_last_command_was_kill) { char *old, *new; slot = kill_ring_loc; old = kill_ring[slot]; new = (char *)xmalloc (1 + strlen (old) + strlen (killed_text)); if (killing_backwards) { /* Prepend TEXT to current kill. */ strcpy (new, killed_text); strcat (new, old); } else { /* Append TEXT to current kill. */ strcpy (new, old); strcat (new, killed_text); } free (old); free (killed_text); kill_ring[slot] = new; } else { /* Try to store the kill in a new slot, unless that would cause there to be too many remembered kills. */ slot = kill_ring_index; if (slot == max_retained_kills) slot = 0; if (slot + 1 > kill_ring_slots) kill_ring = (char **) xrealloc (kill_ring, (kill_ring_slots += max_retained_kills) * sizeof (char *)); if (slot != kill_ring_index) free (kill_ring[slot]); else kill_ring_index++; kill_ring[slot] = killed_text; kill_ring_loc = slot; } /* Notice that the last command was a kill. */ echo_area_last_command_was_kill++;}/* **************************************************************** *//* *//* Echo Area Completion *//* *//* **************************************************************** *//* Pointer to an array of REFERENCE to complete over. */static REFERENCE **echo_area_completion_items = (REFERENCE **)NULL;/* Sorted array of REFERENCE * which is the possible completions found in the variable echo_area_completion_items. If there is only one element, it is the only possible completion. */static REFERENCE **completions_found = (REFERENCE **)NULL;static int completions_found_index = 0;static int completions_found_slots = 0;/* The lowest common denominator found while completing. */static REFERENCE *LCD_completion;/* Internal functions used by the user calls. */static void build_completions (), completions_must_be_rebuilt ();/* Variable which holds the output of completions. */static NODE *possible_completions_output_node = (NODE *)NULL;static char *compwin_name = "*Completions*";/* Return non-zero if WINDOW is a window used for completions output. */static intcompletions_window_p (window) WINDOW *window;{ int result = 0; if (internal_info_node_p (window->node) && (strcmp (window->node->nodename, compwin_name) == 0)) result = 1; return (result);}/* Workhorse for completion readers. If FORCE is non-zero, the user cannot exit unless the line read completes, or is empty. */char *info_read_completing_internal (window, prompt, completions, force) WINDOW *window; char *prompt; REFERENCE **completions; int force;{ char *line; /* If the echo area is already active, remember the current state. */ if (echo_area_is_active) push_echo_area (); echo_area_must_complete_p = force; /* Initialize our local variables. */ initialize_input_line (prompt); /* Initialize the echo area for the first (but maybe not the last) time. */ echo_area_initialize_node (); /* Save away the original node of this window, and the window itself, so echo area commands can temporarily use this window. */ remember_calling_window (window); /* Save away the list of items to complete over. */ echo_area_completion_items = completions; completions_must_be_rebuilt (); active_window = the_echo_area; echo_area_is_active++; /* Read characters in the echo area. */ while (1) { info_read_and_dispatch (); line = echo_area_after_read (); /* Force the completion to take place if the user hasn't accepted a default or aborted, and if FORCE is active. */ if (force && line && *line && completions) { register int i; build_completions (); /* If there is only one completion, then make the line be that completion. */ if (completions_found_index == 1) { free (line); line = xstrdup (completions_found[0]->label); break; } /* If one of the completions matches exactly, then that is okay, so return the current line. */ for (i = 0; i < completions_found_index; i++) if (strcasecmp (completions_found[i]->label, line) == 0) { free (line); line = xstrdup (completions_found[i]->label); break; } /* If no match, go back and try again. */ if (i == completions_found_index) { inform_in_echo_area (_("Not complete")); continue; } } break; } echo_area_is_active--; /* Restore the original active window and show point in it. */ active_window = calling_window; restore_calling_window (); display_cursor_at_point (active_window); fflush (stdout); echo_area_completion_items = (REFERENCE **)NULL; completions_must_be_rebuilt (); /* If there is a previous loop waiting for us, restore it now. */ if (echo_area_is_active) pop_echo_area (); return (line);} /* Read a line in the echo area with completion over COMPLETIONS. */char *info_read_completing_in_echo_area (window, prompt, completions) WINDOW *window; char *prompt; REFERENCE **completions;{ return (info_read_completing_internal (window, prompt, completions, 1));}/* Read a line in the echo area allowing completion over COMPLETIONS, but not requiring it. */char *info_read_maybe_completing (window, prompt, completions) WINDOW *window; char *prompt; REFERENCE **completions;{ return (info_read_completing_internal (window, prompt, completions, 0));}DECLARE_INFO_COMMAND (ea_possible_completions, _("List possible completions")){ if (!echo_area_completion_items) { ea_insert (window, count, key); return; } build_completions (); if (!completions_found_index) { terminal_ring_bell (); inform_in_echo_area (_("No completions")); } else if ((completions_found_index == 1) && (key != '?')) { inform_in_echo_area (_("Sole completion")); } else { register int i, l; int limit, count, max_label = 0; initialize_message_buffer (); printf_to_message_buffer (completions_found_index == 1 ? _("One completion:\n") : _("%d completions:\n")); /* Find the maximum length of a label. */ for (i = 0; i < completions_found_index; i++) { int len = strlen (completions_found[i]->label); if (len > max_label) max_label = len; } max_label += 4; /* Find out how many columns we should print in. */ limit = calling_window->width / max_label; if (limit != 1 && (limit * max_label == calling_window->width)) limit--; /* Avoid a possible floating exception. If max_label > width then the limit will be 0 and a divide-by-zero fault will result. */ if (limit == 0) limit = 1; /* How many iterations of the printing loop? */ count = (completions_found_index + (limit - 1)) / limit; /* Watch out for special case. If the number of completions is less than LIMIT, then just do the inner printing loop. */ if (completions_found_index < limit) count = 1; /* Print the sorted items, up-and-down alphabetically. */ for (i = 0; i < count; i++) { register int j; for (j = 0, l = i; j < limit; j++) { if (l >= completions_found_index) break; else { char *label; int printed_length, k; label = completions_found[l]->label; printed_length = strlen (label); printf_to_message_buffer ("%s", label); if (j + 1 < limit) { for (k = 0; k < max_label - printed_length; k++) printf_to_message_buffer (" "); } } l += count; } printf_to_message_buffer ("\n"); } /* Make a new node to hold onto possible completions. Don't destroy dangling pointers. */ {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -