diff options
| author | Gerd Moellmann | 1999-07-21 21:43:52 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 1999-07-21 21:43:52 +0000 |
| commit | a168702af09590a85cd744f6174d782237b861d8 (patch) | |
| tree | 6d104571c5c0727b9386a9da4551953504e00ab4 /src | |
| parent | 6820433ec30a17a24df70fa4853da5f6a9c312e2 (diff) | |
| download | emacs-a168702af09590a85cd744f6174d782237b861d8.tar.gz emacs-a168702af09590a85cd744f6174d782237b861d8.zip | |
Rewritten.
(append_glyph): New.
(update_end): Turn cursor on only if selected window's
cursor_off_p flag is not set.
(TS_cursor_visible): Renamed from TS_visual_mode.
(TS_cursor_normal): Renamed from TS_end_visual_mode.
(TS_cursor_invisible): New.
(term_init): Initialize TS_cursor_invisible.
(tty_hide_cursor): New.
(tty_show_cursor): New.
(update_end): Show tty cursor.
(update_begin): Hide tty cursor to prevent cursor flickering
during redisplays triggered by timers (stealth fontification).
(estimate_mode_line_height): New.
(estimate_mode_line_height_hook): New.
(OUTPUT_IF): Make replacement text have statement form.
(OUTPUT1_IF): Ditto.
(TS_italic_mode, TS_end_italic_mode): Removed.
(TS_bold_mode): Removed.
(TS_underscore_mode, TS_end_underscore_mode): Removed.
(TS_enter_bold_mode, TS_enter_dim_mode, TS_enter_blink_mode): New.
(TS_enter_reverse_mode): New.
(TS_enter_underline_mode, TS_exit_underline_mode): New.
(TN_magic_cookie_glitch_ul): New.
(TS_enter_alt_charset_mode, TS_exit_alt_charset_mode): New.
(TS_exit_attribute_mode): New.
(TN_max_colors, TN_max_pairs, TS_orig_pairs): New.
(TS_set_foreground, TS_set_background): New.
(reset_terminal_modes): Switch colors back to default.
(write_glyphs): Turn face on before writing text, turn it off
afterwards.
(insert_glyphs): Ditto.
(term_init): Initialize new terminal capability variables.
(turn_on_face): Turn a face on.
(turn_off_face): Turn a face off.
(global): Rewrite for new glyphs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/term.c | 643 |
1 files changed, 566 insertions, 77 deletions
diff --git a/src/term.c b/src/term.c index 112722cfa78..7c05f7cbf10 100644 --- a/src/term.c +++ b/src/term.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* terminal control module for terminals described by TERMCAP | 1 | /* terminal control module for terminals described by TERMCAP |
| 2 | Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc. | 2 | Copyright (C) 1985, 86, 87, 93, 94, 95, 98 |
| 3 | Free Software Foundation, Inc. | ||
| 3 | 4 | ||
| 4 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 5 | 6 | ||
| @@ -18,13 +19,15 @@ along with GNU Emacs; see the file COPYING. If not, write to | |||
| 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 19 | Boston, MA 02111-1307, USA. */ | 20 | Boston, MA 02111-1307, USA. */ |
| 20 | 21 | ||
| 22 | /* New redisplay, TTY faces by Gerd Moellmann <gerd@acm.org>. */ | ||
| 23 | |||
| 21 | 24 | ||
| 22 | #include <config.h> | 25 | #include <config.h> |
| 23 | #include <stdio.h> | 26 | #include <stdio.h> |
| 24 | #include <ctype.h> | 27 | #include <ctype.h> |
| 28 | #include <string.h> | ||
| 25 | #include "termchar.h" | 29 | #include "termchar.h" |
| 26 | #include "termopts.h" | 30 | #include "termopts.h" |
| 27 | #undef NULL | ||
| 28 | #include "lisp.h" | 31 | #include "lisp.h" |
| 29 | #include "charset.h" | 32 | #include "charset.h" |
| 30 | #include "coding.h" | 33 | #include "coding.h" |
| @@ -33,21 +36,35 @@ Boston, MA 02111-1307, USA. */ | |||
| 33 | #include "termhooks.h" | 36 | #include "termhooks.h" |
| 34 | #include "keyboard.h" | 37 | #include "keyboard.h" |
| 35 | #include "dispextern.h" | 38 | #include "dispextern.h" |
| 39 | #include "window.h" | ||
| 40 | |||
| 36 | #include "cm.h" | 41 | #include "cm.h" |
| 37 | #ifdef HAVE_X_WINDOWS | 42 | #ifdef HAVE_X_WINDOWS |
| 38 | #include "xterm.h" | 43 | #include "xterm.h" |
| 39 | #endif | 44 | #endif |
| 40 | 45 | ||
| 46 | static void turn_on_face P_ ((struct frame *, int face_id)); | ||
| 47 | static void turn_off_face P_ ((struct frame *, int face_id)); | ||
| 48 | static void tty_show_cursor P_ ((void)); | ||
| 49 | static void tty_hide_cursor P_ ((void)); | ||
| 50 | |||
| 41 | #define max(a, b) ((a) > (b) ? (a) : (b)) | 51 | #define max(a, b) ((a) > (b) ? (a) : (b)) |
| 42 | #define min(a, b) ((a) < (b) ? (a) : (b)) | 52 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
| 43 | 53 | ||
| 44 | #define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc) | 54 | #define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc) |
| 45 | #define OUTPUT1(a) tputs (a, 1, cmputc) | 55 | #define OUTPUT1(a) tputs (a, 1, cmputc) |
| 46 | #define OUTPUTL(a, lines) tputs (a, lines, cmputc) | 56 | #define OUTPUTL(a, lines) tputs (a, lines, cmputc) |
| 47 | #define OUTPUT_IF(a) { if (a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); } | 57 | |
| 48 | #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); } | 58 | #define OUTPUT_IF(a) \ |
| 59 | if (a) \ | ||
| 60 | tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); \ | ||
| 61 | else \ | ||
| 62 | (void) 0 | ||
| 63 | |||
| 64 | #define OUTPUT1_IF(a) if (a) tputs (a, 1, cmputc); else (void) 0 | ||
| 49 | 65 | ||
| 50 | /* Function to use to ring the bell. */ | 66 | /* Function to use to ring the bell. */ |
| 67 | |||
| 51 | Lisp_Object Vring_bell_function; | 68 | Lisp_Object Vring_bell_function; |
| 52 | 69 | ||
| 53 | /* Terminal characteristics that higher levels want to look at. | 70 | /* Terminal characteristics that higher levels want to look at. |
| @@ -71,6 +88,7 @@ int fast_clear_end_of_line; /* Terminal has a `ce' string */ | |||
| 71 | /* Nonzero means no need to redraw the entire frame on resuming | 88 | /* Nonzero means no need to redraw the entire frame on resuming |
| 72 | a suspended Emacs. This is useful on terminals with multiple pages, | 89 | a suspended Emacs. This is useful on terminals with multiple pages, |
| 73 | where one page is used for Emacs and another for all else. */ | 90 | where one page is used for Emacs and another for all else. */ |
| 91 | |||
| 74 | int no_redraw_on_reenter; | 92 | int no_redraw_on_reenter; |
| 75 | 93 | ||
| 76 | /* Hook functions that you can set to snap out the functions in this file. | 94 | /* Hook functions that you can set to snap out the functions in this file. |
| @@ -78,18 +96,15 @@ int no_redraw_on_reenter; | |||
| 78 | 96 | ||
| 79 | void (*cursor_to_hook) P_ ((int, int)); | 97 | void (*cursor_to_hook) P_ ((int, int)); |
| 80 | void (*raw_cursor_to_hook) P_ ((int, int)); | 98 | void (*raw_cursor_to_hook) P_ ((int, int)); |
| 81 | |||
| 82 | void (*clear_to_end_hook) P_ ((void)); | 99 | void (*clear_to_end_hook) P_ ((void)); |
| 83 | void (*clear_frame_hook) P_ ((void)); | 100 | void (*clear_frame_hook) P_ ((void)); |
| 84 | void (*clear_end_of_line_hook) P_ ((int)); | 101 | void (*clear_end_of_line_hook) P_ ((int)); |
| 85 | 102 | ||
| 86 | void (*ins_del_lines_hook) P_ ((int, int)); | 103 | void (*ins_del_lines_hook) P_ ((int, int)); |
| 87 | 104 | ||
| 88 | void (*change_line_highlight_hook) P_ ((int, int, int)); | 105 | void (*change_line_highlight_hook) P_ ((int, int, int, int)); |
| 89 | void (*reassert_line_highlight_hook) P_ ((int, int)); | 106 | void (*reassert_line_highlight_hook) P_ ((int, int)); |
| 90 | 107 | ||
| 91 | void (*insert_glyphs_hook) P_ ((GLYPH *, int)); | ||
| 92 | void (*write_glyphs_hook) P_ ((GLYPH *, int)); | ||
| 93 | void (*delete_glyphs_hook) P_ ((int)); | 108 | void (*delete_glyphs_hook) P_ ((int)); |
| 94 | 109 | ||
| 95 | void (*ring_bell_hook) P_ ((void)); | 110 | void (*ring_bell_hook) P_ ((void)); |
| @@ -99,6 +114,9 @@ void (*set_terminal_modes_hook) P_ ((void)); | |||
| 99 | void (*update_begin_hook) P_ ((struct frame *)); | 114 | void (*update_begin_hook) P_ ((struct frame *)); |
| 100 | void (*update_end_hook) P_ ((struct frame *)); | 115 | void (*update_end_hook) P_ ((struct frame *)); |
| 101 | void (*set_terminal_window_hook) P_ ((int)); | 116 | void (*set_terminal_window_hook) P_ ((int)); |
| 117 | void (*insert_glyphs_hook) P_ ((struct glyph *, int)); | ||
| 118 | void (*write_glyphs_hook) P_ ((struct glyph *, int)); | ||
| 119 | void (*delete_glyphs_hook) P_ ((int)); | ||
| 102 | 120 | ||
| 103 | int (*read_socket_hook) P_ ((int, struct input_event *, int, int)); | 121 | int (*read_socket_hook) P_ ((int, struct input_event *, int, int)); |
| 104 | 122 | ||
| @@ -130,7 +148,7 @@ void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist, | |||
| 130 | unsigned long *time)); | 148 | unsigned long *time)); |
| 131 | 149 | ||
| 132 | /* When reading from a minibuffer in a different frame, Emacs wants | 150 | /* When reading from a minibuffer in a different frame, Emacs wants |
| 133 | to shift the highlight from the selected frame to the minibuffer's | 151 | to shift the highlight from the selected frame to the mini-buffer's |
| 134 | frame; under X, this means it lies about where the focus is. | 152 | frame; under X, this means it lies about where the focus is. |
| 135 | This hook tells the window system code to re-decide where to put | 153 | This hook tells the window system code to re-decide where to put |
| 136 | the highlight. */ | 154 | the highlight. */ |
| @@ -153,6 +171,7 @@ void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise)); | |||
| 153 | indicate that we are displaying PORTION characters out of a total | 171 | indicate that we are displaying PORTION characters out of a total |
| 154 | of WHOLE characters, starting at POSITION. If WINDOW doesn't yet | 172 | of WHOLE characters, starting at POSITION. If WINDOW doesn't yet |
| 155 | have a scroll bar, create one for it. */ | 173 | have a scroll bar, create one for it. */ |
| 174 | |||
| 156 | void (*set_vertical_scroll_bar_hook) | 175 | void (*set_vertical_scroll_bar_hook) |
| 157 | P_ ((struct window *window, | 176 | P_ ((struct window *window, |
| 158 | int portion, int whole, int position)); | 177 | int portion, int whole, int position)); |
| @@ -168,7 +187,7 @@ void (*set_vertical_scroll_bar_hook) | |||
| 168 | 187 | ||
| 169 | /* Arrange for all scroll bars on FRAME to be removed at the next call | 188 | /* Arrange for all scroll bars on FRAME to be removed at the next call |
| 170 | to `*judge_scroll_bars_hook'. A scroll bar may be spared if | 189 | to `*judge_scroll_bars_hook'. A scroll bar may be spared if |
| 171 | `*redeem_scroll_bar_hook' is applied to its window before the judgement. | 190 | `*redeem_scroll_bar_hook' is applied to its window before the judgment. |
| 172 | 191 | ||
| 173 | This should be applied to each frame each time its window tree is | 192 | This should be applied to each frame each time its window tree is |
| 174 | redisplayed, even if it is not displaying scroll bars at the moment; | 193 | redisplayed, even if it is not displaying scroll bars at the moment; |
| @@ -197,12 +216,14 @@ void (*redeem_scroll_bar_hook) P_ ((struct window *window)); | |||
| 197 | currently displaying them. */ | 216 | currently displaying them. */ |
| 198 | void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME)); | 217 | void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME)); |
| 199 | 218 | ||
| 219 | /* Hook to call in estimate_mode_line_height, if any. */ | ||
| 220 | |||
| 221 | int (* estimate_mode_line_height_hook) P_ ((struct frame *f, enum face_id)); | ||
| 222 | |||
| 200 | 223 | ||
| 201 | /* Strings, numbers and flags taken from the termcap entry. */ | 224 | /* Strings, numbers and flags taken from the termcap entry. */ |
| 202 | 225 | ||
| 203 | char *TS_end_italic_mode; /* termcap "ae" */ | ||
| 204 | char *TS_ins_line; /* "al" */ | 226 | char *TS_ins_line; /* "al" */ |
| 205 | char *TS_italic_mode; /* "as" */ | ||
| 206 | char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */ | 227 | char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */ |
| 207 | char *TS_bell; /* "bl" */ | 228 | char *TS_bell; /* "bl" */ |
| 208 | char *TS_clr_to_bottom; /* "cd" */ | 229 | char *TS_clr_to_bottom; /* "cd" */ |
| @@ -225,8 +246,6 @@ char *TS_insert_mode; /* "im", enter character-insert mode */ | |||
| 225 | char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */ | 246 | char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */ |
| 226 | char *TS_end_keypad_mode; /* "ke" */ | 247 | char *TS_end_keypad_mode; /* "ke" */ |
| 227 | char *TS_keypad_mode; /* "ks" */ | 248 | char *TS_keypad_mode; /* "ks" */ |
| 228 | char *TS_bold_mode; /* "md" */ | ||
| 229 | char *TS_end_bold_mode; /* "me" */ | ||
| 230 | char *TS_pad_char; /* "pc", char to use as padding */ | 249 | char *TS_pad_char; /* "pc", char to use as padding */ |
| 231 | char *TS_repeat; /* "rp" (2 params, # times to repeat | 250 | char *TS_repeat; /* "rp" (2 params, # times to repeat |
| 232 | and character to be repeated) */ | 251 | and character to be repeated) */ |
| @@ -236,19 +255,69 @@ char *TS_standout_mode; /* "so" */ | |||
| 236 | char *TS_rev_scroll; /* "sr" */ | 255 | char *TS_rev_scroll; /* "sr" */ |
| 237 | char *TS_end_termcap_modes; /* "te" */ | 256 | char *TS_end_termcap_modes; /* "te" */ |
| 238 | char *TS_termcap_modes; /* "ti" */ | 257 | char *TS_termcap_modes; /* "ti" */ |
| 239 | char *TS_end_underscore_mode; /* "ue" */ | ||
| 240 | char *TS_underscore_mode; /* "us" */ | ||
| 241 | char *TS_visible_bell; /* "vb" */ | 258 | char *TS_visible_bell; /* "vb" */ |
| 242 | char *TS_end_visual_mode; /* "ve" */ | 259 | char *TS_cursor_normal; /* "ve" */ |
| 243 | char *TS_visual_mode; /* "vi" */ | 260 | char *TS_cursor_visible; /* "vs" */ |
| 261 | char *TS_cursor_invisible; /* "vi" */ | ||
| 244 | char *TS_set_window; /* "wi" (4 params, start and end of window, | 262 | char *TS_set_window; /* "wi" (4 params, start and end of window, |
| 245 | each as vpos and hpos) */ | 263 | each as vpos and hpos) */ |
| 246 | 264 | ||
| 265 | /* "md" -- turn on bold (extra bright mode). */ | ||
| 266 | |||
| 267 | char *TS_enter_bold_mode; | ||
| 268 | |||
| 269 | /* "mh" -- turn on half-bright mode. */ | ||
| 270 | |||
| 271 | char *TS_enter_dim_mode; | ||
| 272 | |||
| 273 | /* "mb" -- enter blinking mode. */ | ||
| 274 | |||
| 275 | char *TS_enter_blink_mode; | ||
| 276 | |||
| 277 | /* "mr" -- enter reverse video mode. */ | ||
| 278 | |||
| 279 | char *TS_enter_reverse_mode; | ||
| 280 | |||
| 281 | /* "us"/"ue" -- start/end underlining. */ | ||
| 282 | |||
| 283 | char *TS_exit_underline_mode, *TS_enter_underline_mode; | ||
| 284 | |||
| 285 | /* "ug" -- number of blanks left by underline. */ | ||
| 286 | |||
| 287 | int TN_magic_cookie_glitch_ul; | ||
| 288 | |||
| 289 | /* "as"/"ae" -- start/end alternate character set. Not really | ||
| 290 | supported, yet. */ | ||
| 291 | |||
| 292 | char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode; | ||
| 293 | |||
| 294 | /* "me" -- switch appearances off. */ | ||
| 295 | |||
| 296 | char *TS_exit_attribute_mode; | ||
| 297 | |||
| 298 | /* "Co" -- number of colors. */ | ||
| 299 | |||
| 300 | int TN_max_colors; | ||
| 301 | |||
| 302 | /* "pa" -- max. number of color pairs on screen. Not handled yet. | ||
| 303 | Could be a problem if not equal to TN_max_colors * TN_max_colors. */ | ||
| 304 | |||
| 305 | int TN_max_pairs; | ||
| 306 | |||
| 307 | /* "op" -- SVr4 set default pair to its original value. */ | ||
| 308 | |||
| 309 | char *TS_orig_pair; | ||
| 310 | |||
| 311 | /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color. | ||
| 312 | 1 param, the color index. */ | ||
| 313 | |||
| 314 | char *TS_set_foreground, *TS_set_background; | ||
| 315 | |||
| 247 | int TF_hazeltine; /* termcap hz flag. */ | 316 | int TF_hazeltine; /* termcap hz flag. */ |
| 248 | int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */ | 317 | int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */ |
| 249 | int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */ | 318 | int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */ |
| 250 | int TF_underscore; /* termcap ul flag: _ underlines if overstruck on | 319 | int TF_underscore; /* termcap ul flag: _ underlines if over-struck on |
| 251 | nonblank position. Must clear before writing _. */ | 320 | non-blank position. Must clear before writing _. */ |
| 252 | int TF_teleray; /* termcap xt flag: many weird consequences. | 321 | int TF_teleray; /* termcap xt flag: many weird consequences. |
| 253 | For t1061. */ | 322 | For t1061. */ |
| 254 | 323 | ||
| @@ -269,8 +338,11 @@ static int se_is_so; /* 1 if same string both enters and leaves | |||
| 269 | /* internal state */ | 338 | /* internal state */ |
| 270 | 339 | ||
| 271 | /* The largest frame width in any call to calculate_costs. */ | 340 | /* The largest frame width in any call to calculate_costs. */ |
| 341 | |||
| 272 | int max_frame_width; | 342 | int max_frame_width; |
| 343 | |||
| 273 | /* The largest frame height in any call to calculate_costs. */ | 344 | /* The largest frame height in any call to calculate_costs. */ |
| 345 | |||
| 274 | int max_frame_height; | 346 | int max_frame_height; |
| 275 | 347 | ||
| 276 | /* Number of chars of space used for standout marker at beginning of line, | 348 | /* Number of chars of space used for standout marker at beginning of line, |
| @@ -283,6 +355,7 @@ static char *chars_wasted; | |||
| 283 | static char *copybuf; | 355 | static char *copybuf; |
| 284 | 356 | ||
| 285 | /* nonzero means supposed to write text in standout mode. */ | 357 | /* nonzero means supposed to write text in standout mode. */ |
| 358 | |||
| 286 | int standout_requested; | 359 | int standout_requested; |
| 287 | 360 | ||
| 288 | int insert_mode; /* Nonzero when in insert mode. */ | 361 | int insert_mode; /* Nonzero when in insert mode. */ |
| @@ -303,6 +376,7 @@ int specified_window; | |||
| 303 | FRAME_PTR updating_frame; | 376 | FRAME_PTR updating_frame; |
| 304 | 377 | ||
| 305 | /* Provided for lisp packages. */ | 378 | /* Provided for lisp packages. */ |
| 379 | |||
| 306 | static int system_uses_terminfo; | 380 | static int system_uses_terminfo; |
| 307 | 381 | ||
| 308 | char *tparam (); | 382 | char *tparam (); |
| @@ -311,6 +385,7 @@ extern char *tgetstr (); | |||
| 311 | 385 | ||
| 312 | 386 | ||
| 313 | #ifdef WINDOWSNT | 387 | #ifdef WINDOWSNT |
| 388 | |||
| 314 | /* We aren't X windows, but we aren't termcap either. This makes me | 389 | /* We aren't X windows, but we aren't termcap either. This makes me |
| 315 | uncertain as to what value to use for frame.output_method. For | 390 | uncertain as to what value to use for frame.output_method. For |
| 316 | this file, we'll define FRAME_TERMCAP_P to be zero so that our | 391 | this file, we'll define FRAME_TERMCAP_P to be zero so that our |
| @@ -361,7 +436,7 @@ set_terminal_modes () | |||
| 361 | return; | 436 | return; |
| 362 | } | 437 | } |
| 363 | OUTPUT_IF (TS_termcap_modes); | 438 | OUTPUT_IF (TS_termcap_modes); |
| 364 | OUTPUT_IF (TS_visual_mode); | 439 | OUTPUT_IF (TS_cursor_visible); |
| 365 | OUTPUT_IF (TS_keypad_mode); | 440 | OUTPUT_IF (TS_keypad_mode); |
| 366 | losecursor (); | 441 | losecursor (); |
| 367 | } | 442 | } |
| @@ -379,8 +454,9 @@ reset_terminal_modes () | |||
| 379 | turn_off_highlight (); | 454 | turn_off_highlight (); |
| 380 | turn_off_insert (); | 455 | turn_off_insert (); |
| 381 | OUTPUT_IF (TS_end_keypad_mode); | 456 | OUTPUT_IF (TS_end_keypad_mode); |
| 382 | OUTPUT_IF (TS_end_visual_mode); | 457 | OUTPUT_IF (TS_cursor_normal); |
| 383 | OUTPUT_IF (TS_end_termcap_modes); | 458 | OUTPUT_IF (TS_end_termcap_modes); |
| 459 | OUTPUT_IF (TS_orig_pair); | ||
| 384 | /* Output raw CR so kernel can track the cursor hpos. */ | 460 | /* Output raw CR so kernel can track the cursor hpos. */ |
| 385 | /* But on magic-cookie terminals this can erase an end-standout marker and | 461 | /* But on magic-cookie terminals this can erase an end-standout marker and |
| 386 | cause the rest of the frame to be in standout, so move down first. */ | 462 | cause the rest of the frame to be in standout, so move down first. */ |
| @@ -396,6 +472,8 @@ update_begin (f) | |||
| 396 | updating_frame = f; | 472 | updating_frame = f; |
| 397 | if (! FRAME_TERMCAP_P (updating_frame)) | 473 | if (! FRAME_TERMCAP_P (updating_frame)) |
| 398 | (*update_begin_hook) (f); | 474 | (*update_begin_hook) (f); |
| 475 | else | ||
| 476 | tty_hide_cursor (); | ||
| 399 | } | 477 | } |
| 400 | 478 | ||
| 401 | void | 479 | void |
| @@ -408,6 +486,10 @@ update_end (f) | |||
| 408 | updating_frame = 0; | 486 | updating_frame = 0; |
| 409 | return; | 487 | return; |
| 410 | } | 488 | } |
| 489 | |||
| 490 | if (!XWINDOW (selected_window)->cursor_off_p) | ||
| 491 | tty_show_cursor (); | ||
| 492 | |||
| 411 | turn_off_insert (); | 493 | turn_off_insert (); |
| 412 | background_highlight (); | 494 | background_highlight (); |
| 413 | standout_requested = 0; | 495 | standout_requested = 0; |
| @@ -499,6 +581,26 @@ turn_on_highlight () | |||
| 499 | } | 581 | } |
| 500 | } | 582 | } |
| 501 | 583 | ||
| 584 | |||
| 585 | /* Make cursor invisible. */ | ||
| 586 | |||
| 587 | static void | ||
| 588 | tty_hide_cursor () | ||
| 589 | { | ||
| 590 | OUTPUT_IF (TS_cursor_invisible); | ||
| 591 | } | ||
| 592 | |||
| 593 | |||
| 594 | /* Ensure that cursor is visible. */ | ||
| 595 | |||
| 596 | static void | ||
| 597 | tty_show_cursor () | ||
| 598 | { | ||
| 599 | OUTPUT_IF (TS_cursor_normal); | ||
| 600 | OUTPUT_IF (TS_cursor_visible); | ||
| 601 | } | ||
| 602 | |||
| 603 | |||
| 502 | /* Set standout mode to the state it should be in for | 604 | /* Set standout mode to the state it should be in for |
| 503 | empty space inside windows. What this is, | 605 | empty space inside windows. What this is, |
| 504 | depends on the user option inverse-video. */ | 606 | depends on the user option inverse-video. */ |
| @@ -569,7 +671,7 @@ reassert_line_highlight (highlight, vpos) | |||
| 569 | if (TN_standout_width < 0) | 671 | if (TN_standout_width < 0) |
| 570 | /* Handle terminals where standout takes affect at output time */ | 672 | /* Handle terminals where standout takes affect at output time */ |
| 571 | standout_requested = highlight; | 673 | standout_requested = highlight; |
| 572 | else if (chars_wasted[vpos] == 0) | 674 | else if (chars_wasted && chars_wasted[vpos] == 0) |
| 573 | /* For terminals with standout markers, write one on this line | 675 | /* For terminals with standout markers, write one on this line |
| 574 | if there isn't one already. */ | 676 | if there isn't one already. */ |
| 575 | write_standout_marker (highlight, vpos); | 677 | write_standout_marker (highlight, vpos); |
| @@ -579,13 +681,13 @@ reassert_line_highlight (highlight, vpos) | |||
| 579 | and change whether it is highlighted. */ | 681 | and change whether it is highlighted. */ |
| 580 | 682 | ||
| 581 | void | 683 | void |
| 582 | change_line_highlight (new_highlight, vpos, first_unused_hpos) | 684 | change_line_highlight (new_highlight, vpos, y, first_unused_hpos) |
| 583 | int new_highlight, vpos, first_unused_hpos; | 685 | int new_highlight, vpos, y, first_unused_hpos; |
| 584 | { | 686 | { |
| 585 | standout_requested = new_highlight; | 687 | standout_requested = new_highlight; |
| 586 | if (! FRAME_TERMCAP_P (updating_frame)) | 688 | if (! FRAME_TERMCAP_P (updating_frame)) |
| 587 | { | 689 | { |
| 588 | (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos); | 690 | (*change_line_highlight_hook) (new_highlight, vpos, y, first_unused_hpos); |
| 589 | return; | 691 | return; |
| 590 | } | 692 | } |
| 591 | 693 | ||
| @@ -613,18 +715,17 @@ change_line_highlight (new_highlight, vpos, first_unused_hpos) | |||
| 613 | } | 715 | } |
| 614 | 716 | ||
| 615 | 717 | ||
| 616 | /* Move to absolute position, specified origin 0 */ | 718 | /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are |
| 719 | frame-relative coordinates. */ | ||
| 617 | 720 | ||
| 618 | void | 721 | void |
| 619 | cursor_to (row, col) | 722 | cursor_to (vpos, hpos) |
| 620 | int row, col; | 723 | int vpos, hpos; |
| 621 | { | 724 | { |
| 622 | if (! FRAME_TERMCAP_P ((updating_frame | 725 | if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)) |
| 623 | ? updating_frame | ||
| 624 | : selected_frame)) | ||
| 625 | && cursor_to_hook) | 726 | && cursor_to_hook) |
| 626 | { | 727 | { |
| 627 | (*cursor_to_hook) (row, col); | 728 | (*cursor_to_hook) (vpos, hpos); |
| 628 | return; | 729 | return; |
| 629 | } | 730 | } |
| 630 | 731 | ||
| @@ -633,14 +734,14 @@ cursor_to (row, col) | |||
| 633 | if (chars_wasted == 0) | 734 | if (chars_wasted == 0) |
| 634 | return; | 735 | return; |
| 635 | 736 | ||
| 636 | col += chars_wasted[row] & 077; | 737 | hpos += chars_wasted[vpos] & 077; |
| 637 | if (curY == row && curX == col) | 738 | if (curY == vpos && curX == hpos) |
| 638 | return; | 739 | return; |
| 639 | if (!TF_standout_motion) | 740 | if (!TF_standout_motion) |
| 640 | background_highlight (); | 741 | background_highlight (); |
| 641 | if (!TF_insmode_motion) | 742 | if (!TF_insmode_motion) |
| 642 | turn_off_insert (); | 743 | turn_off_insert (); |
| 643 | cmgoto (row, col); | 744 | cmgoto (vpos, hpos); |
| 644 | } | 745 | } |
| 645 | 746 | ||
| 646 | /* Similar but don't take any account of the wasted characters. */ | 747 | /* Similar but don't take any account of the wasted characters. */ |
| @@ -728,11 +829,10 @@ void | |||
| 728 | clear_end_of_line (first_unused_hpos) | 829 | clear_end_of_line (first_unused_hpos) |
| 729 | int first_unused_hpos; | 830 | int first_unused_hpos; |
| 730 | { | 831 | { |
| 731 | static GLYPH buf = SPACEGLYPH; | ||
| 732 | if (FRAME_TERMCAP_P (selected_frame) | 832 | if (FRAME_TERMCAP_P (selected_frame) |
| 733 | && chars_wasted != 0 | 833 | && chars_wasted != 0 |
| 734 | && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0) | 834 | && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0) |
| 735 | write_glyphs (&buf, 1); | 835 | write_glyphs (&space_glyph, 1); |
| 736 | clear_end_of_line_raw (first_unused_hpos); | 836 | clear_end_of_line_raw (first_unused_hpos); |
| 737 | } | 837 | } |
| 738 | 838 | ||
| @@ -777,7 +877,7 @@ clear_end_of_line_raw (first_unused_hpos) | |||
| 777 | { /* have to do it the hard way */ | 877 | { /* have to do it the hard way */ |
| 778 | turn_off_insert (); | 878 | turn_off_insert (); |
| 779 | 879 | ||
| 780 | /* Do not write in last row last col with Autowrap on. */ | 880 | /* Do not write in last row last col with Auto-wrap on. */ |
| 781 | if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1 | 881 | if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1 |
| 782 | && first_unused_hpos == FRAME_WIDTH (selected_frame)) | 882 | && first_unused_hpos == FRAME_WIDTH (selected_frame)) |
| 783 | first_unused_hpos--; | 883 | first_unused_hpos--; |
| @@ -802,12 +902,12 @@ clear_end_of_line_raw (first_unused_hpos) | |||
| 802 | 902 | ||
| 803 | int | 903 | int |
| 804 | encode_terminal_code (src, dst, src_len, dst_len, consumed) | 904 | encode_terminal_code (src, dst, src_len, dst_len, consumed) |
| 805 | GLYPH *src; | 905 | struct glyph *src; |
| 806 | int src_len; | 906 | int src_len; |
| 807 | unsigned char *dst; | 907 | unsigned char *dst; |
| 808 | int dst_len, *consumed; | 908 | int dst_len, *consumed; |
| 809 | { | 909 | { |
| 810 | GLYPH *src_start = src, *src_end = src + src_len; | 910 | struct glyph *src_start = src, *src_end = src + src_len; |
| 811 | unsigned char *dst_start = dst, *dst_end = dst + dst_len; | 911 | unsigned char *dst_start = dst, *dst_end = dst + dst_len; |
| 812 | register GLYPH g; | 912 | register GLYPH g; |
| 813 | unsigned int c; | 913 | unsigned int c; |
| @@ -824,11 +924,13 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) | |||
| 824 | 924 | ||
| 825 | while (src < src_end) | 925 | while (src < src_end) |
| 826 | { | 926 | { |
| 827 | g = *src; | 927 | g = GLYPH_FROM_CHAR_GLYPH (*src); |
| 928 | |||
| 828 | /* We must skip glyphs to be padded for a wide character. */ | 929 | /* We must skip glyphs to be padded for a wide character. */ |
| 829 | if (! (g & GLYPH_MASK_PADDING)) | 930 | if (! CHAR_GLYPH_PADDING_P (*src)) |
| 830 | { | 931 | { |
| 831 | if ((c = GLYPH_CHAR (selected_frame, g)) > MAX_CHAR) | 932 | c = src->u.ch.code; |
| 933 | if (! GLYPH_CHAR_VALID_P (c)) | ||
| 832 | { | 934 | { |
| 833 | c = ' '; | 935 | c = ' '; |
| 834 | g = MAKE_GLYPH (selected_frame, c, | 936 | g = MAKE_GLYPH (selected_frame, c, |
| @@ -880,6 +982,7 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) | |||
| 880 | } | 982 | } |
| 881 | src++; | 983 | src++; |
| 882 | } | 984 | } |
| 985 | |||
| 883 | *consumed = src - src_start; | 986 | *consumed = src - src_start; |
| 884 | return (dst - dst_start); | 987 | return (dst - dst_start); |
| 885 | } | 988 | } |
| @@ -887,16 +990,14 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed) | |||
| 887 | 990 | ||
| 888 | void | 991 | void |
| 889 | write_glyphs (string, len) | 992 | write_glyphs (string, len) |
| 890 | register GLYPH *string; | 993 | register struct glyph *string; |
| 891 | register int len; | 994 | register int len; |
| 892 | { | 995 | { |
| 893 | register GLYPH g; | ||
| 894 | register int tlen = GLYPH_TABLE_LENGTH; | ||
| 895 | register Lisp_Object *tbase = GLYPH_TABLE_BASE; | ||
| 896 | int produced, consumed; | 996 | int produced, consumed; |
| 997 | struct frame *f = updating_frame ? updating_frame : selected_frame; | ||
| 897 | 998 | ||
| 898 | if (write_glyphs_hook | 999 | if (write_glyphs_hook |
| 899 | && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame))) | 1000 | && ! FRAME_TERMCAP_P (f)) |
| 900 | { | 1001 | { |
| 901 | (*write_glyphs_hook) (string, len); | 1002 | (*write_glyphs_hook) (string, len); |
| 902 | return; | 1003 | return; |
| @@ -905,7 +1006,7 @@ write_glyphs (string, len) | |||
| 905 | highlight_if_desired (); | 1006 | highlight_if_desired (); |
| 906 | turn_off_insert (); | 1007 | turn_off_insert (); |
| 907 | 1008 | ||
| 908 | /* Don't dare write in last column of bottom line, if AutoWrap, | 1009 | /* Don't dare write in last column of bottom line, if Auto-Wrap, |
| 909 | since that would scroll the whole frame on some terminals. */ | 1010 | since that would scroll the whole frame on some terminals. */ |
| 910 | 1011 | ||
| 911 | if (AutoWrap | 1012 | if (AutoWrap |
| @@ -917,27 +1018,49 @@ write_glyphs (string, len) | |||
| 917 | return; | 1018 | return; |
| 918 | 1019 | ||
| 919 | cmplus (len); | 1020 | cmplus (len); |
| 1021 | |||
| 920 | /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at | 1022 | /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at |
| 921 | the tail. */ | 1023 | the tail. */ |
| 922 | terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; | 1024 | terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; |
| 1025 | |||
| 923 | while (len > 0) | 1026 | while (len > 0) |
| 924 | { | 1027 | { |
| 925 | /* We use shared conversion buffer of the current size (1024 | 1028 | /* Identify a run of glyphs with the same face. */ |
| 926 | bytes at least). Usually it is sufficient, but if not, we | 1029 | int face_id = string->u.ch.face_id; |
| 927 | just repeat the loop. */ | 1030 | int n; |
| 928 | produced = encode_terminal_code (string, conversion_buffer, | 1031 | |
| 929 | len, conversion_buffer_size, &consumed); | 1032 | for (n = 1; n < len; ++n) |
| 930 | if (produced > 0) | 1033 | if (string[n].u.ch.face_id != face_id) |
| 1034 | break; | ||
| 1035 | |||
| 1036 | /* Turn appearance modes of the face of the run on. */ | ||
| 1037 | turn_on_face (f, face_id); | ||
| 1038 | |||
| 1039 | while (n > 0) | ||
| 931 | { | 1040 | { |
| 932 | fwrite (conversion_buffer, 1, produced, stdout); | 1041 | /* We use a shared conversion buffer of the current size |
| 933 | if (ferror (stdout)) | 1042 | (1024 bytes at least). Usually it is sufficient, but if |
| 934 | clearerr (stdout); | 1043 | not, we just repeat the loop. */ |
| 935 | if (termscript) | 1044 | produced = encode_terminal_code (string, conversion_buffer, |
| 936 | fwrite (conversion_buffer, 1, produced, termscript); | 1045 | n, conversion_buffer_size, |
| 1046 | &consumed); | ||
| 1047 | if (produced > 0) | ||
| 1048 | { | ||
| 1049 | fwrite (conversion_buffer, 1, produced, stdout); | ||
| 1050 | if (ferror (stdout)) | ||
| 1051 | clearerr (stdout); | ||
| 1052 | if (termscript) | ||
| 1053 | fwrite (conversion_buffer, 1, produced, termscript); | ||
| 1054 | } | ||
| 1055 | len -= consumed; | ||
| 1056 | n -= consumed; | ||
| 1057 | string += consumed; | ||
| 937 | } | 1058 | } |
| 938 | len -= consumed; | 1059 | |
| 939 | string += consumed; | 1060 | /* Turn appearance modes off. */ |
| 1061 | turn_off_face (f, face_id); | ||
| 940 | } | 1062 | } |
| 1063 | |||
| 941 | /* We may have to output some codes to terminate the writing. */ | 1064 | /* We may have to output some codes to terminate the writing. */ |
| 942 | if (CODING_REQUIRE_FLUSHING (&terminal_coding)) | 1065 | if (CODING_REQUIRE_FLUSHING (&terminal_coding)) |
| 943 | { | 1066 | { |
| @@ -954,6 +1077,7 @@ write_glyphs (string, len) | |||
| 954 | termscript); | 1077 | termscript); |
| 955 | } | 1078 | } |
| 956 | } | 1079 | } |
| 1080 | |||
| 957 | cmcheckmagic (); | 1081 | cmcheckmagic (); |
| 958 | } | 1082 | } |
| 959 | 1083 | ||
| @@ -961,22 +1085,23 @@ write_glyphs (string, len) | |||
| 961 | 1085 | ||
| 962 | void | 1086 | void |
| 963 | insert_glyphs (start, len) | 1087 | insert_glyphs (start, len) |
| 964 | register GLYPH *start; | 1088 | register struct glyph *start; |
| 965 | register int len; | 1089 | register int len; |
| 966 | { | 1090 | { |
| 967 | char *buf; | 1091 | char *buf; |
| 968 | GLYPH g; | 1092 | GLYPH g; |
| 969 | register int tlen = GLYPH_TABLE_LENGTH; | 1093 | struct frame *f; |
| 970 | register Lisp_Object *tbase = GLYPH_TABLE_BASE; | ||
| 971 | 1094 | ||
| 972 | if (len <= 0) | 1095 | if (len <= 0) |
| 973 | return; | 1096 | return; |
| 974 | 1097 | ||
| 975 | if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame)) | 1098 | if (insert_glyphs_hook) |
| 976 | { | 1099 | { |
| 977 | (*insert_glyphs_hook) (start, len); | 1100 | (*insert_glyphs_hook) (start, len); |
| 978 | return; | 1101 | return; |
| 979 | } | 1102 | } |
| 1103 | |||
| 1104 | f = updating_frame ? updating_frame : selected_frame; | ||
| 980 | highlight_if_desired (); | 1105 | highlight_if_desired (); |
| 981 | 1106 | ||
| 982 | if (TS_ins_multi_chars) | 1107 | if (TS_ins_multi_chars) |
| @@ -996,16 +1121,18 @@ insert_glyphs (start, len) | |||
| 996 | while (len-- > 0) | 1121 | while (len-- > 0) |
| 997 | { | 1122 | { |
| 998 | int produced, consumed; | 1123 | int produced, consumed; |
| 1124 | struct glyph glyph; | ||
| 999 | 1125 | ||
| 1000 | OUTPUT1_IF (TS_ins_char); | 1126 | OUTPUT1_IF (TS_ins_char); |
| 1001 | if (!start) | 1127 | if (!start) |
| 1002 | g = SPACEGLYPH; | 1128 | g = SPACEGLYPH; |
| 1003 | else | 1129 | else |
| 1004 | { | 1130 | { |
| 1005 | g = *start++; | 1131 | g = GLYPH_FROM_CHAR_GLYPH (*start); |
| 1132 | ++start; | ||
| 1006 | /* We must open sufficient space for a character which | 1133 | /* We must open sufficient space for a character which |
| 1007 | occupies more than one column. */ | 1134 | occupies more than one column. */ |
| 1008 | while (*start & GLYPH_MASK_PADDING) | 1135 | while (len && CHAR_GLYPH_PADDING_P (*start)) |
| 1009 | { | 1136 | { |
| 1010 | OUTPUT1_IF (TS_ins_char); | 1137 | OUTPUT1_IF (TS_ins_char); |
| 1011 | start++, len--; | 1138 | start++, len--; |
| @@ -1018,7 +1145,9 @@ insert_glyphs (start, len) | |||
| 1018 | 1145 | ||
| 1019 | /* We use shared conversion buffer of the current size (1024 | 1146 | /* We use shared conversion buffer of the current size (1024 |
| 1020 | bytes at least). It is surely sufficient for just one glyph. */ | 1147 | bytes at least). It is surely sufficient for just one glyph. */ |
| 1021 | produced = encode_terminal_code (&g, conversion_buffer, | 1148 | SET_CHAR_GLYPH_FROM_GLYPH (glyph, g); |
| 1149 | turn_on_face (f, glyph.u.ch.face_id); | ||
| 1150 | produced = encode_terminal_code (&glyph, conversion_buffer, | ||
| 1022 | 1, conversion_buffer_size, &consumed); | 1151 | 1, conversion_buffer_size, &consumed); |
| 1023 | if (produced > 0) | 1152 | if (produced > 0) |
| 1024 | { | 1153 | { |
| @@ -1030,7 +1159,9 @@ insert_glyphs (start, len) | |||
| 1030 | } | 1159 | } |
| 1031 | 1160 | ||
| 1032 | OUTPUT1_IF (TS_pad_inserted_char); | 1161 | OUTPUT1_IF (TS_pad_inserted_char); |
| 1162 | turn_off_face (f, glyph.u.ch.face_id); | ||
| 1033 | } | 1163 | } |
| 1164 | |||
| 1034 | cmcheckmagic (); | 1165 | cmcheckmagic (); |
| 1035 | } | 1166 | } |
| 1036 | 1167 | ||
| @@ -1365,7 +1496,8 @@ struct fkey_table { | |||
| 1365 | other keys (as on the IBM PC keyboard) they get overridden. | 1496 | other keys (as on the IBM PC keyboard) they get overridden. |
| 1366 | */ | 1497 | */ |
| 1367 | 1498 | ||
| 1368 | static struct fkey_table keys[] = { | 1499 | static struct fkey_table keys[] = |
| 1500 | { | ||
| 1369 | "kh", "home", /* termcap */ | 1501 | "kh", "home", /* termcap */ |
| 1370 | "kl", "left", /* termcap */ | 1502 | "kl", "left", /* termcap */ |
| 1371 | "ku", "up", /* termcap */ | 1503 | "ku", "up", /* termcap */ |
| @@ -1570,9 +1702,341 @@ term_get_fkeys_1 () | |||
| 1570 | CONDITIONAL_REASSIGN ("*6", "kU", "select"); | 1702 | CONDITIONAL_REASSIGN ("*6", "kU", "select"); |
| 1571 | #undef CONDITIONAL_REASSIGN | 1703 | #undef CONDITIONAL_REASSIGN |
| 1572 | } | 1704 | } |
| 1705 | |||
| 1706 | return Qnil; | ||
| 1573 | } | 1707 | } |
| 1574 | 1708 | ||
| 1575 | 1709 | ||
| 1710 | /*********************************************************************** | ||
| 1711 | Character Display Information | ||
| 1712 | ***********************************************************************/ | ||
| 1713 | |||
| 1714 | static void append_glyph P_ ((struct it *)); | ||
| 1715 | |||
| 1716 | |||
| 1717 | /* Append glyphs to IT's glyph_row. Called from produce_glyphs for | ||
| 1718 | terminal frames if IT->glyph_row != NULL. IT->c is the character | ||
| 1719 | for which to produce glyphs; IT->face_id contains the character's | ||
| 1720 | face. Padding glyphs are appended if IT->c has a IT->pixel_width > | ||
| 1721 | 1. */ | ||
| 1722 | |||
| 1723 | static void | ||
| 1724 | append_glyph (it) | ||
| 1725 | struct it *it; | ||
| 1726 | { | ||
| 1727 | struct glyph *glyph, *end; | ||
| 1728 | int i; | ||
| 1729 | |||
| 1730 | xassert (it->glyph_row); | ||
| 1731 | glyph = (it->glyph_row->glyphs[it->area] | ||
| 1732 | + it->glyph_row->used[it->area]); | ||
| 1733 | end = it->glyph_row->glyphs[1 + it->area]; | ||
| 1734 | |||
| 1735 | for (i = 0; | ||
| 1736 | i < it->pixel_width && glyph < end; | ||
| 1737 | ++i) | ||
| 1738 | { | ||
| 1739 | glyph->type = CHAR_GLYPH; | ||
| 1740 | glyph->pixel_width = 1; | ||
| 1741 | glyph->u.ch.code = it->c; | ||
| 1742 | glyph->u.ch.face_id = it->face_id; | ||
| 1743 | glyph->u.ch.padding_p = i > 0; | ||
| 1744 | glyph->charpos = CHARPOS (it->position); | ||
| 1745 | glyph->object = it->object; | ||
| 1746 | |||
| 1747 | ++it->glyph_row->used[it->area]; | ||
| 1748 | ++glyph; | ||
| 1749 | } | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | |||
| 1753 | /* Produce glyphs for the display element described by IT. The | ||
| 1754 | function fills output fields of IT with pixel information like the | ||
| 1755 | pixel width and height of a character, and maybe produces glyphs at | ||
| 1756 | the same time if IT->glyph_row is non-null. See the explanation of | ||
| 1757 | struct display_iterator in dispextern.h for an overview. */ | ||
| 1758 | |||
| 1759 | void | ||
| 1760 | produce_glyphs (it) | ||
| 1761 | struct it *it; | ||
| 1762 | { | ||
| 1763 | /* If a hook is installed, let it do the work. */ | ||
| 1764 | xassert (it->what == IT_CHARACTER | ||
| 1765 | || it->what == IT_IMAGE | ||
| 1766 | || it->what == IT_STRETCH); | ||
| 1767 | |||
| 1768 | /* Nothing but characters are supported on terminal frames. */ | ||
| 1769 | xassert (it->what == IT_CHARACTER); | ||
| 1770 | |||
| 1771 | if (it->c >= 040 && it->c < 0177) | ||
| 1772 | { | ||
| 1773 | it->pixel_width = it->nglyphs = 1; | ||
| 1774 | if (it->glyph_row) | ||
| 1775 | append_glyph (it); | ||
| 1776 | } | ||
| 1777 | else if (it->c == '\n') | ||
| 1778 | it->pixel_width = it->nglyphs = 0; | ||
| 1779 | else if (it->c == '\t') | ||
| 1780 | { | ||
| 1781 | int absolute_x = (it->current_x - it->prompt_width | ||
| 1782 | + it->continuation_lines_width); | ||
| 1783 | int next_tab_x | ||
| 1784 | = (((1 + absolute_x + it->tab_width - 1) | ||
| 1785 | / it->tab_width) | ||
| 1786 | * it->tab_width); | ||
| 1787 | int nspaces; | ||
| 1788 | |||
| 1789 | /* If part of the TAB has been displayed on the previous line | ||
| 1790 | which is continued now, continuation_lines_width will have | ||
| 1791 | been incremented already by the part that fitted on the | ||
| 1792 | continued line. So, we will get the right number of spaces | ||
| 1793 | here. */ | ||
| 1794 | nspaces = next_tab_x - absolute_x; | ||
| 1795 | |||
| 1796 | if (it->glyph_row) | ||
| 1797 | { | ||
| 1798 | int n = nspaces; | ||
| 1799 | |||
| 1800 | it->c = ' '; | ||
| 1801 | it->pixel_width = it->len = 1; | ||
| 1802 | |||
| 1803 | while (n--) | ||
| 1804 | append_glyph (it); | ||
| 1805 | |||
| 1806 | it->c = '\t'; | ||
| 1807 | } | ||
| 1808 | |||
| 1809 | it->pixel_width = nspaces; | ||
| 1810 | it->nglyphs = nspaces; | ||
| 1811 | } | ||
| 1812 | else | ||
| 1813 | { | ||
| 1814 | /* A multi-byte character. The display width is a per character | ||
| 1815 | value for characters of set CHARSET_COMPOSITION; otherwise | ||
| 1816 | it is fixed for all characters of the set. Some of the | ||
| 1817 | glyphs may have to be ignored because they are already | ||
| 1818 | displayed in a continued line. */ | ||
| 1819 | int charset = CHAR_CHARSET (it->c); | ||
| 1820 | |||
| 1821 | if (charset == CHARSET_COMPOSITION) | ||
| 1822 | it->pixel_width = cmpchar_table[COMPOSITE_CHAR_ID (it->c)]->width; | ||
| 1823 | else | ||
| 1824 | it->pixel_width = CHARSET_WIDTH (charset); | ||
| 1825 | it->nglyphs = it->pixel_width; | ||
| 1826 | |||
| 1827 | if (it->glyph_row) | ||
| 1828 | append_glyph (it); | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | /* Advance current_x by the pixel width as a convenience for | ||
| 1832 | the caller. */ | ||
| 1833 | if (it->area == TEXT_AREA) | ||
| 1834 | it->current_x += it->pixel_width; | ||
| 1835 | it->ascent = it->max_ascent = 0; | ||
| 1836 | it->descent = it->max_descent = 1; | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | |||
| 1840 | /* Get information about special display element WHAT in an | ||
| 1841 | environment described by IT. WHAT is one of IT_TRUNCATION or | ||
| 1842 | IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a | ||
| 1843 | non-null glyph_row member. This function ensures that fields like | ||
| 1844 | face_id, c, len of IT are left untouched. */ | ||
| 1845 | |||
| 1846 | void | ||
| 1847 | produce_special_glyphs (it, what) | ||
| 1848 | struct it *it; | ||
| 1849 | enum display_element_type what; | ||
| 1850 | { | ||
| 1851 | struct it temp_it; | ||
| 1852 | |||
| 1853 | temp_it = *it; | ||
| 1854 | temp_it.dp = NULL; | ||
| 1855 | temp_it.what = IT_CHARACTER; | ||
| 1856 | temp_it.len = 1; | ||
| 1857 | temp_it.object = 0; | ||
| 1858 | bzero (&temp_it.current, sizeof temp_it.current); | ||
| 1859 | |||
| 1860 | if (what == IT_CONTINUATION) | ||
| 1861 | { | ||
| 1862 | /* Continuation glyph. */ | ||
| 1863 | if (it->dp | ||
| 1864 | && INTEGERP (DISP_CONTINUE_GLYPH (it->dp)) | ||
| 1865 | && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp)))) | ||
| 1866 | { | ||
| 1867 | temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp))); | ||
| 1868 | temp_it.len = CHAR_LEN (temp_it.c); | ||
| 1869 | } | ||
| 1870 | else | ||
| 1871 | temp_it.c = '\\'; | ||
| 1872 | |||
| 1873 | produce_glyphs (&temp_it); | ||
| 1874 | it->pixel_width = temp_it.pixel_width; | ||
| 1875 | it->nglyphs = temp_it.pixel_width; | ||
| 1876 | } | ||
| 1877 | else if (what == IT_TRUNCATION) | ||
| 1878 | { | ||
| 1879 | /* Truncation glyph. */ | ||
| 1880 | if (it->dp | ||
| 1881 | && INTEGERP (DISP_TRUNC_GLYPH (it->dp)) | ||
| 1882 | && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp)))) | ||
| 1883 | { | ||
| 1884 | temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp))); | ||
| 1885 | temp_it.len = CHAR_LEN (temp_it.c); | ||
| 1886 | } | ||
| 1887 | else | ||
| 1888 | temp_it.c = '$'; | ||
| 1889 | |||
| 1890 | produce_glyphs (&temp_it); | ||
| 1891 | it->pixel_width = temp_it.pixel_width; | ||
| 1892 | it->nglyphs = temp_it.pixel_width; | ||
| 1893 | } | ||
| 1894 | else | ||
| 1895 | abort (); | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | |||
| 1899 | /* Return an estimation of the pixel height of mode or top lines on | ||
| 1900 | frame F. FACE_ID specifies what line's height to estimate. */ | ||
| 1901 | |||
| 1902 | int | ||
| 1903 | estimate_mode_line_height (f, face_id) | ||
| 1904 | struct frame *f; | ||
| 1905 | enum face_id face_id; | ||
| 1906 | { | ||
| 1907 | if (estimate_mode_line_height_hook) | ||
| 1908 | return estimate_mode_line_height_hook (f, face_id); | ||
| 1909 | else | ||
| 1910 | return 1; | ||
| 1911 | } | ||
| 1912 | |||
| 1913 | |||
| 1914 | |||
| 1915 | /*********************************************************************** | ||
| 1916 | Faces | ||
| 1917 | ***********************************************************************/ | ||
| 1918 | |||
| 1919 | |||
| 1920 | /* Turn appearances of face FACE_ID on tty frame F on. */ | ||
| 1921 | |||
| 1922 | static void | ||
| 1923 | turn_on_face (f, face_id) | ||
| 1924 | struct frame *f; | ||
| 1925 | int face_id; | ||
| 1926 | { | ||
| 1927 | struct face *face = FACE_FROM_ID (f, face_id); | ||
| 1928 | |||
| 1929 | xassert (face != NULL); | ||
| 1930 | |||
| 1931 | if (face->tty_bold_p) | ||
| 1932 | OUTPUT1_IF (TS_enter_bold_mode); | ||
| 1933 | else if (face->tty_dim_p) | ||
| 1934 | OUTPUT1_IF (TS_enter_dim_mode); | ||
| 1935 | |||
| 1936 | /* Alternate charset and blinking not yet used. */ | ||
| 1937 | if (face->tty_alt_charset_p) | ||
| 1938 | OUTPUT1_IF (TS_enter_alt_charset_mode); | ||
| 1939 | |||
| 1940 | if (face->tty_blinking_p) | ||
| 1941 | OUTPUT1_IF (TS_enter_blink_mode); | ||
| 1942 | |||
| 1943 | if (face->tty_underline_p | ||
| 1944 | /* Don't underline if that's difficult. */ | ||
| 1945 | && TN_magic_cookie_glitch_ul <= 0) | ||
| 1946 | OUTPUT1_IF (TS_enter_underline_mode); | ||
| 1947 | |||
| 1948 | if (face->tty_reverse_p) | ||
| 1949 | OUTPUT1_IF (TS_enter_reverse_mode); | ||
| 1950 | |||
| 1951 | if (TN_max_colors > 0) | ||
| 1952 | { | ||
| 1953 | char *p; | ||
| 1954 | |||
| 1955 | if (face->foreground != FACE_TTY_DEFAULT_COLOR | ||
| 1956 | && TS_set_foreground) | ||
| 1957 | { | ||
| 1958 | p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground); | ||
| 1959 | OUTPUT (p); | ||
| 1960 | xfree (p); | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | if (face->background != FACE_TTY_DEFAULT_COLOR | ||
| 1964 | && TS_set_background) | ||
| 1965 | { | ||
| 1966 | p = tparam (TS_set_background, NULL, 0, (int) face->background); | ||
| 1967 | OUTPUT (p); | ||
| 1968 | xfree (p); | ||
| 1969 | } | ||
| 1970 | } | ||
| 1971 | } | ||
| 1972 | |||
| 1973 | |||
| 1974 | /* Turn off appearances of face FACE_ID on tty frame F. */ | ||
| 1975 | |||
| 1976 | static void | ||
| 1977 | turn_off_face (f, face_id) | ||
| 1978 | struct frame *f; | ||
| 1979 | int face_id; | ||
| 1980 | { | ||
| 1981 | struct face *face = FACE_FROM_ID (f, face_id); | ||
| 1982 | Lisp_Object entry; | ||
| 1983 | |||
| 1984 | xassert (face != NULL); | ||
| 1985 | |||
| 1986 | if (TS_exit_attribute_mode) | ||
| 1987 | { | ||
| 1988 | /* Capability "me" will turn off appearance modes double-bright, | ||
| 1989 | half-bright, reverse-video, standout, underline. It may or | ||
| 1990 | may not turn off alt-char-mode. */ | ||
| 1991 | if (face->tty_bold_p | ||
| 1992 | || face->tty_dim_p | ||
| 1993 | || face->tty_reverse_p | ||
| 1994 | || face->tty_alt_charset_p | ||
| 1995 | || face->tty_blinking_p | ||
| 1996 | || face->tty_underline_p) | ||
| 1997 | OUTPUT1_IF (TS_exit_attribute_mode); | ||
| 1998 | |||
| 1999 | if (face->tty_alt_charset_p) | ||
| 2000 | OUTPUT_IF (TS_exit_alt_charset_mode); | ||
| 2001 | } | ||
| 2002 | else | ||
| 2003 | { | ||
| 2004 | /* If we don't have "me" we can only have those appearances | ||
| 2005 | that have exit sequences defined. */ | ||
| 2006 | if (face->tty_alt_charset_p) | ||
| 2007 | OUTPUT_IF (TS_exit_alt_charset_mode); | ||
| 2008 | |||
| 2009 | if (face->tty_underline_p | ||
| 2010 | /* We don't underline if that's difficult. */ | ||
| 2011 | && TN_magic_cookie_glitch_ul <= 0) | ||
| 2012 | OUTPUT_IF (TS_exit_underline_mode); | ||
| 2013 | } | ||
| 2014 | |||
| 2015 | /* Switch back to default colors. */ | ||
| 2016 | if (TN_max_colors > 0 | ||
| 2017 | && (face->foreground != FACE_TTY_DEFAULT_COLOR | ||
| 2018 | || face->background != FACE_TTY_DEFAULT_COLOR)) | ||
| 2019 | OUTPUT1_IF (TS_orig_pair); | ||
| 2020 | } | ||
| 2021 | |||
| 2022 | |||
| 2023 | /* Return non-zero if the terminal is capable to display colors. */ | ||
| 2024 | |||
| 2025 | DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p, | ||
| 2026 | 0, 0, 0, | ||
| 2027 | "Return non-nil if TTY can display colors.") | ||
| 2028 | () | ||
| 2029 | { | ||
| 2030 | return TN_max_colors > 0 ? Qt : Qnil; | ||
| 2031 | } | ||
| 2032 | |||
| 2033 | |||
| 2034 | |||
| 2035 | |||
| 2036 | /*********************************************************************** | ||
| 2037 | Initialization | ||
| 2038 | ***********************************************************************/ | ||
| 2039 | |||
| 1576 | void | 2040 | void |
| 1577 | term_init (terminal_type) | 2041 | term_init (terminal_type) |
| 1578 | char *terminal_type; | 2042 | char *terminal_type; |
| @@ -1708,20 +2172,42 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", | |||
| 1708 | Wcm.cm_tab = tgetstr ("ta", address); | 2172 | Wcm.cm_tab = tgetstr ("ta", address); |
| 1709 | TS_end_termcap_modes = tgetstr ("te", address); | 2173 | TS_end_termcap_modes = tgetstr ("te", address); |
| 1710 | TS_termcap_modes = tgetstr ("ti", address); | 2174 | TS_termcap_modes = tgetstr ("ti", address); |
| 1711 | TS_bold_mode = tgetstr ("md", address); | ||
| 1712 | TS_end_bold_mode = tgetstr ("me", address); | ||
| 1713 | TS_underscore_mode = tgetstr ("us", address); | ||
| 1714 | TS_end_underscore_mode = tgetstr ("ue", address); | ||
| 1715 | Up = tgetstr ("up", address); | 2175 | Up = tgetstr ("up", address); |
| 1716 | TS_visible_bell = tgetstr ("vb", address); | 2176 | TS_visible_bell = tgetstr ("vb", address); |
| 1717 | TS_end_visual_mode = tgetstr ("ve", address); | 2177 | TS_cursor_normal = tgetstr ("ve", address); |
| 1718 | TS_visual_mode = tgetstr ("vs", address); | 2178 | TS_cursor_visible = tgetstr ("vs", address); |
| 2179 | TS_cursor_invisible = tgetstr ("vi", address); | ||
| 1719 | TS_set_window = tgetstr ("wi", address); | 2180 | TS_set_window = tgetstr ("wi", address); |
| 2181 | |||
| 2182 | TS_enter_underline_mode = tgetstr ("us", address); | ||
| 2183 | TS_exit_underline_mode = tgetstr ("ue", address); | ||
| 2184 | TN_magic_cookie_glitch_ul = tgetnum ("ug"); | ||
| 2185 | TS_enter_bold_mode = tgetstr ("md", address); | ||
| 2186 | TS_enter_dim_mode = tgetstr ("mh", address); | ||
| 2187 | TS_enter_blink_mode = tgetstr ("mb", address); | ||
| 2188 | TS_enter_reverse_mode = tgetstr ("mr", address); | ||
| 2189 | TS_enter_alt_charset_mode = tgetstr ("as", address); | ||
| 2190 | TS_exit_alt_charset_mode = tgetstr ("ae", address); | ||
| 2191 | TS_exit_attribute_mode = tgetstr ("me", address); | ||
| 2192 | |||
| 1720 | MultiUp = tgetstr ("UP", address); | 2193 | MultiUp = tgetstr ("UP", address); |
| 1721 | MultiDown = tgetstr ("DO", address); | 2194 | MultiDown = tgetstr ("DO", address); |
| 1722 | MultiLeft = tgetstr ("LE", address); | 2195 | MultiLeft = tgetstr ("LE", address); |
| 1723 | MultiRight = tgetstr ("RI", address); | 2196 | MultiRight = tgetstr ("RI", address); |
| 1724 | 2197 | ||
| 2198 | /* SVr4/ANSI color suppert. */ | ||
| 2199 | TS_orig_pair = tgetstr ("op", address); | ||
| 2200 | TS_set_foreground = tgetstr ("AF", address); | ||
| 2201 | TS_set_background = tgetstr ("AB", address); | ||
| 2202 | if (!TS_set_foreground) | ||
| 2203 | { | ||
| 2204 | /* SVr4. */ | ||
| 2205 | TS_set_foreground = tgetstr ("Sf", address); | ||
| 2206 | TS_set_background = tgetstr ("Sb", address); | ||
| 2207 | } | ||
| 2208 | TN_max_colors = tgetnum ("Co"); | ||
| 2209 | TN_max_pairs = tgetnum ("pa"); | ||
| 2210 | |||
| 1725 | MagicWrap = tgetflag ("xn"); | 2211 | MagicWrap = tgetflag ("xn"); |
| 1726 | /* Since we make MagicWrap terminals look like AutoWrap, we need to have | 2212 | /* Since we make MagicWrap terminals look like AutoWrap, we need to have |
| 1727 | the former flag imply the latter. */ | 2213 | the former flag imply the latter. */ |
| @@ -1972,4 +2458,7 @@ This variable can be used by terminal emulator packages."); | |||
| 1972 | "Non-nil means call this function to ring the bell.\n\ | 2458 | "Non-nil means call this function to ring the bell.\n\ |
| 1973 | The function should accept no arguments."); | 2459 | The function should accept no arguments."); |
| 1974 | Vring_bell_function = Qnil; | 2460 | Vring_bell_function = Qnil; |
| 2461 | |||
| 2462 | defsubr (&Stty_display_color_p); | ||
| 1975 | } | 2463 | } |
| 2464 | |||