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