📄 session.c
字号:
/* session.c -- The user windowing interface to Info. $Id: session.c,v 1.1.1.3 1998/03/24 18:20:15 law Exp $ Copyright (C) 1993, 96, 97 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"#include <sys/ioctl.h>#if defined (HAVE_SYS_TIME_H)# include <sys/time.h># define HAVE_STRUCT_TIMEVAL#endif /* HAVE_SYS_TIME_H */#if defined (HANDLE_MAN_PAGES)# include "man.h"#endifstatic void info_clear_pending_input (), info_set_pending_input ();static void info_handle_pointer ();/* **************************************************************** *//* *//* Running an Info Session *//* *//* **************************************************************** *//* The place that we are reading input from. */static FILE *info_input_stream = NULL;/* The last executed command. */VFunction *info_last_executed_command = NULL;/* Becomes non-zero when 'q' is typed to an Info window. */int quit_info_immediately = 0;/* Array of structures describing for each window which nodes have been visited in that window. */INFO_WINDOW **info_windows = NULL;/* Where to add the next window, if we need to add one. */static int info_windows_index = 0;/* Number of slots allocated to `info_windows'. */static int info_windows_slots = 0;void remember_window_and_node (), forget_window_and_nodes ();void initialize_info_session (), info_session ();void display_startup_message_and_start ();/* Begin an info session finding the nodes specified by FILENAME and NODENAMES. For each loaded node, create a new window. Always split the largest of the available windows. */voidbegin_multiple_window_info_session (filename, nodenames) char *filename; char **nodenames;{ register int i; WINDOW *window = (WINDOW *)NULL; for (i = 0; nodenames[i]; i++) { NODE *node; node = info_get_node (filename, nodenames[i]); if (!node) break; /* If this is the first node, initialize the info session. */ if (!window) { initialize_info_session (node, 1); window = active_window; } else { /* Find the largest window in WINDOWS, and make that be the active one. Then split it and add our window and node to the list of remembered windows and nodes. Then tile the windows. */ register WINDOW *win, *largest = (WINDOW *)NULL; int max_height = 0; for (win = windows; win; win = win->next) if (win->height > max_height) { max_height = win->height; largest = win; } if (!largest) { display_update_display (windows); info_error (CANT_FIND_WIND); info_session (); exit (0); } active_window = largest; window = window_make_window (node); if (window) { window_tile_windows (TILE_INTERNALS); remember_window_and_node (window, node); } else { display_update_display (windows); info_error (WIN_TOO_SMALL); info_session (); exit (0); } } } display_startup_message_and_start ();}/* Start an info session with INITIAL_NODE, and an error message in the echo area made from FORMAT and ARG. */voidbegin_info_session_with_error (initial_node, format, arg) NODE *initial_node; char *format; void *arg;{ initialize_info_session (initial_node, 1); info_error (format, arg, (void *)NULL); info_session ();}/* Start an info session with INITIAL_NODE. */voidbegin_info_session (initial_node) NODE *initial_node;{ initialize_info_session (initial_node, 1); display_startup_message_and_start ();}voiddisplay_startup_message_and_start (){ char *format; format = replace_in_documentation (_("Welcome to Info version %s. \"\\[get-help-window]\" for help, \"\\[menu-item]\" for menu item.")); window_message_in_echo_area (format, version_string ()); info_session ();}/* Run an info session with an already initialized window and node. */voidinfo_session (){ display_update_display (windows); info_last_executed_command = NULL; info_read_and_dispatch (); /* On program exit, leave the cursor at the bottom of the window, and restore the terminal I/O. */ terminal_goto_xy (0, screenheight - 1); terminal_clear_to_eol (); fflush (stdout); terminal_unprep_terminal (); close_dribble_file ();}/* Here is a window-location dependent event loop. Called from the functions info_session (), and from read_xxx_in_echo_area (). */voidinfo_read_and_dispatch (){ unsigned char key; int done; done = 0; while (!done && !quit_info_immediately) { int lk; /* If we haven't just gone up or down a line, there is no goal column for this window. */ if ((info_last_executed_command != info_next_line) && (info_last_executed_command != info_prev_line)) active_window->goal_column = -1; if (echo_area_is_active) { lk = echo_area_last_command_was_kill; echo_area_prep_read (); } if (!info_any_buffered_input_p ()) display_update_display (windows); display_cursor_at_point (active_window); info_initialize_numeric_arg (); initialize_keyseq (); key = info_get_input_char (); /* No errors yet. We just read a character, that's all. Only clear the echo_area if it is not currently active. */ if (!echo_area_is_active) window_clear_echo_area (); info_error_was_printed = 0; /* Do the selected command. */ info_dispatch_on_key (key, active_window->keymap); if (echo_area_is_active) { /* Echo area commands that do killing increment the value of ECHO_AREA_LAST_COMMAND_WAS_KILL. Thus, if there is no change in the value of this variable, the last command executed was not a kill command. */ if (lk == echo_area_last_command_was_kill) echo_area_last_command_was_kill = 0; if (ea_last_executed_command == ea_newline || info_aborted_echo_area) { ea_last_executed_command = (VFunction *)NULL; done = 1; } if (info_last_executed_command == info_quit) quit_info_immediately = 1; } else if (info_last_executed_command == info_quit) done = 1; }}/* Found in signals.c */extern void initialize_info_signal_handler ();/* Initialize the first info session by starting the terminal, window, and display systems. If CLEAR_SCREEN is 0, don't clear the screen. */voidinitialize_info_session (node, clear_screen) NODE *node; int clear_screen;{ char *term_name = getenv ("TERM"); terminal_initialize_terminal (term_name); if (terminal_is_dumb_p) { if (!term_name) term_name = "dumb"; info_error (TERM_TOO_DUMB, term_name); exit (1); } if (clear_screen) { terminal_prep_terminal (); terminal_clear_screen (); } initialize_info_keymaps (); window_initialize_windows (screenwidth, screenheight); initialize_info_signal_handler (); display_initialize_display (screenwidth, screenheight); info_set_node_of_window (active_window, node); /* Tell the window system how to notify us when a window needs to be asynchronously deleted (e.g., user resizes window very small). */ window_deletion_notifier = forget_window_and_nodes; /* If input has not been redirected yet, make it come from unbuffered standard input. */ if (!info_input_stream) { setbuf(stdin, NULL); info_input_stream = stdin; } info_windows_initialized_p = 1;}/* Tell Info that input is coming from the file FILENAME. */voidinfo_set_input_from_file (filename) char *filename;{ FILE *stream; stream = fopen (filename, "r"); if (!stream) return; if ((info_input_stream != (FILE *)NULL) && (info_input_stream != stdin)) fclose (info_input_stream); info_input_stream = stream; if (stream != stdin) display_inhibited = 1;}/* Return the INFO_WINDOW containing WINDOW, or NULL if there isn't one. */static INFO_WINDOW *get_info_window_of_window (window) WINDOW *window;{ register int i; INFO_WINDOW *info_win = (INFO_WINDOW *)NULL; for (i = 0; info_windows && (info_win = info_windows[i]); i++) if (info_win->window == window) break; return (info_win);}/* Reset the remembered pagetop and point of WINDOW to WINDOW's current values if the window and node are the same as the current one being displayed. */voidset_remembered_pagetop_and_point (window) WINDOW *window;{ INFO_WINDOW *info_win; info_win = get_info_window_of_window (window); if (!info_win) return; if (info_win->nodes_index && (info_win->nodes[info_win->current] == window->node)) { info_win->pagetops[info_win->current] = window->pagetop; info_win->points[info_win->current] = window->point; }}voidremember_window_and_node (window, node) WINDOW *window; NODE *node;{ /* See if we already have this window in our list. */ INFO_WINDOW *info_win = get_info_window_of_window (window); /* If the window wasn't already on our list, then make a new entry. */ if (!info_win) { info_win = (INFO_WINDOW *)xmalloc (sizeof (INFO_WINDOW)); info_win->window = window; info_win->nodes = (NODE **)NULL; info_win->pagetops = (int *)NULL; info_win->points = (long *)NULL; info_win->current = 0; info_win->nodes_index = 0; info_win->nodes_slots = 0; add_pointer_to_array (info_win, info_windows_index, info_windows, info_windows_slots, 10, INFO_WINDOW *); } /* If this node, the current pagetop, and the current point are the same as the current saved node and pagetop, don't really add this to the list of history nodes. This may happen only at the very beginning of the program, I'm not sure. --karl */ if (info_win->nodes && info_win->current >= 0 && info_win->nodes[info_win->current]->contents == node->contents && info_win->pagetops[info_win->current] == window->pagetop && info_win->points[info_win->current] == window->point) return; /* Remember this node, the currently displayed pagetop, and the current location of point in this window. Because we are updating pagetops and points as well as nodes, it is more efficient to avoid the add_pointer_to_array macro here. */ if (info_win->nodes_index + 2 >= info_win->nodes_slots) { info_win->nodes_slots += 20; info_win->nodes = (NODE **) xrealloc (info_win->nodes, info_win->nodes_slots * sizeof (NODE *)); info_win->pagetops = (int *) xrealloc (info_win->pagetops, info_win->nodes_slots * sizeof (int)); info_win->points = (long *) xrealloc (info_win->points, info_win->nodes_slots * sizeof (long)); } info_win->nodes[info_win->nodes_index] = node; info_win->pagetops[info_win->nodes_index] = window->pagetop; info_win->points[info_win->nodes_index] = window->point; info_win->current = info_win->nodes_index++; info_win->nodes[info_win->nodes_index] = NULL; info_win->pagetops[info_win->nodes_index] = 0; info_win->points[info_win->nodes_index] = 0;}#define DEBUG_FORGET_WINDOW_AND_NODES#if defined (DEBUG_FORGET_WINDOW_AND_NODES)static voidconsistency_check_info_windows (){ register int i; for (i = 0; i < info_windows_index; i++) { WINDOW *win; for (win = windows; win; win = win->next) if (win == info_windows[i]->window) break; if (!win) abort (); }}#endif /* DEBUG_FORGET_WINDOW_AND_NODES *//* Remove WINDOW and its associated list of nodes from INFO_WINDOWS. */voidforget_window_and_nodes (window) WINDOW *window;{ register int i; INFO_WINDOW *info_win = (INFO_WINDOW *)NULL; for (i = 0; info_windows && (info_win = info_windows[i]); i++) if (info_win->window == window) break; /* If we found the window to forget, then do so. */ if (info_win) { while (i < info_windows_index) { info_windows[i] = info_windows[i + 1]; i++; } info_windows_index--; info_windows[info_windows_index] = (INFO_WINDOW *)NULL; if (info_win->nodes) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -