📄 echo-area.c
字号:
/* echo-area.c -- How to read a line in the echo area. $Id: echo-area.c,v 1.1.1.2 1998/03/24 18:20:08 law Exp $ Copyright (C) 1993, 97, 98 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Written by Brian Fox (bfox@ai.mit.edu). */#include "info.h"#if defined (FD_SET)# if defined (hpux)# define fd_set_cast(x) (int *)(x)# else# define fd_set_cast(x) (fd_set *)(x)# endif /* !hpux */#endif /* FD_SET *//* Non-zero means that C-g was used to quit reading input. */int info_aborted_echo_area = 0;/* Non-zero means that the echo area is being used to read input. */int echo_area_is_active = 0;/* The address of the last command executed in the echo area. */VFunction *ea_last_executed_command = (VFunction *)NULL;/* Non-zero means that the last command executed while reading input killed some text. */int echo_area_last_command_was_kill = 0;/* Variables which hold on to the current state of the input line. */static char input_line[1 + EA_MAX_INPUT];static char *input_line_prompt;static int input_line_point;static int input_line_beg;static int input_line_end;static NODE input_line_node = { (char *)NULL, (char *)NULL, (char *)NULL, input_line, EA_MAX_INPUT, 0};static void echo_area_initialize_node ();static void push_echo_area (), pop_echo_area ();static int echo_area_stack_contains_completions_p ();static void ea_kill_text ();/* Non-zero means we force the user to complete. */static int echo_area_must_complete_p = 0;static int completions_window_p ();/* If non-null, this is a window which was specifically created to display possible completions output. We remember it so we can delete it when appropriate. */static WINDOW *echo_area_completions_window = (WINDOW *)NULL;/* Variables which keep track of the window which was active prior to entering the echo area. */static WINDOW *calling_window = (WINDOW *)NULL;static NODE *calling_window_node = (NODE *)NULL;static long calling_window_point = 0;static long calling_window_pagetop = 0;/* Remember the node and pertinent variables of the calling window. */static voidremember_calling_window (window) WINDOW *window;{ /* Only do this if the calling window is not the completions window, or, if it is the completions window and there is no other window. */ if (!completions_window_p (window) || ((window == windows) && !(window->next))) { calling_window = window; calling_window_node = window->node; calling_window_point = window->point; calling_window_pagetop = window->pagetop; }}/* Restore the caller's window so that it shows the node that it was showing on entry to info_read_xxx_echo_area (). */static voidrestore_calling_window (){ register WINDOW *win, *compwin = (WINDOW *)NULL; /* If the calling window is still visible, and it is the window that we used for completions output, then restore the calling window. */ for (win = windows; win; win = win->next) { if (completions_window_p (win)) compwin = win; if (win == calling_window && win == compwin) { window_set_node_of_window (calling_window, calling_window_node); calling_window->point = calling_window_point; calling_window->pagetop = calling_window_pagetop; compwin = (WINDOW *)NULL; break; } } /* Delete the completions window if it is still present, it isn't the last window on the screen, and there aren't any prior echo area reads pending which created a completions window. */ if (compwin) { if ((compwin != windows || windows->next) && !echo_area_stack_contains_completions_p ()) { WINDOW *next; int pagetop, start, end, amount; next = compwin->next; if (next) { start = next->first_row; end = start + next->height; amount = - (compwin->height + 1); pagetop = next->pagetop; } info_delete_window_internal (compwin); /* This is not necessary because info_delete_window_internal () calls echo_area_inform_of_deleted_window (), which does the right thing. */#if defined (UNNECESSARY) echo_area_completions_window = (WINDOW *)NULL;#endif /* UNNECESSARY */ if (next) { display_scroll_display (start, end, amount); next->pagetop = pagetop; display_update_display (windows); } } }}/* Set up a new input line with PROMPT. */static voidinitialize_input_line (prompt) char *prompt;{ input_line_prompt = prompt; if (prompt) strcpy (input_line, prompt); else input_line[0] = '\0'; input_line_beg = input_line_end = input_line_point = strlen (prompt);}static char *echo_area_after_read (){ char *return_value; if (info_aborted_echo_area) { info_aborted_echo_area = 0; return_value = (char *)NULL; } else { if (input_line_beg == input_line_end) return_value = xstrdup (""); else { int line_len = input_line_end - input_line_beg; return_value = (char *) xmalloc (1 + line_len); strncpy (return_value, &input_line[input_line_beg], line_len); return_value[line_len] = '\0'; } } return (return_value);}/* Read a line of text in the echo area. Return a malloc ()'ed string, or NULL if the user aborted out of this read. WINDOW is the currently active window, so that we can restore it when we need to. PROMPT, if non-null, is a prompt to print before reading the line. */char *info_read_in_echo_area (window, prompt) WINDOW *window; char *prompt;{ char *line; /* If the echo area is already active, remember the current state. */ if (echo_area_is_active) push_echo_area (); /* 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); /* Let the rest of Info know that the echo area is active. */ echo_area_is_active++; active_window = the_echo_area; /* Read characters in the echo area. */ info_read_and_dispatch (); 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); /* Get the value of the line. */ line = echo_area_after_read (); /* If there is a previous loop waiting for us, restore it now. */ if (echo_area_is_active) pop_echo_area (); /* Return the results to the caller. */ return (line);}/* (re) Initialize the echo area node. */static voidecho_area_initialize_node (){ register int i; for (i = input_line_end; i < sizeof (input_line); i++) input_line[i] = ' '; input_line[i - 1] = '\n'; window_set_node_of_window (the_echo_area, &input_line_node); input_line[input_line_end] = '\n';}/* Prepare to read characters in the echo area. This can initialize the echo area node, but its primary purpose is to side effect the input line buffer contents. */voidecho_area_prep_read (){ if (the_echo_area->node != &input_line_node) echo_area_initialize_node (); the_echo_area->point = input_line_point; input_line[input_line_end] = '\n'; display_update_one_window (the_echo_area); display_cursor_at_point (active_window);}/* **************************************************************** *//* *//* Echo Area Movement Commands *//* *//* **************************************************************** */DECLARE_INFO_COMMAND (ea_forward, _("Move forward a character")){ if (count < 0) ea_backward (window, -count, key); else { input_line_point += count; if (input_line_point > input_line_end) input_line_point = input_line_end; }}DECLARE_INFO_COMMAND (ea_backward, _("Move backward a character")){ if (count < 0) ea_forward (window, -count, key); else { input_line_point -= count; if (input_line_point < input_line_beg) input_line_point = input_line_beg; }}DECLARE_INFO_COMMAND (ea_beg_of_line, _("Move to the start of this line")){ input_line_point = input_line_beg;}DECLARE_INFO_COMMAND (ea_end_of_line, _("Move to the end of this line")){ input_line_point = input_line_end;}#define alphabetic(c) (islower (c) || isupper (c) || isdigit (c))/* Move forward a word in the input line. */DECLARE_INFO_COMMAND (ea_forward_word, _("Move forward a word")){ int c; if (count < 0) ea_backward_word (window, -count, key); else { while (count--) { if (input_line_point == input_line_end) return; /* If we are not in a word, move forward until we are in one. Then, move forward until we hit a non-alphabetic character. */ c = input_line[input_line_point]; if (!alphabetic (c)) { while (++input_line_point < input_line_end) { c = input_line[input_line_point]; if (alphabetic (c)) break; } } if (input_line_point == input_line_end) return; while (++input_line_point < input_line_end) { c = input_line[input_line_point]; if (!alphabetic (c)) break; } } }}DECLARE_INFO_COMMAND (ea_backward_word, _("Move backward a word")){ int c; if (count < 0) ea_forward_word (window, -count, key); else { while (count--) { if (input_line_point == input_line_beg) return; /* Like ea_forward_word (), except that we look at the characters just before point. */ c = input_line[input_line_point - 1]; if (!alphabetic (c)) { while ((--input_line_point) != input_line_beg) { c = input_line[input_line_point - 1]; if (alphabetic (c)) break; } } while (input_line_point != input_line_beg) { c = input_line[input_line_point - 1]; if (!alphabetic (c)) break; else --input_line_point; } } }}DECLARE_INFO_COMMAND (ea_delete, _("Delete the character under the cursor")){ register int i; if (count < 0) ea_rubout (window, -count, key); else { if (input_line_point == input_line_end) return; if (info_explicit_arg || count > 1) { int orig_point; orig_point = input_line_point; ea_forward (window, count, key); ea_kill_text (orig_point, input_line_point); input_line_point = orig_point; } else { for (i = input_line_point; i < input_line_end; i++) input_line[i] = input_line[i + 1]; input_line_end--; } }}DECLARE_INFO_COMMAND (ea_rubout, _("Delete the character behind the cursor")){ if (count < 0) ea_delete (window, -count, key); else { int start; if (input_line_point == input_line_beg) return; start = input_line_point; ea_backward (window, count, key); if (info_explicit_arg || count > 1) ea_kill_text (start, input_line_point); else ea_delete (window, count, key); }}DECLARE_INFO_COMMAND (ea_abort, _("Cancel or quit operation")){ /* If any text, just discard it, and restore the calling window's node. If no text, quit. */ if (input_line_end != input_line_beg) { terminal_ring_bell (); input_line_end = input_line_point = input_line_beg; if (calling_window->node != calling_window_node) restore_calling_window (); } else info_aborted_echo_area = 1;}DECLARE_INFO_COMMAND (ea_newline, _("Accept (or force completion of) this line")){ /* Stub does nothing. Simply here to see if it has been executed. */}DECLARE_INFO_COMMAND (ea_quoted_insert, _("Insert next character verbatim")){ unsigned char character; character = info_get_another_input_char (); ea_insert (window, count, character);}DECLARE_INFO_COMMAND (ea_insert, _("Insert this character")){ register int i; if ((input_line_end + 1) == EA_MAX_INPUT) { terminal_ring_bell (); return; } for (i = input_line_end + 1; i != input_line_point; i--) input_line[i] = input_line[i - 1]; input_line[input_line_point] = key; input_line_point++; input_line_end++;}DECLARE_INFO_COMMAND (ea_tab_insert, _("Insert a TAB character")){ ea_insert (window, count, '\t');}/* Transpose the characters at point. If point is at the end of the line,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -