X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/e4019195fdc2c3c121057ab29f7f1045b656db81..65b3d997c854ed75f4557617faeea2e79fc14aac:/src/term.c diff --git a/src/term.c b/src/term.c index 98d3b86834..78bf77d9d7 100644 --- a/src/term.c +++ b/src/term.c @@ -1,13 +1,14 @@ /* Terminal control module for terminals described by TERMCAP Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs 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 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,9 +16,7 @@ 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 GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ /* New redisplay, TTY faces by Gerd Moellmann . */ @@ -37,12 +36,17 @@ Boston, MA 02110-1301, USA. */ #endif #include +#include +#include #include "lisp.h" #include "termchar.h" #include "termopts.h" +#include "buffer.h" +#include "character.h" #include "charset.h" #include "coding.h" +#include "composite.h" #include "keyboard.h" #include "frame.h" #include "disptab.h" @@ -54,6 +58,10 @@ Boston, MA 02110-1301, USA. */ #include "syssignal.h" #include "systty.h" #include "intervals.h" +#ifdef MSDOS +#include "msdos.h" +static int been_here = -1; +#endif /* For now, don't try to include termcap.h. On some systems, configure finds a non-standard termcap.h that the main build @@ -72,9 +80,6 @@ extern int tgetnum P_ ((char *id)); #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif -#ifdef MAC_OS -#include "macterm.h" -#endif #ifndef O_RDWR #define O_RDWR 2 @@ -84,6 +89,13 @@ extern int tgetnum P_ ((char *id)); #define O_NOCTTY 0 #endif +/* The name of the default console device. */ +#ifdef WINDOWSNT +#define DEV_TTY "CONOUT$" +#else +#define DEV_TTY "/dev/tty" +#endif + static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop)); static void turn_on_face P_ ((struct frame *, int face_id)); static void turn_off_face P_ ((struct frame *, int face_id)); @@ -175,31 +187,16 @@ static int system_uses_terminfo; char *tparam (); extern char *tgetstr (); - -static void term_clear_mouse_face (); -static void term_mouse_highlight (struct frame *f, int x, int y); -#ifdef WINDOWSNT -/* We aren't X windows, but we aren't termcap either. This makes me - uncertain as to what value to use for frame.output_method. For - this file, we'll define FRAME_TERMCAP_P to be zero so that our - output hooks get called instead of the termcap functions. Probably - the best long-term solution is to define an output_windows_nt... */ - -#undef FRAME_TERMCAP_P -#define FRAME_TERMCAP_P(_f_) 0 -#endif /* WINDOWSNT */ - #ifdef HAVE_GPM #include -#include "buffer.h" -/* Nonzero means mouse is enabled on Linux console. */ -int term_gpm = 0; +static void term_clear_mouse_face (); +static void term_mouse_highlight (struct frame *f, int x, int y); -/* The id of the terminal device for which we have gpm support. */ -int gpm_tty; +/* The device for which we have enabled gpm support (or NULL). */ +struct tty_display_info *gpm_tty = NULL; /* These variables describe the range of text currently shown in its mouse-face, together with the window they apply to. As long as @@ -209,7 +206,7 @@ int gpm_tty; static int mouse_face_beg_row, mouse_face_beg_col; static int mouse_face_end_row, mouse_face_end_col; static int mouse_face_past_end; -static Lisp_Object Qmouse_face_window; +static Lisp_Object mouse_face_window; static int mouse_face_face_id; static int pos_x, pos_y; @@ -238,7 +235,7 @@ void tty_set_terminal_modes (struct terminal *terminal) { struct tty_display_info *tty = terminal->display_info.tty; - + if (tty->output) { if (tty->TS_termcap_modes) @@ -253,7 +250,6 @@ tty_set_terminal_modes (struct terminal *terminal) cmputc ('\n'); } - OUTPUT_IF (tty, tty->TS_termcap_modes); OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal); OUTPUT_IF (tty, tty->TS_keypad_mode); losecursor (tty); @@ -554,10 +550,12 @@ tty_clear_end_of_line (struct frame *f, int first_unused_hpos) } } -/* Buffer to store the source and result of code conversion for terminal. */ -static unsigned char *encode_terminal_buf; -/* Allocated size of the above buffer. */ -static int encode_terminal_bufsize; +/* Buffers to store the source and result of code conversion for terminal. */ +static unsigned char *encode_terminal_src; +static unsigned char *encode_terminal_dst; +/* Allocated sizes of the above buffers. */ +static int encode_terminal_src_size; +static int encode_terminal_dst_size; /* Encode SRC_LEN glyphs starting at SRC to terminal output codes. Set CODING->produced to the byte-length of the resulting byte @@ -570,42 +568,106 @@ encode_terminal_code (src, src_len, coding) struct coding_system *coding; { struct glyph *src_end = src + src_len; - register GLYPH g; unsigned char *buf; int nchars, nbytes, required; register int tlen = GLYPH_TABLE_LENGTH; register Lisp_Object *tbase = GLYPH_TABLE_BASE; + Lisp_Object charset_list; /* Allocate sufficient size of buffer to store all characters in multibyte-form. But, it may be enlarged on demand if - Vglyph_table contains a string. */ + Vglyph_table contains a string or a composite glyph is + encountered. */ required = MAX_MULTIBYTE_LENGTH * src_len; - if (encode_terminal_bufsize < required) + if (encode_terminal_src_size < required) { - if (encode_terminal_bufsize == 0) - encode_terminal_buf = xmalloc (required); + if (encode_terminal_src) + encode_terminal_src = xrealloc (encode_terminal_src, required); else - encode_terminal_buf = xrealloc (encode_terminal_buf, required); - encode_terminal_bufsize = required; + encode_terminal_src = xmalloc (required); + encode_terminal_src_size = required; } - buf = encode_terminal_buf; + charset_list = coding_charset_list (coding); + + buf = encode_terminal_src; nchars = 0; while (src < src_end) { + if (src->type == COMPOSITE_GLYPH) + { + struct composition *cmp; + Lisp_Object gstring; + int i; + + nbytes = buf - encode_terminal_src; + if (src->u.cmp.automatic) + { + gstring = composition_gstring_from_id (src->u.cmp.id); + required = src->u.cmp.to + 1 - src->u.cmp.from; + } + else + { + cmp = composition_table[src->u.cmp.id]; + required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len; + } + + if (encode_terminal_src_size < nbytes + required) + { + encode_terminal_src_size = nbytes + required; + encode_terminal_src = xrealloc (encode_terminal_src, + encode_terminal_src_size); + buf = encode_terminal_src + nbytes; + } + + if (src->u.cmp.automatic) + for (i = src->u.cmp.from; i <= src->u.cmp.to; i++) + { + Lisp_Object g = LGSTRING_GLYPH (gstring, i); + int c = LGLYPH_CHAR (g); + + if (! char_charset (c, charset_list, NULL)) + c = '?'; + buf += CHAR_STRING (c, buf); + nchars++; + } + else + for (i = 0; i < cmp->glyph_len; i++) + { + int c = COMPOSITION_GLYPH (cmp, i); + + if (c == '\t') + continue; + if (char_charset (c, charset_list, NULL)) + { + if (CHAR_WIDTH (c) == 0 + && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t') + /* Should be left-padded */ + { + buf += CHAR_STRING (' ', buf); + nchars++; + } + } + else + c = '?'; + buf += CHAR_STRING (c, buf); + nchars++; + } + } /* We must skip glyphs to be padded for a wide character. */ - if (! CHAR_GLYPH_PADDING_P (*src)) + else if (! CHAR_GLYPH_PADDING_P (*src)) { - g = GLYPH_FROM_CHAR_GLYPH (src[0]); + GLYPH g; + int c; + Lisp_Object string; + + string = Qnil; + SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]); - if (g < 0 || g >= tlen) + if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g)) { - /* This glyph doesn't has an entry in Vglyph_table. */ - if (CHAR_VALID_P (src->u.ch, 0)) - buf += CHAR_STRING (src->u.ch, buf); - else - *buf++ = SPACEGLYPH; - nchars++; + /* This glyph doesn't have an entry in Vglyph_table. */ + c = src->u.ch; } else { @@ -614,65 +676,95 @@ encode_terminal_code (src, src_len, coding) GLYPH_FOLLOW_ALIASES (tbase, tlen, g); if (GLYPH_SIMPLE_P (tbase, tlen, g)) - { - int c = FAST_GLYPH_CHAR (g); + /* We set the multi-byte form of a character in G + (that should be an ASCII character) at WORKBUF. */ + c = GLYPH_CHAR (g); + else + /* We have a string in Vglyph_table. */ + string = tbase[GLYPH_CHAR (g)]; + } - if (CHAR_VALID_P (c, 0)) - buf += CHAR_STRING (c, buf); - else - *buf++ = SPACEGLYPH; + if (NILP (string)) + { + nbytes = buf - encode_terminal_src; + if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH) + { + encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH; + encode_terminal_src = xrealloc (encode_terminal_src, + encode_terminal_src_size); + buf = encode_terminal_src + nbytes; + } + if (CHAR_BYTE8_P (c) + || char_charset (c, charset_list, NULL)) + { + /* Store the multibyte form of C at BUF. */ + buf += CHAR_STRING (c, buf); nchars++; } else { - /* We have a string in Vglyph_table. */ - Lisp_Object string; - - string = tbase[g]; - if (! STRING_MULTIBYTE (string)) - string = string_to_multibyte (string); - nbytes = buf - encode_terminal_buf; - if (encode_terminal_bufsize < nbytes + SBYTES (string)) + /* C is not encodable. */ + *buf++ = '?'; + nchars++; + while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1])) { - encode_terminal_bufsize = nbytes + SBYTES (string); - encode_terminal_buf = xrealloc (encode_terminal_buf, - encode_terminal_bufsize); - buf = encode_terminal_buf + nbytes; + *buf++ = '?'; + nchars++; + src++; } - bcopy (SDATA (string), buf, SBYTES (string)); - buf += SBYTES (string); - nchars += SCHARS (string); } } + else + { + unsigned char *p = SDATA (string), *pend = p + SBYTES (string); + + if (! STRING_MULTIBYTE (string)) + string = string_to_multibyte (string); + nbytes = buf - encode_terminal_src; + if (encode_terminal_src_size < nbytes + SBYTES (string)) + { + encode_terminal_src_size = nbytes + SBYTES (string); + encode_terminal_src = xrealloc (encode_terminal_src, + encode_terminal_src_size); + buf = encode_terminal_src + nbytes; + } + bcopy (SDATA (string), buf, SBYTES (string)); + buf += SBYTES (string); + nchars += SCHARS (string); + } } src++; } - nbytes = buf - encode_terminal_buf; - coding->src_multibyte = 1; - coding->dst_multibyte = 0; - if (SYMBOLP (coding->pre_write_conversion) - && ! NILP (Ffboundp (coding->pre_write_conversion))) + if (nchars == 0) { - run_pre_write_conversin_on_c_str (&encode_terminal_buf, - &encode_terminal_bufsize, - nchars, nbytes, coding); - nchars = coding->produced_char; - nbytes = coding->produced; + coding->produced = 0; + return NULL; } - required = nbytes + encoding_buffer_size (coding, nbytes); - if (encode_terminal_bufsize < required) + + nbytes = buf - encode_terminal_src; + coding->source = encode_terminal_src; + if (encode_terminal_dst_size == 0) { - encode_terminal_bufsize = required; - encode_terminal_buf = xrealloc (encode_terminal_buf, required); + encode_terminal_dst_size = encode_terminal_src_size; + if (encode_terminal_dst) + encode_terminal_dst = xrealloc (encode_terminal_dst, + encode_terminal_dst_size); + else + encode_terminal_dst = xmalloc (encode_terminal_dst_size); } + coding->destination = encode_terminal_dst; + coding->dst_bytes = encode_terminal_dst_size; + encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil); + /* coding->destination may have been reallocated. */ + encode_terminal_dst = coding->destination; + encode_terminal_dst_size = coding->dst_bytes; - encode_coding (coding, encode_terminal_buf, encode_terminal_buf + nbytes, - nbytes, encode_terminal_bufsize - nbytes); - return encode_terminal_buf + nbytes; + return (encode_terminal_dst); } + /* An implementation of write_glyphs for termcap frames. */ static void @@ -746,6 +838,8 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len) cmcheckmagic (tty); } +#ifdef HAVE_GPM /* Only used by GPM code. */ + static void tty_write_glyphs_with_face (f, string, len, face_id) register struct frame *f; @@ -804,7 +898,7 @@ tty_write_glyphs_with_face (f, string, len, face_id) cmcheckmagic (tty); } - +#endif /* An implementation of insert_glyphs for termcap frames. */ @@ -954,7 +1048,7 @@ tty_ins_del_lines (struct frame *f, int vpos, int n) if (!FRAME_MEMORY_BELOW_FRAME (f) && vpos + i >= FRAME_LINES (f)) return; - + if (multi) { raw_cursor_to (f, vpos, 0); @@ -984,7 +1078,7 @@ tty_ins_del_lines (struct frame *f, int vpos, int n) OUTPUTL (tty, scroll, tty->specified_window - vpos); tty_set_scroll_region (f, 0, tty->specified_window); } - + if (!FRAME_SCROLL_REGION_OK (f) && FRAME_MEMORY_BELOW_FRAME (f) && n < 0) @@ -1279,9 +1373,9 @@ static char **term_get_fkeys_address; static KBOARD *term_get_fkeys_kboard; static Lisp_Object term_get_fkeys_1 (); -/* Find the escape codes sent by the function keys for Vfunction_key_map. +/* Find the escape codes sent by the function keys for Vinput_decode_map. This function scans the termcap function key sequence entries, and - adds entries to Vfunction_key_map for each function key it finds. */ + adds entries to Vinput_decode_map for each function key it finds. */ static void term_get_fkeys (address, kboard) @@ -1309,16 +1403,16 @@ term_get_fkeys_1 () char **address = term_get_fkeys_address; KBOARD *kboard = term_get_fkeys_kboard; - + /* This can happen if CANNOT_DUMP or with strange options. */ - if (!initialized) - kboard->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil); + if (!KEYMAPP (kboard->Vinput_decode_map)) + kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil); for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++) { char *sequence = tgetstr (keys[i].cap, address); if (sequence) - Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence), + Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), Fmake_vector (make_number (1), intern (keys[i].name))); } @@ -1338,13 +1432,13 @@ term_get_fkeys_1 () if (k0) /* Define f0 first, so that f10 takes precedence in case the key sequences happens to be the same. */ - Fdefine_key (kboard->Vlocal_function_key_map, build_string (k0), + Fdefine_key (kboard->Vinput_decode_map, build_string (k0), Fmake_vector (make_number (1), intern ("f0"))); - Fdefine_key (kboard->Vlocal_function_key_map, build_string (k_semi), + Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi), Fmake_vector (make_number (1), intern ("f10"))); } else if (k0) - Fdefine_key (kboard->Vlocal_function_key_map, build_string (k0), + Fdefine_key (kboard->Vinput_decode_map, build_string (k0), Fmake_vector (make_number (1), intern (k0_name))); } @@ -1367,7 +1461,7 @@ term_get_fkeys_1 () if (sequence) { sprintf (fkey, "f%d", i); - Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence), + Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), Fmake_vector (make_number (1), intern (fkey))); } @@ -1384,7 +1478,7 @@ term_get_fkeys_1 () { \ char *sequence = tgetstr (cap2, address); \ if (sequence) \ - Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence), \ + Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \ Fmake_vector (make_number (1), \ intern (sym))); \ } @@ -1424,11 +1518,14 @@ term_get_fkeys_1 () #ifdef static #define append_glyph append_glyph_term #define produce_stretch_glyph produce_stretch_glyph_term +#define append_composite_glyph append_composite_glyph_term +#define produce_composite_glyph produce_composite_glyph_term #endif static void append_glyph P_ ((struct it *)); static void produce_stretch_glyph P_ ((struct it *)); - +static void append_composite_glyph P_ ((struct it *)); +static void produce_composite_glyph P_ ((struct it *)); /* Append glyphs to IT's glyph_row. Called from produce_glyphs for terminal frames if IT->glyph_row != NULL. IT->char_to_display is @@ -1471,8 +1568,9 @@ append_glyph (it) and where in the glyph matrix we currently are (glyph row and hpos). produce_glyphs fills in output fields of *IT with information such as the pixel width and height of a character, and maybe output actual glyphs at - the same time if IT->glyph_row is non-null. See the explanation of - struct display_iterator in dispextern.h for an overview. + the same time if IT->glyph_row is non-null. For an overview, see + the explanation in dispextern.h, before the definition of the + display_element_type enumeration. produce_glyphs also stores the result of glyph width, ascent etc. computations in *IT. @@ -1489,6 +1587,8 @@ produce_glyphs (it) struct it *it; { /* If a hook is installed, let it do the work. */ + + /* Nothing but characters are supported on terminal frames. */ xassert (it->what == IT_CHARACTER || it->what == IT_COMPOSITION || it->what == IT_STRETCH); @@ -1499,24 +1599,21 @@ produce_glyphs (it) goto done; } - /* Nothing but characters are supported on terminal frames. For a - composition sequence, it->c is the first character of the - sequence. */ - xassert (it->what == IT_CHARACTER - || it->what == IT_COMPOSITION); - - /* Maybe translate single-byte characters to multibyte. */ - it->char_to_display = it->c; + if (it->what == IT_COMPOSITION) + { + produce_composite_glyph (it); + goto done; + } - if (it->c >= 040 && it->c < 0177) + if (it->char_to_display >= 040 && it->char_to_display < 0177) { it->pixel_width = it->nglyphs = 1; if (it->glyph_row) append_glyph (it); } - else if (it->c == '\n') + else if (it->char_to_display == '\n') it->pixel_width = it->nglyphs = 0; - else if (it->c == '\t') + else if (it->char_to_display == '\t') { int absolute_x = (it->current_x + it->continuation_lines_width); @@ -1547,42 +1644,19 @@ produce_glyphs (it) it->pixel_width = nspaces; it->nglyphs = nspaces; } - else if (SINGLE_BYTE_CHAR_P (it->c)) + else if (CHAR_BYTE8_P (it->char_to_display)) { - if (unibyte_display_via_language_environment - && (it->c >= 0240 - || !NILP (Vnonascii_translation_table))) - { - int charset; - - it->char_to_display = unibyte_char_to_multibyte (it->c); - charset = CHAR_CHARSET (it->char_to_display); - it->pixel_width = CHARSET_WIDTH (charset); - it->nglyphs = it->pixel_width; - if (it->glyph_row) - append_glyph (it); - } - else - { - /* Coming here means that it->c is from display table, thus we - must send the code as is to the terminal. Although there's - no way to know how many columns it occupies on a screen, it - is a good assumption that a single byte code has 1-column - width. */ - it->pixel_width = it->nglyphs = 1; - if (it->glyph_row) - append_glyph (it); - } + /* Coming here means that we must send the raw 8-bit byte as is + to the terminal. Although there's no way to know how many + columns it occupies on a screen, it is a good assumption that + a single byte code has 1-column width. */ + it->pixel_width = it->nglyphs = 1; + if (it->glyph_row) + append_glyph (it); } else { - /* A multi-byte character. The display width is fixed for all - characters of the set. Some of the glyphs may have to be - ignored because they are already displayed in a continued - line. */ - int charset = CHAR_CHARSET (it->c); - - it->pixel_width = CHARSET_WIDTH (charset); + it->pixel_width = CHAR_WIDTH (it->char_to_display); it->nglyphs = it->pixel_width; if (it->glyph_row) @@ -1652,6 +1726,10 @@ produce_stretch_glyph (it) if (width <= 0 && (width < 0 || !zero_width_ok_p)) width = 1; + if (width > 0 && it->line_wrap != TRUNCATE + && it->current_x + width > it->last_visible_x) + width = it->last_visible_x - it->current_x - 1; + if (width > 0 && it->glyph_row) { Lisp_Object o_object = it->object; @@ -1672,6 +1750,78 @@ produce_stretch_glyph (it) } +/* Append glyphs to IT's glyph_row for the composition IT->cmp_id. + Called from produce_composite_glyph for terminal frames if + IT->glyph_row != NULL. IT->face_id contains the character's + face. */ + +static void +append_composite_glyph (it) + struct it *it; +{ + struct glyph *glyph; + + xassert (it->glyph_row); + glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area]; + if (glyph < it->glyph_row->glyphs[1 + it->area]) + { + glyph->type = COMPOSITE_GLYPH; + glyph->pixel_width = it->pixel_width; + glyph->u.cmp.id = it->cmp_it.id; + if (it->cmp_it.ch < 0) + { + glyph->u.cmp.automatic = 0; + glyph->u.cmp.id = it->cmp_it.id; + } + else + { + glyph->u.cmp.automatic = 1; + glyph->u.cmp.id = it->cmp_it.id; + glyph->u.cmp.from = it->cmp_it.from; + glyph->u.cmp.to = it->cmp_it.to - 1; + } + + glyph->face_id = it->face_id; + glyph->padding_p = 0; + glyph->charpos = CHARPOS (it->position); + glyph->object = it->object; + + ++it->glyph_row->used[it->area]; + ++glyph; + } +} + + +/* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of + the composition. We simply produces components of the composition + assuming that the terminal has a capability to layout/render it + correctly. */ + +static void +produce_composite_glyph (it) + struct it *it; +{ + int c; + + if (it->cmp_it.ch < 0) + { + struct composition *cmp = composition_table[it->cmp_it.id]; + + it->pixel_width = cmp->width; + } + else + { + Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id); + + it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from, + it->cmp_it.to, NULL); + } + it->nglyphs = 1; + if (it->glyph_row) + append_composite_glyph (it); +} + + /* Get information about special display element WHAT in an environment described by IT. WHAT is one of IT_TRUNCATION or IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a @@ -1684,6 +1834,7 @@ produce_special_glyphs (it, what) enum display_element_type what; { struct it temp_it; + Lisp_Object gc; GLYPH glyph; temp_it = *it; @@ -1696,34 +1847,32 @@ produce_special_glyphs (it, what) if (what == IT_CONTINUATION) { /* Continuation glyph. */ + SET_GLYPH_FROM_CHAR (glyph, '\\'); if (it->dp - && INTEGERP (DISP_CONTINUE_GLYPH (it->dp)) - && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp)))) + && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)) + && GLYPH_CODE_CHAR_VALID_P (gc)) { - glyph = XINT (DISP_CONTINUE_GLYPH (it->dp)); - glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph); + SET_GLYPH_FROM_GLYPH_CODE (glyph, gc); + spec_glyph_lookup_face (XWINDOW (it->window), &glyph); } - else - glyph = '\\'; } else if (what == IT_TRUNCATION) { /* Truncation glyph. */ + SET_GLYPH_FROM_CHAR (glyph, '$'); if (it->dp - && INTEGERP (DISP_TRUNC_GLYPH (it->dp)) - && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp)))) + && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)) + && GLYPH_CODE_CHAR_VALID_P (gc)) { - glyph = XINT (DISP_TRUNC_GLYPH (it->dp)); - glyph = spec_glyph_lookup_face (XWINDOW (it->window), glyph); + SET_GLYPH_FROM_GLYPH_CODE (glyph, gc); + spec_glyph_lookup_face (XWINDOW (it->window), &glyph); } - else - glyph = '$'; } else abort (); - temp_it.c = FAST_GLYPH_CHAR (glyph); - temp_it.face_id = FAST_GLYPH_FACE (glyph); + temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph); + temp_it.face_id = GLYPH_FACE (glyph); temp_it.len = CHAR_BYTES (temp_it.c); produce_glyphs (&temp_it); @@ -1806,14 +1955,11 @@ turn_on_face (f, face_id) } } - if (face->tty_bold_p) - { - if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD)) - OUTPUT1_IF (tty, tty->TS_enter_bold_mode); - } - else if (face->tty_dim_p) - if (MAY_USE_WITH_COLORS_P (tty, NC_DIM)) - OUTPUT1_IF (tty, tty->TS_enter_dim_mode); + if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD)) + OUTPUT1_IF (tty, tty->TS_enter_bold_mode); + + if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM)) + OUTPUT1_IF (tty, tty->TS_enter_dim_mode); /* Alternate charset and blinking not yet used. */ if (face->tty_alt_charset_p @@ -1934,9 +2080,9 @@ DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p, 0, 1, 0, doc: /* Return non-nil if the tty device TERMINAL can display colors. -TERMINAL can be a terminal id, a frame or nil (meaning the selected -frame's terminal). This function always returns nil if TERMINAL -is not on a tty device. */) +TERMINAL can be a terminal object, a frame, or nil (meaning the +selected frame's terminal). This function always returns nil if +TERMINAL does not refer to a text-only terminal. */) (terminal) Lisp_Object terminal; { @@ -1952,9 +2098,9 @@ DEFUN ("tty-display-color-cells", Ftty_display_color_cells, Stty_display_color_cells, 0, 1, 0, doc: /* Return the number of colors supported by the tty device TERMINAL. -TERMINAL can be a terminal id, a frame or nil (meaning the selected -frame's terminal). This function always returns 0 if TERMINAL -is not on a tty device. */) +TERMINAL can be a terminal object, a frame, or nil (meaning the +selected frame's terminal). This function always returns 0 if +TERMINAL does not refer to a text-only terminal. */) (terminal) Lisp_Object terminal; { @@ -1965,7 +2111,7 @@ is not on a tty device. */) return make_number (t->display_info.tty->TN_max_colors); } -#ifndef WINDOWSNT +#ifndef DOS_NT /* Declare here rather than in the function, as in the rest of Emacs, to work around an HPUX compiler bug (?). See @@ -1985,17 +2131,14 @@ tty_default_color_capabilities (struct tty_display_info *tty, int save) if (save) { - if (default_orig_pair) - xfree (default_orig_pair); + xfree (default_orig_pair); default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL; - if (default_set_foreground) - xfree (default_set_foreground); + xfree (default_set_foreground); default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground) : NULL; - if (default_set_background) - xfree (default_set_background); + xfree (default_set_background); default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background) : NULL; @@ -2054,60 +2197,42 @@ tty_setup_colors (struct tty_display_info *tty, int mode) } void -set_tty_color_mode (f, val) +set_tty_color_mode (tty, f) + struct tty_display_info *tty; struct frame *f; - Lisp_Object val; { - Lisp_Object color_mode_spec, current_mode_spec; - Lisp_Object color_mode, current_mode; - int mode, old_mode; + Lisp_Object tem, val, color_mode_spec; + Lisp_Object color_mode; + int mode; extern Lisp_Object Qtty_color_mode; - Lisp_Object tty_color_mode_alist; + Lisp_Object tty_color_mode_alist + = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil); - tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"), - Qnil); + tem = assq_no_quit (Qtty_color_mode, f->param_alist); + val = CONSP (tem) ? XCDR (tem) : Qnil; if (INTEGERP (val)) color_mode = val; else { - if (NILP (tty_color_mode_alist)) - color_mode_spec = Qnil; - else - color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value); - - if (CONSP (color_mode_spec)) - color_mode = XCDR (color_mode_spec); - else - color_mode = Qnil; + tem = (NILP (tty_color_mode_alist) ? Qnil + : Fassq (val, XSYMBOL (tty_color_mode_alist)->value)); + color_mode = CONSP (tem) ? XCDR (tem) : Qnil; } - current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist); - - if (CONSP (current_mode_spec)) - current_mode = XCDR (current_mode_spec); - else - current_mode = Qnil; - if (INTEGERP (color_mode)) - mode = XINT (color_mode); - else - mode = 0; /* meaning default */ - if (INTEGERP (current_mode)) - old_mode = XINT (current_mode); - else - old_mode = 0; + mode = INTEGERP (color_mode) ? XINT (color_mode) : 0; - if (mode != old_mode) + if (mode != tty->previous_color_mode) { - tty_setup_colors (FRAME_TTY (f), mode); - /* This recomputes all the faces given the new color - definitions. */ - call0 (intern ("tty-set-up-initial-frame-faces")); - redraw_frame (f); + Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces"); + tty->previous_color_mode = mode; + tty_setup_colors (tty , mode); + /* This recomputes all the faces given the new color definitions. */ + safe_call (1, &funsym); } } -#endif /* !WINDOWSNT */ +#endif /* !DOS_NT */ @@ -2118,10 +2243,7 @@ get_tty_terminal (Lisp_Object terminal, int throw) { struct terminal *t = get_terminal (terminal, throw); - if (t && t->type == output_initial) - return NULL; - - if (t && t->type != output_termcap) + if (t && t->type != output_termcap && t->type != output_msdos_raw) { if (throw) error ("Device %d is not a termcap terminal device", t->id); @@ -2138,7 +2260,7 @@ get_tty_terminal (Lisp_Object terminal, int throw) This function ignores suspended devices. Returns NULL if the named terminal device is not opened. */ - + struct terminal * get_named_tty (name) char *name; @@ -2150,7 +2272,7 @@ get_named_tty (name) for (t = terminal_list; t; t = t->next_terminal) { - if (t->type == output_termcap + if ((t->type == output_termcap || t->type == output_msdos_raw) && !strcmp (t->display_info.tty->name, name) && TERMINAL_ACTIVE_P (t)) return t; @@ -2164,14 +2286,14 @@ DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0, doc: /* Return the type of the tty device that TERMINAL uses. Returns nil if TERMINAL is not on a tty device. -TERMINAL can be a terminal id, a frame or nil (meaning the selected -frame's terminal). */) +TERMINAL can be a terminal object, a frame, or nil (meaning the +selected frame's terminal). */) (terminal) Lisp_Object terminal; { struct terminal *t = get_terminal (terminal, 1); - if (t->type != output_termcap) + if (t->type != output_termcap && t->type != output_msdos_raw) return Qnil; if (t->display_info.tty->type) @@ -2181,17 +2303,18 @@ frame's terminal). */) } DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0, - doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process. + doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process. -TERMINAL can be a terminal id, a frame or nil (meaning the selected -frame's terminal). This function always returns nil if TERMINAL -is not on a tty device. */) +TERMINAL can be a terminal object, a frame, or nil (meaning the +selected frame's terminal). This function always returns nil if +TERMINAL is not on a tty device. */) (terminal) Lisp_Object terminal; { struct terminal *t = get_terminal (terminal, 1); - if (t->type != output_termcap || strcmp (t->display_info.tty->name, "/dev/tty")) + if ((t->type != output_termcap && t->type != output_msdos_raw) + || strcmp (t->display_info.tty->name, DEV_TTY) != 0) return Qnil; else return Qt; @@ -2203,9 +2326,9 @@ This is used to override the terminfo data, for certain terminals that do not really do underlining, but say that they do. This function has no effect if used on a non-tty terminal. -TERMINAL can be a terminal id, a frame or nil (meaning the selected -frame's terminal). This function always returns nil if TERMINAL -is not on a tty device. */) +TERMINAL can be a terminal object, a frame or nil (meaning the +selected frame's terminal). This function always returns nil if +TERMINAL does not refer to a text-only terminal. */) (terminal) Lisp_Object terminal; { @@ -2226,8 +2349,8 @@ access to the tty device. Frames that use the device are not deleted, but input is not read from them and if they change, their display is not updated. -TTY may be a terminal id, a frame, or nil for the terminal device of -the currently selected frame. +TTY may be a terminal object, a frame, or nil for the terminal device +of the currently selected frame. This function runs `suspend-tty-functions' after suspending the device. The functions are run with one arg, the id of the suspended @@ -2242,36 +2365,43 @@ A suspended tty may be resumed by calling `resume-tty' on it. */) { struct terminal *t = get_tty_terminal (tty, 1); FILE *f; - + if (!t) error ("Unknown tty device"); f = t->display_info.tty->input; - + if (f) { + /* First run `suspend-tty-functions' and then clean up the tty + state because `suspend-tty-functions' might need to change + the tty state. */ + if (!NILP (Vrun_hooks)) + { + Lisp_Object args[2]; + args[0] = intern ("suspend-tty-functions"); + XSETTERMINAL (args[1], t); + Frun_hook_with_args (2, args); + } + reset_sys_modes (t->display_info.tty); +#ifdef subprocesses delete_keyboard_wait_descriptor (fileno (f)); - +#endif + +#ifndef MSDOS fclose (f); if (f != t->display_info.tty->output) fclose (t->display_info.tty->output); - +#endif + t->display_info.tty->input = 0; t->display_info.tty->output = 0; if (FRAMEP (t->display_info.tty->top_frame)) FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0); - - /* Run `suspend-tty-functions'. */ - if (!NILP (Vrun_hooks)) - { - Lisp_Object args[2]; - args[0] = intern ("suspend-tty-functions"); - args[1] = make_number (t->id); - Frun_hook_with_args (2, args); - } + } /* Clear display hooks to prevent further output. */ @@ -2295,8 +2425,8 @@ device. `resume-tty' does nothing if it is called on a device that is not suspended. -TTY may be a terminal id, a frame, or nil for the terminal device of -the currently selected frame. */) +TTY may be a terminal object, a frame, or nil (meaning the selected +frame's terminal). */) (tty) Lisp_Object tty; { @@ -2311,21 +2441,40 @@ the currently selected frame. */) if (get_named_tty (t->display_info.tty->name)) error ("Cannot resume display while another display is active on the same device"); +#ifdef MSDOS + t->display_info.tty->output = stdout; + t->display_info.tty->input = stdin; +#else /* !MSDOS */ fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0); if (fd == -1) error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno)); - if (strcmp (t->display_info.tty->name, "/dev/tty")) + if (strcmp (t->display_info.tty->name, DEV_TTY)) dissociate_if_controlling_tty (fd); - + t->display_info.tty->output = fdopen (fd, "w+"); t->display_info.tty->input = t->display_info.tty->output; - +#endif + +#ifdef subprocesses add_keyboard_wait_descriptor (fd); +#endif if (FRAMEP (t->display_info.tty->top_frame)) - FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); + { + struct frame *f = XFRAME (t->display_info.tty->top_frame); + int width, height; + int old_height = FRAME_COLS (f); + int old_width = FRAME_LINES (f); + + /* Check if terminal/window size has changed while the frame + was suspended. */ + get_tty_size (fileno (t->display_info.tty->input), &width, &height); + if (width != old_width || height != old_height) + change_frame_size (f, height, width, 0, 0, 0); + FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1); + } init_sys_modes (t->display_info.tty); @@ -2334,7 +2483,7 @@ the currently selected frame. */) { Lisp_Object args[2]; args[0] = intern ("resume-tty-functions"); - args[1] = make_number (t->id); + XSETTERMINAL (args[1], t); Frun_hook_with_args (2, args); } } @@ -2367,7 +2516,7 @@ term_mouse_moveto (int x, int y) static void term_show_mouse_face (enum draw_glyphs_face draw) { - struct window *w = XWINDOW (Qmouse_face_window); + struct window *w = XWINDOW (mouse_face_window); int save_x, save_y; int i; @@ -2384,7 +2533,7 @@ term_show_mouse_face (enum draw_glyphs_face draw) /* write_glyphs writes at cursor position, so we need to temporarily move cursor coordinates to the beginning of the highlight region. */ - + /* Save current cursor co-ordinates */ save_y = curY (tty); save_x = curX (tty); @@ -2428,7 +2577,7 @@ term_show_mouse_face (enum draw_glyphs_face draw) pos_y = row->y + WINDOW_TOP_EDGE_Y (w); pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); - + cursor_to (f, pos_y, pos_x); if (draw == DRAW_MOUSE_FACE) @@ -2446,12 +2595,12 @@ term_show_mouse_face (enum draw_glyphs_face draw) static void term_clear_mouse_face () { - if (!NILP (Qmouse_face_window)) + if (!NILP (mouse_face_window)) term_show_mouse_face (DRAW_NORMAL_TEXT); mouse_face_beg_row = mouse_face_beg_col = -1; mouse_face_end_row = mouse_face_end_col = -1; - Qmouse_face_window = Qnil; + mouse_face_window = Qnil; } /* Find the glyph matrix position of buffer position POS in window W. @@ -2548,7 +2697,7 @@ term_mouse_highlight (struct frame *f, int x, int y) if (!WINDOWP (window)) return; - if (!EQ (window, Qmouse_face_window)) + if (!EQ (window, mouse_face_window)) term_clear_mouse_face (); w = XWINDOW (window); @@ -2631,7 +2780,7 @@ term_mouse_highlight (struct frame *f, int x, int y) noverlays = sort_overlays (overlay_vec, noverlays, w); /* Check mouse-face highlighting. */ - if (!(EQ (window, Qmouse_face_window) + if (!(EQ (window, mouse_face_window) && y >= mouse_face_beg_row && y <= mouse_face_end_row && (y > mouse_face_beg_row @@ -2667,7 +2816,7 @@ term_mouse_highlight (struct frame *f, int x, int y) /* Find the range of text around this char that should be active. */ Lisp_Object before, after; - int ignore; + EMACS_INT ignore; before = Foverlay_start (overlay); @@ -2681,11 +2830,11 @@ term_mouse_highlight (struct frame *f, int x, int y) = !fast_find_position (w, XFASTINT (after), &mouse_face_end_col, &mouse_face_end_row); - Qmouse_face_window = window; + mouse_face_window = window; mouse_face_face_id = face_at_buffer_position (w, pos, 0, 0, - &ignore, pos + 1, 1); + &ignore, pos + 1, 1, -1); /* Display it as active. */ term_show_mouse_face (DRAW_MOUSE_FACE); @@ -2696,7 +2845,7 @@ term_mouse_highlight (struct frame *f, int x, int y) /* Find the range of text around this char that should be active. */ Lisp_Object before, after, beginning, end; - int ignore; + EMACS_INT ignore; beginning = Fmarker_position (w->start); XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos))); @@ -2716,11 +2865,11 @@ term_mouse_highlight (struct frame *f, int x, int y) = !fast_find_position (w, XFASTINT (after), &mouse_face_end_col, &mouse_face_end_row); - Qmouse_face_window = window; + mouse_face_window = window; mouse_face_face_id = face_at_buffer_position (w, pos, 0, 0, - &ignore, pos + 1, 1); + &ignore, pos + 1, 1, -1); /* Display it as active. */ term_show_mouse_face (DRAW_MOUSE_FACE); @@ -2852,10 +3001,10 @@ term_mouse_click (struct input_event *result, Gpm_Event *event, result->modifiers = down_modifier; else result->modifiers = 0; - + if (event->type & GPM_SINGLE) result->modifiers |= click_modifier; - + if (event->type & GPM_DOUBLE) result->modifiers |= double_modifier; @@ -2888,11 +3037,10 @@ term_mouse_click (struct input_event *result, Gpm_Event *event, return Qnil; } -int +int handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit) { struct frame *f = XFRAME (tty->top_frame); - int fd; struct input_event ie; int do_help = 0; int count = 0; @@ -2902,24 +3050,10 @@ handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct in ie.arg = Qnil; if (event->type & (GPM_MOVE | GPM_DRAG)) { - unsigned char buf[6 * sizeof (short)]; - unsigned short *arg = (unsigned short *) buf + 1; - const char *name; - previous_help_echo_string = help_echo_string; help_echo_string = Qnil; - /* Display mouse pointer */ - buf[sizeof(short) - 1] = 2; /* set selection */ - - arg[0] = arg[2] = (unsigned short) event->x + gpm_zerobased; - arg[1] = arg[3] = (unsigned short) event->y + gpm_zerobased; - arg[4] = (unsigned short) 3; - - name = ttyname (0); - fd = open (name, O_WRONLY); - ioctl (fd, TIOCLINUX, buf + sizeof (short) - 1); - close (fd); + Gpm_DrawPointer (event->x, event->y, fileno (tty->output)); if (!term_mouse_movement (f, event)) help_echo_string = previous_help_echo_string; @@ -2962,48 +3096,75 @@ handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct in return count; } -DEFUN ("term-open-connection", Fterm_open_connection, Sterm_open_connection, +DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start, 0, 0, 0, - doc: /* Open a connection to Gpm. */) + doc: /* Open a connection to Gpm. +Gpm-mouse can only be activated for one tty at a time. */) () { - struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ()); + struct frame *f = SELECTED_FRAME (); + struct tty_display_info *tty + = ((f)->output_method == output_termcap + ? (f)->terminal->display_info.tty : NULL); Gpm_Connect connection; + if (!tty) + error ("Gpm-mouse only works in the GNU/Linux console"); + if (gpm_tty == tty) + return Qnil; /* Already activated, nothing to do. */ + if (gpm_tty) + error ("Gpm-mouse can only be activated for one tty at a time"); + connection.eventMask = ~0; connection.defaultMask = ~GPM_HARD; connection.maxMod = ~0; connection.minMod = 0; gpm_zerobased = 1; - /* We only support GPM on the controlling tty. */ - if (term_gpm || tty->terminal->id > 1 - || Gpm_Open (&connection, 0) < 0) - return Qnil; + if (Gpm_Open (&connection, 0) < 0) + error ("Gpm-mouse failed to connect to the gpm daemon"); else { - term_gpm = 1; - gpm_tty = tty->terminal->id; + gpm_tty = tty; + /* `init_sys_modes' arranges for mouse movements sent through gpm_fd + to generate SIGIOs. Apparently we need to call reset_sys_modes + before calling init_sys_modes. */ reset_sys_modes (tty); init_sys_modes (tty); add_gpm_wait_descriptor (gpm_fd); - return Qt; + return Qnil; } } -DEFUN ("term-close-connection", Fterm_close_connection, Sterm_close_connection, +void +close_gpm (int fd) +{ + if (fd >= 0) + delete_gpm_wait_descriptor (fd); + while (Gpm_Close()); /* close all the stack */ + gpm_tty = NULL; +} + +DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop, 0, 0, 0, doc: /* Close a connection to Gpm. */) () { - delete_gpm_wait_descriptor (gpm_fd); - while (Gpm_Close()); /* close all the stack */ - term_gpm = 0; - return Qnil; + struct frame *f = SELECTED_FRAME (); + struct tty_display_info *tty + = ((f)->output_method == output_termcap + ? (f)->terminal->display_info.tty : NULL); + + if (!tty || gpm_tty != tty) + return Qnil; /* Not activated on this terminal, nothing to do. */ + + close_gpm (gpm_fd); + return Qnil; } #endif /* HAVE_GPM */ +#ifndef MSDOS /*********************************************************************** Initialization ***********************************************************************/ @@ -3027,18 +3188,36 @@ create_tty_output (struct frame *f) f->output_data.tty = t; } -/* Delete the tty-dependent part of frame F. */ +/* Delete frame F's face cache, and its tty-dependent part. */ static void -delete_tty_output (struct frame *f) +tty_free_frame_resources (struct frame *f) { if (! FRAME_TERMCAP_P (f)) abort (); + if (FRAME_FACE_CACHE (f)) + free_frame_faces (f); + xfree (f->output_data.tty); } +#else /* MSDOS */ + +/* Delete frame F's face cache. */ + +static void +tty_free_frame_resources (struct frame *f) +{ + if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f)) + abort (); + + if (FRAME_FACE_CACHE (f)) + free_frame_faces (f); +} +#endif /* MSDOS */ +/* Reset the hooks in TERMINAL. */ static void clear_tty_hooks (struct terminal *terminal) @@ -3072,10 +3251,12 @@ clear_tty_hooks (struct terminal *terminal) /* Leave these two set, or suspended frames are not deleted correctly. */ - terminal->delete_frame_hook = &delete_tty_output; + terminal->delete_frame_hook = &tty_free_frame_resources; terminal->delete_terminal_hook = &delete_tty; } +/* Initialize hooks in TERMINAL with the values needed for a tty. */ + static void set_tty_hooks (struct terminal *terminal) { @@ -3095,7 +3276,7 @@ set_tty_hooks (struct terminal *terminal) terminal->delete_glyphs_hook = &tty_delete_glyphs; terminal->ring_bell_hook = &tty_ring_bell; - + terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes; terminal->set_terminal_modes_hook = &tty_set_terminal_modes; terminal->update_begin_hook = 0; /* Not needed. */ @@ -3113,8 +3294,8 @@ set_tty_hooks (struct terminal *terminal) terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */ terminal->frame_up_to_date_hook = 0; /* Not needed. */ - - terminal->delete_frame_hook = &delete_tty_output; + + terminal->delete_frame_hook = &tty_free_frame_resources; terminal->delete_terminal_hook = &delete_tty; } @@ -3122,7 +3303,7 @@ set_tty_hooks (struct terminal *terminal) static void dissociate_if_controlling_tty (int fd) { -#ifndef WINDOWSNT +#ifndef DOS_NT int pgid; EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */ if (pgid != -1) @@ -3130,10 +3311,13 @@ dissociate_if_controlling_tty (int fd) #if defined (USG) && !defined (BSD_PGRPS) setpgrp (); no_controlling_tty = 1; +#elif defined (CYGWIN) + setsid (); + no_controlling_tty = 1; #else #ifdef TIOCNOTTY /* Try BSD ioctls. */ sigblock (sigmask (SIGTTOU)); - fd = emacs_open ("/dev/tty", O_RDWR, 0); + fd = emacs_open (DEV_TTY, O_RDWR, 0); if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1) { no_controlling_tty = 1; @@ -3147,7 +3331,7 @@ dissociate_if_controlling_tty (int fd) #endif /* ! TIOCNOTTY */ #endif /* ! USG */ } -#endif +#endif /* !DOS_NT */ } static void maybe_fatal(); @@ -3168,7 +3352,6 @@ init_tty (char *name, char *terminal_type, int must_succeed) { char *area = NULL; char **address = &area; - char *buffer = NULL; int buffer_size = 4096; register char *p = NULL; int status; @@ -3177,14 +3360,13 @@ init_tty (char *name, char *terminal_type, int must_succeed) int ctty = 0; /* 1 if asked to open controlling tty. */ if (!terminal_type) - maybe_fatal (must_succeed, 0, 0, + maybe_fatal (must_succeed, 0, "Unknown terminal type", "Unknown terminal type"); -#ifndef WINDOWSNT if (name == NULL) - name = "/dev/tty"; - if (!strcmp (name, "/dev/tty")) + name = DEV_TTY; + if (!strcmp (name, DEV_TTY)) ctty = 1; /* If we already have a terminal on the given device, use that. If @@ -3195,10 +3377,17 @@ init_tty (char *name, char *terminal_type, int must_succeed) terminal = get_named_tty (name); if (terminal) return terminal; -#endif - + terminal = create_terminal (); +#ifdef MSDOS + if (been_here > 0) + maybe_fatal (1, 0, "Attempt to create another terminal %s", "", + name, ""); + been_here = 1; + tty = &the_only_display_info; +#else tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info)); +#endif bzero (tty, sizeof (struct tty_display_info)); tty->next = tty_list; tty_list = tty; @@ -3210,9 +3399,9 @@ init_tty (char *name, char *terminal_type, int must_succeed) tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm)); Wcm_clear (tty); -#ifndef WINDOWSNT +#ifndef DOS_NT set_tty_hooks (terminal); - + { int fd; FILE *file; @@ -3232,15 +3421,18 @@ init_tty (char *name, char *terminal_type, int must_succeed) fd = emacs_open (name, O_RDWR | O_NOCTTY, 0); #endif /* O_IGNORE_CTTY */ + tty->name = xstrdup (name); + terminal->name = xstrdup (name); + if (fd < 0) - maybe_fatal (must_succeed, buffer, terminal, + maybe_fatal (must_succeed, terminal, "Could not open file: %s", "Could not open file: %s", name); if (!isatty (fd)) { close (fd); - maybe_fatal (must_succeed, buffer, terminal, + maybe_fatal (must_succeed, terminal, "Not a tty device: %s", "Not a tty device: %s", name); @@ -3252,45 +3444,49 @@ init_tty (char *name, char *terminal_type, int must_succeed) #endif file = fdopen (fd, "w+"); - tty->name = xstrdup (name); - terminal->name = xstrdup (name); tty->input = file; tty->output = file; } - + tty->type = xstrdup (terminal_type); add_keyboard_wait_descriptor (fileno (tty->input)); -#endif +#endif /* !DOS_NT */ - encode_terminal_bufsize = 0; + encode_terminal_src_size = 0; + encode_terminal_dst_size = 0; #ifdef HAVE_GPM terminal->mouse_position_hook = term_mouse_position; - Qmouse_face_window = Qnil; + mouse_face_window = Qnil; #endif +#ifdef DOS_NT #ifdef WINDOWSNT initialize_w32_display (terminal); +#else /* MSDOS */ + if (strcmp (terminal_type, "internal") == 0) + terminal->type = output_msdos_raw; + initialize_msdos_display (terminal); +#endif /* MSDOS */ + tty->output = stdout; + tty->input = stdin; /* The following two are inaccessible from w32console.c. */ - terminal->delete_frame_hook = &delete_tty_output; + terminal->delete_frame_hook = &tty_free_frame_resources; terminal->delete_terminal_hook = &delete_tty; - /* XXX Can this be non-null? */ - if (name) - { - tty->name = xstrdup (name); - terminal->name = xstrdup (name); - } - tty->type = xstrdup (terminal_type); + tty->name = xstrdup (name); + terminal->name = xstrdup (name); + tty->type = xstrdup (terminal_type); - tty->output = stdout; - tty->input = stdin; +#ifdef subprocesses add_keyboard_wait_descriptor (0); +#endif Wcm_clear (tty); +#ifdef WINDOWSNT { struct frame *f = XFRAME (selected_frame); @@ -3301,6 +3497,14 @@ init_tty (char *name, char *terminal_type, int must_succeed) FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; } +#else /* MSDOS */ + { + int height, width; + get_tty_size (fileno (tty->input), &width, &height); + FrameCols (tty) = width; + FrameRows (tty) = height; + } +#endif /* MSDOS */ tty->delete_in_insert_mode = 1; UseTabs (tty) = 0; @@ -3310,32 +3514,36 @@ init_tty (char *name, char *terminal_type, int must_succeed) 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. */ terminal->line_ins_del_ok = 0; +#ifdef WINDOWSNT terminal->char_ins_del_ok = 1; - baud_rate = 19200; +#else /* MSDOS */ + terminal->char_ins_del_ok = 0; + init_baud_rate (fileno (tty->input)); +#endif /* MSDOS */ tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */ -#else /* not WINDOWSNT */ +#else /* not DOS_NT */ Wcm_clear (tty); - buffer = (char *) xmalloc (buffer_size); - + tty->termcap_term_buffer = (char *) xmalloc (buffer_size); + /* On some systems, tgetent tries to access the controlling terminal. */ sigblock (sigmask (SIGTTOU)); - status = tgetent (buffer, terminal_type); + status = tgetent (tty->termcap_term_buffer, terminal_type); sigunblock (sigmask (SIGTTOU)); - + if (status < 0) { #ifdef TERMINFO - maybe_fatal (must_succeed, buffer, terminal, + maybe_fatal (must_succeed, terminal, "Cannot open terminfo database file", "Cannot open terminfo database file"); #else - maybe_fatal (must_succeed, buffer, terminal, + maybe_fatal (must_succeed, terminal, "Cannot open termcap database file", "Cannot open termcap database file"); #endif @@ -3343,7 +3551,7 @@ init_tty (char *name, char *terminal_type, int must_succeed) if (status == 0) { #ifdef TERMINFO - maybe_fatal (must_succeed, buffer, terminal, + maybe_fatal (must_succeed, terminal, "Terminal type %s is not defined", "Terminal type %s is not defined.\n\ If that is not the actual type of terminal you have,\n\ @@ -3352,7 +3560,7 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", terminal_type); #else - maybe_fatal (must_succeed, buffer, terminal, + maybe_fatal (must_succeed, terminal, "Terminal type %s is not defined", "Terminal type %s is not defined.\n\ If that is not the actual type of terminal you have,\n\ @@ -3364,12 +3572,11 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", } #ifndef TERMINFO - if (strlen (buffer) >= buffer_size) + if (strlen (tty->termcap_term_buffer) >= buffer_size) abort (); - buffer_size = strlen (buffer); + buffer_size = strlen (tty->termcap_term_buffer); #endif - area = (char *) xmalloc (buffer_size); - + tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size); tty->TS_ins_line = tgetstr ("al", address); tty->TS_ins_multi_lines = tgetstr ("AL", address); tty->TS_bell = tgetstr ("bl", address); @@ -3402,12 +3609,6 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", Down (tty) = tgetstr ("do", address); if (!Down (tty)) Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */ -#ifdef VMS - /* VMS puts a carriage return before each linefeed, - so it is not safe to use linefeeds. */ - if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0') - Down (tty) = 0; -#endif /* VMS */ if (tgetflag ("bs")) Left (tty) = "\b"; /* can't possibly be longer! */ else /* (Actually, "bs" is obsolete...) */ @@ -3483,10 +3684,10 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", tty->TF_underscore = tgetflag ("ul"); tty->TF_teleray = tgetflag ("xt"); -#endif /* !WINDOWSNT */ -#ifdef MULTI_KBOARD +#endif /* !DOS_NT */ terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); init_kboard (terminal->kboard); + terminal->kboard->Vwindow_system = Qnil; terminal->kboard->next_kboard = all_kboards; all_kboards = terminal->kboard; terminal->kboard->reference_count++; @@ -3495,12 +3696,9 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", prompt in the mini-buffer. */ if (current_kboard == initial_kboard) current_kboard = terminal->kboard; -#ifndef WINDOWSNT +#ifndef DOS_NT term_get_fkeys (address, terminal->kboard); -#endif -#endif -#ifndef WINDOWSNT /* Get frame size from system, or else from termcap. */ { int height, width; @@ -3515,26 +3713,13 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", FrameRows (tty) = tgetnum ("li"); if (FrameRows (tty) < 3 || FrameCols (tty) < 3) - maybe_fatal (must_succeed, NULL, terminal, + maybe_fatal (must_succeed, terminal, "Screen size %dx%d is too small" "Screen size %dx%d is too small", FrameCols (tty), FrameRows (tty)); -#if 0 /* This is not used anywhere. */ - tty->terminal->min_padding_speed = tgetnum ("pb"); -#endif - TabWidth (tty) = tgetnum ("tw"); -#ifdef VMS - /* These capabilities commonly use ^J. - I don't know why, but sending them on VMS does not work; - it causes following spaces to be lost, sometimes. - For now, the simplest fix is to avoid using these capabilities ever. */ - if (Down (tty) && Down (tty)[0] == '\n') - Down (tty) = 0; -#endif /* VMS */ - if (!tty->TS_bell) tty->TS_bell = "\07"; @@ -3648,15 +3833,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", if (Wcm_init (tty) == -1) /* can't do cursor motion */ { - maybe_fatal (must_succeed, NULL, terminal, + maybe_fatal (must_succeed, terminal, "Terminal type \"%s\" is not powerful enough to run Emacs", -#ifdef VMS - "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, use either the\n\ -DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\ -or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.", -#else /* not VMS */ # ifdef TERMINFO "Terminal type \"%s\" is not powerful enough to run Emacs.\n\ It lacks the ability to position the cursor.\n\ @@ -3672,12 +3850,11 @@ 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.", # endif /* TERMINFO */ -#endif /*VMS */ terminal_type); } if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0) - maybe_fatal (must_succeed, NULL, terminal, + maybe_fatal (must_succeed, terminal, "Could not determine the frame size", "Could not determine the frame size"); @@ -3710,40 +3887,27 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", init_baud_rate (fileno (tty->input)); -#ifdef AIXHFT - /* The HFT system on AIX doesn't optimize for scrolling, so it's - really ugly at times. */ - terminal->line_ins_del_ok = 0; - terminal->char_ins_del_ok = 0; -#endif - - /* Don't do this. I think termcap may still need the buffer. */ - /* xfree (buffer); */ +#endif /* not DOS_NT */ /* Init system terminal modes (RAW or CBREAK, etc.). */ init_sys_modes (tty); -#endif /* not WINDOWSNT */ return terminal; } /* Auxiliary error-handling function for init_tty. - Free BUFFER and delete TERMINAL, then call error or fatal - with str1 or str2, respectively, according to MUST_SUCCEED. */ + Delete TERMINAL, then call error or fatal with str1 or str2, + respectively, according to MUST_SUCCEED. */ static void -maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2) +maybe_fatal (must_succeed, terminal, str1, str2, arg1, arg2) int must_succeed; - char *buffer; struct terminal *terminal; char *str1, *str2, *arg1, *arg2; { - if (buffer) - xfree (buffer); - if (terminal) delete_tty (terminal); - + if (must_succeed) fatal (str2, arg1, arg2); else @@ -3752,14 +3916,16 @@ maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2) abort (); } -/* VARARGS 1 */ void -fatal (str, arg1, arg2) - char *str, *arg1, *arg2; +fatal (const char *str, ...) { + va_list ap; + va_start (ap, str); fprintf (stderr, "emacs: "); - fprintf (stderr, str, arg1, arg2); - fprintf (stderr, "\n"); + vfprintf (stderr, str, ap); + if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n')) + fprintf (stderr, "\n"); + va_end (ap); fflush (stderr); exit (1); } @@ -3772,32 +3938,17 @@ static void delete_tty (struct terminal *terminal) { struct tty_display_info *tty; - Lisp_Object tail, frame; - int last_terminal; - - /* Protect against recursive calls. Fdelete_frame in + + /* Protect against recursive calls. delete_frame in delete_terminal calls us back when it deletes our last frame. */ - if (terminal->deleted) + if (!terminal->name) return; if (terminal->type != output_termcap) abort (); tty = terminal->display_info.tty; - - last_terminal = 1; - FOR_EACH_FRAME (tail, frame) - { - struct frame *f = XFRAME (frame); - if (FRAME_LIVE_P (f) && (!FRAME_TERMCAP_P (f) || FRAME_TTY (f) != tty)) - { - last_terminal = 0; - break; - } - } - if (last_terminal) - error ("Attempt to delete the sole terminal device with live frames"); - + if (tty == tty_list) tty_list = tty->next; else @@ -3820,15 +3971,14 @@ delete_tty (struct terminal *terminal) delete_terminal (terminal); - if (tty->name) - xfree (tty->name); - - if (tty->type) - xfree (tty->type); + xfree (tty->name); + xfree (tty->type); if (tty->input) { +#ifdef subprocesses delete_keyboard_wait_descriptor (fileno (tty->input)); +#endif if (tty->input != stdin) fclose (tty->input); } @@ -3837,11 +3987,10 @@ delete_tty (struct terminal *terminal) if (tty->termscript) fclose (tty->termscript); - if (tty->old_tty) - xfree (tty->old_tty); - - if (tty->Wcm) - xfree (tty->Wcm); + xfree (tty->old_tty); + xfree (tty->Wcm); + xfree (tty->termcap_strings_buffer); + xfree (tty->termcap_term_buffer); bzero (tty, sizeof (struct tty_display_info)); xfree (tty); @@ -3877,14 +4026,14 @@ This variable can be used by terminal emulator packages. */); DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions, doc: /* Functions to be run after suspending a tty. -The functions are run with one argument, the terminal id to be suspended. +The functions are run with one argument, the terminal object to be suspended. See `suspend-tty'. */); Vsuspend_tty_functions = Qnil; DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions, doc: /* Functions to be run after resuming a tty. -The functions are run with one argument, the terminal id that was revived. +The functions are run with one argument, the terminal object that was revived. See `resume-tty'. */); Vresume_tty_functions = Qnil; @@ -3903,11 +4052,20 @@ bigger, or it may make it blink, or it may do nothing at all. */); defsubr (&Ssuspend_tty); defsubr (&Sresume_tty); #ifdef HAVE_GPM - defsubr (&Sterm_open_connection); - defsubr (&Sterm_close_connection); + defsubr (&Sgpm_mouse_start); + defsubr (&Sgpm_mouse_stop); - staticpro (&Qmouse_face_window); + staticpro (&mouse_face_window); #endif /* HAVE_GPM */ + +#ifndef DOS_NT + default_orig_pair = NULL; + default_set_foreground = NULL; + default_set_background = NULL; +#endif /* !DOS_NT */ + + encode_terminal_src = NULL; + encode_terminal_dst = NULL; }