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