#ifndef EL__TERMINAL_TERMINAL_H #define EL__TERMINAL_TERMINAL_H #include "config/options.h" #include "terminal/event.h" #include "util/lists.h" #ifdef __cplusplus extern "C" { #endif struct module; struct option; struct terminal_screen; struct terminal_interlink; /** The terminal type, meaningful for frames (lines) drawing. */ enum term_mode_type { TERM_DUMB = 0, TERM_VT100, TERM_LINUX, TERM_KOI8, TERM_FREEBSD, TERM_FBTERM, }; /** This is a bitmask describing the environment we are living in, * terminal-wise. We can then conditionally use various features available * in such an environment. */ enum term_env_type { /** This basically means that we can use the text i/o :). Always set. */ ENV_CONSOLE = 1, /** We are running in a xterm-compatible box in some windowing * environment. */ ENV_XWIN = 2, /** We are running under a screen. */ ENV_SCREEN = 4, /** We are running in a OS/2 VIO terminal. */ ENV_OS2VIO = 8, /** BeOS text terminal. */ ENV_BE = 16, /** We live in a TWIN text-mode windowing environment. */ ENV_TWIN = 32, /** Microsoft Windows cmdline thing. */ ENV_WIN32 = 64, /** Match all terminal environments */ ENV_ANY = ~0, }; typedef int term_env_type_T; enum term_redrawing_state { TREDRAW_READY = 0, /**< Can redraw */ TREDRAW_BUSY = 1, /**< Redrawing already in progress */ TREDRAW_DELAYED = 2, /**< Do not redraw for now */ }; /** This is one of the axis of ELinks' user interaction. struct terminal * defines the terminal ELinks is running on --- each ELinks instance has * one. It contains the basic terminal attributes, the settings associated * with this terminal, screen content (and more abstract description of what * is currently displayed on it) etc. It also maintains some runtime * information about the actual ELinks instance owning this terminal. * * @todo TODO: Regroup the following into logical chunks. --pasky */ struct terminal { LIST_HEAD(struct terminal); /*!< ::terminals is the sentinel. */ #ifdef CONFIG_SCRIPTING_SPIDERMONKEY struct JSObject *jsobject; /* Instance of terminal_class */ struct JSObject *session_array_jsobject; /* Instance of session_array_class */ #endif /** This is (at least partially) a stack of all the windows living in * this terminal. A window can be wide range of stuff, from a menu box * through classical dialog window to a tab. See terminal/window.h for * more on windows. * * Tabs are special windows, though, and you never want to display them * all, but only one of them. ALWAYS check inactive_tab() during * iterations through this list (unless it is really useless or you * are sure what are you doing) to make sure that you don't distribute * events etc to inactive tabs. * * The stack is top-down, thus @c .next is the stack's top, the * current window; and @c .prev is the bottom, covered by others. * - Dialogs or active menus are at the top. * - Next come all tabs (window.type == ::WINDOW_TAB). The tab * listed leftmost in the tab bar is at the top, and the tab * listed rightmost is at the bottom; but #current_tab controls * which tab is actually displayed. * - If the main menu is inactive, then it is at the very bottom, * hidden under the tabs. * Call assert_window_stacking() to verify this. * * @todo FIXME: Tabs violate the stack nature of this list, they * appear there randomly but always in the order in which they were * inserted there. Eventually, they should all live at the stack * bottom, with the actual tab living on the VERY bottom. --pasky * * Keeping the current tab at the very bottom would require storing * tab numbers explicitly, rather than computing them from the * stack order as is done now. Also, what should be done with the * inactive main menu? --KON */ LIST_OF(struct window) windows; /** The specification of terminal in terms of terminal options. */ struct option *spec; /** This is the terminal's current title, as perhaps displayed * somewhere in the X window frame or so. */ char *title; /** This is the screen. See terminal/screen.h */ struct terminal_screen *screen; /** This is for displaying main menu */ struct menu *main_menu; /** These are pipes for communication with the ELinks instance owning * this terminal. * @see struct itrm */ int fdin, fdout; /** This indicates that the terminal is blocked, that is nothing should * be drawn on it etc. Typically an external program is running on it * right now. This is a file descriptor. */ int blocked; /** Terminal dimensions. */ int width, height; /** Indicates whether we are currently in the process of redrawing the * stuff being displayed on the terminal. It is typically used to * prevent redrawing inside of redrawing. */ enum term_redrawing_state redrawing; /** Indicates the master terminal, that is the terminal under * supervision of the master ELinks instance (the one doing all the * work and even maintaining these structures ;-). */ unsigned int master:1; #ifdef CONFIG_UTF8 /** Indicates whether the charset of the terminal is UTF-8. */ unsigned int utf8_cp:1; /** Indicates whether UTF-8 I/O is used. Forced on if the * UTF-8 charset is selected. (bug 827) */ unsigned int utf8_io:1; #endif /* CONFIG_UTF8 */ /** The current tab number. */ int current_tab; #ifdef CONFIG_LEDS /** Current length of leds part of status bar. */ int leds_length; #endif /** The type of environment this terminal lives in. */ term_env_type_T environment; /** The current working directory for this terminal / ELinks instance. */ char cwd[MAX_CWD_LEN]; /** For communication between instances */ struct terminal_interlink *interlink; /* Data for textarea_edit(). */ void *textarea_data; struct term_event_mouse prev_mouse_event; }; #define do_not_ignore_next_mouse_event(term) \ memset(&(term)->prev_mouse_event, 0, sizeof((term)->prev_mouse_event)) /** We keep track about all the terminals in this list. * The list is sorted so that terminals.next is the terminal * from which ELinks most recently got an event. But please * call get_default_terminal() for that. */ extern LIST_OF(struct terminal) terminals; extern const unsigned char frame_dumb[]; struct terminal *init_term(int, int); void destroy_terminal(struct terminal *); void redraw_terminal(struct terminal *term); void redraw_terminal_cls(struct terminal *term); void cls_redraw_all_terminals(void); struct terminal *get_default_terminal(void); int get_terminal_codepage(const struct terminal *); void redraw_all_terminals(void); void destroy_all_terminals(void); void exec_thread(char *, int); void close_handle(void *); #ifdef CONFIG_FASTMEM #define assert_terminal_ptr_not_dangling(suspect) ((void) 0) #else /* assert() does something */ void assert_terminal_ptr_not_dangling(const struct terminal *); #endif /** Operations that can be requested with do_terminal_function() in * the master and then executed with dispatch_special() in a slave. * The interlink protocol passes these values as one byte in a * null-terminated string, so zero cannot be used. */ enum { TERM_FN_TITLE = 1, TERM_FN_RESIZE = 2, TERM_FN_TITLE_CODEPAGE = 3 }; /** How to execute a program in a terminal. These values are used in * the interlink protocol and must fit in one byte. */ enum term_exec { /** Execute in the background. ELinks keeps using the terminal * and the program should not use it. */ TERM_EXEC_BG = 0, /** Execute in the foreground. The program may use the terminal. * ELinks will redraw when the program exits. */ TERM_EXEC_FG = 1, /** Execute in the background and in a new process group. */ TERM_EXEC_NEWWIN = 2 }; typedef int term_exec_T; void exec_on_terminal(struct terminal *, char *, char *, term_exec_T); void exec_shell(struct terminal *term); int set_terminal_title(struct terminal *, char *); void do_terminal_function(struct terminal *, unsigned char, char *); int check_terminal_pipes(void); void close_terminal_pipes(void); struct terminal *attach_terminal(int in, int out, int ctl, void *info, int len); extern struct module terminal_module; #ifdef __cplusplus } #endif #endif /* EL__TERMINAL_TERMINAL_H */