From 28d440abfe46139dff7278a444e0a35896038ff8 Mon Sep 17 00:00:00 2001 From: Karoly Lorentey Date: Thu, 25 Dec 2003 06:59:31 +0000 Subject: [PATCH] Implemented multiple tty support. README.multi-tty: New file. src/termchar.h (struct terminal): Renamed to struct tty_output. Added name, type, input, output, termscript, old_tty, term_initted, old_tty_valid, background_pixel, foreground_pixel, next fields. (TERMINAL_*): Renamed to TTY_* for brevity. (CURRENT_TERMINAL): Renamed to CURTTY for brevity. (tty_list): New variable. (TERMINAL_PTR): Removed. (FRAME_TTY): New function. (TTY_NAME, TTY_TYPE): New macros. src/term.c (current_terminal): Removed. (_current_terminal): Removed. (tty_list): New variable. (OUTPUT, OUTPUT1, OUTPUTL, OUTPUT_IF, OUTPUT1_IF): Added tty parameter. (set_terminal_modes): Added tty parameter. (reset_terminal_modes): Added tty parameter. (cursor_to, raw_cursor_to): Updated cmgoto() calls. (clear_end_of_line, write_glyphs): Add indirection to terminal output, updated cmcheckmagic() calls. (get_named_tty): New function. (term_dummy_init): New function. (term_init): Added name parameter, added tty_output return value. Changed algorithm to update tty_list. Call init_sys_modes() to set up tty mode on the newly opened terminal device. (get_current_tty): New function, intended for debugging. src/termhooks.h (termscript): Removed. src/w32term.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): Removed redundant definition. src/macterm.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): Ditto. src/window.c (init_window_once): Call make_terminal_frame with two zero parameters. src/cm.h (emacs_tputs): New macro to set current_tty, and then call tputs(). (current_tty): New variable, for cmputc(). (cmcheckmagic, cmputc, cmgoto): Added prototypes. src/cm.c (current_tty): New variable, for cmputc(). (cmputc): Use it. (cmcheckmagic): Added tty parameter, look up terminal streams there. (calccost): Added tty parameter. Use emacs_tputs() instead of tputs(). (cmgoto): Added tty parameter. Pass it on to calccost(). Use emacs_tputs() instead of tputs(). src/dispextern.h (set_terminal_modes, reset_terminal_modes): Added tty parameter. (term_init): Added name parameter (the filename of the terminal device). Added return value (struct tty_output). src/dispnew.c: Replace CURTTY() with local variables throughout the file (where applicable). (termscript): Moved to struct tty_output. (terminal_type): Removed. src/emacs.c (main): Don't call init_sys_modes(), the new term_init() already does that during init_display(). (shut_down_emacs): Call reset_all_sys_modes() instead of reset_sys_modes(). src/frame.c (Qtty, Qtty_type): New variables. (syms_of_frame): Initialize them. (tty_display): Removed. (make_terminal_frame): New parameters (tty filename and type). Initialize output_data.tty field instead of output_data.x. Use term_init() to find the right tty_output. (Use term_dummy_init() during bootstrap.) (Fmake_terminal_frame): Get device filename and type from frame parameters. src/frame.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): Do the right thing if the frame is a tty. (struct frame): New member in output_data: tty. (make_terminal_frame): Updated of prototype. src/keyboard.c (Fset_input_mode): Call reset_all_sys_modes(), not reset_sys_modes(). Ditto with init_sys_modes(). src/lisp.h (tty_output): Added forward declaration. (init_sys_modes, reset_sys_modes): Updated prototype. (init_all_sys_modes, reset_all_sys_modes): New prototypes. src/scroll.c: Replace CURTTY() with local variables throughout the file (where applicable). src/sysdep.c (old_tty, term_initted, old_tty_valid): Moved to struct tty_output.( (init_all_sys_modes): New function. (init_sys_modes): Added tty_output parameter. Use it. (reset_all_sys_modes): New function. (reset_sys_modes): Added tty_output parameter. Use it. src/Makefile.in: Update dependencies. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-2 --- README.multi-tty | 129 +++++++++++++++++ src/Makefile.in | 23 ++-- src/cm.c | 71 ++++++---- src/cm.h | 9 +- src/dispextern.h | 7 +- src/dispnew.c | 69 +++++----- src/emacs.c | 6 +- src/frame.c | 78 +++++++++-- src/frame.h | 17 ++- src/indent.c | 1 + src/keyboard.c | 12 +- src/lisp.h | 10 +- src/macterm.c | 10 +- src/macterm.h | 3 - src/msdos.c | 2 +- src/print.c | 1 + src/scroll.c | 9 +- src/sysdep.c | 72 ++++++---- src/term.c | 352 ++++++++++++++++++++++++++++++----------------- src/termchar.h | 69 ++++++++-- src/termhooks.h | 3 - src/w32term.c | 10 +- src/w32term.h | 2 - src/window.c | 3 +- src/xdisp.c | 7 +- src/xfaces.c | 2 + src/xfns.c | 2 + 27 files changed, 677 insertions(+), 302 deletions(-) create mode 100644 README.multi-tty diff --git a/README.multi-tty b/README.multi-tty new file mode 100644 index 0000000000..482a3a01b5 --- /dev/null +++ b/README.multi-tty @@ -0,0 +1,129 @@ + -*- coding: utf-8; -*- +GOAL +---- + +The ultimate goal of this branch is to implement support for opening +multiple, different tty devices and simultaneous X and tty frames from +a single Emacs session. + +WHO IS DOING IT +--------------- + +I'm Károly Lőrentey. My address: lorentey@elte.hu. + +Patches or suggestions are welcome! + + +STATUS +------ + +We can create frames on new tty devices, but there are problems with +refresh (only the (single) selected frame is refreshed), and input is +read only from the initial terminal. At the moment, the type of the +new terminals must be the same as the initial terminal. + +To try it out, start up emacs, and evaluate the following: + + (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm"))) + +(With your own values, of course.) If you switch to the new frame +with M-x other-frame, the new tty is refreshed with the frame +contents. The result of input from the original terminal appears on +the new. If you exit emacs, both terminals are restored to their +previous states. + +X, Mac, Windows and DOS support is broken. + +NEWS +---- + +For the NEWS file: + +** Support for multiple terminal devices has been added. You can + specify a terminal device (`tty' parameter) and a terminal type + (`tty-type' parameter) to `make-terminal-frame'. + + +CHANGELOG +--------- + +See arch logs. + + +THINGS THAT ARE DONE +-------------------- + +-- Introduce a new abstraction for terminal devices. + + (Done, see struct tty_output. The abstraction is not yet + complete.) + + +-- Change the bootstrap procedure to initialize tty_list. + + (Done, but needs review.) + + +-- Change make-terminal-frame to support specifying another tty. + + (Done, new frame parameters: `tty' and `tty-type'.) + + +THINGS TO DO +------------ + +** Make make-terminal-frame look up the tty and tty-type parameters + from the currently selected terminal before the global default. + +** Move optimalization parameters (costs) from union output_data to + struct frame. + +** Implement terminal deletion, i.e., closing the tty device and + restoring its previous state without exiting Emacs. This should be + exported to the Lisp interpreter. + +** Implement automatic deletion of terminals, when the last frame on + that terminal is closed. + +** Put all cached terminal escape sequences into struct tty_output. + Currently, they are still stored in global variables, so we don't + really support multiple terminal types. + +** Support different terminal sizes. (Should be solved by the + previous entry.) + +** Make sure terminal resizes are handled gracefully. (Could be + problematic.) + +** Implement support for reading from multiple terminals. + +** other-frame should cycle through the frames on the `current' + terminal. This means that Emacs must know from which terminal the + last keyboard event came from. (Multikeyboard support may help + with this.) + +** Redisplay must refresh the topmost on all terminals, not just + the initial terminal. + +** Make struct tty_output available from Lisp. + +** Extend emacsclient to automatically open a new tty when it connects + to Emacs. + +** Implement support for starting an interactive Emacs session without + an initial frame. (The user would connect to it and open frames + later, with emacsclient.) Not necessary a good idea. + +** Fix X support. + +** Allow simultaneous X and tty frames. + +** Fix Mac support (I can't do this myself). + +** Fix W32 support (I can't do this myself). + +** Fix DOS support (I can't do this myself). + + + +;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d diff --git a/src/Makefile.in b/src/Makefile.in index 07b3c82865..c3b7541e7d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1047,7 +1047,7 @@ ccl.o: ccl.c ccl.h charset.h coding.h $(config_h) charset.o: charset.c charset.h buffer.h coding.h composite.h disptab.h \ $(config_h) coding.o: coding.c coding.h ccl.h buffer.h charset.h intervals.h composite.h window.h $(config_h) -cm.o: cm.c cm.h termhooks.h $(config_h) +cm.o: cm.c frame.h cm.h termhooks.h systty.h termchar.h $(config_h) cmds.o: cmds.c syntax.h buffer.h charset.h commands.h window.h $(config_h) \ msdos.h dispextern.h pre-crt0.o: pre-crt0.c @@ -1055,7 +1055,7 @@ ecrt0.o: ecrt0.c $(config_h) CRT0_COMPILE ${srcdir}/ecrt0.c dired.o: dired.c commands.h buffer.h $(config_h) charset.h coding.h regex.h \ systime.h -dispnew.o: dispnew.c systty.h systime.h commands.h process.h frame.h \ +dispnew.o: dispnew.c systty.h systime.h commands.h process.h frame.h \ window.h buffer.h dispextern.h termchar.h termopts.h termhooks.h cm.h \ disptab.h \ xterm.h blockinput.h atimer.h charset.h msdos.h composite.h keyboard.h \ @@ -1073,12 +1073,12 @@ fileio.o: fileio.c window.h buffer.h systime.h $(INTERVAL_SRC) charset.h \ filelock.o: filelock.c buffer.h systime.h epaths.h $(config_h) filemode.o: filemode.c $(config_h) frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \ - blockinput.h atimer.h systime.h buffer.h charset.h fontset.h \ + blockinput.h systty.h atimer.h systime.h buffer.h charset.h fontset.h \ msdos.h dosfns.h dispextern.h $(config_h) fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h charset.h frame.h \ keyboard.h $(config_h) getloadavg.o: getloadavg.c $(config_h) -indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \ +indent.o: indent.c frame.h window.h systty.h indent.h buffer.h $(config_h) termchar.h \ termopts.h disptab.h region-cache.h charset.h composite.h dispextern.h \ keyboard.h insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h charset.h \ @@ -1110,7 +1110,7 @@ process.o: process.c process.h buffer.h window.h termhooks.h termopts.h \ keyboard.h $(config_h) regex.o: regex.c syntax.h buffer.h $(config_h) regex.h category.h charset.h region-cache.o: region-cache.c buffer.h region-cache.h -scroll.o: scroll.c termchar.h dispextern.h frame.h msdos.h keyboard.h \ +scroll.o: scroll.c systty.h termchar.h dispextern.h frame.h msdos.h keyboard.h \ $(config_h) search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \ blockinput.h atimer.h systime.h category.h charset.h composite.h $(config_h) @@ -1120,7 +1120,7 @@ syntax.o: syntax.c syntax.h buffer.h commands.h category.h charset.h \ sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \ process.h dispextern.h termhooks.h termchar.h termopts.h \ frame.h atimer.h window.h msdos.h dosfns.h keyboard.h $(config_h) -term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \ +term.o: term.c systty.h termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \ disptab.h dispextern.h keyboard.h charset.h coding.h ccl.h msdos.h termcap.o: termcap.c $(config_h) terminfo.o: terminfo.c $(config_h) @@ -1134,17 +1134,18 @@ w16select.o: w16select.c dispextern.h frame.h blockinput.h atimer.h systime.h \ msdos.h $(config_h) widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \ $(srcdir)/../lwlib/lwlib.h $(config_h) -window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \ +window.o: window.c indent.h commands.h frame.h window.h buffer.h systty.h termchar.h \ termhooks.h disptab.h keyboard.h dispextern.h msdos.h composite.h \ $(config_h) xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h coding.h \ - termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \ + systty.h termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \ msdos.h composite.h fontset.h blockinput.h atimer.h systime.h keymap.h xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \ - window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h $(config_h) + window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h \ + systty.h termchar.h $(config_h) xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \ $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \ - charset.h gtkutil.h $(config_h) + charset.h gtkutil.h systty.h termchar.h $(config_h) xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h buffer.h \ keyboard.h $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h \ gtkutil.h msdos.h coding.h $(config_h) @@ -1176,7 +1177,7 @@ floatfns.o: floatfns.c $(config_h) fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \ frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h print.o: print.c process.h frame.h window.h buffer.h keyboard.h charset.h \ - $(config_h) dispextern.h msdos.h composite.h + $(config_h) dispextern.h msdos.h composite.h systty.h termchar.h intervals.h lread.o: lread.c commands.h keyboard.h buffer.h epaths.h charset.h $(config_h) \ termhooks.h coding.h msdos.h diff --git a/src/cm.c b/src/cm.c index dcff504846..508729eead 100644 --- a/src/cm.c +++ b/src/cm.c @@ -22,8 +22,16 @@ Boston, MA 02111-1307, USA. */ #include #include + +/* For CURTTY */ +#include "lisp.h" +#include "frame.h" + #include "cm.h" #include "termhooks.h" +#include "systty.h" /* For emacs_tty in termchar.h */ +#include "termchar.h" + /* For now, don't try to include termcap.h. On some systems, configure finds a non-standard termcap.h that the main build @@ -41,6 +49,7 @@ extern char *tgoto P_ ((const char *, int, int)); extern char *BC, *UP; + int cost; /* sums up costs */ /* ARGSUSED */ @@ -52,13 +61,16 @@ evalcost (c) return c; } +/* The terminal to use for low-level output. */ +struct tty_output * current_tty; + int cmputc (c) char c; { - if (termscript) - fputc (c & 0177, termscript); - putchar (c & 0177); + if (TTY_TERMSCRIPT (current_tty)) + putc (c & 0177, TTY_TERMSCRIPT (current_tty)); + putc (c & 0177, TTY_OUTPUT (current_tty)); return c; } @@ -122,18 +134,19 @@ addcol (n) { * after we reach the last column; this takes us to a known state. */ void -cmcheckmagic () +cmcheckmagic (tty) + struct tty_output *tty; { if (curX == FrameCols) { if (!MagicWrap || curY >= FrameRows - 1) abort (); - if (termscript) - putc ('\r', termscript); - putchar ('\r'); - if (termscript) - putc ('\n', termscript); - putchar ('\n'); + if (TTY_TERMSCRIPT (tty)) + putc ('\r', TTY_TERMSCRIPT (tty)); + putc ('\r', TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) + putc ('\n', TTY_TERMSCRIPT (tty)); + putc ('\n', TTY_OUTPUT (tty)); curX = 0; curY++; } @@ -187,8 +200,7 @@ cmcostinit () */ static int -calccost (srcy, srcx, dsty, dstx, doit) - int srcy, srcx, dsty, dstx, doit; +calccost (struct tty_output *tty, int srcy, int srcx, int dsty, int dstx, int doit) { register int deltay, deltax, @@ -223,7 +235,7 @@ calccost (srcy, srcx, dsty, dstx, doit) totalcost = c * deltay; if (doit) while (--deltay >= 0) - tputs (p, 1, cmputc); + emacs_tputs (tty, p, 1, cmputc); x: if ((deltax = dstx - srcx) == 0) goto done; @@ -278,7 +290,7 @@ x: totalcost += tabcost; /* use the tabs */ if (doit) while (--ntabs >= 0) - tputs (Wcm.cm_tab, 1, cmputc); + emacs_tputs (tty, Wcm.cm_tab, 1, cmputc); srcx = tabx; } @@ -305,7 +317,7 @@ fail: totalcost += c * deltax; if (doit) while (--deltax >= 0) - tputs (p, 1, cmputc); + emacs_tputs (tty, p, 1, cmputc); done: return totalcost; } @@ -323,7 +335,8 @@ losecursor () #define USECR 3 void -cmgoto (row, col) +cmgoto (tty, row, col) + struct tty_output *tty; int row, col; { int homecost, @@ -346,24 +359,24 @@ cmgoto (row, col) * start where we are. Examine the options, and pick the cheapest. */ - relcost = calccost (curY, curX, row, col, 0); + relcost = calccost (tty, curY, curX, row, col, 0); use = USEREL; if ((homecost = Wcm.cc_home) < BIG) - homecost += calccost (0, 0, row, col, 0); + homecost += calccost (tty, 0, 0, row, col, 0); if (homecost < relcost) - relcost = homecost, use = USEHOME; + relcost = homecost, use = USEHOME; if ((llcost = Wcm.cc_ll) < BIG) - llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0); + llcost += calccost (tty, Wcm.cm_rows - 1, 0, row, col, 0); if (llcost < relcost) - relcost = llcost, use = USELL; + relcost = llcost, use = USELL; if ((crcost = Wcm.cc_cr) < BIG) { if (Wcm.cm_autolf) if (curY + 1 >= Wcm.cm_rows) crcost = BIG; else - crcost += calccost (curY + 1, 0, row, col, 0); + crcost += calccost (tty, curY + 1, 0, row, col, 0); else - crcost += calccost (curY, 0, row, col, 0); + crcost += calccost (tty, curY, 0, row, col, 0); } if (crcost < relcost) relcost = crcost, use = USECR; @@ -389,10 +402,10 @@ cmgoto (row, col) cost = 0; p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) : tgoto (dcm, col, row); - tputs (p, 1, evalcost); + emacs_tputs (tty, p, 1, evalcost); if (cost <= relcost) { /* really is cheaper */ - tputs (p, 1, cmputc); + emacs_tputs (tty, p, 1, cmputc); curY = row, curX = col; return; } @@ -401,24 +414,24 @@ cmgoto (row, col) switch (use) { case USEHOME: - tputs (Wcm.cm_home, 1, cmputc); + emacs_tputs (tty, Wcm.cm_home, 1, cmputc); curY = 0, curX = 0; break; case USELL: - tputs (Wcm.cm_ll, 1, cmputc); + emacs_tputs (tty, Wcm.cm_ll, 1, cmputc); curY = Wcm.cm_rows - 1, curX = 0; break; case USECR: - tputs (Wcm.cm_cr, 1, cmputc); + emacs_tputs (tty, Wcm.cm_cr, 1, cmputc); if (Wcm.cm_autolf) curY++; curX = 0; break; } - (void) calccost (curY, curX, row, col, 1); + (void) calccost (tty, curY, curX, row, col, 1); curY = row, curX = col; } diff --git a/src/cm.h b/src/cm.h index 5500c5ce58..18d82c3748 100644 --- a/src/cm.h +++ b/src/cm.h @@ -162,10 +162,13 @@ extern char PC; /* Pad character */ extern int cost; extern int evalcost (); -extern void cmcheckmagic (); -extern int cmputc (); +#define emacs_tputs(tty, str, affcnt, putc) (current_tty = (tty), tputs (str, affcnt, putc)) + +extern struct tty_output *current_tty; +extern void cmcheckmagic P_ ((struct tty_output *)); +extern int cmputc P_ ((int)); extern void cmcostinit (); -extern void cmgoto (); +extern void cmgoto P_ ((struct tty_output *, int, int)); extern void Wcm_clear (); extern int Wcm_init (); diff --git a/src/dispextern.h b/src/dispextern.h index f306a939db..2538460dee 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2724,8 +2724,8 @@ extern Lisp_Object Qredisplay_dont_pause; /* Defined in term.c */ extern void ring_bell P_ ((void)); -extern void set_terminal_modes P_ ((void)); -extern void reset_terminal_modes P_ ((void)); +extern void set_terminal_modes P_ ((struct tty_output *)); +extern void reset_terminal_modes P_ ((struct tty_output *)); extern void update_begin P_ ((struct frame *)); extern void update_end P_ ((struct frame *)); extern void set_terminal_window P_ ((int)); @@ -2743,7 +2743,8 @@ extern int per_line_cost P_ ((char *)); extern void calculate_costs P_ ((struct frame *)); extern void set_tty_color_mode P_ ((struct frame *, Lisp_Object)); extern void tty_setup_colors P_ ((int)); -extern void term_init P_ ((char *)); +extern struct tty_output *term_init P_ ((char *, char *)); +extern struct tty_output *term_dummy_init P_ ((void)); extern void fatal P_ ((/* char *, ... */)); void cursor_to P_ ((int, int)); extern int tty_capable_p P_ ((struct frame *, unsigned, unsigned long, unsigned long)); diff --git a/src/dispnew.c b/src/dispnew.c index 9eb69ebf79..cf335cfeed 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */ #endif #include "lisp.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "termopts.h" #include "termhooks.h" @@ -258,10 +259,6 @@ Lisp_Object selected_frame; struct frame *last_nonminibuf_frame; -/* Stdio stream being used for copy of all output. */ - -FILE *termscript; - /* Structure for info on cursor positioning. */ struct cm Wcm; @@ -1397,7 +1394,7 @@ line_hash_code (row) { int c = glyph->u.ch; int face_id = glyph->face_id; - if (TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ())) + if (TTY_MUST_WRITE_SPACES (CURTTY ())) c -= SPACEGLYPH; hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c; hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id; @@ -1429,7 +1426,7 @@ line_draw_cost (matrix, vpos) int glyph_table_len = GLYPH_TABLE_LENGTH; /* Ignore trailing and leading spaces if we can. */ - if (!TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ())) + if (!TTY_MUST_WRITE_SPACES (CURTTY ())) { /* Skip from the end over trailing spaces. */ while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1))) @@ -1643,8 +1640,10 @@ realloc_glyph_pool (pool, matrix_dim) #if GLYPH_DEBUG -/* Flush standard output. This is sometimes useful to call from - the debugger. */ +/* Flush standard output. This is sometimes useful to call from the debugger. + XXX Maybe this should be changed to flush the current terminal instead of + stdout. +*/ void flush_stdout () @@ -3318,7 +3317,7 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0, update_begin (f); if (FRAME_MSDOS_P (f)) - set_terminal_modes (); + set_terminal_modes (0); clear_frame (); clear_current_matrices (f); update_end (f); @@ -3462,7 +3461,7 @@ direct_output_for_insert (g) /* If we can't insert glyphs, we can use this method only at the end of a line. */ - if (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ())) + if (!TTY_CHAR_INS_DEL_OK (CURTTY ())) if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n') return 0; @@ -3841,9 +3840,9 @@ update_frame (f, force_p, inhibit_hairy_id_p) paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p); update_end (f); - if (termscript) - fflush (termscript); - fflush (stdout); + if (TTY_TERMSCRIPT (FRAME_TTY (f))) + fflush (TTY_TERMSCRIPT (FRAME_TTY (f))); + fflush (TTY_OUTPUT (FRAME_TTY (f))); /* Check window matrices for lost pointers. */ #if GLYPH_DEBUG @@ -5075,7 +5074,7 @@ update_frame_1 (f, force_p, inhibit_id_p) } /* If we cannot insert/delete lines, it's no use trying it. */ - if (!TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ())) + if (!TTY_LINE_INS_DEL_OK (FRAME_TTY (f))) inhibit_id_p = 1; /* See if any of the desired lines are enabled; don't compute for @@ -5293,7 +5292,7 @@ scrolling (frame) } /* If changed lines are few, don't allow preemption, don't scroll. */ - if ((!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) + if ((!TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) && changed_lines < baud_rate / 2400) || unchanged_at_bottom == FRAME_LINES (frame)) return 1; @@ -5301,14 +5300,14 @@ scrolling (frame) window_size = (FRAME_LINES (frame) - unchanged_at_top - unchanged_at_bottom); - if (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())) + if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame))) free_at_end_vpos -= unchanged_at_bottom; - else if (TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ())) + else if (TTY_MEMORY_BELOW_FRAME (FRAME_TTY (frame))) free_at_end_vpos = -1; /* If large window, fast terminal and few lines in common between current frame and desired frame, don't bother with i/d calc. */ - if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) + if (!TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) && window_size >= 18 && baud_rate > 2400 && (window_size >= 10 * scrolling_max_lines_saved (unchanged_at_top, @@ -5389,7 +5388,7 @@ update_frame_line (f, vpos) struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos); struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos); int must_write_whole_line_p; - int write_spaces_p = TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ()); + int write_spaces_p = TTY_MUST_WRITE_SPACES (FRAME_TTY (f)); int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background != FACE_TTY_DEFAULT_BG_COLOR); @@ -5468,7 +5467,7 @@ update_frame_line (f, vpos) nlen--; /* If there's no i/d char, quickly do the best we can without it. */ - if (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ())) + if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))) { int i, j; @@ -5571,7 +5570,7 @@ update_frame_line (f, vpos) tem = (nlen - nsp) - (olen - osp); if (endmatch && tem - && (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) + && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)) || endmatch <= char_ins_del_cost (f)[tem])) endmatch = 0; @@ -5581,7 +5580,7 @@ update_frame_line (f, vpos) Is it worth it? */ if (nsp != osp - && (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) + && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)) || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp])) { begmatch = 0; @@ -6113,14 +6112,15 @@ FILE = nil means just close any termscript file currently open. */) (file) Lisp_Object file; { - if (termscript != 0) fclose (termscript); - termscript = 0; + if (TTY_TERMSCRIPT (CURTTY ()) != 0) + fclose (TTY_TERMSCRIPT (CURTTY ())); + TTY_TERMSCRIPT (CURTTY ()) = 0; if (! NILP (file)) { file = Fexpand_file_name (file, Qnil); - termscript = fopen (SDATA (file), "w"); - if (termscript == 0) + TTY_TERMSCRIPT (CURTTY ()) = fopen (SDATA (file), "w"); + if (TTY_TERMSCRIPT (CURTTY ()) == 0) report_file_error ("Opening termscript", Fcons (file, Qnil)); } return Qnil; @@ -6136,14 +6136,15 @@ Control characters in STRING will have terminal-dependent effects. */) { /* ??? Perhaps we should do something special for multibyte strings here. */ CHECK_STRING (string); - fwrite (SDATA (string), 1, SBYTES (string), stdout); - fflush (stdout); - if (termscript) + if (TTY_TERMSCRIPT (CURTTY ())) { fwrite (SDATA (string), 1, SBYTES (string), - termscript); - fflush (termscript); + TTY_TERMSCRIPT (CURTTY ())); + fflush (TTY_TERMSCRIPT (CURTTY ())); } + fwrite (SDATA (string), 1, SBYTES (string), + TTY_OUTPUT (CURTTY ())); + fflush (TTY_OUTPUT (CURTTY ())); return Qnil; } @@ -6463,8 +6464,6 @@ the current state. */) Initialization ***********************************************************************/ -char *terminal_type; - /* Initialization done when Emacs fork is started, before doing stty. Determine terminal type and set terminal_driver. Then invoke its decoding routine to set up variables in the terminal package. */ @@ -6472,6 +6471,8 @@ char *terminal_type; void init_display () { + char *terminal_type; + #ifdef HAVE_X_WINDOWS extern int display_arg; #endif @@ -6593,7 +6594,7 @@ For types not defined in VMS, use define emacs_term \"TYPE\".\n\ } #endif /* VMS */ - term_init (terminal_type); + term_init (0, terminal_type); { struct frame *sf = SELECTED_FRAME (); diff --git a/src/emacs.c b/src/emacs.c index 0b2e678329..9b07b5a17b 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1566,7 +1566,7 @@ main (argc, argv #ifdef VMS init_vms_input ();/* init_display calls get_frame_size, that needs this. */ #endif /* VMS */ - init_display (); /* Determine terminal type. init_sys_modes uses results. */ + init_display (); /* Determine terminal type. Calls init_sys_modes. */ } #ifndef MAC_OS8 /* Called before init_window_once for Mac OS Classic. */ @@ -1575,7 +1575,7 @@ main (argc, argv #ifdef VMS init_vmsproc (); /* And this too. */ #endif /* VMS */ - init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.). */ + /* init_sys_modes (); */ /* Init system terminal modes (RAW or CBREAK, etc.). */ #if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT) init_xfns (); #endif /* HAVE_X_WINDOWS */ @@ -1992,7 +1992,7 @@ shut_down_emacs (sig, no_x, stuff) && tpgrp == pgrp) { fflush (stdout); - reset_sys_modes (); + reset_all_sys_modes (); if (sig && sig != SIGTERM) fprintf (stderr, "Fatal error (%d)", sig); } diff --git a/src/frame.c b/src/frame.c index 934c11d98b..4a97befaf0 100644 --- a/src/frame.c +++ b/src/frame.c @@ -42,6 +42,8 @@ Boston, MA 02111-1307, USA. */ #include "fontset.h" #endif #include "blockinput.h" +#include "systty.h" /* For emacs_tty in termchar.h */ +#include "termchar.h" #include "termhooks.h" #include "dispextern.h" #include "window.h" @@ -106,6 +108,7 @@ Lisp_Object Qmenu_bar_lines, Qtool_bar_lines; Lisp_Object Qleft_fringe, Qright_fringe; Lisp_Object Qbuffer_predicate, Qbuffer_list; Lisp_Object Qtty_color_mode; +Lisp_Object Qtty, Qtty_type; Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth; @@ -180,8 +183,6 @@ set_menu_bar_lines (f, value, oldval) Lisp_Object Vemacs_iconified; Lisp_Object Vframe_list; -struct x_output tty_display; - extern Lisp_Object Vminibuffer_list; extern Lisp_Object get_minibuffer (); extern Lisp_Object Fhandle_switch_frame (); @@ -474,12 +475,14 @@ make_minibuffer_frame () } #endif /* HAVE_WINDOW_SYSTEM */ -/* Construct a frame that refers to the terminal (stdin and stdout). */ +/* Construct a frame that refers to a terminal. */ static int terminal_frame_count; struct frame * -make_terminal_frame () +make_terminal_frame (tty, tty_type) + char *tty; + char *tty_type; { register struct frame *f; Lisp_Object frame; @@ -537,12 +540,16 @@ make_terminal_frame () #else #ifdef WINDOWSNT f->output_method = output_termcap; - f->output_data.x = &tty_display; + f->output_data.x = &tty_display; /* XXX */ #else #ifdef MAC_OS8 make_mac_terminal_frame (f); #else - f->output_data.x = &tty_display; + f->output_method = output_termcap; + if (initialized) + f->output_data.tty = term_init (tty, tty_type); + else + f->output_data.tty = term_dummy_init (); #ifdef CANNOT_DUMP FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR; FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR; @@ -559,11 +566,19 @@ make_terminal_frame () DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame, 1, 1, 0, - doc: /* Create an additional terminal frame. -You can create multiple frames on a text-only terminal in this way. -Only the selected terminal frame is actually displayed. + doc: /* Create an additional terminal frame, possibly on another terminal. This function takes one argument, an alist specifying frame parameters. -In practice, generally you don't need to specify any parameters. + +You can create multiple frames on a single text-only terminal, but +only one of them (the selected terminal frame) is actually displayed. + +In practice, generally you don't need to specify any parameters, +except when you want to create a new frame on another terminal. +In that case, the `tty' parameter specifies the device file to open, +and the `tty-type' parameter specifies the terminal type. Example: + + (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm"))) + Note that changing the size of one terminal frame automatically affects all. */) (parms) Lisp_Object parms; @@ -587,7 +602,44 @@ Note that changing the size of one terminal frame automatically affects all. */ #endif #endif /* not MSDOS */ - f = make_terminal_frame (); + { + Lisp_Object tty, tty_type; + char *name = 0, *type = 0; + + /* XXX Ugh, there must be a better way to do this. */ + tty = Fassq (Qtty, parms); + if (EQ (tty, Qnil)) + tty = Fassq (Qtty, Vdefault_frame_alist); + if (! EQ (tty, Qnil)) + tty = XCDR (tty); + if (EQ (tty, Qnil) || !STRINGP (tty)) + tty = Qnil; + + tty_type = Fassq (Qtty_type, parms); + if (EQ (tty_type, Qnil)) + tty_type = Fassq (Qtty_type, Vdefault_frame_alist); + if (! EQ (tty_type, Qnil)) + tty_type = XCDR (tty_type); + if (EQ (tty_type, Qnil) || !STRINGP (tty_type)) + tty_type = Qnil; + + if (! EQ (tty, Qnil)) + { + name = (char *) alloca (SBYTES (tty) + 1); + strncpy (name, SDATA (tty), SBYTES (tty)); + name[SBYTES (tty)] = 0; + } + + if (! EQ (tty_type, Qnil)) + { + type = (char *) alloca (SBYTES (tty_type) + 1); + strncpy (type, SDATA (tty_type), SBYTES (tty_type)); + type[SBYTES (tty_type)] = 0; + } + + + f = make_terminal_frame (name, type); + } change_frame_size (f, FRAME_LINES (sf), FRAME_COLS (sf), 0, 0, 0); @@ -3937,6 +3989,10 @@ syms_of_frame () staticpro (&Qbackground_mode); Qtty_color_mode = intern ("tty-color-mode"); staticpro (&Qtty_color_mode); + Qtty = intern ("tty"); + staticpro (&Qtty); + Qtty_type = intern ("tty-type"); + staticpro (&Qtty_type); Qface_set_after_frame_default = intern ("face-set-after-frame-default"); staticpro (&Qface_set_after_frame_default); diff --git a/src/frame.h b/src/frame.h index 30d3f4348e..6d7f1fffa8 100644 --- a/src/frame.h +++ b/src/frame.h @@ -84,11 +84,15 @@ struct x_output #endif /* ! HAVE_X_WINDOWS */ -#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel) -#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel) +#define FRAME_FOREGROUND_PIXEL(f) \ + (((f)->output_method == output_termcap) \ + ? ((f)->output_data.tty->foreground_pixel) \ + : ((f)->output_data.x->foreground_pixel)) -/* A structure describing a termcap frame display. */ -extern struct x_output tty_display; +#define FRAME_BACKGROUND_PIXEL(f) \ + (((f)->output_method == output_termcap) \ + ? ((f)->output_data.tty->background_pixel) \ + : ((f)->output_data.x->background_pixel)) #endif /* ! MSDOS && ! WINDOWSNT && ! MAC_OS */ @@ -283,12 +287,15 @@ struct frame enum output_method output_method; /* A structure of auxiliary data used for displaying the contents. + struct tty_output is used for terminal frames; + it is defined in term.h. struct x_output is used for X window frames; it is defined in xterm.h. struct w32_output is used for W32 window frames; it is defined in w32term.h. */ union output_data { + struct tty_output *tty; struct x_output *x; struct w32_output *w32; struct mac_output *mac; @@ -779,7 +786,7 @@ extern Lisp_Object Qframep, Qframe_live_p; extern struct frame *last_nonminibuf_frame; -extern struct frame *make_terminal_frame P_ ((void)); +extern struct frame *make_terminal_frame P_ ((char *tty, char *tty_type)); extern struct frame *make_frame P_ ((int)); #ifdef HAVE_WINDOW_SYSTEM extern struct frame *make_minibuffer_frame P_ ((void)); diff --git a/src/indent.c b/src/indent.c index 0d9fe9aaf9..bc32aa1f40 100644 --- a/src/indent.c +++ b/src/indent.c @@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA. */ #include "keyboard.h" #include "frame.h" #include "window.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "termopts.h" #include "disptab.h" diff --git a/src/keyboard.c b/src/keyboard.c index 6148a2510b..dd4619d796 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */ #include #include #include +#include "systty.h" /* This must be included befor termchar.h. */ #include "termchar.h" #include "termopts.h" #include "lisp.h" @@ -55,7 +56,6 @@ Boston, MA 02111-1307, USA. */ #endif /* not MSDOS */ #include "syssignal.h" -#include "systty.h" #include #ifdef HAVE_UNISTD_H @@ -10067,7 +10067,7 @@ On such systems, Emacs starts a subshell instead of suspending. */) GCPRO1 (stuffstring); get_frame_size (&old_width, &old_height); - reset_sys_modes (); + reset_all_sys_modes (); /* sys_suspend can get an error if it tries to fork a subshell and the system resources aren't available for that. */ record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_sys_modes, @@ -10206,7 +10206,7 @@ interrupt_signal (signalnum) /* If we don't have an argument, */ sigblock (sigmask (SIGINT)); fflush (stdout); - reset_sys_modes (); + reset_all_sys_modes (); #ifdef SIGTSTP /* Support possible in later USG versions */ /* @@ -10285,7 +10285,7 @@ interrupt_signal (signalnum) /* If we don't have an argument, */ printf ("Continuing...\n"); #endif /* not MSDOS */ fflush (stdout); - init_sys_modes (); + init_all_sys_modes (); sigfree (); } else @@ -10372,7 +10372,7 @@ See also `current-input-mode'. */) #ifndef DOS_NT /* this causes startup screen to be restored and messes with the mouse */ - reset_sys_modes (); + reset_all_sys_modes (); #endif #ifdef SIGIO @@ -10410,7 +10410,7 @@ See also `current-input-mode'. */) quit_char = XINT (quit) & (meta_key ? 0377 : 0177); #ifndef DOS_NT - init_sys_modes (); + init_all_sys_modes (); #endif #ifdef POLL_FOR_INPUT diff --git a/src/lisp.h b/src/lisp.h index 94de2c2960..2c30549d53 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2931,17 +2931,21 @@ EXFUN (Fx_popup_menu, 2); EXFUN (Fx_popup_dialog, 2); extern void syms_of_xmenu P_ ((void)); +/* defined in termchar.h */ +struct tty_output; + /* defined in sysdep.c */ extern void stuff_char P_ ((char c)); extern void init_sigio P_ ((int)); extern void request_sigio P_ ((void)); extern void unrequest_sigio P_ ((void)); -extern void reset_sys_modes P_ ((void)); extern void sys_subshell P_ ((void)); extern void sys_suspend P_ ((void)); extern void discard_tty_input P_ ((void)); -extern void init_sys_modes P_ ((void)); -extern void reset_sys_modes P_ ((void)); +extern void init_sys_modes P_ ((struct tty_output *)); +extern void reset_sys_modes P_ ((struct tty_output *)); +extern void init_all_sys_modes P_ ((void)); +extern void reset_all_sys_modes P_ ((void)); extern void get_frame_size P_ ((int *, int *)); extern void wait_for_termination P_ ((int)); extern void flush_pending_output P_ ((int)); diff --git a/src/macterm.c b/src/macterm.c index 7d27e5430e..dd031919a1 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -8674,11 +8674,11 @@ mac_initialize () redeem_scroll_bar_hook = XTredeem_scroll_bar; judge_scroll_bars_hook = XTjudge_scroll_bars; - TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 1; /* we'll scroll partial frames */ - TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; - TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; /* we'll just blt 'em */ - TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = 1; /* X does this well */ - TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 0; /* we don't remember what + TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */ + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1; + TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */ + TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */ + TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what scrolls off the bottom */ baud_rate = 19200; diff --git a/src/macterm.h b/src/macterm.h index b3fe53c86e..212119e08b 100644 --- a/src/macterm.h +++ b/src/macterm.h @@ -406,9 +406,6 @@ typedef struct mac_output mac_output; #define FRAME_MAC_WINDOW(f) ((f)->output_data.mac->mWP) #define FRAME_X_WINDOW(f) ((f)->output_data.mac->mWP) -#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel) -#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel) - #define FRAME_FONT(f) ((f)->output_data.mac->font) #define FRAME_FONTSET(f) ((f)->output_data.mac->fontset) diff --git a/src/msdos.c b/src/msdos.c index 103094141b..da6bfef065 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -2580,7 +2580,7 @@ internal_terminal_init () set_terminal_modes_hook = IT_set_terminal_modes; reset_terminal_modes_hook = IT_reset_terminal_modes; set_terminal_window_hook = IT_set_terminal_window; - TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 0; + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0; #endif } diff --git a/src/print.c b/src/print.c index 441894471a..af76616e42 100644 --- a/src/print.c +++ b/src/print.c @@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA. */ #include "window.h" #include "process.h" #include "dispextern.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "intervals.h" diff --git a/src/scroll.c b/src/scroll.c index a786d3c2cf..f4faca2fad 100644 --- a/src/scroll.c +++ b/src/scroll.c @@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */ #include #include #include +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "lisp.h" #include "dispextern.h" @@ -101,7 +102,7 @@ calculate_scrolling (frame, matrix, window_size, lines_below, register int cost, cost1; int lines_moved = window_size - + (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) ? 0 : lines_below); + + (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) ? 0 : lines_below); /* first_insert_cost[I] is the cost of doing the first insert-line at the i'th line of the lines we are considering, where I is origin 1 (as it is below). */ @@ -468,7 +469,7 @@ calculate_direct_scrolling (frame, matrix, window_size, lines_below, cost of scrolling by a distance of one. The extra cost is added once for consistency with the cost vectors */ scroll_overhead - = TERMINAL_SCROLL_REGION_COST (CURRENT_TERMINAL ()) + extra_cost; + = TTY_SCROLL_REGION_COST (FRAME_TTY (frame)) + extra_cost; /* initialize the top left corner of the matrix */ matrix->writecost = 0; @@ -820,7 +821,7 @@ scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, matrix = ((struct matrix_elt *) alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix)); - if (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())) + if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame))) { calculate_direct_scrolling (frame, matrix, window_size, unchanged_at_bottom, @@ -916,7 +917,7 @@ scroll_cost (frame, from, to, amount) if (amount == 0) return 0; - if (! TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())) + if (! TTY_SCROLL_REGION_OK (FRAME_TTY (frame))) limit = height; else if (amount > 0) limit += amount; diff --git a/src/sysdep.c b/src/sysdep.c index b83e01635c..7573cc4b9d 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1255,14 +1255,6 @@ emacs_set_tty (fd, settings, flushp) } -/* The initial tty mode bits */ -struct emacs_tty old_tty; - -/* 1 if we have been through init_sys_modes. */ -int term_initted; - -/* 1 if outer tty status has been recorded. */ -int old_tty_valid; #ifdef BSD4_1 /* BSD 4.1 needs to keep track of the lmode bits in order to start @@ -1298,7 +1290,18 @@ static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1}; #endif void -init_sys_modes () +init_all_sys_modes (void) +{ + struct tty_output *tty = tty_list; + while (tty) { + init_sys_modes (tty); + tty = tty->next; + } +} + +void +init_sys_modes (otty) + struct tty_output *otty; { struct emacs_tty tty; @@ -1367,14 +1370,14 @@ nil means don't delete them until `list-processes' is run. */); if (!read_socket_hook && EQ (Vwindow_system, Qnil)) #endif { - EMACS_GET_TTY (input_fd, &old_tty); + EMACS_GET_TTY (input_fd, &otty->old_tty); - old_tty_valid = 1; + otty->old_tty_valid = 1; - tty = old_tty; + tty = otty->old_tty; #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS) - XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]); + XSETINT (Vtty_erase_char, otty->old_tty.main.c_cc[VERASE]); #ifdef DGUX /* This allows meta to be sent on 8th bit. */ @@ -1539,7 +1542,7 @@ nil means don't delete them until `list-processes' is run. */); tty.tchars.t_stopc = '\023'; } - tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode; + tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | otty->old_tty.lmode; #ifdef ultrix /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt anything, and leaving it in breaks the meta key. Go figure. */ @@ -1557,7 +1560,7 @@ nil means don't delete them until `list-processes' is run. */); tty.ltchars = new_ltchars; #endif /* HAVE_LTCHARS */ #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */ - if (!term_initted) + if (!otty->term_initted) internal_terminal_init (); dos_ttraw (); #endif @@ -1646,14 +1649,14 @@ nil means don't delete them until `list-processes' is run. */); #endif ) #endif - set_terminal_modes (); + set_terminal_modes (otty); - if (!term_initted + if (!otty->term_initted && FRAMEP (Vterminal_frame) && FRAME_TERMCAP_P (XFRAME (Vterminal_frame))) init_frame_faces (XFRAME (Vterminal_frame)); - if (term_initted && no_redraw_on_reenter) + if (otty->term_initted && no_redraw_on_reenter) { if (display_completed) direct_output_forward_char (0); @@ -1665,7 +1668,7 @@ nil means don't delete them until `list-processes' is run. */); FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1; } - term_initted = 1; + otty->term_initted = 1; } /* Return nonzero if safe to use tabs in output. @@ -1778,10 +1781,21 @@ set_window_size (fd, height, width) } +void +reset_all_sys_modes (void) +{ + struct tty_output *tty = tty_list; + while (tty) { + reset_sys_modes (tty); + tty = tty->next; + } +} + /* Prepare the terminal for exiting Emacs; move the cursor to the bottom of the frame, turn off interrupt-driven I/O, etc. */ void -reset_sys_modes () +reset_sys_modes (otty) + struct tty_output *otty; { struct frame *sf; @@ -1790,7 +1804,7 @@ reset_sys_modes () fflush (stdout); return; } - if (!term_initted) + if (!otty->term_initted) return; #ifdef HAVE_WINDOW_SYSTEM /* Emacs' window system on MSDOG uses the `internal terminal' and therefore @@ -1820,7 +1834,7 @@ reset_sys_modes () } #endif - reset_terminal_modes (); + reset_terminal_modes (otty); fflush (stdout); #ifdef BSD_SYSTEM #ifndef BSD4_1 @@ -1848,8 +1862,8 @@ reset_sys_modes () reset_sigio (); #endif /* BSD4_1 */ - if (old_tty_valid) - while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR) + if (otty->old_tty_valid) + while (EMACS_SET_TTY (input_fd, &otty->old_tty, 0) < 0 && errno == EINTR) ; #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */ @@ -1860,7 +1874,7 @@ reset_sys_modes () /* Ultrix's termios *ignores* any line discipline except TERMIODISC. A different old line discipline is therefore not restored, yet. Restore the old line discipline by hand. */ - ioctl (0, TIOCSETD, &old_tty.main.c_line); + ioctl (0, TIOCSETD, &otty->old_tty.main.c_line); #endif #ifdef AIXHFT @@ -3470,7 +3484,7 @@ croak (badfunc) char *badfunc; { printf ("%s not yet implemented\r\n", badfunc); - reset_sys_modes (); + reset_all_sys_modes (); exit (1); } @@ -5056,7 +5070,7 @@ croak (badfunc) char *badfunc; { printf ("%s not yet implemented\r\n", badfunc); - reset_sys_modes (); + reset_all_sys_modes (); exit (1); } @@ -5126,8 +5140,8 @@ hft_init () } /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly at times. */ - TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 0; - TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 0; + TTY_LINE_INS_DEL_OK (CURTTY ()) = 0; + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0; } /* Reset the rubout key to backspace. */ diff --git a/src/term.c b/src/term.c index 50d47a1dac..5739cd0d19 100644 --- a/src/term.c +++ b/src/term.c @@ -26,6 +26,9 @@ Boston, MA 02111-1307, USA. */ #include #include +#include + +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "termopts.h" #include "lisp.h" @@ -60,32 +63,36 @@ extern int tgetnum P_ ((char *id)); #include "macterm.h" #endif +#ifndef O_RDWR +#define O_RDWR 2 +#endif + static void turn_on_face P_ ((struct frame *, int face_id)); static void turn_off_face P_ ((struct frame *, int face_id)); static void tty_show_cursor P_ ((void)); static void tty_hide_cursor P_ ((void)); -#define OUTPUT(a) \ - tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc) -#define OUTPUT1(a) tputs (a, 1, cmputc) -#define OUTPUTL(a, lines) tputs (a, lines, cmputc) +#define OUTPUT(tty, a) \ + emacs_tputs ((tty), a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc) +#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc) +#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc) -#define OUTPUT_IF(a) \ +#define OUTPUT_IF(tty, a) \ do { \ - if (a) \ - tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) \ + if (a) \ + emacs_tputs ((tty), a, (int) (FRAME_LINES (XFRAME (selected_frame)) \ - curY), cmputc); \ } while (0) -#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0) +#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0) /* Function to use to ring the bell. */ Lisp_Object Vring_bell_function; /* Terminal characteristics that higher levels want to look at. */ -static struct terminal _current_terminal; -TERMINAL_PTR current_terminal = &_current_terminal; + +struct tty_output *tty_list; /* Nonzero means no need to redraw the entire frame on resuming a suspended Emacs. This is useful on terminals with multiple pages, @@ -421,18 +428,19 @@ ring_bell () } else if (!FRAME_TERMCAP_P (XFRAME (selected_frame))) (*ring_bell_hook) (); - else - OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); + else { + OUTPUT (CURTTY (), TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); + } } void -set_terminal_modes () +set_terminal_modes (struct tty_output *tty) { if (FRAME_TERMCAP_P (XFRAME (selected_frame))) { - OUTPUT_IF (TS_termcap_modes); - OUTPUT_IF (TS_cursor_visible); - OUTPUT_IF (TS_keypad_mode); + OUTPUT_IF (tty, TS_termcap_modes); + OUTPUT_IF (tty, TS_cursor_visible); + OUTPUT_IF (tty, TS_keypad_mode); losecursor (); } else @@ -440,17 +448,18 @@ set_terminal_modes () } void -reset_terminal_modes () +reset_terminal_modes (struct tty_output *tty) { if (FRAME_TERMCAP_P (XFRAME (selected_frame))) { turn_off_highlight (); turn_off_insert (); - OUTPUT_IF (TS_end_keypad_mode); - OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_end_termcap_modes); - OUTPUT_IF (TS_orig_pair); + OUTPUT_IF (tty, TS_end_keypad_mode); + OUTPUT_IF (tty, TS_cursor_normal); + OUTPUT_IF (tty, TS_end_termcap_modes); + OUTPUT_IF (tty, TS_orig_pair); /* Output raw CR so kernel can track the cursor hpos. */ + current_tty = tty; cmputc ('\r'); } else if (reset_terminal_modes_hook) @@ -490,7 +499,7 @@ set_terminal_window (size) if (FRAME_TERMCAP_P (updating_frame)) { specified_window = size ? size : FRAME_LINES (updating_frame); - if (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())) + if (TTY_SCROLL_REGION_OK (FRAME_TTY (updating_frame))) set_scroll_region (0, specified_window); } else @@ -514,7 +523,7 @@ set_scroll_region (start, stop) else buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf)); - OUTPUT (buf); + OUTPUT (CURTTY (), buf); xfree (buf); losecursor (); } @@ -524,7 +533,7 @@ static void turn_on_insert () { if (!insert_mode) - OUTPUT (TS_insert_mode); + OUTPUT (CURTTY (), TS_insert_mode); insert_mode = 1; } @@ -532,7 +541,7 @@ void turn_off_insert () { if (insert_mode) - OUTPUT (TS_end_insert_mode); + OUTPUT (CURTTY (), TS_end_insert_mode); insert_mode = 0; } @@ -542,7 +551,7 @@ void turn_off_highlight () { if (standout_mode) - OUTPUT_IF (TS_end_standout_mode); + OUTPUT_IF (CURTTY (), TS_end_standout_mode); standout_mode = 0; } @@ -550,7 +559,7 @@ static void turn_on_highlight () { if (!standout_mode) - OUTPUT_IF (TS_standout_mode); + OUTPUT_IF (CURTTY(), TS_standout_mode); standout_mode = 1; } @@ -572,7 +581,7 @@ tty_hide_cursor () if (tty_cursor_hidden == 0) { tty_cursor_hidden = 1; - OUTPUT_IF (TS_cursor_invisible); + OUTPUT_IF (CURTTY (), TS_cursor_invisible); } } @@ -585,8 +594,8 @@ tty_show_cursor () if (tty_cursor_hidden) { tty_cursor_hidden = 0; - OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_cursor_visible); + OUTPUT_IF (CURTTY (), TS_cursor_normal); + OUTPUT_IF (CURTTY (), TS_cursor_visible); } } @@ -642,7 +651,7 @@ cursor_to (vpos, hpos) background_highlight (); if (!TF_insmode_motion) turn_off_insert (); - cmgoto (vpos, hpos); + cmgoto (FRAME_TTY (f), vpos, hpos); } /* Similar but don't take any account of the wasted characters. */ @@ -663,7 +672,7 @@ raw_cursor_to (row, col) background_highlight (); if (!TF_insmode_motion) turn_off_insert (); - cmgoto (row, col); + cmgoto (FRAME_TTY (f), row, col); } /* Erase operations */ @@ -682,7 +691,7 @@ clear_to_end () if (TS_clr_to_bottom) { background_highlight (); - OUTPUT (TS_clr_to_bottom); + OUTPUT (CURTTY (), TS_clr_to_bottom); } else { @@ -710,7 +719,7 @@ clear_frame () if (TS_clr_frame) { background_highlight (); - OUTPUT (TS_clr_frame); + OUTPUT (FRAME_TTY (updating_frame ? updating_frame : sf), TS_clr_frame); cmat (0, 0); } else @@ -750,7 +759,7 @@ clear_end_of_line (first_unused_hpos) background_highlight (); if (TS_clr_line) { - OUTPUT1 (TS_clr_line); + OUTPUT1 (CURTTY (), TS_clr_line); } else { /* have to do it the hard way */ @@ -764,9 +773,9 @@ clear_end_of_line (first_unused_hpos) for (i = curX; i < first_unused_hpos; i++) { - if (termscript) - fputc (' ', termscript); - putchar (' '); + if (TTY_TERMSCRIPT (CURTTY ())) + fputc (' ', TTY_TERMSCRIPT (CURTTY ())); + fputc (' ', TTY_OUTPUT (CURTTY ())); } cmplus (first_unused_hpos - curX); } @@ -942,11 +951,13 @@ write_glyphs (string, len) &consumed); if (produced > 0) { - fwrite (conversion_buffer, 1, produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); + fwrite (conversion_buffer, 1, produced, + TTY_OUTPUT (FRAME_TTY (f))); + if (ferror (TTY_OUTPUT (FRAME_TTY (f)))) + clearerr (TTY_OUTPUT (FRAME_TTY (f))); + if (TTY_TERMSCRIPT (FRAME_TTY (f))) + fwrite (conversion_buffer, 1, produced, + TTY_TERMSCRIPT (FRAME_TTY (f))); } len -= consumed; n -= consumed; @@ -966,16 +977,17 @@ write_glyphs (string, len) 0, conversion_buffer_size); if (terminal_coding.produced > 0) { - fwrite (conversion_buffer, 1, terminal_coding.produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) + fwrite (conversion_buffer, 1, terminal_coding.produced, + TTY_OUTPUT (FRAME_TTY (f))); + if (ferror (TTY_OUTPUT (FRAME_TTY (f)))) + clearerr (TTY_OUTPUT (FRAME_TTY (f))); + if (TTY_TERMSCRIPT (FRAME_TTY (f))) fwrite (conversion_buffer, 1, terminal_coding.produced, - termscript); + TTY_TERMSCRIPT (FRAME_TTY (f))); } } - cmcheckmagic (); + cmcheckmagic (FRAME_TTY (f)); } /* If start is zero, insert blanks instead of a string at start */ @@ -1004,7 +1016,7 @@ insert_glyphs (start, len) if (TS_ins_multi_chars) { buf = tparam (TS_ins_multi_chars, 0, 0, len); - OUTPUT1 (buf); + OUTPUT1 (FRAME_TTY (f), buf); xfree (buf); if (start) write_glyphs (start, len); @@ -1021,7 +1033,7 @@ insert_glyphs (start, len) unsigned char conversion_buffer[1024]; int conversion_buffer_size = sizeof conversion_buffer; - OUTPUT1_IF (TS_ins_char); + OUTPUT1_IF (FRAME_TTY (f), TS_ins_char); if (!start) { conversion_buffer[0] = SPACEGLYPH; @@ -1037,7 +1049,7 @@ insert_glyphs (start, len) occupies more than one column. */ while (len && CHAR_GLYPH_PADDING_P (*start)) { - OUTPUT1_IF (TS_ins_char); + OUTPUT1_IF (FRAME_TTY (f), TS_ins_char); start++, len--; } @@ -1053,14 +1065,16 @@ insert_glyphs (start, len) if (produced > 0) { - fwrite (conversion_buffer, 1, produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); + fwrite (conversion_buffer, 1, produced, + TTY_OUTPUT (FRAME_TTY (f))); + if (ferror (TTY_OUTPUT (FRAME_TTY (f)))) + clearerr (TTY_OUTPUT (FRAME_TTY (f))); + if (TTY_TERMSCRIPT (FRAME_TTY (f))) + fwrite (conversion_buffer, 1, produced, + TTY_TERMSCRIPT (FRAME_TTY (f))); } - OUTPUT1_IF (TS_pad_inserted_char); + OUTPUT1_IF (FRAME_TTY (f), TS_pad_inserted_char); if (start) { turn_off_face (f, glyph->face_id); @@ -1068,7 +1082,7 @@ insert_glyphs (start, len) } } - cmcheckmagic (); + cmcheckmagic (FRAME_TTY (f)); } void @@ -1091,20 +1105,20 @@ delete_glyphs (n) else { turn_off_insert (); - OUTPUT_IF (TS_delete_mode); + OUTPUT_IF (FRAME_TTY (updating_frame), TS_delete_mode); } if (TS_del_multi_chars) { buf = tparam (TS_del_multi_chars, 0, 0, n); - OUTPUT1 (buf); + OUTPUT1 (FRAME_TTY (updating_frame), buf); xfree (buf); } else for (i = 0; i < n; i++) - OUTPUT1 (TS_del_char); + OUTPUT1 (FRAME_TTY (updating_frame), TS_del_char); if (!delete_in_insert_mode) - OUTPUT_IF (TS_end_delete_mode); + OUTPUT_IF (FRAME_TTY (updating_frame), TS_end_delete_mode); } /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */ @@ -1136,10 +1150,10 @@ ins_del_lines (vpos, n) /* If the lines below the deletion are blank lines coming out of the end of the window, don't bother, as there will be a matching inslines later that will flush them. */ - if (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) + if (TTY_SCROLL_REGION_OK (FRAME_TTY (sf)) && vpos + i >= specified_window) return; - if (!TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) + if (!TTY_MEMORY_BELOW_FRAME (FRAME_TTY (sf)) && vpos + i >= FRAME_LINES (sf)) return; @@ -1148,7 +1162,7 @@ ins_del_lines (vpos, n) raw_cursor_to (vpos, 0); background_highlight (); buf = tparam (multi, 0, 0, i); - OUTPUT (buf); + OUTPUT (FRAME_TTY (sf), buf); xfree (buf); } else if (single) @@ -1156,7 +1170,7 @@ ins_del_lines (vpos, n) raw_cursor_to (vpos, 0); background_highlight (); while (--i >= 0) - OUTPUT (single); + OUTPUT (FRAME_TTY (sf), single); if (TF_teleray) curX = 0; } @@ -1169,12 +1183,12 @@ ins_del_lines (vpos, n) raw_cursor_to (vpos, 0); background_highlight (); while (--i >= 0) - OUTPUTL (scroll, specified_window - vpos); + OUTPUTL (FRAME_TTY (sf), scroll, specified_window - vpos); set_scroll_region (0, specified_window); } - if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) - && TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) + if (!TTY_SCROLL_REGION_OK (FRAME_TTY (sf)) + && TTY_MEMORY_BELOW_FRAME (FRAME_TTY (sf)) && n < 0) { cursor_to (FRAME_LINES (sf) + n, 0); @@ -1306,7 +1320,8 @@ calculate_costs (frame) FRAME_COST_BAUD_RATE (frame) = baud_rate; - TERMINAL_SCROLL_REGION_COST (CURRENT_TERMINAL ()) = string_cost (f); + if (FRAME_TERMCAP_P (frame)) + TTY_SCROLL_REGION_COST (frame->output_data.tty) = string_cost (f); /* These variables are only used for terminal stuff. They are allocated once for the terminal frame of X-windows emacs, but not used afterwards. @@ -1866,23 +1881,23 @@ turn_on_face (f, face_id) if (face->tty_bold_p) { if (MAY_USE_WITH_COLORS_P (NC_BOLD)) - OUTPUT1_IF (TS_enter_bold_mode); + OUTPUT1_IF (FRAME_TTY (f), TS_enter_bold_mode); } else if (face->tty_dim_p) if (MAY_USE_WITH_COLORS_P (NC_DIM)) - OUTPUT1_IF (TS_enter_dim_mode); + OUTPUT1_IF (FRAME_TTY (f), TS_enter_dim_mode); /* Alternate charset and blinking not yet used. */ if (face->tty_alt_charset_p && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET)) - OUTPUT1_IF (TS_enter_alt_charset_mode); + OUTPUT1_IF (FRAME_TTY (f), TS_enter_alt_charset_mode); if (face->tty_blinking_p && MAY_USE_WITH_COLORS_P (NC_BLINK)) - OUTPUT1_IF (TS_enter_blink_mode); + OUTPUT1_IF (FRAME_TTY (f), TS_enter_blink_mode); if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE)) - OUTPUT1_IF (TS_enter_underline_mode); + OUTPUT1_IF (FRAME_TTY (f), TS_enter_underline_mode); if (TN_max_colors > 0) { @@ -1891,14 +1906,14 @@ turn_on_face (f, face_id) if (fg >= 0 && TS_set_foreground) { p = tparam (TS_set_foreground, NULL, 0, (int) fg); - OUTPUT (p); + OUTPUT (FRAME_TTY (f), p); xfree (p); } if (bg >= 0 && TS_set_background) { p = tparam (TS_set_background, NULL, 0, (int) bg); - OUTPUT (p); + OUTPUT (FRAME_TTY (f), p); xfree (p); } } @@ -1928,23 +1943,23 @@ turn_off_face (f, face_id) || face->tty_blinking_p || face->tty_underline_p) { - OUTPUT1_IF (TS_exit_attribute_mode); + OUTPUT1_IF (FRAME_TTY (f), TS_exit_attribute_mode); if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0) standout_mode = 0; } if (face->tty_alt_charset_p) - OUTPUT_IF (TS_exit_alt_charset_mode); + OUTPUT_IF (FRAME_TTY (f), TS_exit_alt_charset_mode); } else { /* If we don't have "me" we can only have those appearances that have exit sequences defined. */ if (face->tty_alt_charset_p) - OUTPUT_IF (TS_exit_alt_charset_mode); + OUTPUT_IF (FRAME_TTY (f), TS_exit_alt_charset_mode); if (face->tty_underline_p) - OUTPUT_IF (TS_exit_underline_mode); + OUTPUT_IF (FRAME_TTY (f), TS_exit_underline_mode); } /* Switch back to default colors. */ @@ -1953,7 +1968,7 @@ turn_off_face (f, face_id) && face->foreground != FACE_TTY_DEFAULT_FG_COLOR) || (face->background != FACE_TTY_DEFAULT_COLOR && face->background != FACE_TTY_DEFAULT_BG_COLOR))) - OUTPUT1_IF (TS_orig_pair); + OUTPUT1_IF (FRAME_TTY (f), TS_orig_pair); } @@ -2144,12 +2159,46 @@ set_tty_color_mode (f, val) #endif /* !WINDOWSNT */ + +struct tty_output * +get_named_tty (name) + char *name; +{ + struct tty_output *tty = tty_list; + + while (tty) { + if ((tty->name == 0 && name == 0) + || (name && tty->name && !strcmp (tty->name, name))) + return tty; + tty = tty->next; + }; + + return 0; +} + + /*********************************************************************** Initialization ***********************************************************************/ -void -term_init (terminal_type) +struct tty_output * +term_dummy_init (void) +{ + if (initialized || tty_list) + error ("tty already initialized"); + + tty_list = xmalloc (sizeof (struct tty_output)); + bzero (tty_list, sizeof (struct tty_output)); + TTY_NAME (tty_list) = 0; + TTY_INPUT (tty_list) = stdin; + TTY_OUTPUT (tty_list) = stdout; + return tty_list; +} + + +struct tty_output * +term_init (name, terminal_type) + char *name; char *terminal_type; { char *area; @@ -2160,6 +2209,52 @@ term_init (terminal_type) int status; struct frame *sf = XFRAME (selected_frame); + struct tty_output *tty; + + tty = get_named_tty (name); + if (tty) + { + /* Return the previously initialized terminal, except if it is the dummy + terminal created for the initial frame. */ + if (tty->type) + return tty; + } + else + { + if (!terminal_type) + error ("Unknown terminal type"); + + tty = (struct tty_output *) xmalloc (sizeof (struct tty_output)); + bzero (tty, sizeof (struct tty_output)); + tty->next = tty_list; + tty_list = tty; + } + + if (name) + { + int fd; + FILE *f; + fd = emacs_open (name, O_RDWR, 0); + if (fd < 0) + { + tty_list = tty->next; + xfree (tty); + error ("could not open file: %s", name); + } + f = fdopen (fd, "w+"); + TTY_NAME (tty) = xstrdup (name); + TTY_INPUT (tty) = f; + TTY_OUTPUT (tty) = f; + } + else + { + TTY_NAME (tty) = 0; + TTY_INPUT (tty) = stdin; + TTY_OUTPUT (tty) = stdout; + } + + init_sys_modes (tty); + #ifdef WINDOWSNT initialize_w32_display (); @@ -2174,15 +2269,15 @@ term_init (terminal_type) delete_in_insert_mode = 1; UseTabs = 0; - TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 0; + TTY_SCROLL_REGION_OK (tty) = 0; /* Seems to insert lines when it's not supposed to, messing up the display. In doing a trace, it didn't seem to be called much, so I don't think we're losing anything by turning it off. */ + TTY_LINE_INS_DEL_OK (tty) = 0; - TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 0; - TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; + TTY_CHAR_INS_DEL_OK (tty) = 1; baud_rate = 19200; @@ -2190,11 +2285,13 @@ term_init (terminal_type) FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none; TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */ - return; + return tty; #else /* not WINDOWSNT */ Wcm_clear (); + TTY_TYPE (tty) = xstrdup (terminal_type); + buffer = (char *) xmalloc (buffer_size); status = tgetent (buffer, terminal_type); if (status < 0) @@ -2213,14 +2310,14 @@ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", - terminal_type); + terminal_type); #else fatal ("Terminal type %s is not defined.\n\ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", - terminal_type); + terminal_type); #endif } @@ -2326,7 +2423,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", TN_no_color_video = tgetnum ("NC"); if (TN_no_color_video == -1) - TN_no_color_video = 0; + TN_no_color_video = 0; } tty_default_color_capabilities (1); @@ -2335,9 +2432,9 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", /* Since we make MagicWrap terminals look like AutoWrap, we need to have the former flag imply the latter. */ AutoWrap = MagicWrap || tgetflag ("am"); - TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = tgetflag ("db"); + TTY_MEMORY_BELOW_FRAME (tty) = tgetflag ("db"); TF_hazeltine = tgetflag ("hz"); - TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ()) = tgetflag ("in"); + TTY_MUST_WRITE_SPACES (tty) = tgetflag ("in"); meta_key = tgetflag ("km") || tgetflag ("MT"); TF_insmode_motion = tgetflag ("mi"); TF_standout_motion = tgetflag ("ms"); @@ -2364,12 +2461,12 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3) fatal ("Screen size %dx%d is too small", - FRAME_LINES (sf), FRAME_COLS (sf)); + FRAME_LINES (sf), FRAME_COLS (sf)); #if 0 /* This is not used anywhere. */ - TERMINAL_MIN_PADDING_SPEED (CURRENT_TERMINAL ()) = tgetnum ("pb"); + TTY_MIN_PADDING_SPEED (tty) = tgetnum ("pb"); #endif - + TabWidth = tgetnum ("tw"); #ifdef VMS @@ -2424,9 +2521,9 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", { char *s = tgetstr ("me", address); if (s != 0) - TS_end_standout_mode = s; + TS_end_standout_mode = s; else - TS_standout_mode = 0; + TS_standout_mode = 0; } if (TF_teleray) @@ -2445,7 +2542,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", if (!strcmp (terminal_type, "supdup")) { - TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 1; + TTY_MEMORY_BELOW_FRAME (tty) = 1; Wcm.cm_losewrap = 1; } if (!strncmp (terminal_type, "c10", 3) @@ -2455,7 +2552,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", This string is not valid in general since it works only for windows starting at the upper left corner; but that is all Emacs uses. - + This string works only if the frame is using the top of the video memory, because addressing is memory-relative. So first check the :ti string to see if that is true. @@ -2472,7 +2569,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", TS_set_window = "\033v%C %C %C %C "; } /* Termcap entry often fails to have :in: flag */ - TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ()) = 1; + TTY_MUST_WRITE_SPACES (tty) = 1; /* :ti string typically fails to have \E^G! in it */ /* This limits scope of insert-char to one line. */ strcpy (area, TS_termcap_modes); @@ -2481,13 +2578,13 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", area += strlen (area) + 1; p = AbsPosition; /* Change all %+ parameters to %C, to handle - values above 96 correctly for the C100. */ + values above 96 correctly for the C100. */ while (*p) - { - if (p[0] == '%' && p[1] == '+') - p[1] = 'C'; - p++; - } + { + if (p[0] == '%' && p[1] == '+') + p[1] = 'C'; + p++; + } } FrameRows = FRAME_LINES (sf); @@ -2504,21 +2601,21 @@ or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.", terminal_type); #else /* not VMS */ # ifdef TERMINFO - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ + fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ It lacks the ability to position the cursor.\n\ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", - terminal_type); + terminal_type); # else /* TERMCAP */ - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ + fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ It lacks the ability to position the cursor.\n\ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", - terminal_type); + terminal_type); # endif /* TERMINFO */ #endif /*VMS */ if (FRAME_LINES (sf) <= 0 @@ -2527,34 +2624,34 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", delete_in_insert_mode = TS_delete_mode && TS_insert_mode - && !strcmp (TS_delete_mode, TS_insert_mode); + && !strcmp (TS_delete_mode, TS_insert_mode); se_is_so = (TS_standout_mode - && TS_end_standout_mode - && !strcmp (TS_standout_mode, TS_end_standout_mode)); + && TS_end_standout_mode + && !strcmp (TS_standout_mode, TS_end_standout_mode)); UseTabs = tabs_safe_p () && TabWidth == 8; - TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) + TTY_SCROLL_REGION_OK (tty) = (Wcm.cm_abs && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1)); - TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) + TTY_LINE_INS_DEL_OK (tty) = (((TS_ins_line || TS_ins_multi_lines) && (TS_del_line || TS_del_multi_lines)) - || (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) + || (TTY_SCROLL_REGION_OK (tty) && TS_fwd_scroll && TS_rev_scroll)); - - TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) + + TTY_CHAR_INS_DEL_OK (tty) = ((TS_ins_char || TS_insert_mode || TS_pad_inserted_char || TS_ins_multi_chars) && (TS_del_char || TS_del_multi_chars)); - TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = TS_clr_line != 0; + TTY_FAST_CLEAR_END_OF_LINE (tty) = TS_clr_line != 0; init_baud_rate (); - if (read_socket_hook) /* Baudrate is somewhat */ - /* meaningless in this case */ + if (read_socket_hook) /* Baudrate is somewhat + meaningless in this case */ baud_rate = 9600; FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0; @@ -2562,6 +2659,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", #endif /* WINDOWSNT */ xfree (buffer); + + return tty; } /* VARARGS 1 */ @@ -2597,5 +2696,12 @@ The function should accept no arguments. */); defsubr (&Stty_display_color_cells); } +struct tty_output * +get_current_tty () +{ + return CURTTY(); +} + + /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193 (do not change this comment) */ diff --git a/src/termchar.h b/src/termchar.h index b7c82d0493..9d7399e80d 100644 --- a/src/termchar.h +++ b/src/termchar.h @@ -18,10 +18,37 @@ along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -struct terminal +/* Each termcap frame points to its own struct tty_output object in the + output_data.tty field. The tty_output structure contains the information + that is specific to terminals. */ +struct tty_output { + char *name; /* The name of the device file or 0 if + stdin/stdout. */ + char *type; /* The type of the tty. */ + + /* Input/output */ + + FILE *input; /* The stream to be used for terminal input. */ + FILE *output; /* The stream to be used for terminal output. */ + + FILE *termscript; /* If nonzero, send all terminal output + characters to this stream also. */ + + struct emacs_tty old_tty; /* The initial tty mode bits */ + + int term_initted; /* 1 if we have been through init_sys_modes. */ + int old_tty_valid; /* 1 if outer tty status has been recorded. */ + + + /* Pixel values. + XXX What are these used for? */ + + unsigned long background_pixel; + unsigned long foreground_pixel; + + /* Terminal characteristics. */ - /* EMACS_INT baud_rate; */ /* Output speed in baud */ int must_write_spaces; /* Nonzero means spaces in the text must actually be output; can't just skip over some columns to leave them blank. */ @@ -37,31 +64,43 @@ struct terminal off bottom */ #if 0 /* These are not used anywhere. */ + /* EMACS_INT baud_rate; */ /* Output speed in baud */ int min_padding_speed; /* Speed below which no padding necessary. */ int dont_calculate_costs; /* Nonzero means don't bother computing various cost tables; we won't use them. */ #endif + + struct tty_output *next; }; -typedef struct terminal *TERMINAL_PTR; +extern struct tty_output *tty_list; + + +#define FRAME_TTY(f) \ + ((f)->output_method == output_termcap \ + ? (f)->output_data.tty : (abort(), (struct tty_output *) 0)) + +#define CURTTY() FRAME_TTY (SELECTED_FRAME()) -extern TERMINAL_PTR current_terminal; +#define TTY_NAME(t) ((t)->name) +#define TTY_TYPE(t) ((t)->type) -#define CURRENT_TERMINAL() \ - (current_terminal ? current_terminal : (abort(), (TERMINAL_PTR) 0)) +#define TTY_INPUT(t) ((t)->input) +#define TTY_OUTPUT(t) ((t)->output) +#define TTY_TERMSCRIPT(t) ((t)->termscript) -#define TERMINAL_MUST_WRITE_SPACES(t) ((t)->must_write_spaces) -#define TERMINAL_FAST_CLEAR_END_OF_LINE(t) ((t)->fast_clear_end_of_line) -#define TERMINAL_LINE_INS_DEL_OK(t) ((t)->line_ins_del_ok) -#define TERMINAL_CHAR_INS_DEL_OK(t) ((t)->char_ins_del_ok) -#define TERMINAL_SCROLL_REGION_OK(t) ((t)->scroll_region_ok) -#define TERMINAL_SCROLL_REGION_COST(t) ((t)->scroll_region_cost) -#define TERMINAL_MEMORY_BELOW_FRAME(t) ((t)->memory_below_frame) +#define TTY_MUST_WRITE_SPACES(t) ((t)->must_write_spaces) +#define TTY_FAST_CLEAR_END_OF_LINE(t) ((t)->fast_clear_end_of_line) +#define TTY_LINE_INS_DEL_OK(t) ((t)->line_ins_del_ok) +#define TTY_CHAR_INS_DEL_OK(t) ((t)->char_ins_del_ok) +#define TTY_SCROLL_REGION_OK(t) ((t)->scroll_region_ok) +#define TTY_SCROLL_REGION_COST(t) ((t)->scroll_region_cost) +#define TTY_MEMORY_BELOW_FRAME(t) ((t)->memory_below_frame) #if 0 /* These are not used anywhere. */ -#define TERMINAL_MIN_PADDING_SPEED(t) ((t)->min_padding_speed) -#define TERMINAL_DONT_CALCULATE_COSTS(t) ((t)->dont_calculate_costs) +#define TTY_MIN_PADDING_SPEED(t) ((t)->min_padding_speed) +#define TTY_DONT_CALCULATE_COSTS(t) ((t)->dont_calculate_costs) #endif /* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193 diff --git a/src/termhooks.h b/src/termhooks.h index d76d06671e..c1ada7b851 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -25,9 +25,6 @@ Boston, MA 02111-1307, USA. */ struct glyph; struct frame; -/* If nonzero, send all terminal output characters to this stream also. */ -extern FILE *termscript; - /* Only use prototypes when lisp.h has been included. */ #ifndef P_ #define P_(X) () diff --git a/src/w32term.c b/src/w32term.c index cf8d07a18f..06d82a7bee 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -6366,11 +6366,11 @@ w32_initialize () redeem_scroll_bar_hook = w32_redeem_scroll_bar; judge_scroll_bars_hook = w32_judge_scroll_bars; - TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 1; /* we'll scroll partial frames */ - TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; - TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; /* we'll just blt 'em */ - TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = 1; /* X does this well */ - TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 0; /* we don't remember what + TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */ + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1; + TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */ + TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */ + TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what scrolls off the bottom */ baud_rate = 19200; diff --git a/src/w32term.h b/src/w32term.h index de28620c7b..68967ad7d2 100644 --- a/src/w32term.h +++ b/src/w32term.h @@ -389,8 +389,6 @@ extern struct w32_output w32term_display; #define FRAME_W32_WINDOW(f) ((f)->output_data.w32->window_desc) #define FRAME_X_WINDOW(f) ((f)->output_data.w32->window_desc) -#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel) -#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel) #define FRAME_FONT(f) ((f)->output_data.w32->font) #define FRAME_FONTSET(f) ((f)->output_data.w32->fontset) #define FRAME_BASELINE_OFFSET(f) ((f)->output_data.w32->baseline_offset) diff --git a/src/window.c b/src/window.c index 3c0f3a1743..48e517a68f 100644 --- a/src/window.c +++ b/src/window.c @@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */ #include "window.h" #include "commands.h" #include "indent.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "disptab.h" #include "dispextern.h" @@ -6381,7 +6382,7 @@ and scrolling positions. */) void init_window_once () { - struct frame *f = make_terminal_frame (); + struct frame *f = make_terminal_frame (0, 0); XSETFRAME (selected_frame, f); Vterminal_frame = selected_frame; minibuf_window = f->minibuffer_window; diff --git a/src/xdisp.c b/src/xdisp.c index 252c6c824b..cedfa9a72d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -173,6 +173,7 @@ Boston, MA 02111-1307, USA. */ #include "keyboard.h" #include "frame.h" #include "window.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "dispextern.h" #include "buffer.h" @@ -12889,7 +12890,7 @@ try_window_id (w) /* Window must either use window-based redisplay or be full width. */ if (!FRAME_WINDOW_P (f) - && (!TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) + && (!TTY_LINE_INS_DEL_OK (CURTTY ()) || !WINDOW_FULL_WIDTH_P (w))) GIVE_UP (4); @@ -13322,7 +13323,7 @@ try_window_id (w) /* On dumb terminals delete dvpos lines at the end before inserting dvpos empty lines. */ - if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())) + if (!TTY_SCROLL_REGION_OK (CURTTY ())) ins_del_lines (end - dvpos, -dvpos); /* Insert dvpos empty lines in front of @@ -13343,7 +13344,7 @@ try_window_id (w) /* On a dumb terminal insert dvpos empty lines at the end. */ - if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())) + if (!TTY_SCROLL_REGION_OK (CURTTY ())) ins_del_lines (end + dvpos, -dvpos); } diff --git a/src/xfaces.c b/src/xfaces.c index 96a1d52b3c..faae8352cb 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -241,6 +241,8 @@ Boston, MA 02111-1307, USA. */ #include "blockinput.h" #include "window.h" #include "intervals.h" +#include "systty.h" /* For emacs_tty in termchar.h */ +#include "termchar.h" #ifdef HAVE_X_WINDOWS diff --git a/src/xfns.c b/src/xfns.c index cd50cbbc91..94a7441798 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -48,6 +48,8 @@ Boston, MA 02111-1307, USA. */ #include "systime.h" #include "termhooks.h" #include "atimer.h" +#include "systty.h" +#include "termchar.h" #ifdef HAVE_X_WINDOWS -- 2.20.1