]> code.delx.au - gnu-emacs/blob - src/term.c
(syms_of_coding): Doc fix for inhibit-eol-conversion.
[gnu-emacs] / src / term.c
1 /* terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include "termchar.h"
26 #include "termopts.h"
27 #undef NULL
28 #include "lisp.h"
29 #include "charset.h"
30 #include "coding.h"
31 #include "frame.h"
32 #include "disptab.h"
33 #include "termhooks.h"
34 #include "keyboard.h"
35 #include "dispextern.h"
36 #include "cm.h"
37 #ifdef HAVE_X_WINDOWS
38 #include "xterm.h"
39 #endif
40
41 #define max(a, b) ((a) > (b) ? (a) : (b))
42 #define min(a, b) ((a) < (b) ? (a) : (b))
43
44 #define OUTPUT(a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc)
45 #define OUTPUT1(a) tputs (a, 1, cmputc)
46 #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
47 #define OUTPUT_IF(a) { if (a) tputs (a, (int) (FRAME_HEIGHT (selected_frame) - curY), cmputc); }
48 #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
49
50 /* Function to use to ring the bell. */
51 Lisp_Object Vring_bell_function;
52
53 /* Terminal characteristics that higher levels want to look at.
54 These are all extern'd in termchar.h */
55
56 int must_write_spaces; /* Nonzero means spaces in the text
57 must actually be output; can't just skip
58 over some columns to leave them blank. */
59 int min_padding_speed; /* Speed below which no padding necessary */
60
61 int line_ins_del_ok; /* Terminal can insert and delete lines */
62 int char_ins_del_ok; /* Terminal can insert and delete chars */
63 int scroll_region_ok; /* Terminal supports setting the
64 scroll window */
65 int scroll_region_cost; /* Cost of setting a scroll window,
66 measured in characters */
67 int memory_below_frame; /* Terminal remembers lines
68 scrolled off bottom */
69 int fast_clear_end_of_line; /* Terminal has a `ce' string */
70
71 /* Nonzero means no need to redraw the entire frame on resuming
72 a suspended Emacs. This is useful on terminals with multiple pages,
73 where one page is used for Emacs and another for all else. */
74 int no_redraw_on_reenter;
75
76 /* Hook functions that you can set to snap out the functions in this file.
77 These are all extern'd in termhooks.h */
78
79 void (*cursor_to_hook) P_ ((int, int));
80 void (*raw_cursor_to_hook) P_ ((int, int));
81
82 void (*clear_to_end_hook) P_ ((void));
83 void (*clear_frame_hook) P_ ((void));
84 void (*clear_end_of_line_hook) P_ ((int));
85
86 void (*ins_del_lines_hook) P_ ((int, int));
87
88 void (*change_line_highlight_hook) P_ ((int, int, int));
89 void (*reassert_line_highlight_hook) P_ ((int, int));
90
91 void (*insert_glyphs_hook) P_ ((GLYPH *, int));
92 void (*write_glyphs_hook) P_ ((GLYPH *, int));
93 void (*delete_glyphs_hook) P_ ((int));
94
95 void (*ring_bell_hook) P_ ((void));
96
97 void (*reset_terminal_modes_hook) P_ ((void));
98 void (*set_terminal_modes_hook) P_ ((void));
99 void (*update_begin_hook) P_ ((struct frame *));
100 void (*update_end_hook) P_ ((struct frame *));
101 void (*set_terminal_window_hook) P_ ((int));
102
103 int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
104
105 void (*frame_up_to_date_hook) P_ ((struct frame *));
106
107 /* Return the current position of the mouse.
108
109 Set *f to the frame the mouse is in, or zero if the mouse is in no
110 Emacs frame. If it is set to zero, all the other arguments are
111 garbage.
112
113 If the motion started in a scroll bar, set *bar_window to the
114 scroll bar's window, *part to the part the mouse is currently over,
115 *x to the position of the mouse along the scroll bar, and *y to the
116 overall length of the scroll bar.
117
118 Otherwise, set *bar_window to Qnil, and *x and *y to the column and
119 row of the character cell the mouse is over.
120
121 Set *time to the time the mouse was at the returned position.
122
123 This should clear mouse_moved until the next motion
124 event arrives. */
125 void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
126 Lisp_Object *bar_window,
127 enum scroll_bar_part *part,
128 Lisp_Object *x,
129 Lisp_Object *y,
130 unsigned long *time));
131
132 /* When reading from a minibuffer in a different frame, Emacs wants
133 to shift the highlight from the selected frame to the minibuffer's
134 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
136 the highlight. */
137 void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
138
139 /* If we're displaying frames using a window system that can stack
140 frames on top of each other, this hook allows you to bring a frame
141 to the front, or bury it behind all the other windows. If this
142 hook is zero, that means the device we're displaying on doesn't
143 support overlapping frames, so there's no need to raise or lower
144 anything.
145
146 If RAISE is non-zero, F is brought to the front, before all other
147 windows. If RAISE is zero, F is sent to the back, behind all other
148 windows. */
149 void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
150
151 /* Set the vertical scroll bar for WINDOW to have its upper left corner
152 at (TOP, LEFT), and be LENGTH rows high. Set its handle to
153 indicate that we are displaying PORTION characters out of a total
154 of WHOLE characters, starting at POSITION. If WINDOW doesn't yet
155 have a scroll bar, create one for it. */
156 void (*set_vertical_scroll_bar_hook)
157 P_ ((struct window *window,
158 int portion, int whole, int position));
159
160
161 /* The following three hooks are used when we're doing a thorough
162 redisplay of the frame. We don't explicitly know which scroll bars
163 are going to be deleted, because keeping track of when windows go
164 away is a real pain - can you say set-window-configuration?
165 Instead, we just assert at the beginning of redisplay that *all*
166 scroll bars are to be removed, and then save scroll bars from the
167 fiery pit when we actually redisplay their window. */
168
169 /* 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
171 `*redeem_scroll_bar_hook' is applied to its window before the judgement.
172
173 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;
175 if the HAS_SCROLL_BARS flag has just been turned off, only calling
176 this and the judge_scroll_bars_hook will get rid of them.
177
178 If non-zero, this hook should be safe to apply to any frame,
179 whether or not it can support scroll bars, and whether or not it is
180 currently displaying them. */
181 void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
182
183 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
184 Note that it's okay to redeem a scroll bar that is not condemned. */
185 void (*redeem_scroll_bar_hook) P_ ((struct window *window));
186
187 /* Remove all scroll bars on FRAME that haven't been saved since the
188 last call to `*condemn_scroll_bars_hook'.
189
190 This should be applied to each frame after each time its window
191 tree is redisplayed, even if it is not displaying scroll bars at the
192 moment; if the HAS_SCROLL_BARS flag has just been turned off, only
193 calling this and condemn_scroll_bars_hook will get rid of them.
194
195 If non-zero, this hook should be safe to apply to any frame,
196 whether or not it can support scroll bars, and whether or not it is
197 currently displaying them. */
198 void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
199
200
201 /* Strings, numbers and flags taken from the termcap entry. */
202
203 char *TS_end_italic_mode; /* termcap "ae" */
204 char *TS_ins_line; /* "al" */
205 char *TS_italic_mode; /* "as" */
206 char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */
207 char *TS_bell; /* "bl" */
208 char *TS_clr_to_bottom; /* "cd" */
209 char *TS_clr_line; /* "ce", clear to end of line */
210 char *TS_clr_frame; /* "cl" */
211 char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */
212 char *TS_set_scroll_region_1; /* "cS" (4 params: total lines,
213 lines above scroll region, lines below it,
214 total lines again) */
215 char *TS_del_char; /* "dc" */
216 char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */
217 char *TS_del_line; /* "dl" */
218 char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */
219 char *TS_delete_mode; /* "dm", enter character-delete mode */
220 char *TS_end_delete_mode; /* "ed", leave character-delete mode */
221 char *TS_end_insert_mode; /* "ei", leave character-insert mode */
222 char *TS_ins_char; /* "ic" */
223 char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */
224 char *TS_insert_mode; /* "im", enter character-insert mode */
225 char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */
226 char *TS_end_keypad_mode; /* "ke" */
227 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 */
231 char *TS_repeat; /* "rp" (2 params, # times to repeat
232 and character to be repeated) */
233 char *TS_end_standout_mode; /* "se" */
234 char *TS_fwd_scroll; /* "sf" */
235 char *TS_standout_mode; /* "so" */
236 char *TS_rev_scroll; /* "sr" */
237 char *TS_end_termcap_modes; /* "te" */
238 char *TS_termcap_modes; /* "ti" */
239 char *TS_end_underscore_mode; /* "ue" */
240 char *TS_underscore_mode; /* "us" */
241 char *TS_visible_bell; /* "vb" */
242 char *TS_end_visual_mode; /* "ve" */
243 char *TS_visual_mode; /* "vi" */
244 char *TS_set_window; /* "wi" (4 params, start and end of window,
245 each as vpos and hpos) */
246
247 int TF_hazeltine; /* termcap hz flag. */
248 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. */
250 int TF_underscore; /* termcap ul flag: _ underlines if overstruck on
251 nonblank position. Must clear before writing _. */
252 int TF_teleray; /* termcap xt flag: many weird consequences.
253 For t1061. */
254
255 int TF_xs; /* Nonzero for "xs". If set together with
256 TN_standout_width == 0, it means don't bother
257 to write any end-standout cookies. */
258
259 int TN_standout_width; /* termcap sg number: width occupied by standout
260 markers */
261
262 static int RPov; /* # chars to start a TS_repeat */
263
264 static int delete_in_insert_mode; /* delete mode == insert mode */
265
266 static int se_is_so; /* 1 if same string both enters and leaves
267 standout mode */
268
269 /* internal state */
270
271 /* The largest frame width in any call to calculate_costs. */
272 int max_frame_width;
273 /* The largest frame height in any call to calculate_costs. */
274 int max_frame_height;
275
276 /* Number of chars of space used for standout marker at beginning of line,
277 or'd with 0100. Zero if no standout marker at all.
278 The length of these vectors is max_frame_height.
279
280 Used IFF TN_standout_width >= 0. */
281
282 static char *chars_wasted;
283 static char *copybuf;
284
285 /* nonzero means supposed to write text in standout mode. */
286 int standout_requested;
287
288 int insert_mode; /* Nonzero when in insert mode. */
289 int standout_mode; /* Nonzero when in standout mode. */
290
291 /* Size of window specified by higher levels.
292 This is the number of lines, from the top of frame downwards,
293 which can participate in insert-line/delete-line operations.
294
295 Effectively it excludes the bottom frame_height - specified_window_size
296 lines from those operations. */
297
298 int specified_window;
299
300 /* Frame currently being redisplayed; 0 if not currently redisplaying.
301 (Direct output does not count). */
302
303 FRAME_PTR updating_frame;
304
305 /* Provided for lisp packages. */
306 static int system_uses_terminfo;
307
308 char *tparam ();
309
310 extern char *tgetstr ();
311 \f
312
313 #ifdef WINDOWSNT
314 /* 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
316 this file, we'll define FRAME_TERMCAP_P to be zero so that our
317 output hooks get called instead of the termcap functions. Probably
318 the best long-term solution is to define an output_windows_nt... */
319
320 #undef FRAME_TERMCAP_P
321 #define FRAME_TERMCAP_P(_f_) 0
322 #endif /* WINDOWSNT */
323
324 void
325 ring_bell ()
326 {
327 if (! NILP (Vring_bell_function))
328 {
329 Lisp_Object function;
330
331 /* Temporarily set the global variable to nil
332 so that if we get an error, it stays nil
333 and we don't call it over and over.
334
335 We don't specbind it, because that would carefully
336 restore the bad value if there's an error
337 and make the loop of errors happen anyway. */
338 function = Vring_bell_function;
339 Vring_bell_function = Qnil;
340
341 call0 (function);
342
343 Vring_bell_function = function;
344 return;
345 }
346
347 if (! FRAME_TERMCAP_P (selected_frame))
348 {
349 (*ring_bell_hook) ();
350 return;
351 }
352 OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
353 }
354
355 void
356 set_terminal_modes ()
357 {
358 if (! FRAME_TERMCAP_P (selected_frame))
359 {
360 (*set_terminal_modes_hook) ();
361 return;
362 }
363 OUTPUT_IF (TS_termcap_modes);
364 OUTPUT_IF (TS_visual_mode);
365 OUTPUT_IF (TS_keypad_mode);
366 losecursor ();
367 }
368
369 void
370 reset_terminal_modes ()
371 {
372 if (! FRAME_TERMCAP_P (selected_frame))
373 {
374 if (reset_terminal_modes_hook)
375 (*reset_terminal_modes_hook) ();
376 return;
377 }
378 if (TN_standout_width < 0)
379 turn_off_highlight ();
380 turn_off_insert ();
381 OUTPUT_IF (TS_end_keypad_mode);
382 OUTPUT_IF (TS_end_visual_mode);
383 OUTPUT_IF (TS_end_termcap_modes);
384 /* Output raw CR so kernel can track the cursor hpos. */
385 /* 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. */
387 if (TN_standout_width >= 0)
388 cmputc ('\n');
389 cmputc ('\r');
390 }
391
392 void
393 update_begin (f)
394 FRAME_PTR f;
395 {
396 updating_frame = f;
397 if (! FRAME_TERMCAP_P (updating_frame))
398 (*update_begin_hook) (f);
399 }
400
401 void
402 update_end (f)
403 FRAME_PTR f;
404 {
405 if (! FRAME_TERMCAP_P (updating_frame))
406 {
407 (*update_end_hook) (f);
408 updating_frame = 0;
409 return;
410 }
411 turn_off_insert ();
412 background_highlight ();
413 standout_requested = 0;
414 updating_frame = 0;
415 }
416
417 void
418 set_terminal_window (size)
419 int size;
420 {
421 if (! FRAME_TERMCAP_P (updating_frame))
422 {
423 (*set_terminal_window_hook) (size);
424 return;
425 }
426 specified_window = size ? size : FRAME_HEIGHT (selected_frame);
427 if (!scroll_region_ok)
428 return;
429 set_scroll_region (0, specified_window);
430 }
431
432 void
433 set_scroll_region (start, stop)
434 int start, stop;
435 {
436 char *buf;
437 if (TS_set_scroll_region)
438 {
439 buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1);
440 }
441 else if (TS_set_scroll_region_1)
442 {
443 buf = tparam (TS_set_scroll_region_1, 0, 0,
444 FRAME_HEIGHT (selected_frame), start,
445 FRAME_HEIGHT (selected_frame) - stop,
446 FRAME_HEIGHT (selected_frame));
447 }
448 else
449 {
450 buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_WIDTH (selected_frame));
451 }
452 OUTPUT (buf);
453 xfree (buf);
454 losecursor ();
455 }
456 \f
457 void
458 turn_on_insert ()
459 {
460 if (!insert_mode)
461 OUTPUT (TS_insert_mode);
462 insert_mode = 1;
463 }
464
465 void
466 turn_off_insert ()
467 {
468 if (insert_mode)
469 OUTPUT (TS_end_insert_mode);
470 insert_mode = 0;
471 }
472 \f
473 /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
474 In these terminals, output is affected by the value of standout
475 mode when the output is written.
476
477 These functions are called on all terminals, but do nothing
478 on terminals whose standout mode does not work that way. */
479
480 void
481 turn_off_highlight ()
482 {
483 if (TN_standout_width < 0)
484 {
485 if (standout_mode)
486 OUTPUT_IF (TS_end_standout_mode);
487 standout_mode = 0;
488 }
489 }
490
491 void
492 turn_on_highlight ()
493 {
494 if (TN_standout_width < 0)
495 {
496 if (!standout_mode)
497 OUTPUT_IF (TS_standout_mode);
498 standout_mode = 1;
499 }
500 }
501
502 /* Set standout mode to the state it should be in for
503 empty space inside windows. What this is,
504 depends on the user option inverse-video. */
505
506 void
507 background_highlight ()
508 {
509 if (TN_standout_width >= 0)
510 return;
511 if (inverse_video)
512 turn_on_highlight ();
513 else
514 turn_off_highlight ();
515 }
516
517 /* Set standout mode to the mode specified for the text to be output. */
518
519 static void
520 highlight_if_desired ()
521 {
522 if (TN_standout_width >= 0)
523 return;
524 if (!inverse_video == !standout_requested)
525 turn_off_highlight ();
526 else
527 turn_on_highlight ();
528 }
529 \f
530 /* Handle standout mode for terminals in which TN_standout_width >= 0.
531 On these terminals, standout is controlled by markers that
532 live inside the terminal's memory. TN_standout_width is the width
533 that the marker occupies in memory. Standout runs from the marker
534 to the end of the line on some terminals, or to the next
535 turn-off-standout marker (TS_end_standout_mode) string
536 on other terminals. */
537
538 /* Write a standout marker or end-standout marker at the front of the line
539 at vertical position vpos. */
540
541 void
542 write_standout_marker (flag, vpos)
543 int flag, vpos;
544 {
545 if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so
546 && !(TF_xs && TN_standout_width == 0)))
547 {
548 cmgoto (vpos, 0);
549 cmplus (TN_standout_width);
550 OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
551 chars_wasted[curY] = TN_standout_width | 0100;
552 }
553 }
554 \f
555 /* External interface to control of standout mode.
556 Call this when about to modify line at position VPOS
557 and not change whether it is highlighted. */
558
559 void
560 reassert_line_highlight (highlight, vpos)
561 int highlight;
562 int vpos;
563 {
564 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
565 {
566 (*reassert_line_highlight_hook) (highlight, vpos);
567 return;
568 }
569 if (TN_standout_width < 0)
570 /* Handle terminals where standout takes affect at output time */
571 standout_requested = highlight;
572 else if (chars_wasted[vpos] == 0)
573 /* For terminals with standout markers, write one on this line
574 if there isn't one already. */
575 write_standout_marker (highlight, vpos);
576 }
577
578 /* Call this when about to modify line at position VPOS
579 and change whether it is highlighted. */
580
581 void
582 change_line_highlight (new_highlight, vpos, first_unused_hpos)
583 int new_highlight, vpos, first_unused_hpos;
584 {
585 standout_requested = new_highlight;
586 if (! FRAME_TERMCAP_P (updating_frame))
587 {
588 (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
589 return;
590 }
591
592 cursor_to (vpos, 0);
593
594 if (TN_standout_width < 0)
595 background_highlight ();
596 /* If line starts with a marker, delete the marker */
597 else if (TS_clr_line && chars_wasted[curY])
598 {
599 turn_off_insert ();
600 /* On Teleray, make sure to erase the SO marker. */
601 if (TF_teleray)
602 {
603 cmgoto (curY - 1, FRAME_WIDTH (selected_frame) - 4);
604 OUTPUT ("\033S");
605 curY++; /* ESC S moves to next line where the TS_standout_mode was */
606 curX = 0;
607 }
608 else
609 cmgoto (curY, 0); /* reposition to kill standout marker */
610 }
611 clear_end_of_line_raw (first_unused_hpos);
612 reassert_line_highlight (new_highlight, curY);
613 }
614 \f
615
616 /* Move to absolute position, specified origin 0 */
617
618 void
619 cursor_to (row, col)
620 int row, col;
621 {
622 if (! FRAME_TERMCAP_P ((updating_frame
623 ? updating_frame
624 : selected_frame))
625 && cursor_to_hook)
626 {
627 (*cursor_to_hook) (row, col);
628 return;
629 }
630
631 /* Detect the case where we are called from reset_sys_modes
632 and the costs have never been calculated. Do nothing. */
633 if (chars_wasted == 0)
634 return;
635
636 col += chars_wasted[row] & 077;
637 if (curY == row && curX == col)
638 return;
639 if (!TF_standout_motion)
640 background_highlight ();
641 if (!TF_insmode_motion)
642 turn_off_insert ();
643 cmgoto (row, col);
644 }
645
646 /* Similar but don't take any account of the wasted characters. */
647
648 void
649 raw_cursor_to (row, col)
650 int row, col;
651 {
652 if (! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
653 {
654 (*raw_cursor_to_hook) (row, col);
655 return;
656 }
657 if (curY == row && curX == col)
658 return;
659 if (!TF_standout_motion)
660 background_highlight ();
661 if (!TF_insmode_motion)
662 turn_off_insert ();
663 cmgoto (row, col);
664 }
665 \f
666 /* Erase operations */
667
668 /* clear from cursor to end of frame */
669 void
670 clear_to_end ()
671 {
672 register int i;
673
674 if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame))
675 {
676 (*clear_to_end_hook) ();
677 return;
678 }
679 if (TS_clr_to_bottom)
680 {
681 background_highlight ();
682 OUTPUT (TS_clr_to_bottom);
683 bzero (chars_wasted + curY, FRAME_HEIGHT (selected_frame) - curY);
684 }
685 else
686 {
687 for (i = curY; i < FRAME_HEIGHT (selected_frame); i++)
688 {
689 cursor_to (i, 0);
690 clear_end_of_line_raw (FRAME_WIDTH (selected_frame));
691 }
692 }
693 }
694
695 /* Clear entire frame */
696
697 void
698 clear_frame ()
699 {
700 if (clear_frame_hook
701 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
702 {
703 (*clear_frame_hook) ();
704 return;
705 }
706 if (TS_clr_frame)
707 {
708 background_highlight ();
709 OUTPUT (TS_clr_frame);
710 bzero (chars_wasted, FRAME_HEIGHT (selected_frame));
711 cmat (0, 0);
712 }
713 else
714 {
715 cursor_to (0, 0);
716 clear_to_end ();
717 }
718 }
719
720 /* Clear to end of line, but do not clear any standout marker.
721 Assumes that the cursor is positioned at a character of real text,
722 which implies it cannot be before a standout marker
723 unless the marker has zero width.
724
725 Note that the cursor may be moved. */
726
727 void
728 clear_end_of_line (first_unused_hpos)
729 int first_unused_hpos;
730 {
731 static GLYPH buf = SPACEGLYPH;
732 if (FRAME_TERMCAP_P (selected_frame)
733 && chars_wasted != 0
734 && TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
735 write_glyphs (&buf, 1);
736 clear_end_of_line_raw (first_unused_hpos);
737 }
738
739 /* Clear from cursor to end of line.
740 Assume that the line is already clear starting at column first_unused_hpos.
741 If the cursor is at a standout marker, erase the marker.
742
743 Note that the cursor may be moved, on terminals lacking a `ce' string. */
744
745 void
746 clear_end_of_line_raw (first_unused_hpos)
747 int first_unused_hpos;
748 {
749 register int i;
750
751 if (clear_end_of_line_hook
752 && ! FRAME_TERMCAP_P ((updating_frame
753 ? updating_frame
754 : selected_frame)))
755 {
756 (*clear_end_of_line_hook) (first_unused_hpos);
757 return;
758 }
759
760 /* Detect the case where we are called from reset_sys_modes
761 and the costs have never been calculated. Do nothing. */
762 if (chars_wasted == 0)
763 return;
764
765 first_unused_hpos += chars_wasted[curY] & 077;
766 if (curX >= first_unused_hpos)
767 return;
768 /* Notice if we are erasing a magic cookie */
769 if (curX == 0)
770 chars_wasted[curY] = 0;
771 background_highlight ();
772 if (TS_clr_line)
773 {
774 OUTPUT1 (TS_clr_line);
775 }
776 else
777 { /* have to do it the hard way */
778 turn_off_insert ();
779
780 /* Do not write in last row last col with Autowrap on. */
781 if (AutoWrap && curY == FRAME_HEIGHT (selected_frame) - 1
782 && first_unused_hpos == FRAME_WIDTH (selected_frame))
783 first_unused_hpos--;
784
785 for (i = curX; i < first_unused_hpos; i++)
786 {
787 if (termscript)
788 fputc (' ', termscript);
789 putchar (' ');
790 }
791 cmplus (first_unused_hpos - curX);
792 }
793 }
794 \f
795 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes and
796 store them at DST. Do not write more than DST_LEN bytes. That may
797 require stopping before all SRC_LEN input glyphs have been
798 converted.
799
800 We store the number of glyphs actually converted in *CONSUMED. The
801 return value is the number of bytes store in DST. */
802
803 int
804 encode_terminal_code (src, dst, src_len, dst_len, consumed)
805 GLYPH *src;
806 int src_len;
807 unsigned char *dst;
808 int dst_len, *consumed;
809 {
810 GLYPH *src_start = src, *src_end = src + src_len;
811 unsigned char *dst_start = dst, *dst_end = dst + dst_len;
812 register GLYPH g;
813 unsigned int c;
814 unsigned char workbuf[4], *buf;
815 int len;
816 register int tlen = GLYPH_TABLE_LENGTH;
817 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
818 struct coding_system *coding;
819
820 coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
821 ? &terminal_coding
822 : &safe_terminal_coding);
823
824 while (src < src_end)
825 {
826 g = *src;
827 /* We must skip glyphs to be padded for a wide character. */
828 if (! (g & GLYPH_MASK_PADDING))
829 {
830 if ((c = GLYPH_CHAR (selected_frame, g)) > MAX_CHAR)
831 {
832 c = ' ';
833 g = MAKE_GLYPH (selected_frame, c,
834 GLYPH_FACE (selected_frame, g));
835 }
836 if (COMPOSITE_CHAR_P (c))
837 {
838 /* If C is a composite character, we can display
839 only the first component. */
840 g = cmpchar_table[COMPOSITE_CHAR_ID (c)]->glyph[0],
841 c = GLYPH_CHAR (selected_frame, g);
842 }
843 if (c < tlen)
844 {
845 /* G has an entry in Vglyph_table,
846 so process any alias before testing for simpleness. */
847 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
848 c = GLYPH_CHAR (selected_frame, g);
849 }
850 if (GLYPH_SIMPLE_P (tbase, tlen, g))
851 /* We set the multi-byte form of C at BUF. */
852 len = CHAR_STRING (c, workbuf, buf);
853 else
854 {
855 /* We have a string in Vglyph_table. */
856 len = GLYPH_LENGTH (tbase, g);
857 buf = GLYPH_STRING (tbase, g);
858 }
859
860 encode_coding (coding, buf, dst, len, dst_end - dst);
861 len -= coding->consumed;
862 dst += coding->produced;
863 if (len > 0)
864 {
865 if (len > dst_end - dst)
866 /* The remaining output buffer is too short. We must
867 break the loop here without increasing SRC so that
868 the next call of this function start from the same
869 glyph. */
870 break;
871 buf += len;
872 while (len--) *dst++ = *buf++;
873 }
874 }
875 src++;
876 }
877 *consumed = src - src_start;
878 return (dst - dst_start);
879 }
880
881
882 void
883 write_glyphs (string, len)
884 register GLYPH *string;
885 register int len;
886 {
887 register GLYPH g;
888 register int tlen = GLYPH_TABLE_LENGTH;
889 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
890 int produced, consumed;
891
892 if (write_glyphs_hook
893 && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : selected_frame)))
894 {
895 (*write_glyphs_hook) (string, len);
896 return;
897 }
898
899 highlight_if_desired ();
900 turn_off_insert ();
901
902 /* Don't dare write in last column of bottom line, if AutoWrap,
903 since that would scroll the whole frame on some terminals. */
904
905 if (AutoWrap
906 && curY + 1 == FRAME_HEIGHT (selected_frame)
907 && (curX + len - (chars_wasted[curY] & 077)
908 == FRAME_WIDTH (selected_frame)))
909 len --;
910 if (len <= 0)
911 return;
912
913 cmplus (len);
914 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
915 the tail. */
916 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
917 while (len > 0)
918 {
919 /* We use shared conversion buffer of the current size (1024
920 bytes at least). Usually it is sufficient, but if not, we
921 just repeat the loop. */
922 produced = encode_terminal_code (string, conversion_buffer,
923 len, conversion_buffer_size, &consumed);
924 if (produced > 0)
925 {
926 fwrite (conversion_buffer, 1, produced, stdout);
927 if (ferror (stdout))
928 clearerr (stdout);
929 if (termscript)
930 fwrite (conversion_buffer, 1, produced, termscript);
931 }
932 len -= consumed;
933 string += consumed;
934 }
935 /* We may have to output some codes to terminate the writing. */
936 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
937 {
938 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
939 encode_coding (&terminal_coding, "", conversion_buffer,
940 0, conversion_buffer_size);
941 if (terminal_coding.produced > 0)
942 {
943 fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
944 if (ferror (stdout))
945 clearerr (stdout);
946 if (termscript)
947 fwrite (conversion_buffer, 1, terminal_coding.produced,
948 termscript);
949 }
950 }
951 cmcheckmagic ();
952 }
953
954 /* If start is zero, insert blanks instead of a string at start */
955
956 void
957 insert_glyphs (start, len)
958 register GLYPH *start;
959 register int len;
960 {
961 char *buf;
962 GLYPH g;
963 register int tlen = GLYPH_TABLE_LENGTH;
964 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
965
966 if (len <= 0)
967 return;
968
969 if (insert_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
970 {
971 (*insert_glyphs_hook) (start, len);
972 return;
973 }
974 highlight_if_desired ();
975
976 if (TS_ins_multi_chars)
977 {
978 buf = tparam (TS_ins_multi_chars, 0, 0, len);
979 OUTPUT1 (buf);
980 xfree (buf);
981 if (start)
982 write_glyphs (start, len);
983 return;
984 }
985
986 turn_on_insert ();
987 cmplus (len);
988 /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */
989 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
990 while (len-- > 0)
991 {
992 int produced, consumed;
993
994 OUTPUT1_IF (TS_ins_char);
995 if (!start)
996 g = SPACEGLYPH;
997 else
998 {
999 g = *start++;
1000 /* We must open sufficient space for a character which
1001 occupies more than one column. */
1002 while (*start & GLYPH_MASK_PADDING)
1003 {
1004 OUTPUT1_IF (TS_ins_char);
1005 start++, len--;
1006 }
1007 }
1008
1009 if (len <= 0)
1010 /* This is the last glyph. */
1011 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
1012
1013 /* We use shared conversion buffer of the current size (1024
1014 bytes at least). It is surely sufficient for just one glyph. */
1015 produced = encode_terminal_code (&g, conversion_buffer,
1016 1, conversion_buffer_size, &consumed);
1017 if (produced > 0)
1018 {
1019 fwrite (conversion_buffer, 1, produced, stdout);
1020 if (ferror (stdout))
1021 clearerr (stdout);
1022 if (termscript)
1023 fwrite (conversion_buffer, 1, produced, termscript);
1024 }
1025
1026 OUTPUT1_IF (TS_pad_inserted_char);
1027 }
1028 cmcheckmagic ();
1029 }
1030
1031 void
1032 delete_glyphs (n)
1033 register int n;
1034 {
1035 char *buf;
1036 register int i;
1037
1038 if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame))
1039 {
1040 (*delete_glyphs_hook) (n);
1041 return;
1042 }
1043
1044 if (delete_in_insert_mode)
1045 {
1046 turn_on_insert ();
1047 }
1048 else
1049 {
1050 turn_off_insert ();
1051 OUTPUT_IF (TS_delete_mode);
1052 }
1053
1054 if (TS_del_multi_chars)
1055 {
1056 buf = tparam (TS_del_multi_chars, 0, 0, n);
1057 OUTPUT1 (buf);
1058 xfree (buf);
1059 }
1060 else
1061 for (i = 0; i < n; i++)
1062 OUTPUT1 (TS_del_char);
1063 if (!delete_in_insert_mode)
1064 OUTPUT_IF (TS_end_delete_mode);
1065 }
1066 \f
1067 /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */
1068
1069 void
1070 ins_del_lines (vpos, n)
1071 int vpos, n;
1072 {
1073 char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
1074 char *single = n > 0 ? TS_ins_line : TS_del_line;
1075 char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
1076
1077 register int i = n > 0 ? n : -n;
1078 register char *buf;
1079
1080 if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame))
1081 {
1082 (*ins_del_lines_hook) (vpos, n);
1083 return;
1084 }
1085
1086 /* If the lines below the insertion are being pushed
1087 into the end of the window, this is the same as clearing;
1088 and we know the lines are already clear, since the matching
1089 deletion has already been done. So can ignore this. */
1090 /* If the lines below the deletion are blank lines coming
1091 out of the end of the window, don't bother,
1092 as there will be a matching inslines later that will flush them. */
1093 if (scroll_region_ok && vpos + i >= specified_window)
1094 return;
1095 if (!memory_below_frame && vpos + i >= FRAME_HEIGHT (selected_frame))
1096 return;
1097
1098 if (multi)
1099 {
1100 raw_cursor_to (vpos, 0);
1101 background_highlight ();
1102 buf = tparam (multi, 0, 0, i);
1103 OUTPUT (buf);
1104 xfree (buf);
1105 }
1106 else if (single)
1107 {
1108 raw_cursor_to (vpos, 0);
1109 background_highlight ();
1110 while (--i >= 0)
1111 OUTPUT (single);
1112 if (TF_teleray)
1113 curX = 0;
1114 }
1115 else
1116 {
1117 set_scroll_region (vpos, specified_window);
1118 if (n < 0)
1119 raw_cursor_to (specified_window - 1, 0);
1120 else
1121 raw_cursor_to (vpos, 0);
1122 background_highlight ();
1123 while (--i >= 0)
1124 OUTPUTL (scroll, specified_window - vpos);
1125 set_scroll_region (0, specified_window);
1126 }
1127
1128 if (TN_standout_width >= 0)
1129 {
1130 register int lower_limit
1131 = (scroll_region_ok
1132 ? specified_window
1133 : FRAME_HEIGHT (selected_frame));
1134
1135 if (n < 0)
1136 {
1137 bcopy (&chars_wasted[vpos - n], &chars_wasted[vpos],
1138 lower_limit - vpos + n);
1139 bzero (&chars_wasted[lower_limit + n], - n);
1140 }
1141 else
1142 {
1143 bcopy (&chars_wasted[vpos], &copybuf[vpos], lower_limit - vpos - n);
1144 bcopy (&copybuf[vpos], &chars_wasted[vpos + n],
1145 lower_limit - vpos - n);
1146 bzero (&chars_wasted[vpos], n);
1147 }
1148 }
1149 if (!scroll_region_ok && memory_below_frame && n < 0)
1150 {
1151 cursor_to (FRAME_HEIGHT (selected_frame) + n, 0);
1152 clear_to_end ();
1153 }
1154 }
1155 \f
1156 /* Compute cost of sending "str", in characters,
1157 not counting any line-dependent padding. */
1158
1159 int
1160 string_cost (str)
1161 char *str;
1162 {
1163 cost = 0;
1164 if (str)
1165 tputs (str, 0, evalcost);
1166 return cost;
1167 }
1168
1169 /* Compute cost of sending "str", in characters,
1170 counting any line-dependent padding at one line. */
1171
1172 static int
1173 string_cost_one_line (str)
1174 char *str;
1175 {
1176 cost = 0;
1177 if (str)
1178 tputs (str, 1, evalcost);
1179 return cost;
1180 }
1181
1182 /* Compute per line amount of line-dependent padding,
1183 in tenths of characters. */
1184
1185 int
1186 per_line_cost (str)
1187 register char *str;
1188 {
1189 cost = 0;
1190 if (str)
1191 tputs (str, 0, evalcost);
1192 cost = - cost;
1193 if (str)
1194 tputs (str, 10, evalcost);
1195 return cost;
1196 }
1197
1198 #ifndef old
1199 /* char_ins_del_cost[n] is cost of inserting N characters.
1200 char_ins_del_cost[-n] is cost of deleting N characters.
1201 The length of this vector is based on max_frame_width. */
1202
1203 int *char_ins_del_vector;
1204
1205 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH ((f))])
1206 #endif
1207
1208 /* ARGSUSED */
1209 static void
1210 calculate_ins_del_char_costs (frame)
1211 FRAME_PTR frame;
1212 {
1213 int ins_startup_cost, del_startup_cost;
1214 int ins_cost_per_char, del_cost_per_char;
1215 register int i;
1216 register int *p;
1217
1218 if (TS_ins_multi_chars)
1219 {
1220 ins_cost_per_char = 0;
1221 ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
1222 }
1223 else if (TS_ins_char || TS_pad_inserted_char
1224 || (TS_insert_mode && TS_end_insert_mode))
1225 {
1226 ins_startup_cost = (30 * (string_cost (TS_insert_mode)
1227 + string_cost (TS_end_insert_mode))) / 100;
1228 ins_cost_per_char = (string_cost_one_line (TS_ins_char)
1229 + string_cost_one_line (TS_pad_inserted_char));
1230 }
1231 else
1232 {
1233 ins_startup_cost = 9999;
1234 ins_cost_per_char = 0;
1235 }
1236
1237 if (TS_del_multi_chars)
1238 {
1239 del_cost_per_char = 0;
1240 del_startup_cost = string_cost_one_line (TS_del_multi_chars);
1241 }
1242 else if (TS_del_char)
1243 {
1244 del_startup_cost = (string_cost (TS_delete_mode)
1245 + string_cost (TS_end_delete_mode));
1246 if (delete_in_insert_mode)
1247 del_startup_cost /= 2;
1248 del_cost_per_char = string_cost_one_line (TS_del_char);
1249 }
1250 else
1251 {
1252 del_startup_cost = 9999;
1253 del_cost_per_char = 0;
1254 }
1255
1256 /* Delete costs are at negative offsets */
1257 p = &char_ins_del_cost (frame)[0];
1258 for (i = FRAME_WIDTH (frame); --i >= 0;)
1259 *--p = (del_startup_cost += del_cost_per_char);
1260
1261 /* Doing nothing is free */
1262 p = &char_ins_del_cost (frame)[0];
1263 *p++ = 0;
1264
1265 /* Insert costs are at positive offsets */
1266 for (i = FRAME_WIDTH (frame); --i >= 0;)
1267 *p++ = (ins_startup_cost += ins_cost_per_char);
1268 }
1269
1270 void
1271 calculate_costs (frame)
1272 FRAME_PTR frame;
1273 {
1274 register char *f = (TS_set_scroll_region
1275 ? TS_set_scroll_region
1276 : TS_set_scroll_region_1);
1277
1278 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1279
1280 scroll_region_cost = string_cost (f);
1281 #ifdef HAVE_X_WINDOWS
1282 if (FRAME_X_P (frame))
1283 {
1284 do_line_insertion_deletion_costs (frame, 0, ".5*", 0, ".5*",
1285 0, 0,
1286 x_screen_planes (frame));
1287 scroll_region_cost = 0;
1288 return;
1289 }
1290 #endif
1291
1292 /* These variables are only used for terminal stuff. They are allocated
1293 once for the terminal frame of X-windows emacs, but not used afterwards.
1294
1295 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1296 X turns off char_ins_del_ok.
1297
1298 chars_wasted and copybuf are only used here in term.c in cases where
1299 the term hook isn't called. */
1300
1301 max_frame_height = max (max_frame_height, FRAME_HEIGHT (frame));
1302 max_frame_width = max (max_frame_width, FRAME_WIDTH (frame));
1303
1304 if (chars_wasted != 0)
1305 chars_wasted = (char *) xrealloc (chars_wasted, max_frame_height);
1306 else
1307 chars_wasted = (char *) xmalloc (max_frame_height);
1308
1309 if (copybuf != 0)
1310 copybuf = (char *) xrealloc (copybuf, max_frame_height);
1311 else
1312 copybuf = (char *) xmalloc (max_frame_height);
1313
1314 if (char_ins_del_vector != 0)
1315 char_ins_del_vector
1316 = (int *) xrealloc (char_ins_del_vector,
1317 (sizeof (int)
1318 + 2 * max_frame_width * sizeof (int)));
1319 else
1320 char_ins_del_vector
1321 = (int *) xmalloc (sizeof (int)
1322 + 2 * max_frame_width * sizeof (int));
1323
1324 bzero (chars_wasted, max_frame_height);
1325 bzero (copybuf, max_frame_height);
1326 bzero (char_ins_del_vector, (sizeof (int)
1327 + 2 * max_frame_width * sizeof (int)));
1328
1329 if (f && (!TS_ins_line && !TS_del_line))
1330 do_line_insertion_deletion_costs (frame,
1331 TS_rev_scroll, TS_ins_multi_lines,
1332 TS_fwd_scroll, TS_del_multi_lines,
1333 f, f, 1);
1334 else
1335 do_line_insertion_deletion_costs (frame,
1336 TS_ins_line, TS_ins_multi_lines,
1337 TS_del_line, TS_del_multi_lines,
1338 0, 0, 1);
1339
1340 calculate_ins_del_char_costs (frame);
1341
1342 /* Don't use TS_repeat if its padding is worse than sending the chars */
1343 if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
1344 RPov = string_cost (TS_repeat);
1345 else
1346 RPov = FRAME_WIDTH (frame) * 2;
1347
1348 cmcostinit (); /* set up cursor motion costs */
1349 }
1350 \f
1351 struct fkey_table {
1352 char *cap, *name;
1353 };
1354
1355 /* Termcap capability names that correspond directly to X keysyms.
1356 Some of these (marked "terminfo") aren't supplied by old-style
1357 (Berkeley) termcap entries. They're listed in X keysym order;
1358 except we put the keypad keys first, so that if they clash with
1359 other keys (as on the IBM PC keyboard) they get overridden.
1360 */
1361
1362 static struct fkey_table keys[] = {
1363 "kh", "home", /* termcap */
1364 "kl", "left", /* termcap */
1365 "ku", "up", /* termcap */
1366 "kr", "right", /* termcap */
1367 "kd", "down", /* termcap */
1368 "%8", "prior", /* terminfo */
1369 "%5", "next", /* terminfo */
1370 "@7", "end", /* terminfo */
1371 "@1", "begin", /* terminfo */
1372 "*6", "select", /* terminfo */
1373 "%9", "print", /* terminfo */
1374 "@4", "execute", /* terminfo --- actually the `command' key */
1375 /*
1376 * "insert" --- see below
1377 */
1378 "&8", "undo", /* terminfo */
1379 "%0", "redo", /* terminfo */
1380 "%7", "menu", /* terminfo --- actually the `options' key */
1381 "@0", "find", /* terminfo */
1382 "@2", "cancel", /* terminfo */
1383 "%1", "help", /* terminfo */
1384 /*
1385 * "break" goes here, but can't be reliably intercepted with termcap
1386 */
1387 "&4", "reset", /* terminfo --- actually `restart' */
1388 /*
1389 * "system" and "user" --- no termcaps
1390 */
1391 "kE", "clearline", /* terminfo */
1392 "kA", "insertline", /* terminfo */
1393 "kL", "deleteline", /* terminfo */
1394 "kI", "insertchar", /* terminfo */
1395 "kD", "deletechar", /* terminfo */
1396 "kB", "backtab", /* terminfo */
1397 /*
1398 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1399 */
1400 "@8", "kp-enter", /* terminfo */
1401 /*
1402 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1403 * "kp-multiply", "kp-add", "kp-separator",
1404 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1405 * --- no termcaps for any of these.
1406 */
1407 "K4", "kp-1", /* terminfo */
1408 /*
1409 * "kp-2" --- no termcap
1410 */
1411 "K5", "kp-3", /* terminfo */
1412 /*
1413 * "kp-4" --- no termcap
1414 */
1415 "K2", "kp-5", /* terminfo */
1416 /*
1417 * "kp-6" --- no termcap
1418 */
1419 "K1", "kp-7", /* terminfo */
1420 /*
1421 * "kp-8" --- no termcap
1422 */
1423 "K3", "kp-9", /* terminfo */
1424 /*
1425 * "kp-equal" --- no termcap
1426 */
1427 "k1", "f1",
1428 "k2", "f2",
1429 "k3", "f3",
1430 "k4", "f4",
1431 "k5", "f5",
1432 "k6", "f6",
1433 "k7", "f7",
1434 "k8", "f8",
1435 "k9", "f9",
1436 };
1437
1438 static char **term_get_fkeys_arg;
1439 static Lisp_Object term_get_fkeys_1 ();
1440
1441 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1442 This function scans the termcap function key sequence entries, and
1443 adds entries to Vfunction_key_map for each function key it finds. */
1444
1445 void
1446 term_get_fkeys (address)
1447 char **address;
1448 {
1449 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1450 errors during the call. The only errors should be from Fdefine_key
1451 when given a key sequence containing an invalid prefix key. If the
1452 termcap defines function keys which use a prefix that is already bound
1453 to a command by the default bindings, we should silently ignore that
1454 function key specification, rather than giving the user an error and
1455 refusing to run at all on such a terminal. */
1456
1457 extern Lisp_Object Fidentity ();
1458 term_get_fkeys_arg = address;
1459 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1460 }
1461
1462 static Lisp_Object
1463 term_get_fkeys_1 ()
1464 {
1465 int i;
1466
1467 char **address = term_get_fkeys_arg;
1468
1469 /* This can happen if CANNOT_DUMP or with strange options. */
1470 if (!initialized)
1471 Vfunction_key_map = Fmake_sparse_keymap (Qnil);
1472
1473 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1474 {
1475 char *sequence = tgetstr (keys[i].cap, address);
1476 if (sequence)
1477 Fdefine_key (Vfunction_key_map, build_string (sequence),
1478 Fmake_vector (make_number (1),
1479 intern (keys[i].name)));
1480 }
1481
1482 /* The uses of the "k0" capability are inconsistent; sometimes it
1483 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1484 We will attempt to politely accommodate both systems by testing for
1485 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1486 */
1487 {
1488 char *k_semi = tgetstr ("k;", address);
1489 char *k0 = tgetstr ("k0", address);
1490 char *k0_name = "f10";
1491
1492 if (k_semi)
1493 {
1494 Fdefine_key (Vfunction_key_map, build_string (k_semi),
1495 Fmake_vector (make_number (1), intern ("f10")));
1496 k0_name = "f0";
1497 }
1498
1499 if (k0)
1500 Fdefine_key (Vfunction_key_map, build_string (k0),
1501 Fmake_vector (make_number (1), intern (k0_name)));
1502 }
1503
1504 /* Set up cookies for numbered function keys above f10. */
1505 {
1506 char fcap[3], fkey[4];
1507
1508 fcap[0] = 'F'; fcap[2] = '\0';
1509 for (i = 11; i < 64; i++)
1510 {
1511 if (i <= 19)
1512 fcap[1] = '1' + i - 11;
1513 else if (i <= 45)
1514 fcap[1] = 'A' + i - 20;
1515 else
1516 fcap[1] = 'a' + i - 46;
1517
1518 {
1519 char *sequence = tgetstr (fcap, address);
1520 if (sequence)
1521 {
1522 sprintf (fkey, "f%d", i);
1523 Fdefine_key (Vfunction_key_map, build_string (sequence),
1524 Fmake_vector (make_number (1),
1525 intern (fkey)));
1526 }
1527 }
1528 }
1529 }
1530
1531 /*
1532 * Various mappings to try and get a better fit.
1533 */
1534 {
1535 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1536 if (!tgetstr (cap1, address)) \
1537 { \
1538 char *sequence = tgetstr (cap2, address); \
1539 if (sequence) \
1540 Fdefine_key (Vfunction_key_map, build_string (sequence), \
1541 Fmake_vector (make_number (1), \
1542 intern (sym))); \
1543 }
1544
1545 /* if there's no key_next keycap, map key_npage to `next' keysym */
1546 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1547 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1548 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1549 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1550 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1551 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1552 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1553
1554 /* IBM has their own non-standard dialect of terminfo.
1555 If the standard name isn't found, try the IBM name. */
1556 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1557 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1558 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1559 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1560 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1561 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1562 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1563 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1564 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1565 #undef CONDITIONAL_REASSIGN
1566 }
1567 }
1568
1569 \f
1570 void
1571 term_init (terminal_type)
1572 char *terminal_type;
1573 {
1574 char *area;
1575 char **address = &area;
1576 char buffer[2044];
1577 register char *p;
1578 int status;
1579
1580 #ifdef WINDOWSNT
1581 initialize_w32_display ();
1582
1583 Wcm_clear ();
1584
1585 area = (char *) malloc (2044);
1586
1587 if (area == 0)
1588 abort ();
1589
1590 FrameRows = FRAME_HEIGHT (selected_frame);
1591 FrameCols = FRAME_WIDTH (selected_frame);
1592 specified_window = FRAME_HEIGHT (selected_frame);
1593
1594 delete_in_insert_mode = 1;
1595
1596 UseTabs = 0;
1597 scroll_region_ok = 0;
1598
1599 /* Seems to insert lines when it's not supposed to, messing
1600 up the display. In doing a trace, it didn't seem to be
1601 called much, so I don't think we're losing anything by
1602 turning it off. */
1603
1604 line_ins_del_ok = 0;
1605 char_ins_del_ok = 1;
1606
1607 baud_rate = 19200;
1608
1609 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1610 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
1611
1612 return;
1613 #else /* not WINDOWSNT */
1614
1615 Wcm_clear ();
1616
1617 status = tgetent (buffer, terminal_type);
1618 if (status < 0)
1619 {
1620 #ifdef TERMINFO
1621 fatal ("Cannot open terminfo database file");
1622 #else
1623 fatal ("Cannot open termcap database file");
1624 #endif
1625 }
1626 if (status == 0)
1627 {
1628 #ifdef TERMINFO
1629 fatal ("Terminal type %s is not defined.\n\
1630 If that is not the actual type of terminal you have,\n\
1631 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1632 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1633 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
1634 terminal_type);
1635 #else
1636 fatal ("Terminal type %s is not defined.\n\
1637 If that is not the actual type of terminal you have,\n\
1638 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1639 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1640 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
1641 terminal_type);
1642 #endif
1643 }
1644 #ifdef TERMINFO
1645 area = (char *) malloc (2044);
1646 #else
1647 area = (char *) malloc (strlen (buffer));
1648 #endif /* not TERMINFO */
1649 if (area == 0)
1650 abort ();
1651
1652 TS_ins_line = tgetstr ("al", address);
1653 TS_ins_multi_lines = tgetstr ("AL", address);
1654 TS_bell = tgetstr ("bl", address);
1655 BackTab = tgetstr ("bt", address);
1656 TS_clr_to_bottom = tgetstr ("cd", address);
1657 TS_clr_line = tgetstr ("ce", address);
1658 TS_clr_frame = tgetstr ("cl", address);
1659 ColPosition = tgetstr ("ch", address);
1660 AbsPosition = tgetstr ("cm", address);
1661 CR = tgetstr ("cr", address);
1662 TS_set_scroll_region = tgetstr ("cs", address);
1663 TS_set_scroll_region_1 = tgetstr ("cS", address);
1664 RowPosition = tgetstr ("cv", address);
1665 TS_del_char = tgetstr ("dc", address);
1666 TS_del_multi_chars = tgetstr ("DC", address);
1667 TS_del_line = tgetstr ("dl", address);
1668 TS_del_multi_lines = tgetstr ("DL", address);
1669 TS_delete_mode = tgetstr ("dm", address);
1670 TS_end_delete_mode = tgetstr ("ed", address);
1671 TS_end_insert_mode = tgetstr ("ei", address);
1672 Home = tgetstr ("ho", address);
1673 TS_ins_char = tgetstr ("ic", address);
1674 TS_ins_multi_chars = tgetstr ("IC", address);
1675 TS_insert_mode = tgetstr ("im", address);
1676 TS_pad_inserted_char = tgetstr ("ip", address);
1677 TS_end_keypad_mode = tgetstr ("ke", address);
1678 TS_keypad_mode = tgetstr ("ks", address);
1679 LastLine = tgetstr ("ll", address);
1680 Right = tgetstr ("nd", address);
1681 Down = tgetstr ("do", address);
1682 if (!Down)
1683 Down = tgetstr ("nl", address); /* Obsolete name for "do" */
1684 #ifdef VMS
1685 /* VMS puts a carriage return before each linefeed,
1686 so it is not safe to use linefeeds. */
1687 if (Down && Down[0] == '\n' && Down[1] == '\0')
1688 Down = 0;
1689 #endif /* VMS */
1690 if (tgetflag ("bs"))
1691 Left = "\b"; /* can't possibly be longer! */
1692 else /* (Actually, "bs" is obsolete...) */
1693 Left = tgetstr ("le", address);
1694 if (!Left)
1695 Left = tgetstr ("bc", address); /* Obsolete name for "le" */
1696 TS_pad_char = tgetstr ("pc", address);
1697 TS_repeat = tgetstr ("rp", address);
1698 TS_end_standout_mode = tgetstr ("se", address);
1699 TS_fwd_scroll = tgetstr ("sf", address);
1700 TS_standout_mode = tgetstr ("so", address);
1701 TS_rev_scroll = tgetstr ("sr", address);
1702 Wcm.cm_tab = tgetstr ("ta", address);
1703 TS_end_termcap_modes = tgetstr ("te", address);
1704 TS_termcap_modes = tgetstr ("ti", address);
1705 TS_bold_mode = tgetstr ("md", address);
1706 TS_end_bold_mode = tgetstr ("me", address);
1707 TS_underscore_mode = tgetstr ("us", address);
1708 TS_end_underscore_mode = tgetstr ("ue", address);
1709 Up = tgetstr ("up", address);
1710 TS_visible_bell = tgetstr ("vb", address);
1711 TS_end_visual_mode = tgetstr ("ve", address);
1712 TS_visual_mode = tgetstr ("vs", address);
1713 TS_set_window = tgetstr ("wi", address);
1714 MultiUp = tgetstr ("UP", address);
1715 MultiDown = tgetstr ("DO", address);
1716 MultiLeft = tgetstr ("LE", address);
1717 MultiRight = tgetstr ("RI", address);
1718
1719 MagicWrap = tgetflag ("xn");
1720 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
1721 the former flag imply the latter. */
1722 AutoWrap = MagicWrap || tgetflag ("am");
1723 memory_below_frame = tgetflag ("db");
1724 TF_hazeltine = tgetflag ("hz");
1725 must_write_spaces = tgetflag ("in");
1726 meta_key = tgetflag ("km") || tgetflag ("MT");
1727 TF_insmode_motion = tgetflag ("mi");
1728 TF_standout_motion = tgetflag ("ms");
1729 TF_underscore = tgetflag ("ul");
1730 TF_xs = tgetflag ("xs");
1731 TF_teleray = tgetflag ("xt");
1732
1733 term_get_fkeys (address);
1734
1735 /* Get frame size from system, or else from termcap. */
1736 {
1737 int height, width;
1738 get_frame_size (&width, &height);
1739 FRAME_WIDTH (selected_frame) = width;
1740 FRAME_HEIGHT (selected_frame) = height;
1741 }
1742
1743 if (FRAME_WIDTH (selected_frame) <= 0)
1744 SET_FRAME_WIDTH (selected_frame, tgetnum ("co"));
1745 else
1746 /* Keep width and external_width consistent */
1747 SET_FRAME_WIDTH (selected_frame, FRAME_WIDTH (selected_frame));
1748 if (FRAME_HEIGHT (selected_frame) <= 0)
1749 FRAME_HEIGHT (selected_frame) = tgetnum ("li");
1750
1751 if (FRAME_HEIGHT (selected_frame) < 3
1752 || FRAME_WIDTH (selected_frame) < 3)
1753 fatal ("Screen size %dx%d is too small",
1754 FRAME_HEIGHT (selected_frame), FRAME_WIDTH (selected_frame));
1755
1756 min_padding_speed = tgetnum ("pb");
1757 TN_standout_width = tgetnum ("sg");
1758 TabWidth = tgetnum ("tw");
1759
1760 #ifdef VMS
1761 /* These capabilities commonly use ^J.
1762 I don't know why, but sending them on VMS does not work;
1763 it causes following spaces to be lost, sometimes.
1764 For now, the simplest fix is to avoid using these capabilities ever. */
1765 if (Down && Down[0] == '\n')
1766 Down = 0;
1767 #endif /* VMS */
1768
1769 if (!TS_bell)
1770 TS_bell = "\07";
1771
1772 if (!TS_fwd_scroll)
1773 TS_fwd_scroll = Down;
1774
1775 PC = TS_pad_char ? *TS_pad_char : 0;
1776
1777 if (TabWidth < 0)
1778 TabWidth = 8;
1779
1780 /* Turned off since /etc/termcap seems to have :ta= for most terminals
1781 and newer termcap doc does not seem to say there is a default.
1782 if (!Wcm.cm_tab)
1783 Wcm.cm_tab = "\t";
1784 */
1785
1786 if (TS_standout_mode == 0)
1787 {
1788 TN_standout_width = tgetnum ("ug");
1789 TS_end_standout_mode = tgetstr ("ue", address);
1790 TS_standout_mode = tgetstr ("us", address);
1791 }
1792
1793 /* If no `se' string, try using a `me' string instead.
1794 If that fails, we can't use standout mode at all. */
1795 if (TS_end_standout_mode == 0)
1796 {
1797 char *s = tgetstr ("me", address);
1798 if (s != 0)
1799 TS_end_standout_mode = s;
1800 else
1801 TS_standout_mode = 0;
1802 }
1803
1804 if (TF_teleray)
1805 {
1806 Wcm.cm_tab = 0;
1807 /* Teleray: most programs want a space in front of TS_standout_mode,
1808 but Emacs can do without it (and give one extra column). */
1809 TS_standout_mode = "\033RD";
1810 TN_standout_width = 1;
1811 /* But that means we cannot rely on ^M to go to column zero! */
1812 CR = 0;
1813 /* LF can't be trusted either -- can alter hpos */
1814 /* if move at column 0 thru a line with TS_standout_mode */
1815 Down = 0;
1816 }
1817
1818 /* Special handling for certain terminal types known to need it */
1819
1820 if (!strcmp (terminal_type, "supdup"))
1821 {
1822 memory_below_frame = 1;
1823 Wcm.cm_losewrap = 1;
1824 }
1825 if (!strncmp (terminal_type, "c10", 3)
1826 || !strcmp (terminal_type, "perq"))
1827 {
1828 /* Supply a makeshift :wi string.
1829 This string is not valid in general since it works only
1830 for windows starting at the upper left corner;
1831 but that is all Emacs uses.
1832
1833 This string works only if the frame is using
1834 the top of the video memory, because addressing is memory-relative.
1835 So first check the :ti string to see if that is true.
1836
1837 It would be simpler if the :wi string could go in the termcap
1838 entry, but it can't because it is not fully valid.
1839 If it were in the termcap entry, it would confuse other programs. */
1840 if (!TS_set_window)
1841 {
1842 p = TS_termcap_modes;
1843 while (*p && strcmp (p, "\033v "))
1844 p++;
1845 if (*p)
1846 TS_set_window = "\033v%C %C %C %C ";
1847 }
1848 /* Termcap entry often fails to have :in: flag */
1849 must_write_spaces = 1;
1850 /* :ti string typically fails to have \E^G! in it */
1851 /* This limits scope of insert-char to one line. */
1852 strcpy (area, TS_termcap_modes);
1853 strcat (area, "\033\007!");
1854 TS_termcap_modes = area;
1855 area += strlen (area) + 1;
1856 p = AbsPosition;
1857 /* Change all %+ parameters to %C, to handle
1858 values above 96 correctly for the C100. */
1859 while (*p)
1860 {
1861 if (p[0] == '%' && p[1] == '+')
1862 p[1] = 'C';
1863 p++;
1864 }
1865 }
1866
1867 FrameRows = FRAME_HEIGHT (selected_frame);
1868 FrameCols = FRAME_WIDTH (selected_frame);
1869 specified_window = FRAME_HEIGHT (selected_frame);
1870
1871 if (Wcm_init () == -1) /* can't do cursor motion */
1872 #ifdef VMS
1873 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1874 It lacks the ability to position the cursor.\n\
1875 If that is not the actual type of terminal you have, use either the\n\
1876 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
1877 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
1878 terminal_type);
1879 #else /* not VMS */
1880 # ifdef TERMINFO
1881 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1882 It lacks the ability to position the cursor.\n\
1883 If that is not the actual type of terminal you have,\n\
1884 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1885 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1886 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
1887 terminal_type);
1888 # else /* TERMCAP */
1889 fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
1890 It lacks the ability to position the cursor.\n\
1891 If that is not the actual type of terminal you have,\n\
1892 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
1893 `setenv TERM ...') to specify the correct type. It may be necessary\n\
1894 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
1895 terminal_type);
1896 # endif /* TERMINFO */
1897 #endif /*VMS */
1898 if (FRAME_HEIGHT (selected_frame) <= 0
1899 || FRAME_WIDTH (selected_frame) <= 0)
1900 fatal ("The frame size has not been specified");
1901
1902 delete_in_insert_mode
1903 = TS_delete_mode && TS_insert_mode
1904 && !strcmp (TS_delete_mode, TS_insert_mode);
1905
1906 se_is_so = (TS_standout_mode
1907 && TS_end_standout_mode
1908 && !strcmp (TS_standout_mode, TS_end_standout_mode));
1909
1910 /* Remove width of standout marker from usable width of line */
1911 if (TN_standout_width > 0)
1912 SET_FRAME_WIDTH (selected_frame,
1913 FRAME_WIDTH (selected_frame) - TN_standout_width);
1914
1915 UseTabs = tabs_safe_p () && TabWidth == 8;
1916
1917 scroll_region_ok
1918 = (Wcm.cm_abs
1919 && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
1920
1921 line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
1922 && (TS_del_line || TS_del_multi_lines))
1923 || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll));
1924
1925 char_ins_del_ok = ((TS_ins_char || TS_insert_mode
1926 || TS_pad_inserted_char || TS_ins_multi_chars)
1927 && (TS_del_char || TS_del_multi_chars));
1928
1929 fast_clear_end_of_line = TS_clr_line != 0;
1930
1931 init_baud_rate ();
1932 if (read_socket_hook) /* Baudrate is somewhat */
1933 /* meaningless in this case */
1934 baud_rate = 9600;
1935
1936 FRAME_CAN_HAVE_SCROLL_BARS (selected_frame) = 0;
1937 FRAME_VERTICAL_SCROLL_BAR_TYPE (selected_frame) = vertical_scroll_bar_none;
1938 #endif /* WINDOWSNT */
1939 }
1940
1941 /* VARARGS 1 */
1942 void
1943 fatal (str, arg1, arg2)
1944 char *str, *arg1, *arg2;
1945 {
1946 fprintf (stderr, "emacs: ");
1947 fprintf (stderr, str, arg1, arg2);
1948 fprintf (stderr, "\n");
1949 fflush (stderr);
1950 exit (1);
1951 }
1952
1953 void
1954 syms_of_term ()
1955 {
1956 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
1957 "Non-nil means the system uses terminfo rather than termcap.\n\
1958 This variable can be used by terminal emulator packages.");
1959 #ifdef TERMINFO
1960 system_uses_terminfo = 1;
1961 #else
1962 system_uses_terminfo = 0;
1963 #endif
1964
1965 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
1966 "Non-nil means call this function to ring the bell.\n\
1967 The function should accept no arguments.");
1968 Vring_bell_function = Qnil;
1969 }