]> code.delx.au - gnu-emacs/blob - src/term.c
Convert consecutive FSF copyright years to ranges.
[gnu-emacs] / src / term.c
1 /* Terminal control module for terminals described by TERMCAP
2 Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2011
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <sys/file.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <setjmp.h>
31
32 #include "lisp.h"
33 #include "termchar.h"
34 #include "termopts.h"
35 #include "buffer.h"
36 #include "character.h"
37 #include "charset.h"
38 #include "coding.h"
39 #include "composite.h"
40 #include "keyboard.h"
41 #include "frame.h"
42 #include "disptab.h"
43 #include "termhooks.h"
44 #include "dispextern.h"
45 #include "window.h"
46 #include "keymap.h"
47 #include "blockinput.h"
48 #include "syssignal.h"
49 #include "systty.h"
50 #include "intervals.h"
51 #ifdef MSDOS
52 #include "msdos.h"
53 static int been_here = -1;
54 #endif
55
56 /* For now, don't try to include termcap.h. On some systems,
57 configure finds a non-standard termcap.h that the main build
58 won't find. */
59 extern void tputs (const char *, int, int (*)(int));
60 extern int tgetent (char *, const char *);
61 extern int tgetflag (char *id);
62 extern int tgetnum (char *id);
63
64 char *tparam (char *, char *, int, int, ...);
65
66 extern char *tgetstr (char *, char **);
67
68 #include "cm.h"
69 #ifdef HAVE_X_WINDOWS
70 #include "xterm.h"
71 #endif
72
73 #ifndef O_RDWR
74 #define O_RDWR 2
75 #endif
76
77 #ifndef O_NOCTTY
78 #define O_NOCTTY 0
79 #endif
80
81 /* The name of the default console device. */
82 #ifdef WINDOWSNT
83 #define DEV_TTY "CONOUT$"
84 #else
85 #define DEV_TTY "/dev/tty"
86 #endif
87
88 static void tty_set_scroll_region (struct frame *f, int start, int stop);
89 static void turn_on_face (struct frame *, int face_id);
90 static void turn_off_face (struct frame *, int face_id);
91 static void tty_show_cursor (struct tty_display_info *);
92 static void tty_hide_cursor (struct tty_display_info *);
93 static void tty_background_highlight (struct tty_display_info *tty);
94 static void clear_tty_hooks (struct terminal *terminal);
95 static void set_tty_hooks (struct terminal *terminal);
96 static void dissociate_if_controlling_tty (int fd);
97 static void delete_tty (struct terminal *);
98 static void maybe_fatal (int must_succeed, struct terminal *terminal,
99 const char *str1, const char *str2, ...) NO_RETURN;
100 static void vfatal (const char *str, va_list ap) NO_RETURN;
101
102
103 #define OUTPUT(tty, a) \
104 emacs_tputs ((tty), a, \
105 (int) (FRAME_LINES (XFRAME (selected_frame)) \
106 - curY (tty)), \
107 cmputc)
108
109 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
110 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
111
112 #define OUTPUT_IF(tty, a) \
113 do { \
114 if (a) \
115 emacs_tputs ((tty), a, \
116 (int) (FRAME_LINES (XFRAME (selected_frame)) \
117 - curY (tty) ), \
118 cmputc); \
119 } while (0)
120
121 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
122
123 /* Display space properties */
124
125 /* Chain of all tty device parameters. */
126 struct tty_display_info *tty_list;
127
128 /* Meaning of bits in no_color_video. Each bit set means that the
129 corresponding attribute cannot be combined with colors. */
130
131 enum no_color_bit
132 {
133 NC_STANDOUT = 1 << 0,
134 NC_UNDERLINE = 1 << 1,
135 NC_REVERSE = 1 << 2,
136 NC_BLINK = 1 << 3,
137 NC_DIM = 1 << 4,
138 NC_BOLD = 1 << 5,
139 NC_INVIS = 1 << 6,
140 NC_PROTECT = 1 << 7,
141 NC_ALT_CHARSET = 1 << 8
142 };
143
144 /* internal state */
145
146 /* The largest frame width in any call to calculate_costs. */
147
148 int max_frame_cols;
149
150 /* The largest frame height in any call to calculate_costs. */
151
152 int max_frame_lines;
153
154 /* Non-zero if we have dropped our controlling tty and therefore
155 should not open a frame on stdout. */
156 static int no_controlling_tty;
157
158 \f
159
160 #ifdef HAVE_GPM
161 #include <sys/fcntl.h>
162
163 /* The device for which we have enabled gpm support (or NULL). */
164 struct tty_display_info *gpm_tty = NULL;
165
166 /* Last recorded mouse coordinates. */
167 static int last_mouse_x, last_mouse_y;
168 #endif /* HAVE_GPM */
169
170 /* Ring the bell on a tty. */
171
172 static void
173 tty_ring_bell (struct frame *f)
174 {
175 struct tty_display_info *tty = FRAME_TTY (f);
176
177 if (tty->output)
178 {
179 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
180 ? tty->TS_visible_bell
181 : tty->TS_bell));
182 fflush (tty->output);
183 }
184 }
185
186 /* Set up termcap modes for Emacs. */
187
188 void
189 tty_set_terminal_modes (struct terminal *terminal)
190 {
191 struct tty_display_info *tty = terminal->display_info.tty;
192
193 if (tty->output)
194 {
195 if (tty->TS_termcap_modes)
196 OUTPUT (tty, tty->TS_termcap_modes);
197 else
198 {
199 /* Output enough newlines to scroll all the old screen contents
200 off the screen, so it won't be overwritten and lost. */
201 int i;
202 current_tty = tty;
203 for (i = 0; i < FRAME_LINES (XFRAME (selected_frame)); i++)
204 cmputc ('\n');
205 }
206
207 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
208 OUTPUT_IF (tty, tty->TS_keypad_mode);
209 losecursor (tty);
210 fflush (tty->output);
211 }
212 }
213
214 /* Reset termcap modes before exiting Emacs. */
215
216 void
217 tty_reset_terminal_modes (struct terminal *terminal)
218 {
219 struct tty_display_info *tty = terminal->display_info.tty;
220
221 if (tty->output)
222 {
223 tty_turn_off_highlight (tty);
224 tty_turn_off_insert (tty);
225 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
226 OUTPUT_IF (tty, tty->TS_cursor_normal);
227 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
228 OUTPUT_IF (tty, tty->TS_orig_pair);
229 /* Output raw CR so kernel can track the cursor hpos. */
230 current_tty = tty;
231 cmputc ('\r');
232 fflush (tty->output);
233 }
234 }
235
236 /* Flag the end of a display update on a termcap terminal. */
237
238 static void
239 tty_update_end (struct frame *f)
240 {
241 struct tty_display_info *tty = FRAME_TTY (f);
242
243 if (!XWINDOW (selected_window)->cursor_off_p)
244 tty_show_cursor (tty);
245 tty_turn_off_insert (tty);
246 tty_background_highlight (tty);
247 }
248
249 /* The implementation of set_terminal_window for termcap frames. */
250
251 static void
252 tty_set_terminal_window (struct frame *f, int size)
253 {
254 struct tty_display_info *tty = FRAME_TTY (f);
255
256 tty->specified_window = size ? size : FRAME_LINES (f);
257 if (FRAME_SCROLL_REGION_OK (f))
258 tty_set_scroll_region (f, 0, tty->specified_window);
259 }
260
261 static void
262 tty_set_scroll_region (struct frame *f, int start, int stop)
263 {
264 char *buf;
265 struct tty_display_info *tty = FRAME_TTY (f);
266
267 if (tty->TS_set_scroll_region)
268 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
269 else if (tty->TS_set_scroll_region_1)
270 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
271 FRAME_LINES (f), start,
272 FRAME_LINES (f) - stop,
273 FRAME_LINES (f));
274 else
275 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
276
277 OUTPUT (tty, buf);
278 xfree (buf);
279 losecursor (tty);
280 }
281
282 \f
283 static void
284 tty_turn_on_insert (struct tty_display_info *tty)
285 {
286 if (!tty->insert_mode)
287 OUTPUT (tty, tty->TS_insert_mode);
288 tty->insert_mode = 1;
289 }
290
291 void
292 tty_turn_off_insert (struct tty_display_info *tty)
293 {
294 if (tty->insert_mode)
295 OUTPUT (tty, tty->TS_end_insert_mode);
296 tty->insert_mode = 0;
297 }
298 \f
299 /* Handle highlighting. */
300
301 void
302 tty_turn_off_highlight (struct tty_display_info *tty)
303 {
304 if (tty->standout_mode)
305 OUTPUT_IF (tty, tty->TS_end_standout_mode);
306 tty->standout_mode = 0;
307 }
308
309 static void
310 tty_turn_on_highlight (struct tty_display_info *tty)
311 {
312 if (!tty->standout_mode)
313 OUTPUT_IF (tty, tty->TS_standout_mode);
314 tty->standout_mode = 1;
315 }
316
317 static void
318 tty_toggle_highlight (struct tty_display_info *tty)
319 {
320 if (tty->standout_mode)
321 tty_turn_off_highlight (tty);
322 else
323 tty_turn_on_highlight (tty);
324 }
325
326
327 /* Make cursor invisible. */
328
329 static void
330 tty_hide_cursor (struct tty_display_info *tty)
331 {
332 if (tty->cursor_hidden == 0)
333 {
334 tty->cursor_hidden = 1;
335 OUTPUT_IF (tty, tty->TS_cursor_invisible);
336 }
337 }
338
339
340 /* Ensure that cursor is visible. */
341
342 static void
343 tty_show_cursor (struct tty_display_info *tty)
344 {
345 if (tty->cursor_hidden)
346 {
347 tty->cursor_hidden = 0;
348 OUTPUT_IF (tty, tty->TS_cursor_normal);
349 if (visible_cursor)
350 OUTPUT_IF (tty, tty->TS_cursor_visible);
351 }
352 }
353
354
355 /* Set standout mode to the state it should be in for
356 empty space inside windows. What this is,
357 depends on the user option inverse-video. */
358
359 static void
360 tty_background_highlight (struct tty_display_info *tty)
361 {
362 if (inverse_video)
363 tty_turn_on_highlight (tty);
364 else
365 tty_turn_off_highlight (tty);
366 }
367
368 /* Set standout mode to the mode specified for the text to be output. */
369
370 static void
371 tty_highlight_if_desired (struct tty_display_info *tty)
372 {
373 if (inverse_video)
374 tty_turn_on_highlight (tty);
375 else
376 tty_turn_off_highlight (tty);
377 }
378 \f
379
380 /* Move cursor to row/column position VPOS/HPOS. HPOS/VPOS are
381 frame-relative coordinates. */
382
383 static void
384 tty_cursor_to (struct frame *f, int vpos, int hpos)
385 {
386 struct tty_display_info *tty = FRAME_TTY (f);
387
388 /* Detect the case where we are called from reset_sys_modes
389 and the costs have never been calculated. Do nothing. */
390 if (! tty->costs_set)
391 return;
392
393 if (curY (tty) == vpos
394 && curX (tty) == hpos)
395 return;
396 if (!tty->TF_standout_motion)
397 tty_background_highlight (tty);
398 if (!tty->TF_insmode_motion)
399 tty_turn_off_insert (tty);
400 cmgoto (tty, vpos, hpos);
401 }
402
403 /* Similar but don't take any account of the wasted characters. */
404
405 static void
406 tty_raw_cursor_to (struct frame *f, int row, int col)
407 {
408 struct tty_display_info *tty = FRAME_TTY (f);
409
410 if (curY (tty) == row
411 && curX (tty) == col)
412 return;
413 if (!tty->TF_standout_motion)
414 tty_background_highlight (tty);
415 if (!tty->TF_insmode_motion)
416 tty_turn_off_insert (tty);
417 cmgoto (tty, row, col);
418 }
419 \f
420 /* Erase operations */
421
422 /* Clear from cursor to end of frame on a termcap device. */
423
424 static void
425 tty_clear_to_end (struct frame *f)
426 {
427 register int i;
428 struct tty_display_info *tty = FRAME_TTY (f);
429
430 if (tty->TS_clr_to_bottom)
431 {
432 tty_background_highlight (tty);
433 OUTPUT (tty, tty->TS_clr_to_bottom);
434 }
435 else
436 {
437 for (i = curY (tty); i < FRAME_LINES (f); i++)
438 {
439 cursor_to (f, i, 0);
440 clear_end_of_line (f, FRAME_COLS (f));
441 }
442 }
443 }
444
445 /* Clear an entire termcap frame. */
446
447 static void
448 tty_clear_frame (struct frame *f)
449 {
450 struct tty_display_info *tty = FRAME_TTY (f);
451
452 if (tty->TS_clr_frame)
453 {
454 tty_background_highlight (tty);
455 OUTPUT (tty, tty->TS_clr_frame);
456 cmat (tty, 0, 0);
457 }
458 else
459 {
460 cursor_to (f, 0, 0);
461 clear_to_end (f);
462 }
463 }
464
465 /* An implementation of clear_end_of_line for termcap frames.
466
467 Note that the cursor may be moved, on terminals lacking a `ce' string. */
468
469 static void
470 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
471 {
472 register int i;
473 struct tty_display_info *tty = FRAME_TTY (f);
474
475 /* Detect the case where we are called from reset_sys_modes
476 and the costs have never been calculated. Do nothing. */
477 if (! tty->costs_set)
478 return;
479
480 if (curX (tty) >= first_unused_hpos)
481 return;
482 tty_background_highlight (tty);
483 if (tty->TS_clr_line)
484 {
485 OUTPUT1 (tty, tty->TS_clr_line);
486 }
487 else
488 { /* have to do it the hard way */
489 tty_turn_off_insert (tty);
490
491 /* Do not write in last row last col with Auto-wrap on. */
492 if (AutoWrap (tty)
493 && curY (tty) == FrameRows (tty) - 1
494 && first_unused_hpos == FrameCols (tty))
495 first_unused_hpos--;
496
497 for (i = curX (tty); i < first_unused_hpos; i++)
498 {
499 if (tty->termscript)
500 fputc (' ', tty->termscript);
501 fputc (' ', tty->output);
502 }
503 cmplus (tty, first_unused_hpos - curX (tty));
504 }
505 }
506 \f
507 /* Buffers to store the source and result of code conversion for terminal. */
508 static unsigned char *encode_terminal_src;
509 static unsigned char *encode_terminal_dst;
510 /* Allocated sizes of the above buffers. */
511 static int encode_terminal_src_size;
512 static int encode_terminal_dst_size;
513
514 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
515 Set CODING->produced to the byte-length of the resulting byte
516 sequence, and return a pointer to that byte sequence. */
517
518 unsigned char *
519 encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
520 {
521 struct glyph *src_end = src + src_len;
522 unsigned char *buf;
523 int nchars, nbytes, required;
524 register int tlen = GLYPH_TABLE_LENGTH;
525 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
526 Lisp_Object charset_list;
527
528 /* Allocate sufficient size of buffer to store all characters in
529 multibyte-form. But, it may be enlarged on demand if
530 Vglyph_table contains a string or a composite glyph is
531 encountered. */
532 required = MAX_MULTIBYTE_LENGTH * src_len;
533 if (encode_terminal_src_size < required)
534 {
535 if (encode_terminal_src)
536 encode_terminal_src = xrealloc (encode_terminal_src, required);
537 else
538 encode_terminal_src = xmalloc (required);
539 encode_terminal_src_size = required;
540 }
541
542 charset_list = coding_charset_list (coding);
543
544 buf = encode_terminal_src;
545 nchars = 0;
546 while (src < src_end)
547 {
548 if (src->type == COMPOSITE_GLYPH)
549 {
550 struct composition *cmp;
551 Lisp_Object gstring;
552 int i;
553
554 nbytes = buf - encode_terminal_src;
555 if (src->u.cmp.automatic)
556 {
557 gstring = composition_gstring_from_id (src->u.cmp.id);
558 required = src->slice.cmp.to + 1 - src->slice.cmp.from;
559 }
560 else
561 {
562 cmp = composition_table[src->u.cmp.id];
563 required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
564 }
565
566 if (encode_terminal_src_size < nbytes + required)
567 {
568 encode_terminal_src_size = nbytes + required;
569 encode_terminal_src = xrealloc (encode_terminal_src,
570 encode_terminal_src_size);
571 buf = encode_terminal_src + nbytes;
572 }
573
574 if (src->u.cmp.automatic)
575 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
576 {
577 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
578 int c = LGLYPH_CHAR (g);
579
580 if (! char_charset (c, charset_list, NULL))
581 c = '?';
582 buf += CHAR_STRING (c, buf);
583 nchars++;
584 }
585 else
586 for (i = 0; i < cmp->glyph_len; i++)
587 {
588 int c = COMPOSITION_GLYPH (cmp, i);
589
590 if (c == '\t')
591 continue;
592 if (char_charset (c, charset_list, NULL))
593 {
594 if (CHAR_WIDTH (c) == 0
595 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
596 /* Should be left-padded */
597 {
598 buf += CHAR_STRING (' ', buf);
599 nchars++;
600 }
601 }
602 else
603 c = '?';
604 buf += CHAR_STRING (c, buf);
605 nchars++;
606 }
607 }
608 /* We must skip glyphs to be padded for a wide character. */
609 else if (! CHAR_GLYPH_PADDING_P (*src))
610 {
611 GLYPH g;
612 int c;
613 Lisp_Object string;
614
615 string = Qnil;
616 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
617
618 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
619 {
620 /* This glyph doesn't have an entry in Vglyph_table. */
621 c = src->u.ch;
622 }
623 else
624 {
625 /* This glyph has an entry in Vglyph_table,
626 so process any alias before testing for simpleness. */
627 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
628
629 if (GLYPH_SIMPLE_P (tbase, tlen, g))
630 /* We set the multi-byte form of a character in G
631 (that should be an ASCII character) at WORKBUF. */
632 c = GLYPH_CHAR (g);
633 else
634 /* We have a string in Vglyph_table. */
635 string = tbase[GLYPH_CHAR (g)];
636 }
637
638 if (NILP (string))
639 {
640 nbytes = buf - encode_terminal_src;
641 if (encode_terminal_src_size < nbytes + MAX_MULTIBYTE_LENGTH)
642 {
643 encode_terminal_src_size = nbytes + MAX_MULTIBYTE_LENGTH;
644 encode_terminal_src = xrealloc (encode_terminal_src,
645 encode_terminal_src_size);
646 buf = encode_terminal_src + nbytes;
647 }
648 if (CHAR_BYTE8_P (c)
649 || char_charset (c, charset_list, NULL))
650 {
651 /* Store the multibyte form of C at BUF. */
652 buf += CHAR_STRING (c, buf);
653 nchars++;
654 }
655 else
656 {
657 /* C is not encodable. */
658 *buf++ = '?';
659 nchars++;
660 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
661 {
662 *buf++ = '?';
663 nchars++;
664 src++;
665 }
666 }
667 }
668 else
669 {
670 unsigned char *p = SDATA (string);
671
672 if (! STRING_MULTIBYTE (string))
673 string = string_to_multibyte (string);
674 nbytes = buf - encode_terminal_src;
675 if (encode_terminal_src_size < nbytes + SBYTES (string))
676 {
677 encode_terminal_src_size = nbytes + SBYTES (string);
678 encode_terminal_src = xrealloc (encode_terminal_src,
679 encode_terminal_src_size);
680 buf = encode_terminal_src + nbytes;
681 }
682 memcpy (buf, SDATA (string), SBYTES (string));
683 buf += SBYTES (string);
684 nchars += SCHARS (string);
685 }
686 }
687 src++;
688 }
689
690 if (nchars == 0)
691 {
692 coding->produced = 0;
693 return NULL;
694 }
695
696 nbytes = buf - encode_terminal_src;
697 coding->source = encode_terminal_src;
698 if (encode_terminal_dst_size == 0)
699 {
700 encode_terminal_dst_size = encode_terminal_src_size;
701 if (encode_terminal_dst)
702 encode_terminal_dst = xrealloc (encode_terminal_dst,
703 encode_terminal_dst_size);
704 else
705 encode_terminal_dst = xmalloc (encode_terminal_dst_size);
706 }
707 coding->destination = encode_terminal_dst;
708 coding->dst_bytes = encode_terminal_dst_size;
709 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
710 /* coding->destination may have been reallocated. */
711 encode_terminal_dst = coding->destination;
712 encode_terminal_dst_size = coding->dst_bytes;
713
714 return (encode_terminal_dst);
715 }
716
717
718
719 /* An implementation of write_glyphs for termcap frames. */
720
721 static void
722 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
723 {
724 unsigned char *conversion_buffer;
725 struct coding_system *coding;
726
727 struct tty_display_info *tty = FRAME_TTY (f);
728
729 tty_turn_off_insert (tty);
730 tty_hide_cursor (tty);
731
732 /* Don't dare write in last column of bottom line, if Auto-Wrap,
733 since that would scroll the whole frame on some terminals. */
734
735 if (AutoWrap (tty)
736 && curY (tty) + 1 == FRAME_LINES (f)
737 && (curX (tty) + len) == FRAME_COLS (f))
738 len --;
739 if (len <= 0)
740 return;
741
742 cmplus (tty, len);
743
744 /* If terminal_coding does any conversion, use it, otherwise use
745 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
746 because it always return 1 if the member src_multibyte is 1. */
747 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
748 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
749 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
750 the tail. */
751 coding->mode &= ~CODING_MODE_LAST_BLOCK;
752
753 while (len > 0)
754 {
755 /* Identify a run of glyphs with the same face. */
756 int face_id = string->face_id;
757 int n;
758
759 for (n = 1; n < len; ++n)
760 if (string[n].face_id != face_id)
761 break;
762
763 /* Turn appearance modes of the face of the run on. */
764 tty_highlight_if_desired (tty);
765 turn_on_face (f, face_id);
766
767 if (n == len)
768 /* This is the last run. */
769 coding->mode |= CODING_MODE_LAST_BLOCK;
770 conversion_buffer = encode_terminal_code (string, n, coding);
771 if (coding->produced > 0)
772 {
773 BLOCK_INPUT;
774 fwrite (conversion_buffer, 1, coding->produced, tty->output);
775 if (ferror (tty->output))
776 clearerr (tty->output);
777 if (tty->termscript)
778 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
779 UNBLOCK_INPUT;
780 }
781 len -= n;
782 string += n;
783
784 /* Turn appearance modes off. */
785 turn_off_face (f, face_id);
786 tty_turn_off_highlight (tty);
787 }
788
789 cmcheckmagic (tty);
790 }
791
792 #ifdef HAVE_GPM /* Only used by GPM code. */
793
794 static void
795 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
796 register int len, register int face_id)
797 {
798 unsigned char *conversion_buffer;
799 struct coding_system *coding;
800
801 struct tty_display_info *tty = FRAME_TTY (f);
802
803 tty_turn_off_insert (tty);
804 tty_hide_cursor (tty);
805
806 /* Don't dare write in last column of bottom line, if Auto-Wrap,
807 since that would scroll the whole frame on some terminals. */
808
809 if (AutoWrap (tty)
810 && curY (tty) + 1 == FRAME_LINES (f)
811 && (curX (tty) + len) == FRAME_COLS (f))
812 len --;
813 if (len <= 0)
814 return;
815
816 cmplus (tty, len);
817
818 /* If terminal_coding does any conversion, use it, otherwise use
819 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
820 because it always return 1 if the member src_multibyte is 1. */
821 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
822 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
823 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
824 the tail. */
825 coding->mode &= ~CODING_MODE_LAST_BLOCK;
826
827 /* Turn appearance modes of the face. */
828 tty_highlight_if_desired (tty);
829 turn_on_face (f, face_id);
830
831 coding->mode |= CODING_MODE_LAST_BLOCK;
832 conversion_buffer = encode_terminal_code (string, len, coding);
833 if (coding->produced > 0)
834 {
835 BLOCK_INPUT;
836 fwrite (conversion_buffer, 1, coding->produced, tty->output);
837 if (ferror (tty->output))
838 clearerr (tty->output);
839 if (tty->termscript)
840 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
841 UNBLOCK_INPUT;
842 }
843
844 /* Turn appearance modes off. */
845 turn_off_face (f, face_id);
846 tty_turn_off_highlight (tty);
847
848 cmcheckmagic (tty);
849 }
850 #endif
851
852 /* An implementation of insert_glyphs for termcap frames. */
853
854 static void
855 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
856 {
857 char *buf;
858 struct glyph *glyph = NULL;
859 unsigned char *conversion_buffer;
860 unsigned char space[1];
861 struct coding_system *coding;
862
863 struct tty_display_info *tty = FRAME_TTY (f);
864
865 if (tty->TS_ins_multi_chars)
866 {
867 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len);
868 OUTPUT1 (tty, buf);
869 xfree (buf);
870 if (start)
871 write_glyphs (f, start, len);
872 return;
873 }
874
875 tty_turn_on_insert (tty);
876 cmplus (tty, len);
877
878 if (! start)
879 space[0] = SPACEGLYPH;
880
881 /* If terminal_coding does any conversion, use it, otherwise use
882 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
883 because it always return 1 if the member src_multibyte is 1. */
884 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
885 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
886 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
887 the tail. */
888 coding->mode &= ~CODING_MODE_LAST_BLOCK;
889
890 while (len-- > 0)
891 {
892 OUTPUT1_IF (tty, tty->TS_ins_char);
893 if (!start)
894 {
895 conversion_buffer = space;
896 coding->produced = 1;
897 }
898 else
899 {
900 tty_highlight_if_desired (tty);
901 turn_on_face (f, start->face_id);
902 glyph = start;
903 ++start;
904 /* We must open sufficient space for a character which
905 occupies more than one column. */
906 while (len && CHAR_GLYPH_PADDING_P (*start))
907 {
908 OUTPUT1_IF (tty, tty->TS_ins_char);
909 start++, len--;
910 }
911
912 if (len <= 0)
913 /* This is the last glyph. */
914 coding->mode |= CODING_MODE_LAST_BLOCK;
915
916 conversion_buffer = encode_terminal_code (glyph, 1, coding);
917 }
918
919 if (coding->produced > 0)
920 {
921 BLOCK_INPUT;
922 fwrite (conversion_buffer, 1, coding->produced, tty->output);
923 if (ferror (tty->output))
924 clearerr (tty->output);
925 if (tty->termscript)
926 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
927 UNBLOCK_INPUT;
928 }
929
930 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
931 if (start)
932 {
933 turn_off_face (f, glyph->face_id);
934 tty_turn_off_highlight (tty);
935 }
936 }
937
938 cmcheckmagic (tty);
939 }
940
941 /* An implementation of delete_glyphs for termcap frames. */
942
943 static void
944 tty_delete_glyphs (struct frame *f, int n)
945 {
946 char *buf;
947 register int i;
948
949 struct tty_display_info *tty = FRAME_TTY (f);
950
951 if (tty->delete_in_insert_mode)
952 {
953 tty_turn_on_insert (tty);
954 }
955 else
956 {
957 tty_turn_off_insert (tty);
958 OUTPUT_IF (tty, tty->TS_delete_mode);
959 }
960
961 if (tty->TS_del_multi_chars)
962 {
963 buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
964 OUTPUT1 (tty, buf);
965 xfree (buf);
966 }
967 else
968 for (i = 0; i < n; i++)
969 OUTPUT1 (tty, tty->TS_del_char);
970 if (!tty->delete_in_insert_mode)
971 OUTPUT_IF (tty, tty->TS_end_delete_mode);
972 }
973 \f
974 /* An implementation of ins_del_lines for termcap frames. */
975
976 static void
977 tty_ins_del_lines (struct frame *f, int vpos, int n)
978 {
979 struct tty_display_info *tty = FRAME_TTY (f);
980 char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
981 char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
982 char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
983
984 register int i = n > 0 ? n : -n;
985 register char *buf;
986
987 /* If the lines below the insertion are being pushed
988 into the end of the window, this is the same as clearing;
989 and we know the lines are already clear, since the matching
990 deletion has already been done. So can ignore this. */
991 /* If the lines below the deletion are blank lines coming
992 out of the end of the window, don't bother,
993 as there will be a matching inslines later that will flush them. */
994 if (FRAME_SCROLL_REGION_OK (f)
995 && vpos + i >= tty->specified_window)
996 return;
997 if (!FRAME_MEMORY_BELOW_FRAME (f)
998 && vpos + i >= FRAME_LINES (f))
999 return;
1000
1001 if (multi)
1002 {
1003 raw_cursor_to (f, vpos, 0);
1004 tty_background_highlight (tty);
1005 buf = tparam (multi, 0, 0, i);
1006 OUTPUT (tty, buf);
1007 xfree (buf);
1008 }
1009 else if (single)
1010 {
1011 raw_cursor_to (f, vpos, 0);
1012 tty_background_highlight (tty);
1013 while (--i >= 0)
1014 OUTPUT (tty, single);
1015 if (tty->TF_teleray)
1016 curX (tty) = 0;
1017 }
1018 else
1019 {
1020 tty_set_scroll_region (f, vpos, tty->specified_window);
1021 if (n < 0)
1022 raw_cursor_to (f, tty->specified_window - 1, 0);
1023 else
1024 raw_cursor_to (f, vpos, 0);
1025 tty_background_highlight (tty);
1026 while (--i >= 0)
1027 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1028 tty_set_scroll_region (f, 0, tty->specified_window);
1029 }
1030
1031 if (!FRAME_SCROLL_REGION_OK (f)
1032 && FRAME_MEMORY_BELOW_FRAME (f)
1033 && n < 0)
1034 {
1035 cursor_to (f, FRAME_LINES (f) + n, 0);
1036 clear_to_end (f);
1037 }
1038 }
1039 \f
1040 /* Compute cost of sending "str", in characters,
1041 not counting any line-dependent padding. */
1042
1043 int
1044 string_cost (const char *str)
1045 {
1046 cost = 0;
1047 if (str)
1048 tputs (str, 0, evalcost);
1049 return cost;
1050 }
1051
1052 /* Compute cost of sending "str", in characters,
1053 counting any line-dependent padding at one line. */
1054
1055 static int
1056 string_cost_one_line (const char *str)
1057 {
1058 cost = 0;
1059 if (str)
1060 tputs (str, 1, evalcost);
1061 return cost;
1062 }
1063
1064 /* Compute per line amount of line-dependent padding,
1065 in tenths of characters. */
1066
1067 int
1068 per_line_cost (const char *str)
1069 {
1070 cost = 0;
1071 if (str)
1072 tputs (str, 0, evalcost);
1073 cost = - cost;
1074 if (str)
1075 tputs (str, 10, evalcost);
1076 return cost;
1077 }
1078
1079 /* char_ins_del_cost[n] is cost of inserting N characters.
1080 char_ins_del_cost[-n] is cost of deleting N characters.
1081 The length of this vector is based on max_frame_cols. */
1082
1083 int *char_ins_del_vector;
1084
1085 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1086
1087 /* ARGSUSED */
1088 static void
1089 calculate_ins_del_char_costs (struct frame *f)
1090 {
1091 struct tty_display_info *tty = FRAME_TTY (f);
1092 int ins_startup_cost, del_startup_cost;
1093 int ins_cost_per_char, del_cost_per_char;
1094 register int i;
1095 register int *p;
1096
1097 if (tty->TS_ins_multi_chars)
1098 {
1099 ins_cost_per_char = 0;
1100 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1101 }
1102 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1103 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1104 {
1105 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1106 + string_cost (tty->TS_end_insert_mode))) / 100;
1107 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1108 + string_cost_one_line (tty->TS_pad_inserted_char));
1109 }
1110 else
1111 {
1112 ins_startup_cost = 9999;
1113 ins_cost_per_char = 0;
1114 }
1115
1116 if (tty->TS_del_multi_chars)
1117 {
1118 del_cost_per_char = 0;
1119 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1120 }
1121 else if (tty->TS_del_char)
1122 {
1123 del_startup_cost = (string_cost (tty->TS_delete_mode)
1124 + string_cost (tty->TS_end_delete_mode));
1125 if (tty->delete_in_insert_mode)
1126 del_startup_cost /= 2;
1127 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1128 }
1129 else
1130 {
1131 del_startup_cost = 9999;
1132 del_cost_per_char = 0;
1133 }
1134
1135 /* Delete costs are at negative offsets */
1136 p = &char_ins_del_cost (f)[0];
1137 for (i = FRAME_COLS (f); --i >= 0;)
1138 *--p = (del_startup_cost += del_cost_per_char);
1139
1140 /* Doing nothing is free */
1141 p = &char_ins_del_cost (f)[0];
1142 *p++ = 0;
1143
1144 /* Insert costs are at positive offsets */
1145 for (i = FRAME_COLS (f); --i >= 0;)
1146 *p++ = (ins_startup_cost += ins_cost_per_char);
1147 }
1148
1149 void
1150 calculate_costs (struct frame *frame)
1151 {
1152 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1153
1154 if (FRAME_TERMCAP_P (frame))
1155 {
1156 struct tty_display_info *tty = FRAME_TTY (frame);
1157 register char *f = (tty->TS_set_scroll_region
1158 ? tty->TS_set_scroll_region
1159 : tty->TS_set_scroll_region_1);
1160
1161 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1162
1163 tty->costs_set = 1;
1164
1165 /* These variables are only used for terminal stuff. They are
1166 allocated once for the terminal frame of X-windows emacs, but not
1167 used afterwards.
1168
1169 char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
1170 X turns off char_ins_del_ok. */
1171
1172 max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
1173 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1174
1175 if (char_ins_del_vector != 0)
1176 char_ins_del_vector
1177 = (int *) xrealloc (char_ins_del_vector,
1178 (sizeof (int)
1179 + 2 * max_frame_cols * sizeof (int)));
1180 else
1181 char_ins_del_vector
1182 = (int *) xmalloc (sizeof (int)
1183 + 2 * max_frame_cols * sizeof (int));
1184
1185 memset (char_ins_del_vector, 0,
1186 (sizeof (int) + 2 * max_frame_cols * sizeof (int)));
1187
1188
1189 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1190 do_line_insertion_deletion_costs (frame,
1191 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1192 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1193 f, f, 1);
1194 else
1195 do_line_insertion_deletion_costs (frame,
1196 tty->TS_ins_line, tty->TS_ins_multi_lines,
1197 tty->TS_del_line, tty->TS_del_multi_lines,
1198 0, 0, 1);
1199
1200 calculate_ins_del_char_costs (frame);
1201
1202 /* Don't use TS_repeat if its padding is worse than sending the chars */
1203 if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
1204 tty->RPov = string_cost (tty->TS_repeat);
1205 else
1206 tty->RPov = FRAME_COLS (frame) * 2;
1207
1208 cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
1209 }
1210 }
1211 \f
1212 struct fkey_table {
1213 char *cap, *name;
1214 };
1215
1216 /* Termcap capability names that correspond directly to X keysyms.
1217 Some of these (marked "terminfo") aren't supplied by old-style
1218 (Berkeley) termcap entries. They're listed in X keysym order;
1219 except we put the keypad keys first, so that if they clash with
1220 other keys (as on the IBM PC keyboard) they get overridden.
1221 */
1222
1223 static const struct fkey_table keys[] =
1224 {
1225 {"kh", "home"}, /* termcap */
1226 {"kl", "left"}, /* termcap */
1227 {"ku", "up"}, /* termcap */
1228 {"kr", "right"}, /* termcap */
1229 {"kd", "down"}, /* termcap */
1230 {"%8", "prior"}, /* terminfo */
1231 {"%5", "next"}, /* terminfo */
1232 {"@7", "end"}, /* terminfo */
1233 {"@1", "begin"}, /* terminfo */
1234 {"*6", "select"}, /* terminfo */
1235 {"%9", "print"}, /* terminfo */
1236 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1237 /*
1238 * "insert" --- see below
1239 */
1240 {"&8", "undo"}, /* terminfo */
1241 {"%0", "redo"}, /* terminfo */
1242 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1243 {"@0", "find"}, /* terminfo */
1244 {"@2", "cancel"}, /* terminfo */
1245 {"%1", "help"}, /* terminfo */
1246 /*
1247 * "break" goes here, but can't be reliably intercepted with termcap
1248 */
1249 {"&4", "reset"}, /* terminfo --- actually `restart' */
1250 /*
1251 * "system" and "user" --- no termcaps
1252 */
1253 {"kE", "clearline"}, /* terminfo */
1254 {"kA", "insertline"}, /* terminfo */
1255 {"kL", "deleteline"}, /* terminfo */
1256 {"kI", "insertchar"}, /* terminfo */
1257 {"kD", "deletechar"}, /* terminfo */
1258 {"kB", "backtab"}, /* terminfo */
1259 /*
1260 * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
1261 */
1262 {"@8", "kp-enter"}, /* terminfo */
1263 /*
1264 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1265 * "kp-multiply", "kp-add", "kp-separator",
1266 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1267 * --- no termcaps for any of these.
1268 */
1269 {"K4", "kp-1"}, /* terminfo */
1270 /*
1271 * "kp-2" --- no termcap
1272 */
1273 {"K5", "kp-3"}, /* terminfo */
1274 /*
1275 * "kp-4" --- no termcap
1276 */
1277 {"K2", "kp-5"}, /* terminfo */
1278 /*
1279 * "kp-6" --- no termcap
1280 */
1281 {"K1", "kp-7"}, /* terminfo */
1282 /*
1283 * "kp-8" --- no termcap
1284 */
1285 {"K3", "kp-9"}, /* terminfo */
1286 /*
1287 * "kp-equal" --- no termcap
1288 */
1289 {"k1", "f1"},
1290 {"k2", "f2"},
1291 {"k3", "f3"},
1292 {"k4", "f4"},
1293 {"k5", "f5"},
1294 {"k6", "f6"},
1295 {"k7", "f7"},
1296 {"k8", "f8"},
1297 {"k9", "f9"},
1298
1299 {"&0", "S-cancel"}, /*shifted cancel key*/
1300 {"&9", "S-begin"}, /*shifted begin key*/
1301 {"*0", "S-find"}, /*shifted find key*/
1302 {"*1", "S-execute"}, /*shifted execute? actually shifted command key*/
1303 {"*4", "S-delete"}, /*shifted delete-character key*/
1304 {"*7", "S-end"}, /*shifted end key*/
1305 {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
1306 {"#1", "S-help"}, /*shifted help key*/
1307 {"#2", "S-home"}, /*shifted home key*/
1308 {"#3", "S-insert"}, /*shifted insert-character key*/
1309 {"#4", "S-left"}, /*shifted left-arrow key*/
1310 {"%d", "S-menu"}, /*shifted menu? actually shifted options key*/
1311 {"%c", "S-next"}, /*shifted next key*/
1312 {"%e", "S-prior"}, /*shifted previous key*/
1313 {"%f", "S-print"}, /*shifted print key*/
1314 {"%g", "S-redo"}, /*shifted redo key*/
1315 {"%i", "S-right"}, /*shifted right-arrow key*/
1316 {"!3", "S-undo"} /*shifted undo key*/
1317 };
1318
1319 #ifndef DOS_NT
1320 static char **term_get_fkeys_address;
1321 static KBOARD *term_get_fkeys_kboard;
1322 static Lisp_Object term_get_fkeys_1 (void);
1323
1324 /* Find the escape codes sent by the function keys for Vinput_decode_map.
1325 This function scans the termcap function key sequence entries, and
1326 adds entries to Vinput_decode_map for each function key it finds. */
1327
1328 static void
1329 term_get_fkeys (char **address, KBOARD *kboard)
1330 {
1331 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1332 errors during the call. The only errors should be from Fdefine_key
1333 when given a key sequence containing an invalid prefix key. If the
1334 termcap defines function keys which use a prefix that is already bound
1335 to a command by the default bindings, we should silently ignore that
1336 function key specification, rather than giving the user an error and
1337 refusing to run at all on such a terminal. */
1338
1339 term_get_fkeys_address = address;
1340 term_get_fkeys_kboard = kboard;
1341 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1342 }
1343
1344 static Lisp_Object
1345 term_get_fkeys_1 (void)
1346 {
1347 int i;
1348
1349 char **address = term_get_fkeys_address;
1350 KBOARD *kboard = term_get_fkeys_kboard;
1351
1352 /* This can happen if CANNOT_DUMP or with strange options. */
1353 if (!KEYMAPP (kboard->Vinput_decode_map))
1354 kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
1355
1356 for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
1357 {
1358 char *sequence = tgetstr (keys[i].cap, address);
1359 if (sequence)
1360 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1361 Fmake_vector (make_number (1),
1362 intern (keys[i].name)));
1363 }
1364
1365 /* The uses of the "k0" capability are inconsistent; sometimes it
1366 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1367 We will attempt to politely accommodate both systems by testing for
1368 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1369 */
1370 {
1371 char *k_semi = tgetstr ("k;", address);
1372 char *k0 = tgetstr ("k0", address);
1373 char *k0_name = "f10";
1374
1375 if (k_semi)
1376 {
1377 if (k0)
1378 /* Define f0 first, so that f10 takes precedence in case the
1379 key sequences happens to be the same. */
1380 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1381 Fmake_vector (make_number (1), intern ("f0")));
1382 Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
1383 Fmake_vector (make_number (1), intern ("f10")));
1384 }
1385 else if (k0)
1386 Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
1387 Fmake_vector (make_number (1), intern (k0_name)));
1388 }
1389
1390 /* Set up cookies for numbered function keys above f10. */
1391 {
1392 char fcap[3], fkey[4];
1393
1394 fcap[0] = 'F'; fcap[2] = '\0';
1395 for (i = 11; i < 64; i++)
1396 {
1397 if (i <= 19)
1398 fcap[1] = '1' + i - 11;
1399 else if (i <= 45)
1400 fcap[1] = 'A' + i - 20;
1401 else
1402 fcap[1] = 'a' + i - 46;
1403
1404 {
1405 char *sequence = tgetstr (fcap, address);
1406 if (sequence)
1407 {
1408 sprintf (fkey, "f%d", i);
1409 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
1410 Fmake_vector (make_number (1),
1411 intern (fkey)));
1412 }
1413 }
1414 }
1415 }
1416
1417 /*
1418 * Various mappings to try and get a better fit.
1419 */
1420 {
1421 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1422 if (!tgetstr (cap1, address)) \
1423 { \
1424 char *sequence = tgetstr (cap2, address); \
1425 if (sequence) \
1426 Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
1427 Fmake_vector (make_number (1), \
1428 intern (sym))); \
1429 }
1430
1431 /* if there's no key_next keycap, map key_npage to `next' keysym */
1432 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1433 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1434 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1435 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1436 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1437 /* if there's no key_end keycap, map key_ll to 'end' keysym */
1438 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1439
1440 /* IBM has their own non-standard dialect of terminfo.
1441 If the standard name isn't found, try the IBM name. */
1442 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1443 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1444 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1445 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1446 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1447 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1448 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1449 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1450 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1451 #undef CONDITIONAL_REASSIGN
1452 }
1453
1454 return Qnil;
1455 }
1456 #endif /* not DOS_NT */
1457
1458 \f
1459 /***********************************************************************
1460 Character Display Information
1461 ***********************************************************************/
1462 static void append_glyph (struct it *);
1463 static void produce_stretch_glyph (struct it *);
1464 static void append_composite_glyph (struct it *);
1465 static void produce_composite_glyph (struct it *);
1466 static void append_glyphless_glyph (struct it *, int, char *);
1467 static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
1468
1469 /* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1470 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
1471 the character for which to produce glyphs; IT->face_id contains the
1472 character's face. Padding glyphs are appended if IT->c has a
1473 IT->pixel_width > 1. */
1474
1475 static void
1476 append_glyph (struct it *it)
1477 {
1478 struct glyph *glyph, *end;
1479 int i;
1480
1481 xassert (it->glyph_row);
1482 glyph = (it->glyph_row->glyphs[it->area]
1483 + it->glyph_row->used[it->area]);
1484 end = it->glyph_row->glyphs[1 + it->area];
1485
1486 /* If the glyph row is reversed, we need to prepend the glyph rather
1487 than append it. */
1488 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1489 {
1490 struct glyph *g;
1491 int move_by = it->pixel_width;
1492
1493 /* Make room for the new glyphs. */
1494 if (move_by > end - glyph) /* don't overstep end of this area */
1495 move_by = end - glyph;
1496 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1497 g[move_by] = *g;
1498 glyph = it->glyph_row->glyphs[it->area];
1499 end = glyph + move_by;
1500 }
1501
1502 /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
1503 right, even in the REVERSED_P case, since (a) all of its u.ch are
1504 identical, and (b) the PADDING_P flag needs to be set for the
1505 leftmost one, because we write to the terminal left-to-right. */
1506 for (i = 0;
1507 i < it->pixel_width && glyph < end;
1508 ++i)
1509 {
1510 glyph->type = CHAR_GLYPH;
1511 glyph->pixel_width = 1;
1512 glyph->u.ch = it->char_to_display;
1513 glyph->face_id = it->face_id;
1514 glyph->padding_p = i > 0;
1515 glyph->charpos = CHARPOS (it->position);
1516 glyph->object = it->object;
1517 if (it->bidi_p)
1518 {
1519 glyph->resolved_level = it->bidi_it.resolved_level;
1520 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1521 abort ();
1522 glyph->bidi_type = it->bidi_it.type;
1523 }
1524 else
1525 {
1526 glyph->resolved_level = 0;
1527 glyph->bidi_type = UNKNOWN_BT;
1528 }
1529
1530 ++it->glyph_row->used[it->area];
1531 ++glyph;
1532 }
1533 }
1534
1535 /* Produce glyphs for the display element described by IT. *IT
1536 specifies what we want to produce a glyph for (character, image, ...),
1537 and where in the glyph matrix we currently are (glyph row and hpos).
1538 produce_glyphs fills in output fields of *IT with information such as the
1539 pixel width and height of a character, and maybe output actual glyphs at
1540 the same time if IT->glyph_row is non-null. For an overview, see
1541 the explanation in dispextern.h, before the definition of the
1542 display_element_type enumeration.
1543
1544 produce_glyphs also stores the result of glyph width, ascent
1545 etc. computations in *IT.
1546
1547 IT->glyph_row may be null, in which case produce_glyphs does not
1548 actually fill in the glyphs. This is used in the move_* functions
1549 in xdisp.c for text width and height computations.
1550
1551 Callers usually don't call produce_glyphs directly;
1552 instead they use the macro PRODUCE_GLYPHS. */
1553
1554 void
1555 produce_glyphs (struct it *it)
1556 {
1557 /* If a hook is installed, let it do the work. */
1558
1559 /* Nothing but characters are supported on terminal frames. */
1560 xassert (it->what == IT_CHARACTER
1561 || it->what == IT_COMPOSITION
1562 || it->what == IT_STRETCH);
1563
1564 if (it->what == IT_STRETCH)
1565 {
1566 produce_stretch_glyph (it);
1567 goto done;
1568 }
1569
1570 if (it->what == IT_COMPOSITION)
1571 {
1572 produce_composite_glyph (it);
1573 goto done;
1574 }
1575
1576 if (it->what == IT_GLYPHLESS)
1577 {
1578 produce_glyphless_glyph (it, 0, Qnil);
1579 goto done;
1580 }
1581
1582 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1583 {
1584 it->pixel_width = it->nglyphs = 1;
1585 if (it->glyph_row)
1586 append_glyph (it);
1587 }
1588 else if (it->char_to_display == '\n')
1589 it->pixel_width = it->nglyphs = 0;
1590 else if (it->char_to_display == '\t')
1591 {
1592 int absolute_x = (it->current_x
1593 + it->continuation_lines_width);
1594 int next_tab_x
1595 = (((1 + absolute_x + it->tab_width - 1)
1596 / it->tab_width)
1597 * it->tab_width);
1598 int nspaces;
1599
1600 /* If part of the TAB has been displayed on the previous line
1601 which is continued now, continuation_lines_width will have
1602 been incremented already by the part that fitted on the
1603 continued line. So, we will get the right number of spaces
1604 here. */
1605 nspaces = next_tab_x - absolute_x;
1606
1607 if (it->glyph_row)
1608 {
1609 int n = nspaces;
1610
1611 it->char_to_display = ' ';
1612 it->pixel_width = it->len = 1;
1613
1614 while (n--)
1615 append_glyph (it);
1616 }
1617
1618 it->pixel_width = nspaces;
1619 it->nglyphs = nspaces;
1620 }
1621 else if (CHAR_BYTE8_P (it->char_to_display))
1622 {
1623 /* Coming here means that we must send the raw 8-bit byte as is
1624 to the terminal. Although there's no way to know how many
1625 columns it occupies on a screen, it is a good assumption that
1626 a single byte code has 1-column width. */
1627 it->pixel_width = it->nglyphs = 1;
1628 if (it->glyph_row)
1629 append_glyph (it);
1630 }
1631 else
1632 {
1633 Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list;
1634
1635 if (char_charset (it->char_to_display, charset_list, NULL))
1636 {
1637 it->pixel_width = CHAR_WIDTH (it->char_to_display);
1638 it->nglyphs = it->pixel_width;
1639 if (it->glyph_row)
1640 append_glyph (it);
1641 }
1642 else
1643 {
1644 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1645
1646 xassert (it->what == IT_GLYPHLESS);
1647 produce_glyphless_glyph (it, 1, acronym);
1648 }
1649 }
1650
1651 done:
1652 /* Advance current_x by the pixel width as a convenience for
1653 the caller. */
1654 if (it->area == TEXT_AREA)
1655 it->current_x += it->pixel_width;
1656 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1657 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1658 }
1659
1660
1661 /* Produce a stretch glyph for iterator IT. IT->object is the value
1662 of the glyph property displayed. The value must be a list
1663 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1664 being recognized:
1665
1666 1. `:width WIDTH' specifies that the space should be WIDTH *
1667 canonical char width wide. WIDTH may be an integer or floating
1668 point number.
1669
1670 2. `:align-to HPOS' specifies that the space should be wide enough
1671 to reach HPOS, a value in canonical character units. */
1672
1673 static void
1674 produce_stretch_glyph (struct it *it)
1675 {
1676 /* (space :width WIDTH ...) */
1677 Lisp_Object prop, plist;
1678 int width = 0, align_to = -1;
1679 int zero_width_ok_p = 0;
1680 double tem;
1681
1682 /* List should start with `space'. */
1683 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1684 plist = XCDR (it->object);
1685
1686 /* Compute the width of the stretch. */
1687 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
1688 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, 0))
1689 {
1690 /* Absolute width `:width WIDTH' specified and valid. */
1691 zero_width_ok_p = 1;
1692 width = (int)(tem + 0.5);
1693 }
1694 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
1695 && calc_pixel_width_or_height (&tem, it, prop, 0, 1, &align_to))
1696 {
1697 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
1698 align_to = (align_to < 0
1699 ? 0
1700 : align_to - window_box_left_offset (it->w, TEXT_AREA));
1701 else if (align_to < 0)
1702 align_to = window_box_left_offset (it->w, TEXT_AREA);
1703 width = max (0, (int)(tem + 0.5) + align_to - it->current_x);
1704 zero_width_ok_p = 1;
1705 }
1706 else
1707 /* Nothing specified -> width defaults to canonical char width. */
1708 width = FRAME_COLUMN_WIDTH (it->f);
1709
1710 if (width <= 0 && (width < 0 || !zero_width_ok_p))
1711 width = 1;
1712
1713 if (width > 0 && it->line_wrap != TRUNCATE
1714 && it->current_x + width > it->last_visible_x)
1715 width = it->last_visible_x - it->current_x - 1;
1716
1717 if (width > 0 && it->glyph_row)
1718 {
1719 Lisp_Object o_object = it->object;
1720 Lisp_Object object = it->stack[it->sp - 1].string;
1721 int n = width;
1722
1723 if (!STRINGP (object))
1724 object = it->w->buffer;
1725 it->object = object;
1726 it->char_to_display = ' ';
1727 it->pixel_width = it->len = 1;
1728 while (n--)
1729 append_glyph (it);
1730 it->object = o_object;
1731 }
1732 it->pixel_width = width;
1733 it->nglyphs = width;
1734 }
1735
1736
1737 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
1738 Called from produce_composite_glyph for terminal frames if
1739 IT->glyph_row != NULL. IT->face_id contains the character's
1740 face. */
1741
1742 static void
1743 append_composite_glyph (struct it *it)
1744 {
1745 struct glyph *glyph;
1746
1747 xassert (it->glyph_row);
1748 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1749 if (glyph < it->glyph_row->glyphs[1 + it->area])
1750 {
1751 /* If the glyph row is reversed, we need to prepend the glyph
1752 rather than append it. */
1753 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1754 {
1755 struct glyph *g;
1756
1757 /* Make room for the new glyph. */
1758 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1759 g[1] = *g;
1760 glyph = it->glyph_row->glyphs[it->area];
1761 }
1762 glyph->type = COMPOSITE_GLYPH;
1763 glyph->pixel_width = it->pixel_width;
1764 glyph->u.cmp.id = it->cmp_it.id;
1765 if (it->cmp_it.ch < 0)
1766 {
1767 glyph->u.cmp.automatic = 0;
1768 glyph->u.cmp.id = it->cmp_it.id;
1769 }
1770 else
1771 {
1772 glyph->u.cmp.automatic = 1;
1773 glyph->u.cmp.id = it->cmp_it.id;
1774 glyph->slice.cmp.from = it->cmp_it.from;
1775 glyph->slice.cmp.to = it->cmp_it.to - 1;
1776 }
1777
1778 glyph->face_id = it->face_id;
1779 glyph->padding_p = 0;
1780 glyph->charpos = CHARPOS (it->position);
1781 glyph->object = it->object;
1782 if (it->bidi_p)
1783 {
1784 glyph->resolved_level = it->bidi_it.resolved_level;
1785 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1786 abort ();
1787 glyph->bidi_type = it->bidi_it.type;
1788 }
1789 else
1790 {
1791 glyph->resolved_level = 0;
1792 glyph->bidi_type = UNKNOWN_BT;
1793 }
1794
1795 ++it->glyph_row->used[it->area];
1796 ++glyph;
1797 }
1798 }
1799
1800
1801 /* Produce a composite glyph for iterator IT. IT->cmp_id is the ID of
1802 the composition. We simply produces components of the composition
1803 assuming that the terminal has a capability to layout/render it
1804 correctly. */
1805
1806 static void
1807 produce_composite_glyph (struct it *it)
1808 {
1809 if (it->cmp_it.ch < 0)
1810 {
1811 struct composition *cmp = composition_table[it->cmp_it.id];
1812
1813 it->pixel_width = cmp->width;
1814 }
1815 else
1816 {
1817 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1818
1819 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1820 it->cmp_it.to, NULL);
1821 }
1822 it->nglyphs = 1;
1823 if (it->glyph_row)
1824 append_composite_glyph (it);
1825 }
1826
1827
1828 /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID
1829 is a face ID to be used for the glyph. What is actually appended
1830 are glyphs of type CHAR_GLYPH whose characters are in STR (which
1831 comes from it->nglyphs bytes). */
1832
1833 static void
1834 append_glyphless_glyph (struct it *it, int face_id, char *str)
1835 {
1836 struct glyph *glyph, *end;
1837 int i;
1838
1839 xassert (it->glyph_row);
1840 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1841 end = it->glyph_row->glyphs[1 + it->area];
1842
1843 /* If the glyph row is reversed, we need to prepend the glyph rather
1844 than append it. */
1845 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1846 {
1847 struct glyph *g;
1848 int move_by = it->pixel_width;
1849
1850 /* Make room for the new glyphs. */
1851 if (move_by > end - glyph) /* don't overstep end of this area */
1852 move_by = end - glyph;
1853 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1854 g[move_by] = *g;
1855 glyph = it->glyph_row->glyphs[it->area];
1856 end = glyph + move_by;
1857 }
1858
1859 if (glyph >= end)
1860 return;
1861 glyph->type = CHAR_GLYPH;
1862 glyph->pixel_width = 1;
1863 glyph->face_id = face_id;
1864 glyph->padding_p = 0;
1865 glyph->charpos = CHARPOS (it->position);
1866 glyph->object = it->object;
1867 if (it->bidi_p)
1868 {
1869 glyph->resolved_level = it->bidi_it.resolved_level;
1870 if ((it->bidi_it.type & 7) != it->bidi_it.type)
1871 abort ();
1872 glyph->bidi_type = it->bidi_it.type;
1873 }
1874 else
1875 {
1876 glyph->resolved_level = 0;
1877 glyph->bidi_type = UNKNOWN_BT;
1878 }
1879
1880 /* BIDI Note: we put the glyphs of characters left to right, even in
1881 the REVERSED_P case because we write to the terminal
1882 left-to-right. */
1883 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1884 {
1885 if (i > 0)
1886 glyph[0] = glyph[-1];
1887 glyph->u.ch = str[i];
1888 ++it->glyph_row->used[it->area];
1889 ++glyph;
1890 }
1891 }
1892
1893 /* Produce glyphs for a glyphless character for iterator IT.
1894 IT->glyphless_method specifies which method to use for displaying
1895 the character. See the description of enum
1896 glyphless_display_method in dispextern.h for the details.
1897
1898 FOR_NO_FONT is nonzero if and only if this is for a character that
1899 is not supproted by the coding system of the terminal. ACRONYM, if
1900 non-nil, is an acronym string for the character.
1901
1902 The glyphs actually produced are of type CHAR_GLYPH. */
1903
1904 static void
1905 produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
1906 {
1907 int face_id;
1908 int len;
1909 char buf[9], *str = " ";
1910
1911 /* Get a face ID for the glyph by utilizing a cache (the same way as
1912 done for `escape-glyph' in get_next_display_element). */
1913 if (it->f == last_glyphless_glyph_frame
1914 && it->face_id == last_glyphless_glyph_face_id)
1915 {
1916 face_id = last_glyphless_glyph_merged_face_id;
1917 }
1918 else
1919 {
1920 /* Merge the `glyphless-char' face into the current face. */
1921 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
1922 last_glyphless_glyph_frame = it->f;
1923 last_glyphless_glyph_face_id = it->face_id;
1924 last_glyphless_glyph_merged_face_id = face_id;
1925 }
1926
1927 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1928 {
1929 /* As there's no way to produce a thin space, we produce a space
1930 of canonical width. */
1931 len = 1;
1932 }
1933 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1934 {
1935 len = CHAR_WIDTH (it->c);
1936 if (len == 0)
1937 len = 1;
1938 else if (len > 4)
1939 len = 4;
1940 sprintf (buf, "[%.*s]", len, str);
1941 len += 2;
1942 str = buf;
1943 }
1944 else
1945 {
1946 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1947 {
1948 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1949 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1950 buf[0] = '[';
1951 str = STRINGP (acronym) ? SSDATA (acronym) : "";
1952 for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
1953 buf[1 + len] = str[len];
1954 buf[1 + len] = ']';
1955 len += 2;
1956 }
1957 else
1958 {
1959 xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1960 len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c)
1961 : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c)
1962 : sprintf (buf, "\\x%06X", it->c));
1963 }
1964 str = buf;
1965 }
1966
1967 it->pixel_width = len;
1968 it->nglyphs = len;
1969 if (len > 0 && it->glyph_row)
1970 append_glyphless_glyph (it, face_id, str);
1971 }
1972
1973
1974 /* Get information about special display element WHAT in an
1975 environment described by IT. WHAT is one of IT_TRUNCATION or
1976 IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
1977 non-null glyph_row member. This function ensures that fields like
1978 face_id, c, len of IT are left untouched. */
1979
1980 void
1981 produce_special_glyphs (struct it *it, enum display_element_type what)
1982 {
1983 struct it temp_it;
1984 Lisp_Object gc;
1985 GLYPH glyph;
1986
1987 temp_it = *it;
1988 temp_it.dp = NULL;
1989 temp_it.what = IT_CHARACTER;
1990 temp_it.len = 1;
1991 temp_it.object = make_number (0);
1992 memset (&temp_it.current, 0, sizeof temp_it.current);
1993
1994 if (what == IT_CONTINUATION)
1995 {
1996 /* Continuation glyph. For R2L lines, we mirror it by hand. */
1997 if (it->bidi_it.paragraph_dir == R2L)
1998 SET_GLYPH_FROM_CHAR (glyph, '/');
1999 else
2000 SET_GLYPH_FROM_CHAR (glyph, '\\');
2001 if (it->dp
2002 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
2003 && GLYPH_CODE_CHAR_VALID_P (gc))
2004 {
2005 /* FIXME: Should we mirror GC for R2L lines? */
2006 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2007 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2008 }
2009 }
2010 else if (what == IT_TRUNCATION)
2011 {
2012 /* Truncation glyph. */
2013 SET_GLYPH_FROM_CHAR (glyph, '$');
2014 if (it->dp
2015 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
2016 && GLYPH_CODE_CHAR_VALID_P (gc))
2017 {
2018 /* FIXME: Should we mirror GC for R2L lines? */
2019 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
2020 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
2021 }
2022 }
2023 else
2024 abort ();
2025
2026 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
2027 temp_it.face_id = GLYPH_FACE (glyph);
2028 temp_it.len = CHAR_BYTES (temp_it.c);
2029
2030 produce_glyphs (&temp_it);
2031 it->pixel_width = temp_it.pixel_width;
2032 it->nglyphs = temp_it.pixel_width;
2033 }
2034
2035
2036 \f
2037 /***********************************************************************
2038 Faces
2039 ***********************************************************************/
2040
2041 /* Value is non-zero if attribute ATTR may be used. ATTR should be
2042 one of the enumerators from enum no_color_bit, or a bit set built
2043 from them. Some display attributes may not be used together with
2044 color; the termcap capability `NC' specifies which ones. */
2045
2046 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
2047 (tty->TN_max_colors > 0 \
2048 ? (tty->TN_no_color_video & (ATTR)) == 0 \
2049 : 1)
2050
2051 /* Turn appearances of face FACE_ID on tty frame F on.
2052 FACE_ID is a realized face ID number, in the face cache. */
2053
2054 static void
2055 turn_on_face (struct frame *f, int face_id)
2056 {
2057 struct face *face = FACE_FROM_ID (f, face_id);
2058 long fg = face->foreground;
2059 long bg = face->background;
2060 struct tty_display_info *tty = FRAME_TTY (f);
2061
2062 /* Do this first because TS_end_standout_mode may be the same
2063 as TS_exit_attribute_mode, which turns all appearances off. */
2064 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
2065 {
2066 if (tty->TN_max_colors > 0)
2067 {
2068 if (fg >= 0 && bg >= 0)
2069 {
2070 /* If the terminal supports colors, we can set them
2071 below without using reverse video. The face's fg
2072 and bg colors are set as they should appear on
2073 the screen, i.e. they take the inverse-video'ness
2074 of the face already into account. */
2075 }
2076 else if (inverse_video)
2077 {
2078 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2079 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2080 tty_toggle_highlight (tty);
2081 }
2082 else
2083 {
2084 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2085 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2086 tty_toggle_highlight (tty);
2087 }
2088 }
2089 else
2090 {
2091 /* If we can't display colors, use reverse video
2092 if the face specifies that. */
2093 if (inverse_video)
2094 {
2095 if (fg == FACE_TTY_DEFAULT_FG_COLOR
2096 || bg == FACE_TTY_DEFAULT_BG_COLOR)
2097 tty_toggle_highlight (tty);
2098 }
2099 else
2100 {
2101 if (fg == FACE_TTY_DEFAULT_BG_COLOR
2102 || bg == FACE_TTY_DEFAULT_FG_COLOR)
2103 tty_toggle_highlight (tty);
2104 }
2105 }
2106 }
2107
2108 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
2109 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
2110
2111 if (face->tty_dim_p && MAY_USE_WITH_COLORS_P (tty, NC_DIM))
2112 OUTPUT1_IF (tty, tty->TS_enter_dim_mode);
2113
2114 /* Alternate charset and blinking not yet used. */
2115 if (face->tty_alt_charset_p
2116 && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET))
2117 OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode);
2118
2119 if (face->tty_blinking_p
2120 && MAY_USE_WITH_COLORS_P (tty, NC_BLINK))
2121 OUTPUT1_IF (tty, tty->TS_enter_blink_mode);
2122
2123 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2124 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2125
2126 if (tty->TN_max_colors > 0)
2127 {
2128 char *ts, *p;
2129
2130 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2131 if (fg >= 0 && ts)
2132 {
2133 p = tparam (ts, NULL, 0, (int) fg);
2134 OUTPUT (tty, p);
2135 xfree (p);
2136 }
2137
2138 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2139 if (bg >= 0 && ts)
2140 {
2141 p = tparam (ts, NULL, 0, (int) bg);
2142 OUTPUT (tty, p);
2143 xfree (p);
2144 }
2145 }
2146 }
2147
2148
2149 /* Turn off appearances of face FACE_ID on tty frame F. */
2150
2151 static void
2152 turn_off_face (struct frame *f, int face_id)
2153 {
2154 struct face *face = FACE_FROM_ID (f, face_id);
2155 struct tty_display_info *tty = FRAME_TTY (f);
2156
2157 xassert (face != NULL);
2158
2159 if (tty->TS_exit_attribute_mode)
2160 {
2161 /* Capability "me" will turn off appearance modes double-bright,
2162 half-bright, reverse-video, standout, underline. It may or
2163 may not turn off alt-char-mode. */
2164 if (face->tty_bold_p
2165 || face->tty_dim_p
2166 || face->tty_reverse_p
2167 || face->tty_alt_charset_p
2168 || face->tty_blinking_p
2169 || face->tty_underline_p)
2170 {
2171 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2172 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2173 tty->standout_mode = 0;
2174 }
2175
2176 if (face->tty_alt_charset_p)
2177 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2178 }
2179 else
2180 {
2181 /* If we don't have "me" we can only have those appearances
2182 that have exit sequences defined. */
2183 if (face->tty_alt_charset_p)
2184 OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode);
2185
2186 if (face->tty_underline_p)
2187 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2188 }
2189
2190 /* Switch back to default colors. */
2191 if (tty->TN_max_colors > 0
2192 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2193 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2194 || (face->background != FACE_TTY_DEFAULT_COLOR
2195 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2196 OUTPUT1_IF (tty, tty->TS_orig_pair);
2197 }
2198
2199
2200 /* Return non-zero if the terminal on frame F supports all of the
2201 capabilities in CAPS simultaneously, with foreground and background
2202 colors FG and BG. */
2203
2204 int
2205 tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2206 unsigned long fg, unsigned long bg)
2207 {
2208 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2209 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
2210 return 0;
2211
2212 TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2213 TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE);
2214 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2215 TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2216 TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK);
2217 TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET);
2218
2219 /* We can do it! */
2220 return 1;
2221 }
2222
2223 /* Return non-zero if the terminal is capable to display colors. */
2224
2225 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2226 0, 1, 0,
2227 doc: /* Return non-nil if the tty device TERMINAL can display colors.
2228
2229 TERMINAL can be a terminal object, a frame, or nil (meaning the
2230 selected frame's terminal). This function always returns nil if
2231 TERMINAL does not refer to a text-only terminal. */)
2232 (Lisp_Object terminal)
2233 {
2234 struct terminal *t = get_tty_terminal (terminal, 0);
2235 if (!t)
2236 return Qnil;
2237 else
2238 return t->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
2239 }
2240
2241 /* Return the number of supported colors. */
2242 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2243 Stty_display_color_cells, 0, 1, 0,
2244 doc: /* Return the number of colors supported by the tty device TERMINAL.
2245
2246 TERMINAL can be a terminal object, a frame, or nil (meaning the
2247 selected frame's terminal). This function always returns 0 if
2248 TERMINAL does not refer to a text-only terminal. */)
2249 (Lisp_Object terminal)
2250 {
2251 struct terminal *t = get_tty_terminal (terminal, 0);
2252 if (!t)
2253 return make_number (0);
2254 else
2255 return make_number (t->display_info.tty->TN_max_colors);
2256 }
2257
2258 #ifndef DOS_NT
2259
2260 /* Declare here rather than in the function, as in the rest of Emacs,
2261 to work around an HPUX compiler bug (?). See
2262 http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00410.html */
2263 static int default_max_colors;
2264 static int default_max_pairs;
2265 static int default_no_color_video;
2266 static char *default_orig_pair;
2267 static char *default_set_foreground;
2268 static char *default_set_background;
2269
2270 /* Save or restore the default color-related capabilities of this
2271 terminal. */
2272 static void
2273 tty_default_color_capabilities (struct tty_display_info *tty, int save)
2274 {
2275
2276 if (save)
2277 {
2278 xfree (default_orig_pair);
2279 default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
2280
2281 xfree (default_set_foreground);
2282 default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
2283 : NULL;
2284
2285 xfree (default_set_background);
2286 default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
2287 : NULL;
2288
2289 default_max_colors = tty->TN_max_colors;
2290 default_max_pairs = tty->TN_max_pairs;
2291 default_no_color_video = tty->TN_no_color_video;
2292 }
2293 else
2294 {
2295 tty->TS_orig_pair = default_orig_pair;
2296 tty->TS_set_foreground = default_set_foreground;
2297 tty->TS_set_background = default_set_background;
2298 tty->TN_max_colors = default_max_colors;
2299 tty->TN_max_pairs = default_max_pairs;
2300 tty->TN_no_color_video = default_no_color_video;
2301 }
2302 }
2303
2304 /* Setup one of the standard tty color schemes according to MODE.
2305 MODE's value is generally the number of colors which we want to
2306 support; zero means set up for the default capabilities, the ones
2307 we saw at init_tty time; -1 means turn off color support. */
2308 static void
2309 tty_setup_colors (struct tty_display_info *tty, int mode)
2310 {
2311 /* Canonicalize all negative values of MODE. */
2312 if (mode < -1)
2313 mode = -1;
2314
2315 switch (mode)
2316 {
2317 case -1: /* no colors at all */
2318 tty->TN_max_colors = 0;
2319 tty->TN_max_pairs = 0;
2320 tty->TN_no_color_video = 0;
2321 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2322 break;
2323 case 0: /* default colors, if any */
2324 default:
2325 tty_default_color_capabilities (tty, 0);
2326 break;
2327 case 8: /* 8 standard ANSI colors */
2328 tty->TS_orig_pair = "\033[0m";
2329 #ifdef TERMINFO
2330 tty->TS_set_foreground = "\033[3%p1%dm";
2331 tty->TS_set_background = "\033[4%p1%dm";
2332 #else
2333 tty->TS_set_foreground = "\033[3%dm";
2334 tty->TS_set_background = "\033[4%dm";
2335 #endif
2336 tty->TN_max_colors = 8;
2337 tty->TN_max_pairs = 64;
2338 tty->TN_no_color_video = 0;
2339 break;
2340 }
2341 }
2342
2343 void
2344 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2345 {
2346 Lisp_Object tem, val;
2347 Lisp_Object color_mode;
2348 int mode;
2349 Lisp_Object tty_color_mode_alist
2350 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2351
2352 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2353 val = CONSP (tem) ? XCDR (tem) : Qnil;
2354
2355 if (INTEGERP (val))
2356 color_mode = val;
2357 else if (SYMBOLP (tty_color_mode_alist))
2358 {
2359 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2360 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2361 }
2362 else
2363 color_mode = Qnil;
2364
2365 mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
2366
2367 if (mode != tty->previous_color_mode)
2368 {
2369 Lisp_Object funsym = intern ("tty-set-up-initial-frame-faces");
2370 tty->previous_color_mode = mode;
2371 tty_setup_colors (tty , mode);
2372 /* This recomputes all the faces given the new color definitions. */
2373 safe_call (1, &funsym);
2374 }
2375 }
2376
2377 #endif /* !DOS_NT */
2378
2379 \f
2380
2381 /* Return the tty display object specified by TERMINAL. */
2382
2383 struct terminal *
2384 get_tty_terminal (Lisp_Object terminal, int throw)
2385 {
2386 struct terminal *t = get_terminal (terminal, throw);
2387
2388 if (t && t->type != output_termcap && t->type != output_msdos_raw)
2389 {
2390 if (throw)
2391 error ("Device %d is not a termcap terminal device", t->id);
2392 else
2393 return NULL;
2394 }
2395
2396 return t;
2397 }
2398
2399 /* Return an active termcap device that uses the tty device with the
2400 given name.
2401
2402 This function ignores suspended devices.
2403
2404 Returns NULL if the named terminal device is not opened. */
2405
2406 struct terminal *
2407 get_named_tty (const char *name)
2408 {
2409 struct terminal *t;
2410
2411 if (!name)
2412 abort ();
2413
2414 for (t = terminal_list; t; t = t->next_terminal)
2415 {
2416 if ((t->type == output_termcap || t->type == output_msdos_raw)
2417 && !strcmp (t->display_info.tty->name, name)
2418 && TERMINAL_ACTIVE_P (t))
2419 return t;
2420 }
2421
2422 return 0;
2423 }
2424
2425 \f
2426 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2427 doc: /* Return the type of the tty device that TERMINAL uses.
2428 Returns nil if TERMINAL is not on a tty device.
2429
2430 TERMINAL can be a terminal object, a frame, or nil (meaning the
2431 selected frame's terminal). */)
2432 (Lisp_Object terminal)
2433 {
2434 struct terminal *t = get_terminal (terminal, 1);
2435
2436 if (t->type != output_termcap && t->type != output_msdos_raw)
2437 return Qnil;
2438
2439 if (t->display_info.tty->type)
2440 return build_string (t->display_info.tty->type);
2441 else
2442 return Qnil;
2443 }
2444
2445 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2446 doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
2447
2448 TERMINAL can be a terminal object, a frame, or nil (meaning the
2449 selected frame's terminal). This function always returns nil if
2450 TERMINAL is not on a tty device. */)
2451 (Lisp_Object terminal)
2452 {
2453 struct terminal *t = get_terminal (terminal, 1);
2454
2455 if ((t->type != output_termcap && t->type != output_msdos_raw)
2456 || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2457 return Qnil;
2458 else
2459 return Qt;
2460 }
2461
2462 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2463 doc: /* Declare that the tty used by TERMINAL does not handle underlining.
2464 This is used to override the terminfo data, for certain terminals that
2465 do not really do underlining, but say that they do. This function has
2466 no effect if used on a non-tty terminal.
2467
2468 TERMINAL can be a terminal object, a frame or nil (meaning the
2469 selected frame's terminal). This function always returns nil if
2470 TERMINAL does not refer to a text-only terminal. */)
2471 (Lisp_Object terminal)
2472 {
2473 struct terminal *t = get_terminal (terminal, 1);
2474
2475 if (t->type == output_termcap)
2476 t->display_info.tty->TS_enter_underline_mode = 0;
2477 return Qnil;
2478 }
2479
2480 \f
2481
2482 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2483 doc: /* Suspend the terminal device TTY.
2484
2485 The device is restored to its default state, and Emacs ceases all
2486 access to the tty device. Frames that use the device are not deleted,
2487 but input is not read from them and if they change, their display is
2488 not updated.
2489
2490 TTY may be a terminal object, a frame, or nil for the terminal device
2491 of the currently selected frame.
2492
2493 This function runs `suspend-tty-functions' after suspending the
2494 device. The functions are run with one arg, the id of the suspended
2495 terminal device.
2496
2497 `suspend-tty' does nothing if it is called on a device that is already
2498 suspended.
2499
2500 A suspended tty may be resumed by calling `resume-tty' on it. */)
2501 (Lisp_Object tty)
2502 {
2503 struct terminal *t = get_tty_terminal (tty, 1);
2504 FILE *f;
2505
2506 if (!t)
2507 error ("Unknown tty device");
2508
2509 f = t->display_info.tty->input;
2510
2511 if (f)
2512 {
2513 /* First run `suspend-tty-functions' and then clean up the tty
2514 state because `suspend-tty-functions' might need to change
2515 the tty state. */
2516 if (!NILP (Vrun_hooks))
2517 {
2518 Lisp_Object args[2];
2519 args[0] = intern ("suspend-tty-functions");
2520 XSETTERMINAL (args[1], t);
2521 Frun_hook_with_args (2, args);
2522 }
2523
2524 reset_sys_modes (t->display_info.tty);
2525 delete_keyboard_wait_descriptor (fileno (f));
2526
2527 #ifndef MSDOS
2528 fclose (f);
2529 if (f != t->display_info.tty->output)
2530 fclose (t->display_info.tty->output);
2531 #endif
2532
2533 t->display_info.tty->input = 0;
2534 t->display_info.tty->output = 0;
2535
2536 if (FRAMEP (t->display_info.tty->top_frame))
2537 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2538
2539 }
2540
2541 /* Clear display hooks to prevent further output. */
2542 clear_tty_hooks (t);
2543
2544 return Qnil;
2545 }
2546
2547 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2548 doc: /* Resume the previously suspended terminal device TTY.
2549 The terminal is opened and reinitialized. Frames that are on the
2550 suspended terminal are revived.
2551
2552 It is an error to resume a terminal while another terminal is active
2553 on the same device.
2554
2555 This function runs `resume-tty-functions' after resuming the terminal.
2556 The functions are run with one arg, the id of the resumed terminal
2557 device.
2558
2559 `resume-tty' does nothing if it is called on a device that is not
2560 suspended.
2561
2562 TTY may be a terminal object, a frame, or nil (meaning the selected
2563 frame's terminal). */)
2564 (Lisp_Object tty)
2565 {
2566 struct terminal *t = get_tty_terminal (tty, 1);
2567 int fd;
2568
2569 if (!t)
2570 error ("Unknown tty device");
2571
2572 if (!t->display_info.tty->input)
2573 {
2574 if (get_named_tty (t->display_info.tty->name))
2575 error ("Cannot resume display while another display is active on the same device");
2576
2577 #ifdef MSDOS
2578 t->display_info.tty->output = stdout;
2579 t->display_info.tty->input = stdin;
2580 #else /* !MSDOS */
2581 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2582
2583 if (fd == -1)
2584 error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
2585
2586 if (strcmp (t->display_info.tty->name, DEV_TTY))
2587 dissociate_if_controlling_tty (fd);
2588
2589 t->display_info.tty->output = fdopen (fd, "w+");
2590 t->display_info.tty->input = t->display_info.tty->output;
2591 #endif
2592
2593 add_keyboard_wait_descriptor (fd);
2594
2595 if (FRAMEP (t->display_info.tty->top_frame))
2596 {
2597 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2598 int width, height;
2599 int old_height = FRAME_COLS (f);
2600 int old_width = FRAME_LINES (f);
2601
2602 /* Check if terminal/window size has changed while the frame
2603 was suspended. */
2604 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2605 if (width != old_width || height != old_height)
2606 change_frame_size (f, height, width, 0, 0, 0);
2607 FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2608 }
2609
2610 init_sys_modes (t->display_info.tty);
2611
2612 /* Run `resume-tty-functions'. */
2613 if (!NILP (Vrun_hooks))
2614 {
2615 Lisp_Object args[2];
2616 args[0] = intern ("resume-tty-functions");
2617 XSETTERMINAL (args[1], t);
2618 Frun_hook_with_args (2, args);
2619 }
2620 }
2621
2622 set_tty_hooks (t);
2623
2624 return Qnil;
2625 }
2626
2627 \f
2628 /***********************************************************************
2629 Mouse
2630 ***********************************************************************/
2631
2632 #ifdef HAVE_GPM
2633 void
2634 term_mouse_moveto (int x, int y)
2635 {
2636 /* TODO: how to set mouse position?
2637 const char *name;
2638 int fd;
2639 name = (const char *) ttyname (0);
2640 fd = open (name, O_WRONLY);
2641 SOME_FUNCTION (x, y, fd);
2642 close (fd);
2643 last_mouse_x = x;
2644 last_mouse_y = y; */
2645 }
2646
2647 /* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2648 void
2649 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2650 int start_hpos, int end_hpos,
2651 enum draw_glyphs_face draw)
2652 {
2653 int nglyphs = end_hpos - start_hpos;
2654 struct frame *f = XFRAME (WINDOW_FRAME (w));
2655 struct tty_display_info *tty = FRAME_TTY (f);
2656 int face_id = tty->mouse_highlight.mouse_face_face_id;
2657 int save_x, save_y, pos_x, pos_y;
2658
2659 if (end_hpos >= row->used[TEXT_AREA])
2660 nglyphs = row->used[TEXT_AREA] - start_hpos;
2661
2662 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2663 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2664
2665 /* Save current cursor co-ordinates. */
2666 save_y = curY (tty);
2667 save_x = curX (tty);
2668 cursor_to (f, pos_y, pos_x);
2669
2670 if (draw == DRAW_MOUSE_FACE)
2671 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2672 nglyphs, face_id);
2673 else if (draw == DRAW_NORMAL_TEXT)
2674 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2675
2676 cursor_to (f, save_y, save_x);
2677 }
2678
2679 static int
2680 term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2681 {
2682 /* Has the mouse moved off the glyph it was on at the last sighting? */
2683 if (event->x != last_mouse_x || event->y != last_mouse_y)
2684 {
2685 frame->mouse_moved = 1;
2686 note_mouse_highlight (frame, event->x, event->y);
2687 /* Remember which glyph we're now on. */
2688 last_mouse_x = event->x;
2689 last_mouse_y = event->y;
2690 return 1;
2691 }
2692 return 0;
2693 }
2694
2695 /* Return the current position of the mouse.
2696
2697 Set *f to the frame the mouse is in, or zero if the mouse is in no
2698 Emacs frame. If it is set to zero, all the other arguments are
2699 garbage.
2700
2701 Set *bar_window to Qnil, and *x and *y to the column and
2702 row of the character cell the mouse is over.
2703
2704 Set *time to the time the mouse was at the returned position.
2705
2706 This clears mouse_moved until the next motion
2707 event arrives. */
2708 static void
2709 term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
2710 enum scroll_bar_part *part, Lisp_Object *x,
2711 Lisp_Object *y, unsigned long *time)
2712 {
2713 struct timeval now;
2714
2715 *fp = SELECTED_FRAME ();
2716 (*fp)->mouse_moved = 0;
2717
2718 *bar_window = Qnil;
2719 *part = 0;
2720
2721 XSETINT (*x, last_mouse_x);
2722 XSETINT (*y, last_mouse_y);
2723 gettimeofday(&now, 0);
2724 *time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2725 }
2726
2727 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2728
2729 If the event is a button press, then note that we have grabbed
2730 the mouse. */
2731
2732 static Lisp_Object
2733 term_mouse_click (struct input_event *result, Gpm_Event *event,
2734 struct frame *f)
2735 {
2736 struct timeval now;
2737 int i, j;
2738
2739 result->kind = GPM_CLICK_EVENT;
2740 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2741 {
2742 if (event->buttons & j) {
2743 result->code = i; /* button number */
2744 break;
2745 }
2746 }
2747 gettimeofday(&now, 0);
2748 result->timestamp = (now.tv_sec * 1000) + (now.tv_usec / 1000);
2749
2750 if (event->type & GPM_UP)
2751 result->modifiers = up_modifier;
2752 else if (event->type & GPM_DOWN)
2753 result->modifiers = down_modifier;
2754 else
2755 result->modifiers = 0;
2756
2757 if (event->type & GPM_SINGLE)
2758 result->modifiers |= click_modifier;
2759
2760 if (event->type & GPM_DOUBLE)
2761 result->modifiers |= double_modifier;
2762
2763 if (event->type & GPM_TRIPLE)
2764 result->modifiers |= triple_modifier;
2765
2766 if (event->type & GPM_DRAG)
2767 result->modifiers |= drag_modifier;
2768
2769 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2770
2771 /* 1 << KG_SHIFT */
2772 if (event->modifiers & (1 << 0))
2773 result->modifiers |= shift_modifier;
2774
2775 /* 1 << KG_CTRL */
2776 if (event->modifiers & (1 << 2))
2777 result->modifiers |= ctrl_modifier;
2778
2779 /* 1 << KG_ALT || KG_ALTGR */
2780 if (event->modifiers & (1 << 3)
2781 || event->modifiers & (1 << 1))
2782 result->modifiers |= meta_modifier;
2783 }
2784
2785 XSETINT (result->x, event->x);
2786 XSETINT (result->y, event->y);
2787 XSETFRAME (result->frame_or_window, f);
2788 result->arg = Qnil;
2789 return Qnil;
2790 }
2791
2792 int
2793 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
2794 {
2795 struct frame *f = XFRAME (tty->top_frame);
2796 struct input_event ie;
2797 int do_help = 0;
2798 int count = 0;
2799
2800 EVENT_INIT (ie);
2801 ie.kind = NO_EVENT;
2802 ie.arg = Qnil;
2803
2804 if (event->type & (GPM_MOVE | GPM_DRAG)) {
2805 previous_help_echo_string = help_echo_string;
2806 help_echo_string = Qnil;
2807
2808 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2809
2810 if (!term_mouse_movement (f, event))
2811 help_echo_string = previous_help_echo_string;
2812
2813 /* If the contents of the global variable help_echo_string
2814 has changed, generate a HELP_EVENT. */
2815 if (!NILP (help_echo_string)
2816 || !NILP (previous_help_echo_string))
2817 do_help = 1;
2818
2819 goto done;
2820 }
2821 else {
2822 f->mouse_moved = 0;
2823 term_mouse_click (&ie, event, f);
2824 }
2825
2826 done:
2827 if (ie.kind != NO_EVENT)
2828 {
2829 kbd_buffer_store_event_hold (&ie, hold_quit);
2830 count++;
2831 }
2832
2833 if (do_help
2834 && !(hold_quit && hold_quit->kind != NO_EVENT))
2835 {
2836 Lisp_Object frame;
2837
2838 if (f)
2839 XSETFRAME (frame, f);
2840 else
2841 frame = Qnil;
2842
2843 gen_help_event (help_echo_string, frame, help_echo_window,
2844 help_echo_object, help_echo_pos);
2845 count++;
2846 }
2847
2848 return count;
2849 }
2850
2851 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2852 0, 0, 0,
2853 doc: /* Open a connection to Gpm.
2854 Gpm-mouse can only be activated for one tty at a time. */)
2855 (void)
2856 {
2857 struct frame *f = SELECTED_FRAME ();
2858 struct tty_display_info *tty
2859 = ((f)->output_method == output_termcap
2860 ? (f)->terminal->display_info.tty : NULL);
2861 Gpm_Connect connection;
2862
2863 if (!tty)
2864 error ("Gpm-mouse only works in the GNU/Linux console");
2865 if (gpm_tty == tty)
2866 return Qnil; /* Already activated, nothing to do. */
2867 if (gpm_tty)
2868 error ("Gpm-mouse can only be activated for one tty at a time");
2869
2870 connection.eventMask = ~0;
2871 connection.defaultMask = ~GPM_HARD;
2872 connection.maxMod = ~0;
2873 connection.minMod = 0;
2874 gpm_zerobased = 1;
2875
2876 if (Gpm_Open (&connection, 0) < 0)
2877 error ("Gpm-mouse failed to connect to the gpm daemon");
2878 else
2879 {
2880 gpm_tty = tty;
2881 /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
2882 to generate SIGIOs. Apparently we need to call reset_sys_modes
2883 before calling init_sys_modes. */
2884 reset_sys_modes (tty);
2885 init_sys_modes (tty);
2886 add_gpm_wait_descriptor (gpm_fd);
2887 return Qnil;
2888 }
2889 }
2890
2891 void
2892 close_gpm (int fd)
2893 {
2894 if (fd >= 0)
2895 delete_gpm_wait_descriptor (fd);
2896 while (Gpm_Close()); /* close all the stack */
2897 gpm_tty = NULL;
2898 }
2899
2900 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2901 0, 0, 0,
2902 doc: /* Close a connection to Gpm. */)
2903 (void)
2904 {
2905 struct frame *f = SELECTED_FRAME ();
2906 struct tty_display_info *tty
2907 = ((f)->output_method == output_termcap
2908 ? (f)->terminal->display_info.tty : NULL);
2909
2910 if (!tty || gpm_tty != tty)
2911 return Qnil; /* Not activated on this terminal, nothing to do. */
2912
2913 close_gpm (gpm_fd);
2914 return Qnil;
2915 }
2916 #endif /* HAVE_GPM */
2917
2918 \f
2919 #ifndef MSDOS
2920 /***********************************************************************
2921 Initialization
2922 ***********************************************************************/
2923
2924 /* Initialize the tty-dependent part of frame F. The frame must
2925 already have its device initialized. */
2926
2927 void
2928 create_tty_output (struct frame *f)
2929 {
2930 struct tty_output *t;
2931
2932 if (! FRAME_TERMCAP_P (f))
2933 abort ();
2934
2935 t = xmalloc (sizeof (struct tty_output));
2936 memset (t, 0, sizeof (struct tty_output));
2937
2938 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
2939
2940 f->output_data.tty = t;
2941 }
2942
2943 /* Delete frame F's face cache, and its tty-dependent part. */
2944
2945 static void
2946 tty_free_frame_resources (struct frame *f)
2947 {
2948 if (! FRAME_TERMCAP_P (f))
2949 abort ();
2950
2951 if (FRAME_FACE_CACHE (f))
2952 free_frame_faces (f);
2953
2954 xfree (f->output_data.tty);
2955 }
2956
2957 #else /* MSDOS */
2958
2959 /* Delete frame F's face cache. */
2960
2961 static void
2962 tty_free_frame_resources (struct frame *f)
2963 {
2964 if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
2965 abort ();
2966
2967 if (FRAME_FACE_CACHE (f))
2968 free_frame_faces (f);
2969 }
2970 #endif /* MSDOS */
2971 \f
2972 /* Reset the hooks in TERMINAL. */
2973
2974 static void
2975 clear_tty_hooks (struct terminal *terminal)
2976 {
2977 terminal->rif = 0;
2978 terminal->cursor_to_hook = 0;
2979 terminal->raw_cursor_to_hook = 0;
2980 terminal->clear_to_end_hook = 0;
2981 terminal->clear_frame_hook = 0;
2982 terminal->clear_end_of_line_hook = 0;
2983 terminal->ins_del_lines_hook = 0;
2984 terminal->insert_glyphs_hook = 0;
2985 terminal->write_glyphs_hook = 0;
2986 terminal->delete_glyphs_hook = 0;
2987 terminal->ring_bell_hook = 0;
2988 terminal->reset_terminal_modes_hook = 0;
2989 terminal->set_terminal_modes_hook = 0;
2990 terminal->update_begin_hook = 0;
2991 terminal->update_end_hook = 0;
2992 terminal->set_terminal_window_hook = 0;
2993 terminal->mouse_position_hook = 0;
2994 terminal->frame_rehighlight_hook = 0;
2995 terminal->frame_raise_lower_hook = 0;
2996 terminal->fullscreen_hook = 0;
2997 terminal->set_vertical_scroll_bar_hook = 0;
2998 terminal->condemn_scroll_bars_hook = 0;
2999 terminal->redeem_scroll_bar_hook = 0;
3000 terminal->judge_scroll_bars_hook = 0;
3001 terminal->read_socket_hook = 0;
3002 terminal->frame_up_to_date_hook = 0;
3003
3004 /* Leave these two set, or suspended frames are not deleted
3005 correctly. */
3006 terminal->delete_frame_hook = &tty_free_frame_resources;
3007 terminal->delete_terminal_hook = &delete_tty;
3008 }
3009
3010 /* Initialize hooks in TERMINAL with the values needed for a tty. */
3011
3012 static void
3013 set_tty_hooks (struct terminal *terminal)
3014 {
3015 terminal->rif = 0; /* ttys don't support window-based redisplay. */
3016
3017 terminal->cursor_to_hook = &tty_cursor_to;
3018 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3019
3020 terminal->clear_to_end_hook = &tty_clear_to_end;
3021 terminal->clear_frame_hook = &tty_clear_frame;
3022 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3023
3024 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3025
3026 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3027 terminal->write_glyphs_hook = &tty_write_glyphs;
3028 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3029
3030 terminal->ring_bell_hook = &tty_ring_bell;
3031
3032 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3033 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3034 terminal->update_begin_hook = 0; /* Not needed. */
3035 terminal->update_end_hook = &tty_update_end;
3036 terminal->set_terminal_window_hook = &tty_set_terminal_window;
3037
3038 terminal->mouse_position_hook = 0; /* Not needed. */
3039 terminal->frame_rehighlight_hook = 0; /* Not needed. */
3040 terminal->frame_raise_lower_hook = 0; /* Not needed. */
3041
3042 terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
3043 terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
3044 terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
3045 terminal->judge_scroll_bars_hook = 0; /* Not needed. */
3046
3047 terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
3048 terminal->frame_up_to_date_hook = 0; /* Not needed. */
3049
3050 terminal->delete_frame_hook = &tty_free_frame_resources;
3051 terminal->delete_terminal_hook = &delete_tty;
3052 }
3053
3054 /* Drop the controlling terminal if fd is the same device. */
3055 static void
3056 dissociate_if_controlling_tty (int fd)
3057 {
3058 #ifndef DOS_NT
3059 int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
3060 if (pgid != -1)
3061 {
3062 #if defined (USG5)
3063 setpgrp ();
3064 no_controlling_tty = 1;
3065 #elif defined (CYGWIN)
3066 setsid ();
3067 no_controlling_tty = 1;
3068 #else
3069 #ifdef TIOCNOTTY /* Try BSD ioctls. */
3070 sigblock (sigmask (SIGTTOU));
3071 fd = emacs_open (DEV_TTY, O_RDWR, 0);
3072 if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
3073 {
3074 no_controlling_tty = 1;
3075 }
3076 if (fd != -1)
3077 emacs_close (fd);
3078 sigunblock (sigmask (SIGTTOU));
3079 #else
3080 /* Unknown system. */
3081 croak ();
3082 #endif /* ! TIOCNOTTY */
3083 #endif /* ! USG */
3084 }
3085 #endif /* !DOS_NT */
3086 }
3087
3088 /* Create a termcap display on the tty device with the given name and
3089 type.
3090
3091 If NAME is NULL, then use the controlling tty, i.e., "/dev/tty".
3092 Otherwise NAME should be a path to the tty device file,
3093 e.g. "/dev/pts/7".
3094
3095 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
3096
3097 If MUST_SUCCEED is true, then all errors are fatal. */
3098
3099 struct terminal *
3100 init_tty (const char *name, const char *terminal_type, int must_succeed)
3101 {
3102 char *area = NULL;
3103 char **address = &area;
3104 int buffer_size = 4096;
3105 register char *p = NULL;
3106 int status;
3107 struct tty_display_info *tty = NULL;
3108 struct terminal *terminal = NULL;
3109 int ctty = 0; /* 1 if asked to open controlling tty. */
3110
3111 if (!terminal_type)
3112 maybe_fatal (must_succeed, 0,
3113 "Unknown terminal type",
3114 "Unknown terminal type");
3115
3116 if (name == NULL)
3117 name = DEV_TTY;
3118 if (!strcmp (name, DEV_TTY))
3119 ctty = 1;
3120
3121 /* If we already have a terminal on the given device, use that. If
3122 all such terminals are suspended, create a new one instead. */
3123 /* XXX Perhaps this should be made explicit by having init_tty
3124 always create a new terminal and separating terminal and frame
3125 creation on Lisp level. */
3126 terminal = get_named_tty (name);
3127 if (terminal)
3128 return terminal;
3129
3130 terminal = create_terminal ();
3131 #ifdef MSDOS
3132 if (been_here > 0)
3133 maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
3134 name, "");
3135 been_here = 1;
3136 tty = &the_only_display_info;
3137 #else
3138 tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
3139 #endif
3140 memset (tty, 0, sizeof (struct tty_display_info));
3141 tty->next = tty_list;
3142 tty_list = tty;
3143
3144 terminal->type = output_termcap;
3145 terminal->display_info.tty = tty;
3146 tty->terminal = terminal;
3147
3148 tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
3149 Wcm_clear (tty);
3150
3151 encode_terminal_src_size = 0;
3152 encode_terminal_dst_size = 0;
3153
3154 #ifdef HAVE_GPM
3155 terminal->mouse_position_hook = term_mouse_position;
3156 tty->mouse_highlight.mouse_face_window = Qnil;
3157 #endif
3158
3159
3160 #ifndef DOS_NT
3161 set_tty_hooks (terminal);
3162
3163 {
3164 int fd;
3165 FILE *file;
3166
3167 #ifdef O_IGNORE_CTTY
3168 if (!ctty)
3169 /* Open the terminal device. Don't recognize it as our
3170 controlling terminal, and don't make it the controlling tty
3171 if we don't have one at the moment. */
3172 fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
3173 else
3174 #else
3175 /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
3176 defined on Hurd. On other systems, we need to explicitly
3177 dissociate ourselves from the controlling tty when we want to
3178 open a frame on the same terminal. */
3179 fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
3180 #endif /* O_IGNORE_CTTY */
3181
3182 tty->name = xstrdup (name);
3183 terminal->name = xstrdup (name);
3184
3185 if (fd < 0)
3186 maybe_fatal (must_succeed, terminal,
3187 "Could not open file: %s",
3188 "Could not open file: %s",
3189 name);
3190 if (!isatty (fd))
3191 {
3192 close (fd);
3193 maybe_fatal (must_succeed, terminal,
3194 "Not a tty device: %s",
3195 "Not a tty device: %s",
3196 name);
3197 }
3198
3199 #ifndef O_IGNORE_CTTY
3200 if (!ctty)
3201 dissociate_if_controlling_tty (fd);
3202 #endif
3203
3204 file = fdopen (fd, "w+");
3205 tty->input = file;
3206 tty->output = file;
3207 }
3208
3209 tty->type = xstrdup (terminal_type);
3210
3211 add_keyboard_wait_descriptor (fileno (tty->input));
3212
3213 Wcm_clear (tty);
3214
3215 tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
3216
3217 /* On some systems, tgetent tries to access the controlling
3218 terminal. */
3219 sigblock (sigmask (SIGTTOU));
3220 status = tgetent (tty->termcap_term_buffer, terminal_type);
3221 sigunblock (sigmask (SIGTTOU));
3222
3223 if (status < 0)
3224 {
3225 #ifdef TERMINFO
3226 maybe_fatal (must_succeed, terminal,
3227 "Cannot open terminfo database file",
3228 "Cannot open terminfo database file");
3229 #else
3230 maybe_fatal (must_succeed, terminal,
3231 "Cannot open termcap database file",
3232 "Cannot open termcap database file");
3233 #endif
3234 }
3235 if (status == 0)
3236 {
3237 maybe_fatal (must_succeed, terminal,
3238 "Terminal type %s is not defined",
3239 "Terminal type %s is not defined.\n\
3240 If that is not the actual type of terminal you have,\n\
3241 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3242 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3243 #ifdef TERMINFO
3244 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3245 #else
3246 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3247 #endif
3248 terminal_type);
3249 }
3250
3251 #ifndef TERMINFO
3252 if (strlen (tty->termcap_term_buffer) >= buffer_size)
3253 abort ();
3254 buffer_size = strlen (tty->termcap_term_buffer);
3255 #endif
3256 tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
3257 tty->TS_ins_line = tgetstr ("al", address);
3258 tty->TS_ins_multi_lines = tgetstr ("AL", address);
3259 tty->TS_bell = tgetstr ("bl", address);
3260 BackTab (tty) = tgetstr ("bt", address);
3261 tty->TS_clr_to_bottom = tgetstr ("cd", address);
3262 tty->TS_clr_line = tgetstr ("ce", address);
3263 tty->TS_clr_frame = tgetstr ("cl", address);
3264 ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
3265 AbsPosition (tty) = tgetstr ("cm", address);
3266 CR (tty) = tgetstr ("cr", address);
3267 tty->TS_set_scroll_region = tgetstr ("cs", address);
3268 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
3269 RowPosition (tty) = tgetstr ("cv", address);
3270 tty->TS_del_char = tgetstr ("dc", address);
3271 tty->TS_del_multi_chars = tgetstr ("DC", address);
3272 tty->TS_del_line = tgetstr ("dl", address);
3273 tty->TS_del_multi_lines = tgetstr ("DL", address);
3274 tty->TS_delete_mode = tgetstr ("dm", address);
3275 tty->TS_end_delete_mode = tgetstr ("ed", address);
3276 tty->TS_end_insert_mode = tgetstr ("ei", address);
3277 Home (tty) = tgetstr ("ho", address);
3278 tty->TS_ins_char = tgetstr ("ic", address);
3279 tty->TS_ins_multi_chars = tgetstr ("IC", address);
3280 tty->TS_insert_mode = tgetstr ("im", address);
3281 tty->TS_pad_inserted_char = tgetstr ("ip", address);
3282 tty->TS_end_keypad_mode = tgetstr ("ke", address);
3283 tty->TS_keypad_mode = tgetstr ("ks", address);
3284 LastLine (tty) = tgetstr ("ll", address);
3285 Right (tty) = tgetstr ("nd", address);
3286 Down (tty) = tgetstr ("do", address);
3287 if (!Down (tty))
3288 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
3289 if (tgetflag ("bs"))
3290 Left (tty) = "\b"; /* can't possibly be longer! */
3291 else /* (Actually, "bs" is obsolete...) */
3292 Left (tty) = tgetstr ("le", address);
3293 if (!Left (tty))
3294 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
3295 tty->TS_pad_char = tgetstr ("pc", address);
3296 tty->TS_repeat = tgetstr ("rp", address);
3297 tty->TS_end_standout_mode = tgetstr ("se", address);
3298 tty->TS_fwd_scroll = tgetstr ("sf", address);
3299 tty->TS_standout_mode = tgetstr ("so", address);
3300 tty->TS_rev_scroll = tgetstr ("sr", address);
3301 tty->Wcm->cm_tab = tgetstr ("ta", address);
3302 tty->TS_end_termcap_modes = tgetstr ("te", address);
3303 tty->TS_termcap_modes = tgetstr ("ti", address);
3304 Up (tty) = tgetstr ("up", address);
3305 tty->TS_visible_bell = tgetstr ("vb", address);
3306 tty->TS_cursor_normal = tgetstr ("ve", address);
3307 tty->TS_cursor_visible = tgetstr ("vs", address);
3308 tty->TS_cursor_invisible = tgetstr ("vi", address);
3309 tty->TS_set_window = tgetstr ("wi", address);
3310
3311 tty->TS_enter_underline_mode = tgetstr ("us", address);
3312 tty->TS_exit_underline_mode = tgetstr ("ue", address);
3313 tty->TS_enter_bold_mode = tgetstr ("md", address);
3314 tty->TS_enter_dim_mode = tgetstr ("mh", address);
3315 tty->TS_enter_blink_mode = tgetstr ("mb", address);
3316 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
3317 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
3318 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
3319 tty->TS_exit_attribute_mode = tgetstr ("me", address);
3320
3321 MultiUp (tty) = tgetstr ("UP", address);
3322 MultiDown (tty) = tgetstr ("DO", address);
3323 MultiLeft (tty) = tgetstr ("LE", address);
3324 MultiRight (tty) = tgetstr ("RI", address);
3325
3326 /* SVr4/ANSI color suppert. If "op" isn't available, don't support
3327 color because we can't switch back to the default foreground and
3328 background. */
3329 tty->TS_orig_pair = tgetstr ("op", address);
3330 if (tty->TS_orig_pair)
3331 {
3332 tty->TS_set_foreground = tgetstr ("AF", address);
3333 tty->TS_set_background = tgetstr ("AB", address);
3334 if (!tty->TS_set_foreground)
3335 {
3336 /* SVr4. */
3337 tty->TS_set_foreground = tgetstr ("Sf", address);
3338 tty->TS_set_background = tgetstr ("Sb", address);
3339 }
3340
3341 tty->TN_max_colors = tgetnum ("Co");
3342 tty->TN_max_pairs = tgetnum ("pa");
3343
3344 tty->TN_no_color_video = tgetnum ("NC");
3345 if (tty->TN_no_color_video == -1)
3346 tty->TN_no_color_video = 0;
3347 }
3348
3349 tty_default_color_capabilities (tty, 1);
3350
3351 MagicWrap (tty) = tgetflag ("xn");
3352 /* Since we make MagicWrap terminals look like AutoWrap, we need to have
3353 the former flag imply the latter. */
3354 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
3355 terminal->memory_below_frame = tgetflag ("db");
3356 tty->TF_hazeltine = tgetflag ("hz");
3357 terminal->must_write_spaces = tgetflag ("in");
3358 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
3359 tty->TF_insmode_motion = tgetflag ("mi");
3360 tty->TF_standout_motion = tgetflag ("ms");
3361 tty->TF_underscore = tgetflag ("ul");
3362 tty->TF_teleray = tgetflag ("xt");
3363
3364 #else /* DOS_NT */
3365 #ifdef WINDOWSNT
3366 {
3367 struct frame *f = XFRAME (selected_frame);
3368
3369 initialize_w32_display (terminal);
3370
3371 FrameRows (tty) = FRAME_LINES (f);
3372 FrameCols (tty) = FRAME_COLS (f);
3373 tty->specified_window = FRAME_LINES (f);
3374
3375 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
3376 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
3377 terminal->char_ins_del_ok = 1;
3378 baud_rate = 19200;
3379 }
3380 #else /* MSDOS */
3381 {
3382 int height, width;
3383 if (strcmp (terminal_type, "internal") == 0)
3384 terminal->type = output_msdos_raw;
3385 initialize_msdos_display (terminal);
3386
3387 get_tty_size (fileno (tty->input), &width, &height);
3388 FrameCols (tty) = width;
3389 FrameRows (tty) = height;
3390 terminal->char_ins_del_ok = 0;
3391 init_baud_rate (fileno (tty->input));
3392 }
3393 #endif /* MSDOS */
3394 tty->output = stdout;
3395 tty->input = stdin;
3396 /* The following two are inaccessible from w32console.c. */
3397 terminal->delete_frame_hook = &tty_free_frame_resources;
3398 terminal->delete_terminal_hook = &delete_tty;
3399
3400 tty->name = xstrdup (name);
3401 terminal->name = xstrdup (name);
3402 tty->type = xstrdup (terminal_type);
3403
3404 add_keyboard_wait_descriptor (0);
3405
3406 tty->delete_in_insert_mode = 1;
3407
3408 UseTabs (tty) = 0;
3409 terminal->scroll_region_ok = 0;
3410
3411 /* Seems to insert lines when it's not supposed to, messing up the
3412 display. In doing a trace, it didn't seem to be called much, so I
3413 don't think we're losing anything by turning it off. */
3414 terminal->line_ins_del_ok = 0;
3415
3416 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
3417 #endif /* DOS_NT */
3418
3419 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3420 init_kboard (terminal->kboard);
3421 terminal->kboard->Vwindow_system = Qnil;
3422 terminal->kboard->next_kboard = all_kboards;
3423 all_kboards = terminal->kboard;
3424 terminal->kboard->reference_count++;
3425 /* Don't let the initial kboard remain current longer than necessary.
3426 That would cause problems if a file loaded on startup tries to
3427 prompt in the mini-buffer. */
3428 if (current_kboard == initial_kboard)
3429 current_kboard = terminal->kboard;
3430 #ifndef DOS_NT
3431 term_get_fkeys (address, terminal->kboard);
3432
3433 /* Get frame size from system, or else from termcap. */
3434 {
3435 int height, width;
3436 get_tty_size (fileno (tty->input), &width, &height);
3437 FrameCols (tty) = width;
3438 FrameRows (tty) = height;
3439 }
3440
3441 if (FrameCols (tty) <= 0)
3442 FrameCols (tty) = tgetnum ("co");
3443 if (FrameRows (tty) <= 0)
3444 FrameRows (tty) = tgetnum ("li");
3445
3446 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
3447 maybe_fatal (must_succeed, terminal,
3448 "Screen size %dx%d is too small",
3449 "Screen size %dx%d is too small",
3450 FrameCols (tty), FrameRows (tty));
3451
3452 TabWidth (tty) = tgetnum ("tw");
3453
3454 if (!tty->TS_bell)
3455 tty->TS_bell = "\07";
3456
3457 if (!tty->TS_fwd_scroll)
3458 tty->TS_fwd_scroll = Down (tty);
3459
3460 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
3461
3462 if (TabWidth (tty) < 0)
3463 TabWidth (tty) = 8;
3464
3465 /* Turned off since /etc/termcap seems to have :ta= for most terminals
3466 and newer termcap doc does not seem to say there is a default.
3467 if (!tty->Wcm->cm_tab)
3468 tty->Wcm->cm_tab = "\t";
3469 */
3470
3471 /* We don't support standout modes that use `magic cookies', so
3472 turn off any that do. */
3473 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
3474 {
3475 tty->TS_standout_mode = 0;
3476 tty->TS_end_standout_mode = 0;
3477 }
3478 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
3479 {
3480 tty->TS_enter_underline_mode = 0;
3481 tty->TS_exit_underline_mode = 0;
3482 }
3483
3484 /* If there's no standout mode, try to use underlining instead. */
3485 if (tty->TS_standout_mode == 0)
3486 {
3487 tty->TS_standout_mode = tty->TS_enter_underline_mode;
3488 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
3489 }
3490
3491 /* If no `se' string, try using a `me' string instead.
3492 If that fails, we can't use standout mode at all. */
3493 if (tty->TS_end_standout_mode == 0)
3494 {
3495 char *s = tgetstr ("me", address);
3496 if (s != 0)
3497 tty->TS_end_standout_mode = s;
3498 else
3499 tty->TS_standout_mode = 0;
3500 }
3501
3502 if (tty->TF_teleray)
3503 {
3504 tty->Wcm->cm_tab = 0;
3505 /* We can't support standout mode, because it uses magic cookies. */
3506 tty->TS_standout_mode = 0;
3507 /* But that means we cannot rely on ^M to go to column zero! */
3508 CR (tty) = 0;
3509 /* LF can't be trusted either -- can alter hpos */
3510 /* if move at column 0 thru a line with TS_standout_mode */
3511 Down (tty) = 0;
3512 }
3513
3514 /* Special handling for certain terminal types known to need it */
3515
3516 if (!strcmp (terminal_type, "supdup"))
3517 {
3518 terminal->memory_below_frame = 1;
3519 tty->Wcm->cm_losewrap = 1;
3520 }
3521 if (!strncmp (terminal_type, "c10", 3)
3522 || !strcmp (terminal_type, "perq"))
3523 {
3524 /* Supply a makeshift :wi string.
3525 This string is not valid in general since it works only
3526 for windows starting at the upper left corner;
3527 but that is all Emacs uses.
3528
3529 This string works only if the frame is using
3530 the top of the video memory, because addressing is memory-relative.
3531 So first check the :ti string to see if that is true.
3532
3533 It would be simpler if the :wi string could go in the termcap
3534 entry, but it can't because it is not fully valid.
3535 If it were in the termcap entry, it would confuse other programs. */
3536 if (!tty->TS_set_window)
3537 {
3538 p = tty->TS_termcap_modes;
3539 while (*p && strcmp (p, "\033v "))
3540 p++;
3541 if (*p)
3542 tty->TS_set_window = "\033v%C %C %C %C ";
3543 }
3544 /* Termcap entry often fails to have :in: flag */
3545 terminal->must_write_spaces = 1;
3546 /* :ti string typically fails to have \E^G! in it */
3547 /* This limits scope of insert-char to one line. */
3548 strcpy (area, tty->TS_termcap_modes);
3549 strcat (area, "\033\007!");
3550 tty->TS_termcap_modes = area;
3551 area += strlen (area) + 1;
3552 p = AbsPosition (tty);
3553 /* Change all %+ parameters to %C, to handle
3554 values above 96 correctly for the C100. */
3555 while (*p)
3556 {
3557 if (p[0] == '%' && p[1] == '+')
3558 p[1] = 'C';
3559 p++;
3560 }
3561 }
3562
3563 tty->specified_window = FrameRows (tty);
3564
3565 if (Wcm_init (tty) == -1) /* can't do cursor motion */
3566 {
3567 maybe_fatal (must_succeed, terminal,
3568 "Terminal type \"%s\" is not powerful enough to run Emacs",
3569 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
3570 It lacks the ability to position the cursor.\n\
3571 If that is not the actual type of terminal you have,\n\
3572 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3573 `setenv TERM ...') to specify the correct type. It may be necessary\n"
3574 # ifdef TERMINFO
3575 "to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
3576 # else /* TERMCAP */
3577 "to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
3578 # endif /* TERMINFO */
3579 terminal_type);
3580 }
3581
3582 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
3583 maybe_fatal (must_succeed, terminal,
3584 "Could not determine the frame size",
3585 "Could not determine the frame size");
3586
3587 tty->delete_in_insert_mode
3588 = tty->TS_delete_mode && tty->TS_insert_mode
3589 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
3590
3591 tty->se_is_so = (tty->TS_standout_mode
3592 && tty->TS_end_standout_mode
3593 && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
3594
3595 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
3596
3597 terminal->scroll_region_ok
3598 = (tty->Wcm->cm_abs
3599 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
3600
3601 terminal->line_ins_del_ok
3602 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
3603 && (tty->TS_del_line || tty->TS_del_multi_lines))
3604 || (terminal->scroll_region_ok
3605 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
3606
3607 terminal->char_ins_del_ok
3608 = ((tty->TS_ins_char || tty->TS_insert_mode
3609 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
3610 && (tty->TS_del_char || tty->TS_del_multi_chars));
3611
3612 terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
3613
3614 init_baud_rate (fileno (tty->input));
3615
3616 #endif /* not DOS_NT */
3617
3618 /* Init system terminal modes (RAW or CBREAK, etc.). */
3619 init_sys_modes (tty);
3620
3621 return terminal;
3622 }
3623
3624
3625 static void
3626 vfatal (const char *str, va_list ap)
3627 {
3628 fprintf (stderr, "emacs: ");
3629 vfprintf (stderr, str, ap);
3630 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n'))
3631 fprintf (stderr, "\n");
3632 va_end (ap);
3633 fflush (stderr);
3634 exit (1);
3635 }
3636
3637
3638 /* Auxiliary error-handling function for init_tty.
3639 Delete TERMINAL, then call error or fatal with str1 or str2,
3640 respectively, according to MUST_SUCCEED. */
3641
3642 static void
3643 maybe_fatal (int must_succeed, struct terminal *terminal,
3644 const char *str1, const char *str2, ...)
3645 {
3646 va_list ap;
3647 va_start (ap, str2);
3648 if (terminal)
3649 delete_tty (terminal);
3650
3651 if (must_succeed)
3652 vfatal (str2, ap);
3653 else
3654 verror (str1, ap);
3655
3656 va_end (ap);
3657 abort ();
3658 }
3659
3660 void
3661 fatal (const char *str, ...)
3662 {
3663 va_list ap;
3664 va_start (ap, str);
3665 vfatal (str, ap);
3666 va_end (ap);
3667 }
3668
3669 \f
3670
3671 /* Delete the given tty terminal, closing all frames on it. */
3672
3673 static void
3674 delete_tty (struct terminal *terminal)
3675 {
3676 struct tty_display_info *tty;
3677
3678 /* Protect against recursive calls. delete_frame in
3679 delete_terminal calls us back when it deletes our last frame. */
3680 if (!terminal->name)
3681 return;
3682
3683 if (terminal->type != output_termcap)
3684 abort ();
3685
3686 tty = terminal->display_info.tty;
3687
3688 if (tty == tty_list)
3689 tty_list = tty->next;
3690 else
3691 {
3692 struct tty_display_info *p;
3693 for (p = tty_list; p && p->next != tty; p = p->next)
3694 ;
3695
3696 if (! p)
3697 /* This should not happen. */
3698 abort ();
3699
3700 p->next = tty->next;
3701 tty->next = 0;
3702 }
3703
3704 /* reset_sys_modes needs a valid device, so this call needs to be
3705 before delete_terminal. */
3706 reset_sys_modes (tty);
3707
3708 delete_terminal (terminal);
3709
3710 xfree (tty->name);
3711 xfree (tty->type);
3712
3713 if (tty->input)
3714 {
3715 delete_keyboard_wait_descriptor (fileno (tty->input));
3716 if (tty->input != stdin)
3717 fclose (tty->input);
3718 }
3719 if (tty->output && tty->output != stdout && tty->output != tty->input)
3720 fclose (tty->output);
3721 if (tty->termscript)
3722 fclose (tty->termscript);
3723
3724 xfree (tty->old_tty);
3725 xfree (tty->Wcm);
3726 xfree (tty->termcap_strings_buffer);
3727 xfree (tty->termcap_term_buffer);
3728
3729 memset (tty, 0, sizeof (struct tty_display_info));
3730 xfree (tty);
3731 }
3732
3733 \f
3734
3735 /* Mark the pointers in the tty_display_info objects.
3736 Called by the Fgarbage_collector. */
3737
3738 void
3739 mark_ttys (void)
3740 {
3741 struct tty_display_info *tty;
3742
3743 for (tty = tty_list; tty; tty = tty->next)
3744 mark_object (tty->top_frame);
3745 }
3746
3747 \f
3748
3749 void
3750 syms_of_term (void)
3751 {
3752 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
3753 doc: /* Non-nil means the system uses terminfo rather than termcap.
3754 This variable can be used by terminal emulator packages. */);
3755 #ifdef TERMINFO
3756 system_uses_terminfo = 1;
3757 #else
3758 system_uses_terminfo = 0;
3759 #endif
3760
3761 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions,
3762 doc: /* Functions to be run after suspending a tty.
3763 The functions are run with one argument, the terminal object to be suspended.
3764 See `suspend-tty'. */);
3765 Vsuspend_tty_functions = Qnil;
3766
3767
3768 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions,
3769 doc: /* Functions to be run after resuming a tty.
3770 The functions are run with one argument, the terminal object that was revived.
3771 See `resume-tty'. */);
3772 Vresume_tty_functions = Qnil;
3773
3774 DEFVAR_BOOL ("visible-cursor", visible_cursor,
3775 doc: /* Non-nil means to make the cursor very visible.
3776 This only has an effect when running in a text terminal.
3777 What means \"very visible\" is up to your terminal. It may make the cursor
3778 bigger, or it may make it blink, or it may do nothing at all. */);
3779 visible_cursor = 1;
3780
3781 defsubr (&Stty_display_color_p);
3782 defsubr (&Stty_display_color_cells);
3783 defsubr (&Stty_no_underline);
3784 defsubr (&Stty_type);
3785 defsubr (&Scontrolling_tty_p);
3786 defsubr (&Ssuspend_tty);
3787 defsubr (&Sresume_tty);
3788 #ifdef HAVE_GPM
3789 defsubr (&Sgpm_mouse_start);
3790 defsubr (&Sgpm_mouse_stop);
3791 #endif /* HAVE_GPM */
3792
3793 #ifndef DOS_NT
3794 default_orig_pair = NULL;
3795 default_set_foreground = NULL;
3796 default_set_background = NULL;
3797 #endif /* !DOS_NT */
3798
3799 encode_terminal_src = NULL;
3800 encode_terminal_dst = NULL;
3801 }