X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/f2a003428d6cf16dbb0701b6998259cc15d0739e..b735c9913f34f4a9645e835ebc52733bedf6882d:/src/term.c diff --git a/src/term.c b/src/term.c index c58de2cb82..17607cea5d 100644 --- a/src/term.c +++ b/src/term.c @@ -1,5 +1,5 @@ /* terminal control module for terminals described by TERMCAP - Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -15,31 +15,41 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ +#include #include #include -#include #include "termchar.h" #include "termopts.h" -#include "cm.h" #undef NULL #include "lisp.h" +#include "charset.h" +#include "coding.h" #include "frame.h" #include "disptab.h" #include "termhooks.h" #include "keyboard.h" +#include "dispextern.h" +#include "cm.h" +#ifdef HAVE_X_WINDOWS +#include "xterm.h" +#endif #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) -#define OUTPUT(a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc) +#define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc) #define OUTPUT1(a) tputs (a, 1, cmputc) #define OUTPUTL(a, lines) tputs (a, lines, cmputc) -#define OUTPUT_IF(a) { if (a) tputs (a, FRAME_HEIGHT (selected_frame) - curY, cmputc); } +#define OUTPUT_IF(a) { if (a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); } #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); } +/* Function to use to ring the bell. */ +Lisp_Object Vring_bell_function; + /* Terminal characteristics that higher levels want to look at. These are all extern'd in termchar.h */ @@ -52,13 +62,12 @@ int line_ins_del_ok; /* Terminal can insert and delete lines */ int char_ins_del_ok; /* Terminal can insert and delete chars */ int scroll_region_ok; /* Terminal supports setting the scroll window */ +int scroll_region_cost; /* Cost of setting a scroll window, + measured in characters */ int memory_below_frame; /* Terminal remembers lines scrolled off bottom */ int fast_clear_end_of_line; /* Terminal has a `ce' string */ -int dont_calculate_costs; /* Nonzero means don't bother computing */ - /* various cost tables; we won't use them. */ - /* Nonzero means no need to redraw the entire frame on resuming a suspended Emacs. This is useful on terminals with multiple pages, where one page is used for Emacs and another for all else. */ @@ -67,31 +76,33 @@ int no_redraw_on_reenter; /* Hook functions that you can set to snap out the functions in this file. These are all extern'd in termhooks.h */ -int (*cursor_to_hook) (); -int (*raw_cursor_to_hook) (); +void (*cursor_to_hook) P_ ((int, int)); +void (*raw_cursor_to_hook) P_ ((int, int)); + +void (*clear_to_end_hook) P_ ((void)); +void (*clear_frame_hook) P_ ((void)); +void (*clear_end_of_line_hook) P_ ((int)); -int (*clear_to_end_hook) (); -int (*clear_frame_hook) (); -int (*clear_end_of_line_hook) (); +void (*ins_del_lines_hook) P_ ((int, int)); -int (*ins_del_lines_hook) (); +void (*change_line_highlight_hook) P_ ((int, int, int)); +void (*reassert_line_highlight_hook) P_ ((int, int)); -int (*change_line_highlight_hook) (); -int (*reassert_line_highlight_hook) (); +void (*insert_glyphs_hook) P_ ((GLYPH *, int)); +void (*write_glyphs_hook) P_ ((GLYPH *, int)); +void (*delete_glyphs_hook) P_ ((int)); -int (*insert_glyphs_hook) (); -int (*write_glyphs_hook) (); -int (*delete_glyphs_hook) (); +void (*ring_bell_hook) P_ ((void)); -int (*ring_bell_hook) (); +void (*reset_terminal_modes_hook) P_ ((void)); +void (*set_terminal_modes_hook) P_ ((void)); +void (*update_begin_hook) P_ ((struct frame *)); +void (*update_end_hook) P_ ((struct frame *)); +void (*set_terminal_window_hook) P_ ((int)); -int (*reset_terminal_modes_hook) (); -int (*set_terminal_modes_hook) (); -int (*update_begin_hook) (); -int (*update_end_hook) (); -int (*set_terminal_window_hook) (); +int (*read_socket_hook) P_ ((int, struct input_event *, int, int)); -int (*read_socket_hook) (); +void (*frame_up_to_date_hook) P_ ((struct frame *)); /* Return the current position of the mouse. @@ -111,19 +122,19 @@ int (*read_socket_hook) (); This should clear mouse_moved until the next motion event arrives. */ -void (*mouse_position_hook) ( /* FRAME_PTR *f, +void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, - unsigned long *time */ ); + unsigned long *time)); /* When reading from a minibuffer in a different frame, Emacs wants to shift the highlight from the selected frame to the minibuffer's frame; under X, this means it lies about where the focus is. This hook tells the window system code to re-decide where to put the highlight. */ -void (*frame_rehighlight_hook) ( /* FRAME_PTR f */ ); +void (*frame_rehighlight_hook) P_ ((FRAME_PTR f)); /* If we're displaying frames using a window system that can stack frames on top of each other, this hook allows you to bring a frame @@ -135,7 +146,7 @@ void (*frame_rehighlight_hook) ( /* FRAME_PTR f */ ); If RAISE is non-zero, F is brought to the front, before all other windows. If RAISE is zero, F is sent to the back, behind all other windows. */ -void (*frame_raise_lower_hook) ( /* FRAME_PTR f, int raise */ ); +void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise)); /* Set the vertical scroll bar for WINDOW to have its upper left corner at (TOP, LEFT), and be LENGTH rows high. Set its handle to @@ -143,8 +154,8 @@ void (*frame_raise_lower_hook) ( /* FRAME_PTR f, int raise */ ); of WHOLE characters, starting at POSITION. If WINDOW doesn't yet have a scroll bar, create one for it. */ void (*set_vertical_scroll_bar_hook) - ( /* struct window *window, - int portion, int whole, int position */ ); + P_ ((struct window *window, + int portion, int whole, int position)); /* The following three hooks are used when we're doing a thorough @@ -153,7 +164,7 @@ void (*set_vertical_scroll_bar_hook) away is a real pain - can you say set-window-configuration? Instead, we just assert at the beginning of redisplay that *all* scroll bars are to be removed, and then save scroll bars from the - firey pit when we actually redisplay their window. */ + fiery pit when we actually redisplay their window. */ /* Arrange for all scroll bars on FRAME to be removed at the next call to `*judge_scroll_bars_hook'. A scroll bar may be spared if @@ -167,11 +178,11 @@ void (*set_vertical_scroll_bar_hook) If non-zero, this hook should be safe to apply to any frame, whether or not it can support scroll bars, and whether or not it is currently displaying them. */ -void (*condemn_scroll_bars_hook)( /* FRAME_PTR *frame */ ); +void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame)); /* Unmark WINDOW's scroll bar for deletion in this judgement cycle. Note that it's okay to redeem a scroll bar that is not condemned. */ -void (*redeem_scroll_bar_hook)( /* struct window *window */ ); +void (*redeem_scroll_bar_hook) P_ ((struct window *window)); /* Remove all scroll bars on FRAME that haven't been saved since the last call to `*condemn_scroll_bars_hook'. @@ -184,12 +195,14 @@ void (*redeem_scroll_bar_hook)( /* struct window *window */ ); If non-zero, this hook should be safe to apply to any frame, whether or not it can support scroll bars, and whether or not it is currently displaying them. */ -void (*judge_scroll_bars_hook)( /* FRAME_PTR *FRAME */ ); +void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME)); /* Strings, numbers and flags taken from the termcap entry. */ -char *TS_ins_line; /* termcap "al" */ +char *TS_end_italic_mode; /* termcap "ae" */ +char *TS_ins_line; /* "al" */ +char *TS_italic_mode; /* "as" */ char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */ char *TS_bell; /* "bl" */ char *TS_clr_to_bottom; /* "cd" */ @@ -212,6 +225,8 @@ char *TS_insert_mode; /* "im", enter character-insert mode */ char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */ char *TS_end_keypad_mode; /* "ke" */ char *TS_keypad_mode; /* "ks" */ +char *TS_bold_mode; /* "md" */ +char *TS_end_bold_mode; /* "me" */ char *TS_pad_char; /* "pc", char to use as padding */ char *TS_repeat; /* "rp" (2 params, # times to repeat and character to be repeated) */ @@ -221,6 +236,8 @@ char *TS_standout_mode; /* "so" */ char *TS_rev_scroll; /* "sr" */ char *TS_end_termcap_modes; /* "te" */ char *TS_termcap_modes; /* "ti" */ +char *TS_end_underscore_mode; /* "ue" */ +char *TS_underscore_mode; /* "us" */ char *TS_visible_bell; /* "vb" */ char *TS_end_visual_mode; /* "ve" */ char *TS_visual_mode; /* "vi" */ @@ -251,8 +268,14 @@ static int se_is_so; /* 1 if same string both enters and leaves /* internal state */ +/* The largest frame width in any call to calculate_costs. */ +int max_frame_width; +/* The largest frame height in any call to calculate_costs. */ +int max_frame_height; + /* Number of chars of space used for standout marker at beginning of line, or'd with 0100. Zero if no standout marker at all. + The length of these vectors is max_frame_height. Used IFF TN_standout_width >= 0. */ @@ -279,10 +302,48 @@ int specified_window; FRAME_PTR updating_frame; +/* Provided for lisp packages. */ +static int system_uses_terminfo; + char *tparam (); + +extern char *tgetstr (); + +#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 */ + +void ring_bell () { + if (! NILP (Vring_bell_function)) + { + Lisp_Object function; + + /* Temporarily set the global variable to nil + so that if we get an error, it stays nil + and we don't call it over and over. + + We don't specbind it, because that would carefully + restore the bad value if there's an error + and make the loop of errors happen anyway. */ + function = Vring_bell_function; + Vring_bell_function = Qnil; + + call0 (function); + + Vring_bell_function = function; + return; + } + if (! FRAME_TERMCAP_P (selected_frame)) { (*ring_bell_hook) (); @@ -291,6 +352,7 @@ ring_bell () OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); } +void set_terminal_modes () { if (! FRAME_TERMCAP_P (selected_frame)) @@ -304,11 +366,13 @@ set_terminal_modes () losecursor (); } +void reset_terminal_modes () { if (! FRAME_TERMCAP_P (selected_frame)) { - (*reset_terminal_modes_hook) (); + if (reset_terminal_modes_hook) + (*reset_terminal_modes_hook) (); return; } if (TN_standout_width < 0) @@ -325,6 +389,7 @@ reset_terminal_modes () cmputc ('\r'); } +void update_begin (f) FRAME_PTR f; { @@ -333,13 +398,14 @@ update_begin (f) (*update_begin_hook) (f); } +void update_end (f) FRAME_PTR f; { if (! FRAME_TERMCAP_P (updating_frame)) { - updating_frame = 0; (*update_end_hook) (f); + updating_frame = 0; return; } turn_off_insert (); @@ -348,6 +414,7 @@ update_end (f) updating_frame = 0; } +void set_terminal_window (size) int size; { @@ -362,6 +429,7 @@ set_terminal_window (size) set_scroll_region (0, specified_window); } +void set_scroll_region (start, stop) int start, stop; { @@ -386,6 +454,7 @@ set_scroll_region (start, stop) losecursor (); } +void turn_on_insert () { if (!insert_mode) @@ -393,6 +462,7 @@ turn_on_insert () insert_mode = 1; } +void turn_off_insert () { if (insert_mode) @@ -407,6 +477,7 @@ turn_off_insert () These functions are called on all terminals, but do nothing on terminals whose standout mode does not work that way. */ +void turn_off_highlight () { if (TN_standout_width < 0) @@ -417,6 +488,7 @@ turn_off_highlight () } } +void turn_on_highlight () { if (TN_standout_width < 0) @@ -431,6 +503,7 @@ turn_on_highlight () empty space inside windows. What this is, depends on the user option inverse-video. */ +void background_highlight () { if (TN_standout_width >= 0) @@ -443,7 +516,7 @@ background_highlight () /* Set standout mode to the mode specified for the text to be output. */ -static +static void highlight_if_desired () { if (TN_standout_width >= 0) @@ -465,6 +538,7 @@ highlight_if_desired () /* Write a standout marker or end-standout marker at the front of the line at vertical position vpos. */ +void write_standout_marker (flag, vpos) int flag, vpos; { @@ -482,6 +556,7 @@ write_standout_marker (flag, vpos) Call this when about to modify line at position VPOS and not change whether it is highlighted. */ +void reassert_line_highlight (highlight, vpos) int highlight; int vpos; @@ -503,6 +578,7 @@ reassert_line_highlight (highlight, vpos) /* Call this when about to modify line at position VPOS and change whether it is highlighted. */ +void change_line_highlight (new_highlight, vpos, first_unused_hpos) int new_highlight, vpos, first_unused_hpos; { @@ -539,6 +615,7 @@ change_line_highlight (new_highlight, vpos, first_unused_hpos) /* Move to absolute position, specified origin 0 */ +void cursor_to (row, col) int row, col; { @@ -551,6 +628,11 @@ cursor_to (row, col) return; } + /* Detect the case where we are called from reset_sys_modes + and the costs have never been calculated. Do nothing. */ + if (chars_wasted == 0) + return; + col += chars_wasted[row] & 077; if (curY == row && curX == col) return; @@ -563,6 +645,7 @@ cursor_to (row, col) /* Similar but don't take any account of the wasted characters. */ +void raw_cursor_to (row, col) int row, col; { @@ -583,11 +666,12 @@ raw_cursor_to (row, col) /* Erase operations */ /* clear from cursor to end of frame */ +void clear_to_end () { register int i; - if (clear_to_end_hook && FRAME_TERMCAP_P (updating_frame)) + if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame)) { (*clear_to_end_hook) (); return; @@ -610,6 +694,7 @@ clear_to_end () /* Clear entire frame */ +void clear_frame () { if (clear_frame_hook @@ -639,11 +724,13 @@ clear_frame () Note that the cursor may be moved. */ +void clear_end_of_line (first_unused_hpos) int first_unused_hpos; { static GLYPH buf = SPACEGLYPH; if (FRAME_TERMCAP_P (selected_frame) + && chars_wasted != 0 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0) write_glyphs (&buf, 1); clear_end_of_line_raw (first_unused_hpos); @@ -655,6 +742,7 @@ clear_end_of_line (first_unused_hpos) Note that the cursor may be moved, on terminals lacking a `ce' string. */ +void clear_end_of_line_raw (first_unused_hpos) int first_unused_hpos; { @@ -669,6 +757,11 @@ clear_end_of_line_raw (first_unused_hpos) return; } + /* Detect the case where we are called from reset_sys_modes + and the costs have never been calculated. Do nothing. */ + if (chars_wasted == 0) + return; + first_unused_hpos += chars_wasted[curY] & 077; if (curX >= first_unused_hpos) return; @@ -699,7 +792,94 @@ clear_end_of_line_raw (first_unused_hpos) } } +/* Encode SRC_LEN glyphs starting at SRC to terminal output codes and + store them at DST. Do not write more than DST_LEN bytes. That may + require stopping before all SRC_LEN input glyphs have been + converted. + We store the number of glyphs actually converted in *CONSUMED. The + return value is the number of bytes store in DST. */ + +int +encode_terminal_code (src, dst, src_len, dst_len, consumed) + GLYPH *src; + int src_len; + unsigned char *dst; + int dst_len, *consumed; +{ + GLYPH *src_start = src, *src_end = src + src_len; + unsigned char *dst_start = dst, *dst_end = dst + dst_len; + register GLYPH g; + unsigned int c; + unsigned char workbuf[4], *buf; + int len; + register int tlen = GLYPH_TABLE_LENGTH; + register Lisp_Object *tbase = GLYPH_TABLE_BASE; + struct coding_system *coding; + + coding = (CODING_REQUIRE_ENCODING (&terminal_coding) + ? &terminal_coding + : &safe_terminal_coding); + + while (src < src_end) + { + g = *src; + /* We must skip glyphs to be padded for a wide character. */ + if (! (g & GLYPH_MASK_PADDING)) + { + if ((c = GLYPH_CHAR (selected_frame, g)) > MAX_CHAR) + { + c = ' '; + g = MAKE_GLYPH (selected_frame, c, + GLYPH_FACE (selected_frame, g)); + } + if (COMPOSITE_CHAR_P (c)) + { + /* If C is a composite character, we can display + only the first component. */ + g = cmpchar_table[COMPOSITE_CHAR_ID (c)]->glyph[0], + c = GLYPH_CHAR (selected_frame, g); + } + if (c < tlen) + { + /* G has an entry in Vglyph_table, + so process any alias before testing for simpleness. */ + GLYPH_FOLLOW_ALIASES (tbase, tlen, g); + c = GLYPH_CHAR (selected_frame, g); + } + if (GLYPH_SIMPLE_P (tbase, tlen, g)) + /* We set the multi-byte form of C at BUF. */ + len = CHAR_STRING (c, workbuf, buf); + else + { + /* We have a string in Vglyph_table. */ + len = GLYPH_LENGTH (tbase, g); + buf = GLYPH_STRING (tbase, g); + } + + encode_coding (coding, buf, dst, len, dst_end - dst); + len -= coding->consumed; + dst += coding->produced; + if (len > 0) + { + if (len > dst_end - dst) + /* The remaining output buffer is too short. We must + break the loop here without increasing SRC so that + the next call of this function start from the same + glyph. */ + break; + buf += len; + while (len--) *dst++ = *buf++; + } + } + src++; + } + *consumed = src - src_start; + return (dst - dst_start); +} + + +void write_glyphs (string, len) register GLYPH *string; register int len; @@ -707,6 +887,7 @@ write_glyphs (string, len) register GLYPH g; register int tlen = GLYPH_TABLE_LENGTH; register Lisp_Object *tbase = GLYPH_TABLE_BASE; + int produced, consumed; if (write_glyphs_hook && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame))) @@ -726,56 +907,65 @@ write_glyphs (string, len) && (curX + len - (chars_wasted[curY] & 077) == FRAME_WIDTH (selected_frame))) len --; + if (len <= 0) + return; cmplus (len); - while (--len >= 0) + /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at + the tail. */ + terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; + while (len > 0) { - g = *string++; - /* Check quickly for G beyond length of table. - That implies it isn't an alias and is simple. */ - if (g >= tlen) + /* We use shared conversion buffer of the current size (1024 + bytes at least). Usually it is sufficient, but if not, we + just repeat the loop. */ + produced = encode_terminal_code (string, conversion_buffer, + len, conversion_buffer_size, &consumed); + if (produced > 0) { - simple: - putc (g & 0xff, stdout); + fwrite (conversion_buffer, 1, produced, stdout); if (ferror (stdout)) clearerr (stdout); if (termscript) - putc (g & 0xff, termscript); + fwrite (conversion_buffer, 1, produced, termscript); } - else + len -= consumed; + string += consumed; + } + /* We may have to output some codes to terminate the writing. */ + if (CODING_REQUIRE_FLUSHING (&terminal_coding)) + { + terminal_coding.mode |= CODING_MODE_LAST_BLOCK; + encode_coding (&terminal_coding, "", conversion_buffer, + 0, conversion_buffer_size); + if (terminal_coding.produced > 0) { - /* G has an entry in Vglyph_table, - so process any alias and then test for simpleness. */ - while (GLYPH_ALIAS_P (tbase, tlen, g)) - g = GLYPH_ALIAS (tbase, g); - if (GLYPH_SIMPLE_P (tbase, tlen, g)) - goto simple; - else - { - /* Here if G (or its definition as an alias) is not simple. */ - fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), - stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), - termscript); - } + fwrite (conversion_buffer, 1, terminal_coding.produced, stdout); + if (ferror (stdout)) + clearerr (stdout); + if (termscript) + fwrite (conversion_buffer, 1, terminal_coding.produced, + termscript); } } + cmcheckmagic (); } /* If start is zero, insert blanks instead of a string at start */ +void insert_glyphs (start, len) register GLYPH *start; register int len; { char *buf; - register GLYPH g; + GLYPH g; register int tlen = GLYPH_TABLE_LENGTH; register Lisp_Object *tbase = GLYPH_TABLE_BASE; + if (len <= 0) + return; + if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame)) { (*insert_glyphs_hook) (start, len); @@ -795,36 +985,50 @@ insert_glyphs (start, len) turn_on_insert (); cmplus (len); - while (--len >= 0) + /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ + terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; + while (len-- > 0) { + int produced, consumed; + OUTPUT1_IF (TS_ins_char); if (!start) g = SPACEGLYPH; else - g = *start++; - - if (GLYPH_SIMPLE_P (tbase, tlen, g)) { - putc (g & 0xff, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - putc (g & 0xff, termscript); + g = *start++; + /* We must open sufficient space for a character which + occupies more than one column. */ + while (*start & GLYPH_MASK_PADDING) + { + OUTPUT1_IF (TS_ins_char); + start++, len--; + } } - else + + if (len <= 0) + /* This is the last glyph. */ + terminal_coding.mode |= CODING_MODE_LAST_BLOCK; + + /* We use shared conversion buffer of the current size (1024 + bytes at least). It is surely sufficient for just one glyph. */ + produced = encode_terminal_code (&g, conversion_buffer, + 1, conversion_buffer_size, &consumed); + if (produced > 0) { - fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), stdout); + fwrite (conversion_buffer, 1, produced, stdout); if (ferror (stdout)) clearerr (stdout); if (termscript) - fwrite (GLYPH_STRING (tbase, g), 1, GLYPH_LENGTH (tbase, g), - termscript); + fwrite (conversion_buffer, 1, produced, termscript); } - OUTPUT1_IF (TS_pad_inserted_char); - } + OUTPUT1_IF (TS_pad_inserted_char); + } + cmcheckmagic (); } +void delete_glyphs (n) register int n; { @@ -862,6 +1066,7 @@ delete_glyphs (n) /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */ +void ins_del_lines (vpos, n) int vpos, n; { @@ -922,7 +1127,7 @@ ins_del_lines (vpos, n) if (TN_standout_width >= 0) { - register lower_limit + register int lower_limit = (scroll_region_ok ? specified_window : FRAME_HEIGHT (selected_frame)); @@ -992,7 +1197,8 @@ per_line_cost (str) #ifndef old /* char_ins_del_cost[n] is cost of inserting N characters. - char_ins_del_cost[-n] is cost of deleting N characters. */ + char_ins_del_cost[-n] is cost of deleting N characters. + The length of this vector is based on max_frame_width. */ int *char_ins_del_vector; @@ -1049,7 +1255,7 @@ calculate_ins_del_char_costs (frame) /* Delete costs are at negative offsets */ p = &char_ins_del_cost (frame)[0]; - for (i = FRAME_WIDTH (selected_frame); --i >= 0;) + for (i = FRAME_WIDTH (frame); --i >= 0;) *--p = (del_startup_cost += del_cost_per_char); /* Doing nothing is free */ @@ -1061,27 +1267,24 @@ calculate_ins_del_char_costs (frame) *p++ = (ins_startup_cost += ins_cost_per_char); } -#ifdef HAVE_X_WINDOWS -extern int x_screen_planes; -#endif - -extern do_line_insertion_deletion_costs (); - +void calculate_costs (frame) FRAME_PTR frame; { - register char *f = TS_set_scroll_region ? - TS_set_scroll_region - : TS_set_scroll_region_1; + register char *f = (TS_set_scroll_region + ? TS_set_scroll_region + : TS_set_scroll_region_1); - if (dont_calculate_costs) - return; + FRAME_COST_BAUD_RATE (frame) = baud_rate; + scroll_region_cost = string_cost (f); #ifdef HAVE_X_WINDOWS if (FRAME_X_P (frame)) { do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*", - 0, 0, x_screen_planes); + 0, 0, + x_screen_planes (frame)); + scroll_region_cost = 0; return; } #endif @@ -1095,30 +1298,33 @@ calculate_costs (frame) chars_wasted and copybuf are only used here in term.c in cases where the term hook isn't called. */ + max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame)); + max_frame_width = max (max_frame_width, FRAME_WIDTH (frame)); + if (chars_wasted != 0) - chars_wasted = (char *) xrealloc (chars_wasted, FRAME_HEIGHT (frame)); + chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height); else - chars_wasted = (char *) xmalloc (FRAME_HEIGHT (frame)); + chars_wasted = (char *) xmalloc (max_frame_height); if (copybuf != 0) - copybuf = (char *) xrealloc (copybuf, FRAME_HEIGHT (frame)); + copybuf = (char *) xrealloc (copybuf, max_frame_height); else - copybuf = (char *) xmalloc (FRAME_HEIGHT (frame)); + copybuf = (char *) xmalloc (max_frame_height); if (char_ins_del_vector != 0) char_ins_del_vector = (int *) xrealloc (char_ins_del_vector, (sizeof (int) - + 2 * FRAME_WIDTH (frame) * sizeof (int))); + + 2 * max_frame_width * sizeof (int))); else char_ins_del_vector = (int *) xmalloc (sizeof (int) - + 2 * FRAME_WIDTH (frame) * sizeof (int)); + + 2 * max_frame_width * sizeof (int)); - bzero (chars_wasted, FRAME_HEIGHT (frame)); - bzero (copybuf, FRAME_HEIGHT (frame)); + bzero (chars_wasted, max_frame_height); + bzero (copybuf, max_frame_height); bzero (char_ins_del_vector, (sizeof (int) - + 2 * FRAME_WIDTH (frame) * sizeof (int))); + + 2 * max_frame_width * sizeof (int))); if (f && (!TS_ins_line && !TS_del_line)) do_line_insertion_deletion_costs (frame, @@ -1249,7 +1455,6 @@ term_get_fkeys (address) refusing to run at all on such a terminal. */ extern Lisp_Object Fidentity (); - static Lisp_Object term_get_fkeys_1 (); term_get_fkeys_arg = address; internal_condition_case (term_get_fkeys_1, Qerror, Fidentity); } @@ -1257,9 +1462,10 @@ term_get_fkeys (address) static Lisp_Object term_get_fkeys_1 () { - extern char *tgetstr (); int i; + char **address = term_get_fkeys_arg; + /* This can happen if CANNOT_DUMP or with strange options. */ if (!initialized) Vfunction_key_map = Fmake_sparse_keymap (Qnil); @@ -1305,9 +1511,9 @@ term_get_fkeys_1 () if (i <= 19) fcap[1] = '1' + i - 11; else if (i <= 45) - fcap[1] = 'A' + i - 11; + fcap[1] = 'A' + i - 20; else - fcap[1] = 'a' + i - 11; + fcap[1] = 'a' + i - 46; { char *sequence = tgetstr (fcap, address); @@ -1342,11 +1548,26 @@ term_get_fkeys_1 () CONDITIONAL_REASSIGN ("%8", "kP", "prior"); /* if there's no key_dc keycap, map key_ic to `insert' keysym */ CONDITIONAL_REASSIGN ("kD", "kI", "insert"); + /* if there's no key_end keycap, map key_ll to 'end' keysym */ + CONDITIONAL_REASSIGN ("@7", "kH", "end"); + + /* IBM has their own non-standard dialect of terminfo. + If the standard name isn't found, try the IBM name. */ + CONDITIONAL_REASSIGN ("kB", "KO", "backtab"); + CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */ + CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */ + CONDITIONAL_REASSIGN ("%7", "ki", "menu"); + CONDITIONAL_REASSIGN ("@7", "kw", "end"); + CONDITIONAL_REASSIGN ("F1", "k<", "f11"); + CONDITIONAL_REASSIGN ("F2", "k>", "f12"); + CONDITIONAL_REASSIGN ("%1", "kq", "help"); + CONDITIONAL_REASSIGN ("*6", "kU", "select"); #undef CONDITIONAL_REASSIGN } } +void term_init (terminal_type) char *terminal_type; { @@ -1356,22 +1577,70 @@ term_init (terminal_type) register char *p; int status; - extern char *tgetstr (); +#ifdef WINDOWSNT + initialize_w32_display (); + + Wcm_clear (); + + area = (char *) malloc (2044); + + if (area == 0) + abort (); + + FrameRows = FRAME_HEIGHT (selected_frame); + FrameCols = FRAME_WIDTH (selected_frame); + specified_window = FRAME_HEIGHT (selected_frame); + + delete_in_insert_mode = 1; + + UseTabs = 0; + scroll_region_ok = 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. */ + + line_ins_del_ok = 0; + char_ins_del_ok = 1; + + baud_rate = 19200; + + FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0; + FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none; + + return; +#else /* not WINDOWSNT */ Wcm_clear (); - dont_calculate_costs = 0; status = tgetent (buffer, terminal_type); if (status < 0) - fatal ("Cannot open termcap database file.\n"); + { +#ifdef TERMINFO + fatal ("Cannot open terminfo database file"); +#else + fatal ("Cannot open termcap database file"); +#endif + } if (status == 0) - fatal ("Terminal type %s is not defined.\n\ + { +#ifdef TERMINFO + 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.\n", - terminal_type); - +to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", + 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); +#endif + } #ifdef TERMINFO area = (char *) malloc (2044); #else @@ -1433,6 +1702,10 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n", Wcm.cm_tab = tgetstr ("ta", address); TS_end_termcap_modes = tgetstr ("te", address); TS_termcap_modes = tgetstr ("ti", address); + TS_bold_mode = tgetstr ("md", address); + TS_end_bold_mode = tgetstr ("me", address); + TS_underscore_mode = tgetstr ("us", address); + TS_end_underscore_mode = tgetstr ("ue", address); Up = tgetstr ("up", address); TS_visible_bell = tgetstr ("vb", address); TS_end_visual_mode = tgetstr ("ve", address); @@ -1443,7 +1716,10 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n", MultiLeft = tgetstr ("LE", address); MultiRight = tgetstr ("RI", address); - AutoWrap = tgetflag ("am"); + MagicWrap = tgetflag ("xn"); + /* Since we make MagicWrap terminals look like AutoWrap, we need to have + the former flag imply the latter. */ + AutoWrap = MagicWrap || tgetflag ("am"); memory_below_frame = tgetflag ("db"); TF_hazeltine = tgetflag ("hz"); must_write_spaces = tgetflag ("in"); @@ -1451,19 +1727,31 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n", TF_insmode_motion = tgetflag ("mi"); TF_standout_motion = tgetflag ("ms"); TF_underscore = tgetflag ("ul"); - MagicWrap = tgetflag ("xn"); TF_xs = tgetflag ("xs"); TF_teleray = tgetflag ("xt"); term_get_fkeys (address); /* Get frame size from system, or else from termcap. */ - get_frame_size (&FRAME_WIDTH (selected_frame), - &FRAME_HEIGHT (selected_frame)); + { + int height, width; + get_frame_size (&width, &height); + FRAME_WIDTH (selected_frame) = width; + FRAME_HEIGHT (selected_frame) = height; + } + if (FRAME_WIDTH (selected_frame) <= 0) - FRAME_WIDTH (selected_frame) = tgetnum ("co"); + SET_FRAME_WIDTH (selected_frame, tgetnum ("co")); + else + /* Keep width and external_width consistent */ + SET_FRAME_WIDTH (selected_frame, FRAME_WIDTH (selected_frame)); if (FRAME_HEIGHT (selected_frame) <= 0) FRAME_HEIGHT (selected_frame) = tgetnum ("li"); + + if (FRAME_HEIGHT (selected_frame) < 3 + || FRAME_WIDTH (selected_frame) < 3) + fatal ("Screen size %dx%d is too small", + FRAME_HEIGHT (selected_frame), FRAME_WIDTH (selected_frame)); min_padding_speed = tgetnum ("pb"); TN_standout_width = tgetnum ("sg"); @@ -1506,7 +1794,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n", If that fails, we can't use standout mode at all. */ if (TS_end_standout_mode == 0) { - char *s = tgetstr ("me"); + char *s = tgetstr ("me", address); if (s != 0) TS_end_standout_mode = s; else @@ -1586,20 +1874,30 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\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.\n", +or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.", terminal_type); -#else +#else /* not VMS */ +# ifdef TERMINFO 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.\n", +to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", terminal_type); -#endif +# else /* TERMCAP */ + 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); +# endif /* TERMINFO */ +#endif /*VMS */ if (FRAME_HEIGHT (selected_frame) <= 0 || FRAME_WIDTH (selected_frame) <= 0) - fatal ("The frame size has not been specified."); + fatal ("The frame size has not been specified"); delete_in_insert_mode = TS_delete_mode && TS_insert_mode @@ -1611,7 +1909,8 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n", /* Remove width of standout marker from usable width of line */ if (TN_standout_width > 0) - FRAME_WIDTH (selected_frame) -= TN_standout_width; + SET_FRAME_WIDTH (selected_frame, + FRAME_WIDTH (selected_frame) - TN_standout_width); UseTabs = tabs_safe_p () && TabWidth == 8; @@ -1635,15 +1934,36 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.\n", baud_rate = 9600; FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0; - FRAME_HAS_VERTICAL_SCROLL_BARS (selected_frame) = 0; + FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none; +#endif /* WINDOWSNT */ } /* VARARGS 1 */ +void fatal (str, arg1, arg2) char *str, *arg1, *arg2; { fprintf (stderr, "emacs: "); fprintf (stderr, str, arg1, arg2); + fprintf (stderr, "\n"); fflush (stderr); exit (1); } + +void +syms_of_term () +{ + DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo, + "Non-nil means the system uses terminfo rather than termcap.\n\ +This variable can be used by terminal emulator packages."); +#ifdef TERMINFO + system_uses_terminfo = 1; +#else + system_uses_terminfo = 0; +#endif + + DEFVAR_LISP ("ring-bell-function", &Vring_bell_function, + "Non-nil means call this function to ring the bell.\n\ +The function should accept no arguments."); + Vring_bell_function = Qnil; +}