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