comparison src/redisplay-tty.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 8de8e3f6228a
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /* Communication module for TTY terminals.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1996 Chuck Thompson.
6
7 This file is part of XEmacs.
8
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 /* Synched up with: Not completely synched with FSF. Mostly divergent
25 from FSF. */
26
27 /* This file has been Mule-ized. */
28
29 /* Written by Chuck Thompson. */
30 /* Color support added by Ben Wing. */
31
32 #include <config.h>
33 #include "lisp.h"
34
35 #include "buffer.h"
36 #include "console-tty.h"
37 #include "events.h"
38 #include "faces.h"
39 #include "frame.h"
40 #include "glyphs.h"
41 #include "lstream.h"
42 #include "objects-tty.h"
43 #include "redisplay.h"
44 #include "sysdep.h"
45 #include "window.h"
46
47 /* These headers #define all kinds of common words like "columns"...
48 What a bunch of losers. If we were to include them, we'd have to
49 include them last to prevent them from messing up our own header
50 files (struct slot names, etc.). But it turns out that there are
51 other conflicts as well on some systems, so screw it: we'll just
52 re-declare the routines we use and assume the code in this file is
53 invoking them correctly. */
54 /* # include <curses.h> */
55 /* # include <term.h> */
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59 extern int tgetent (CONST char *, CONST char *);
60 extern int tgetflag (CONST char *);
61 extern int tgetnum (CONST char *);
62 extern char *tgetstr (CONST char *, char **);
63 extern void tputs (CONST char *, int, void (*)(int));
64 #ifdef __cplusplus
65 }
66 #endif
67 #define FORCE_CURSOR_UPDATE(c) send_string_to_tty_console (c, 0, 0)
68 #define OUTPUTN(c, a, n) \
69 do { \
70 cmputc_console = c; \
71 FORCE_CURSOR_UPDATE (c); \
72 tputs (a, n, cmputc); \
73 } while (0)
74 #define OUTPUT1(c, a) OUTPUTN (c, a, 1)
75 #define OUTPUTN_IF(c, a, n) \
76 do { \
77 cmputc_console = c; \
78 FORCE_CURSOR_UPDATE (c); \
79 if (a) \
80 tputs (a, n, cmputc); \
81 } while (0)
82 #define OUTPUT1_IF(c, a) OUTPUTN_IF (c, a, 1)
83
84 static void tty_output_emchar_dynarr (struct window *w,
85 struct display_line *dl,
86 Emchar_dynarr *buf, int xpos,
87 face_index findex,
88 int cursor);
89 static void tty_output_bufbyte_string (struct window *w,
90 struct display_line *dl,
91 Bufbyte *str, Bytecount len,
92 int xpos, face_index findex,
93 int cursor);
94 static void tty_turn_on_face (struct window *w, face_index findex);
95 static void tty_turn_off_face (struct window *w, face_index findex);
96 static void tty_turn_on_frame_face (struct frame *f, Lisp_Object face);
97 static void tty_turn_off_frame_face (struct frame *f, Lisp_Object face);
98
99 static void term_get_fkeys (Lisp_Object keymap, char **address);
100
101 /*****************************************************************************
102 tty_text_width
103
104 Non-Mule tty's don't have fonts (that we use at least), so everything
105 is considered to be fixed width -- in other words, we return LEN.
106 Under Mule, however, a character can still cover more than one
107 column, so we use emchar_string_displayed_columns().
108 ****************************************************************************/
109 static int
110 tty_text_width (struct frame *f, struct face_cachel *cachel, CONST Emchar *str,
111 Charcount len)
112 {
113 return emchar_string_displayed_columns (str, len);
114 }
115
116 /*****************************************************************************
117 tty_divider_height
118
119 Return the width of the horizontal divider. This is a function
120 because divider_height is a console method.
121 ****************************************************************************/
122 static int
123 tty_divider_height (void)
124 {
125 return 1;
126 }
127
128 /*****************************************************************************
129 tty_eol_cursor_width
130
131 Return the width of the end-of-line cursor. This is a function
132 because eol_cursor_width is a console method.
133 ****************************************************************************/
134 static int
135 tty_eol_cursor_width (void)
136 {
137 return 1;
138 }
139
140 /*****************************************************************************
141 tty_output_begin
142
143 Perform any necessary initialization prior to an update.
144 ****************************************************************************/
145 #ifdef DEBUG_XEMACS
146 void tty_output_begin (struct device *d);
147 void
148 #else
149 static void
150 #endif
151 tty_output_begin (struct device *d)
152 {
153 #ifndef HAVE_TERMIOS
154 /* Termcap requires `ospeed' to be a global variable so we have to
155 always set it for whatever tty console we are actually currently
156 working with. */
157 ospeed = DEVICE_TTY_DATA (d)->ospeed;
158 #endif
159 }
160
161 /*****************************************************************************
162 tty_output_end
163
164 Perform any necessary flushing of queues when an update has completed.
165 ****************************************************************************/
166 #ifdef DEBUG_XEMACS
167 void tty_output_end (struct device *d);
168 void
169 #else
170 static void
171 #endif
172 tty_output_end (struct device *d)
173 {
174 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
175
176 CONSOLE_TTY_CURSOR_X (c) = CONSOLE_TTY_FINAL_CURSOR_X (c);
177 CONSOLE_TTY_CURSOR_Y (c) = CONSOLE_TTY_FINAL_CURSOR_Y (c);
178 FORCE_CURSOR_UPDATE (c);
179 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream));
180 }
181
182 static void
183 tty_set_final_cursor_coords (struct frame *f, int y, int x)
184 {
185 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
186
187 CONSOLE_TTY_FINAL_CURSOR_X (c) = x;
188 CONSOLE_TTY_FINAL_CURSOR_Y (c) = y;
189 }
190
191 /*****************************************************************************
192 tty_output_display_block
193
194 Given a display line, a block number for that start line, output all
195 runes between start and end in the specified display block.
196 ****************************************************************************/
197 static void
198 tty_output_display_block (struct window *w, struct display_line *dl, int block,
199 int start, int end, int start_pixpos,
200 int cursor_start, int cursor_width,
201 int cursor_height)
202 {
203 struct frame *f = XFRAME (w->frame);
204 Emchar_dynarr *buf = Dynarr_new (Emchar);
205
206 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
207 rune_dynarr *rba = db->runes;
208 struct rune *rb;
209
210 int elt = start;
211 face_index findex;
212 int xpos;
213
214 rb = Dynarr_atp (rba, elt);
215
216 if (!rb)
217 {
218 /* Nothing to do so don't do anything. */
219 return;
220 }
221 else
222 {
223 findex = rb->findex;
224 xpos = rb->xpos;
225 }
226
227 if (end < 0)
228 end = Dynarr_length (rba);
229
230 Dynarr_reset (buf);
231
232 while (elt < end && Dynarr_atp (rba, elt)->xpos < start_pixpos)
233 {
234 elt++;
235 findex = Dynarr_atp (rba, elt)->findex;
236 xpos = Dynarr_atp (rba, elt)->xpos;
237 }
238
239 while (elt < end)
240 {
241 rb = Dynarr_atp (rba, elt);
242
243 if (rb->findex == findex && rb->type == RUNE_CHAR
244 && rb->object.chr.ch != '\n'
245 && (rb->cursor_type != CURSOR_ON
246 || NILP (w->text_cursor_visible_p)))
247 {
248 Dynarr_add (buf, rb->object.chr.ch);
249 elt++;
250 }
251 else
252 {
253 if (Dynarr_length (buf))
254 {
255 tty_output_emchar_dynarr (w, dl, buf, xpos, findex, 0);
256 xpos = rb->xpos;
257 }
258 Dynarr_reset (buf);
259
260 if (rb->type == RUNE_CHAR)
261 {
262 findex = rb->findex;
263 xpos = rb->xpos;
264
265 if (rb->object.chr.ch == '\n')
266 {
267 /* Clear in case a cursor was formerly here. */
268
269 Dynarr_add (buf, ' ');
270 tty_output_emchar_dynarr (w, dl, buf, rb->xpos,
271 DEFAULT_INDEX, 0);
272 Dynarr_reset (buf);
273
274 cmgoto (f, dl->ypos - 1, rb->xpos);
275
276 elt++;
277 }
278 else if (rb->cursor_type == CURSOR_ON)
279 {
280 /* There is not a distinct eol cursor on tty's. */
281
282 Dynarr_add (buf, rb->object.chr.ch);
283 tty_output_emchar_dynarr (w, dl, buf, xpos, findex, 0);
284 Dynarr_reset (buf);
285
286 cmgoto (f, dl->ypos - 1, xpos);
287
288 xpos += rb->width;
289 elt++;
290 }
291 }
292 /* #### RUNE_HLINE is actually a little more complicated than this
293 but at the moment it is only used to draw a turned off
294 modeline and this will suffice for that. */
295 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE)
296 {
297 Emchar ch_to_add;
298 int size = rb->width;
299
300 if (rb->type == RUNE_BLANK)
301 ch_to_add = ' ';
302 else
303 ch_to_add = '-';
304
305 while (size--)
306 Dynarr_add (buf, ch_to_add);
307 tty_output_emchar_dynarr (w, dl, buf, rb->xpos, findex, 0);
308
309 if (xpos >= cursor_start
310 && cursor_start < xpos + Dynarr_length (buf))
311 {
312 cmgoto (f, dl->ypos - 1, cursor_start);
313 }
314
315 Dynarr_reset (buf);
316
317 elt++;
318 if (elt < end)
319 {
320 rb = Dynarr_atp (rba, elt);
321
322 findex = rb->findex;
323 xpos = rb->xpos;
324 }
325 }
326 else if (rb->type == RUNE_DGLYPH)
327 {
328 Lisp_Object window;
329 Lisp_Object instance;
330
331 XSETWINDOW (window, w);
332 instance = glyph_image_instance (rb->object.dglyph.glyph,
333 window, ERROR_ME_NOT, 1);
334
335 if (IMAGE_INSTANCEP (instance))
336 switch (XIMAGE_INSTANCE_TYPE (instance))
337 {
338 case IMAGE_TEXT:
339 {
340 Bufbyte *temptemp;
341 Lisp_Object string =
342 XIMAGE_INSTANCE_TEXT_STRING (instance);
343 Bytecount len = XSTRING_LENGTH (string);
344
345 /* In the unlikely instance that a garbage-collect
346 occurs during encoding, we at least need to
347 copy the string.
348 */
349 temptemp = (Bufbyte *) alloca (len);
350 memcpy (temptemp, XSTRING_DATA (string), len);
351 {
352 int i;
353
354 /* Now truncate the first rb->object.dglyph.xoffset
355 columns. */
356 for (i = 0; i < rb->object.dglyph.xoffset;)
357 {
358 #ifdef MULE
359 Emchar ch = charptr_emchar (temptemp);
360 i += XCHARSET_COLUMNS (CHAR_CHARSET (ch));
361 #else
362 i++; /* telescope this */
363 #endif
364 INC_CHARPTR (temptemp);
365 }
366
367 /* If we truncated one column too many, then
368 add a space at the beginning. */
369 if (i > rb->object.dglyph.xoffset)
370 {
371 assert (i > 0);
372 *--temptemp = ' ';
373 i--;
374 }
375 len -= i;
376 }
377
378 tty_output_bufbyte_string (w, dl, temptemp, len,
379 xpos, findex, 0);
380
381 if (xpos >= cursor_start
382 && (cursor_start <
383 xpos + (bufbyte_string_displayed_columns
384 (temptemp, len))))
385 {
386 cmgoto (f, dl->ypos - 1, cursor_start);
387 }
388 }
389 break;
390
391 case IMAGE_MONO_PIXMAP:
392 case IMAGE_COLOR_PIXMAP:
393 case IMAGE_SUBWINDOW:
394 case IMAGE_WIDGET:
395 case IMAGE_LAYOUT:
396 /* just do nothing here */
397 break;
398
399 case IMAGE_POINTER:
400 abort ();
401
402 case IMAGE_NOTHING:
403 /* nothing is as nothing does */
404 break;
405
406 default:
407 abort ();
408 }
409
410 xpos += rb->width;
411 elt++;
412 }
413 else
414 abort ();
415 }
416 }
417
418 if (Dynarr_length (buf))
419 tty_output_emchar_dynarr (w, dl, buf, xpos, findex, 0);
420 Dynarr_free (buf);
421
422 }
423
424
425
426 /*****************************************************************************
427 tty_output_vertical_divider
428
429 Draw a vertical divider down the right side of the given window.
430 ****************************************************************************/
431 static void
432 tty_output_vertical_divider (struct window *w, int clear)
433 {
434 /* Divider width can either be 0 or 1 on TTYs */
435 if (window_divider_width (w))
436 {
437 struct frame *f = XFRAME (w->frame);
438 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
439 int line;
440 int y_top = WINDOW_TEXT_TOP (w);
441 int y_bot = WINDOW_TEXT_BOTTOM (w);
442 unsigned char divv = '|';
443
444 tty_turn_on_face (w, MODELINE_INDEX);
445 for (line = y_top; line < y_bot; line++)
446 {
447 cmgoto (f, line, WINDOW_TEXT_RIGHT (w));
448 send_string_to_tty_console (c, &divv, 1);
449 TTY_INC_CURSOR_X (c, 1);
450 }
451
452 /* Draw the divider in the modeline. */
453 cmgoto (f, y_bot, WINDOW_TEXT_RIGHT (w));
454 send_string_to_tty_console (c, &divv, 1);
455 TTY_INC_CURSOR_X (c, 1);
456 tty_turn_off_face (w, MODELINE_INDEX);
457 }
458 }
459
460 /****************************************************************************
461 tty_clear_region
462
463 Clear the area in the box defined by the given parameters.
464 ****************************************************************************/
465 static void
466 tty_clear_region (Lisp_Object window, struct device* d, struct frame * f,
467 face_index findex, int x, int y,
468 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
469 Lisp_Object background_pixmap)
470 {
471 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
472 int line;
473 struct window* w = XWINDOW (window);
474
475 tty_turn_on_face (w, findex);
476 for (line = y; line < y + height; line++)
477 {
478 int col;
479
480 cmgoto (f, line, x);
481
482 if (window_is_leftmost (w)
483 && window_is_rightmost (w)
484 && TTY_SE (c).clr_to_eol)
485 {
486 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
487 }
488 else
489 {
490 unsigned char sp = ' ';
491 /* #### Of course, this is all complete and utter crap. */
492 for (col = x; col < x + width; col++)
493 send_string_to_tty_console (c, &sp, 1);
494 TTY_INC_CURSOR_X (c, width);
495 }
496 }
497 tty_turn_off_face (w, findex);
498 cmgoto (f, y, x);
499 }
500
501 /*****************************************************************************
502 tty_clear_to_window_end
503
504 Clear the area between ypos1 and ypos2. Each margin area and the
505 text area is handled separately since they may each have their own
506 background color.
507 ****************************************************************************/
508 static void
509 tty_clear_to_window_end (struct window *w, int ypos1, int ypos2)
510 {
511 struct frame *f = XFRAME (w->frame);
512 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
513 int x, width;
514
515 x = WINDOW_TEXT_LEFT (w);
516 width = WINDOW_TEXT_WIDTH (w);
517
518 if (window_is_rightmost (w))
519 {
520 /* #### Optimize to use clr_to_eol function of tty if available, if
521 the window is the entire width of the frame. */
522 /* #### Is this actually an optimization? */
523 int line;
524 tty_turn_on_face (w, DEFAULT_INDEX);
525 for (line = ypos1; line < ypos2; line++)
526 {
527 cmgoto (XFRAME (w->frame), line, x);
528 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
529 }
530 tty_turn_off_face (w, DEFAULT_INDEX);
531 }
532 else
533 {
534 Lisp_Object window;
535
536 XSETWINDOW (window, w);
537 redisplay_clear_region (window, DEFAULT_INDEX, x, ypos1, width, ypos2 - ypos1);
538 }
539 }
540
541 /****************************************************************************
542 tty_clear_frame
543
544 Clear the entire frame.
545 ****************************************************************************/
546 static void
547 tty_clear_frame (struct frame *f)
548 {
549 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
550
551 tty_turn_on_frame_face (f, Vdefault_face);
552 if (TTY_SE (c).clr_frame)
553 {
554 OUTPUT1 (c, TTY_SE (c).clr_frame);
555 CONSOLE_TTY_REAL_CURSOR_X (c) = 0;
556 CONSOLE_TTY_REAL_CURSOR_Y (c) = 0;
557 #ifdef NOT_SURE
558 FRAME_CURSOR_X (f) = 0;
559 FRAME_CURSOR_Y (f) = 0;
560 #endif
561 }
562 else
563 {
564 #ifdef NOT_SURE
565 internal_cursor_to (f, 0, 0);
566 clear_to_end (f);
567 #else
568 /* #### Not implemented. */
569 fprintf (stderr, "Not yet.\n");
570 #endif
571 }
572 tty_turn_off_frame_face (f, Vdefault_face);
573 }
574
575 static void
576 tty_output_bufbyte_string (struct window *w, struct display_line *dl,
577 Bufbyte *str, Bytecount len, int xpos,
578 face_index findex, int cursor)
579 {
580 struct frame *f = XFRAME (w->frame);
581 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
582
583 /* First position the cursor. */
584 cmgoto (f, dl->ypos - 1, xpos);
585
586 /* Enable any face properties. */
587 tty_turn_on_face (w, findex);
588
589 send_string_to_tty_console (c, str, len);
590 TTY_INC_CURSOR_X (c, bufbyte_string_displayed_columns (str, len));
591
592 /* Turn the face properties back off. */
593 tty_turn_off_face (w, findex);
594 }
595
596 static Bufbyte_dynarr *tty_output_emchar_dynarr_dynarr;
597
598 /*****************************************************************************
599 tty_output_emchar_dynarr
600
601 Given a string and a starting position, output that string in the
602 given face. If cursor is true, draw a cursor around the string.
603 ****************************************************************************/
604 static void
605 tty_output_emchar_dynarr (struct window *w, struct display_line *dl,
606 Emchar_dynarr *buf, int xpos, face_index findex,
607 int cursor)
608 {
609 if (!tty_output_emchar_dynarr_dynarr)
610 tty_output_emchar_dynarr_dynarr = Dynarr_new (Bufbyte);
611 else
612 Dynarr_reset (tty_output_emchar_dynarr_dynarr);
613
614 convert_emchar_string_into_bufbyte_dynarr (Dynarr_atp (buf, 0),
615 Dynarr_length (buf),
616 tty_output_emchar_dynarr_dynarr);
617
618 tty_output_bufbyte_string (w, dl,
619 Dynarr_atp (tty_output_emchar_dynarr_dynarr, 0),
620 Dynarr_length (tty_output_emchar_dynarr_dynarr),
621 xpos, findex, cursor);
622 }
623
624 #if 0
625
626 static Bufbyte_dynarr *sidcs_dynarr;
627
628 static void
629 substitute_in_dynamic_color_string (Lisp_Object spec, Lisp_Object string)
630 {
631 int i;
632 Bufbyte *specdata = XSTRING_DATA (spec);
633 Bytecount speclen = XSTRING_LENGTH (spec);
634
635 if (!sidcs_dynarr)
636 sidcs_dynarr = Dynarr_new (Bufbyte);
637 else
638 Dynarr_reset (sidcs_dynarr);
639
640 for (i = 0; i < speclen; i++)
641 {
642 if (specdata[i] == '%' && specdata[i+1] == '%')
643 {
644 Dynarr_add (sidcs_dynarr, '%');
645 i++;
646 }
647 else if (specdata[i] == '%' && specdata[i+1] == 's')
648 {
649 Dynarr_add_many (sidcs_dynarr,
650 XSTRING_DATA (string),
651 XSTRING_LENGTH (string));
652 i++;
653 }
654 else
655 Dynarr_add (sidcs_dynarr, specdata[i]);
656 }
657 }
658
659 #endif
660
661 static void
662 set_foreground_to (struct console *c, Lisp_Object sym)
663 {
664 Lisp_Object result;
665 Bufbyte *escseq = 0;
666 Bytecount escseqlen = 0;
667
668 result = assq_no_quit (sym, Vtty_color_alist);
669 if (!NILP (result))
670 {
671 Lisp_Object esc_seq = XCAR (XCDR (result));
672 escseq = XSTRING_DATA (esc_seq);
673 escseqlen = XSTRING_LENGTH (esc_seq);
674 }
675 #if 0
676 else if (STRINGP (Vtty_dynamic_color_fg))
677 {
678 substitute_in_dynamic_color_string (Vtty_dynamic_color_fg,
679 Fsymbol_name (sym));
680 escseq = Dynarr_atp (sidcs_dynarr, 0);
681 escseqlen = Dynarr_length (sidcs_dynarr);
682 }
683 #endif
684
685 if (escseq)
686 {
687 send_string_to_tty_console (c, escseq, escseqlen);
688 }
689 }
690
691 static void
692 set_background_to (struct console *c, Lisp_Object sym)
693 {
694 Lisp_Object result;
695 Bufbyte *escseq = 0;
696 Bytecount escseqlen = 0;
697
698 result = assq_no_quit (sym, Vtty_color_alist);
699 if (!NILP (result))
700 {
701 Lisp_Object esc_seq = XCDR (XCDR (result));
702 escseq = XSTRING_DATA (esc_seq);
703 escseqlen = XSTRING_LENGTH (esc_seq);
704 }
705 #if 0
706 else if (STRINGP (Vtty_dynamic_color_bg))
707 {
708 substitute_in_dynamic_color_string (Vtty_dynamic_color_bg,
709 Fsymbol_name (sym));
710 escseq = Dynarr_atp (sidcs_dynarr, 0);
711 escseqlen = Dynarr_length (sidcs_dynarr);
712 }
713 #endif
714
715 if (escseq)
716 {
717 send_string_to_tty_console (c, escseq, escseqlen);
718 }
719 }
720
721 static void
722 tty_turn_on_face_1 (struct console *c, int highlight_p,
723 int blinking_p, int dim_p, int underline_p,
724 int reverse_p, Lisp_Object cinst_fore,
725 Lisp_Object cinst_back)
726 {
727 if (highlight_p)
728 {
729 OUTPUT1_IF (c, TTY_SD (c).turn_on_bold);
730 }
731
732 if (blinking_p)
733 {
734 OUTPUT1_IF (c, TTY_SD (c).turn_on_blinking);
735 }
736
737 if (dim_p)
738 {
739 OUTPUT1_IF (c, TTY_SD (c).turn_on_dim);
740 }
741
742 if (underline_p)
743 {
744 /* #### punt for now if underline mode is glitchy */
745 if (!TTY_FLAGS (c).underline_width)
746 {
747 OUTPUT1_IF (c, TTY_SD (c).begin_underline);
748 }
749 }
750
751 if (reverse_p)
752 {
753 /* #### punt for now if standout mode is glitchy */
754 if (!TTY_FLAGS (c).standout_width)
755 {
756 OUTPUT1_IF (c, TTY_SD (c).begin_standout);
757 }
758 else
759 reverse_p = 0;
760 }
761
762 if (reverse_p)
763 {
764 Lisp_Object temp = cinst_fore;
765 cinst_fore = cinst_back;
766 cinst_back = temp;
767 }
768
769 if (COLOR_INSTANCEP (cinst_fore)
770 && !EQ (cinst_fore, Vthe_null_color_instance))
771 set_foreground_to (c, COLOR_INSTANCE_TTY_SYMBOL
772 (XCOLOR_INSTANCE (cinst_fore)));
773
774 if (COLOR_INSTANCEP (cinst_back)
775 && !EQ (cinst_back, Vthe_null_color_instance))
776 set_background_to (c, COLOR_INSTANCE_TTY_SYMBOL
777 (XCOLOR_INSTANCE (cinst_back)));
778 }
779
780 /*****************************************************************************
781 tty_turn_on_face
782
783 Turn on all set properties of the given face.
784 ****************************************************************************/
785 static void
786 tty_turn_on_face (struct window *w, face_index findex)
787 {
788 struct frame *f = XFRAME (w->frame);
789 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
790
791 tty_turn_on_face_1 (c,
792 WINDOW_FACE_CACHEL_HIGHLIGHT_P (w, findex),
793 WINDOW_FACE_CACHEL_BLINKING_P (w, findex),
794 WINDOW_FACE_CACHEL_DIM_P (w, findex),
795 WINDOW_FACE_CACHEL_UNDERLINE_P (w, findex),
796 WINDOW_FACE_CACHEL_REVERSE_P (w, findex),
797 WINDOW_FACE_CACHEL_FOREGROUND (w, findex),
798 WINDOW_FACE_CACHEL_BACKGROUND (w, findex));
799 }
800
801 /*****************************************************************************
802 tty_turn_off_face
803
804 Turn off all set properties of the given face (revert to default
805 face). We assume that tty_turn_on_face has been called for the given
806 face so that its properties are actually active.
807 ****************************************************************************/
808 static void
809 tty_turn_off_face (struct window *w, face_index findex)
810 {
811 struct frame *f = XFRAME (w->frame);
812 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
813
814 if (WINDOW_FACE_CACHEL_REVERSE_P (w, findex))
815 {
816 /* #### punt for now if standout mode is glitchy */
817 if (!TTY_FLAGS (c).standout_width)
818 {
819 OUTPUT1_IF (c, TTY_SD (c).end_standout);
820 }
821 }
822
823 if (WINDOW_FACE_CACHEL_UNDERLINE_P (w, findex))
824 {
825 /* #### punt for now if underline mode is glitchy */
826 if (!TTY_FLAGS (c).underline_width)
827 {
828 OUTPUT1_IF (c, TTY_SD (c).end_underline);
829 }
830 }
831
832 if (WINDOW_FACE_CACHEL_HIGHLIGHT_P (w, findex) ||
833 WINDOW_FACE_CACHEL_BLINKING_P (w, findex) ||
834 WINDOW_FACE_CACHEL_DIM_P (w, findex) ||
835 !EQ (WINDOW_FACE_CACHEL_FOREGROUND (w, findex),
836 Vthe_null_color_instance) ||
837 !EQ (WINDOW_FACE_CACHEL_BACKGROUND (w, findex),
838 Vthe_null_color_instance))
839 {
840 OUTPUT1_IF (c, TTY_SD (c).turn_off_attributes);
841 }
842 }
843
844 /*****************************************************************************
845 tty_turn_on_frame_face
846
847 Turn on all set properties of the given face.
848 ****************************************************************************/
849 static void
850 tty_turn_on_frame_face (struct frame *f, Lisp_Object face)
851 {
852 Lisp_Object frame;
853 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
854
855 XSETFRAME (frame, f);
856 tty_turn_on_face_1 (c,
857 FACE_HIGHLIGHT_P (face, frame),
858 FACE_BLINKING_P (face, frame),
859 FACE_DIM_P (face, frame),
860 FACE_UNDERLINE_P (face, frame),
861 FACE_REVERSE_P (face, frame),
862 FACE_FOREGROUND (face, frame),
863 FACE_BACKGROUND (face, frame));
864 }
865
866 /*****************************************************************************
867 tty_turn_off_frame_face
868
869 Turn off all set properties of the given face (revert to default
870 face). We assume that tty_turn_on_face has been called for the given
871 face so that its properties are actually active.
872 ****************************************************************************/
873 static void
874 tty_turn_off_frame_face (struct frame *f, Lisp_Object face)
875 {
876 Lisp_Object frame;
877 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
878
879 XSETFRAME (frame, f);
880
881 if (FACE_REVERSE_P (face, frame))
882 {
883 /* #### punt for now if standout mode is glitchy */
884 if (!TTY_FLAGS (c).standout_width)
885 {
886 OUTPUT1_IF (c, TTY_SD (c).end_standout);
887 }
888 }
889
890 if (FACE_UNDERLINE_P (face, frame))
891 {
892 /* #### punt for now if underline mode is glitchy */
893 if (!TTY_FLAGS (c).underline_width)
894 {
895 OUTPUT1_IF (c, TTY_SD (c).end_underline);
896 }
897 }
898
899 if (FACE_HIGHLIGHT_P (face, frame) ||
900 FACE_BLINKING_P (face, frame) ||
901 FACE_DIM_P (face, frame) ||
902 !EQ (FACE_FOREGROUND (face, frame), Vthe_null_color_instance) ||
903 !EQ (FACE_BACKGROUND (face, frame), Vthe_null_color_instance))
904 {
905 OUTPUT1_IF (c, TTY_SD (c).turn_off_attributes);
906 }
907 }
908
909 /*****************************************************************************
910 set_tty_modes
911
912 Sets up various parameters on tty modes.
913 ****************************************************************************/
914 void
915 set_tty_modes (struct console *c)
916 {
917 if (!CONSOLE_TTY_P (c))
918 return;
919
920 OUTPUT1_IF (c, TTY_SD (c).init_motion);
921 OUTPUT1_IF (c, TTY_SD (c).cursor_visible);
922 OUTPUT1_IF (c, TTY_SD (c).keypad_on);
923 }
924
925 /*****************************************************************************
926 reset_tty_modes
927
928 Restore default state of tty.
929 ****************************************************************************/
930 void
931 reset_tty_modes (struct console *c)
932 {
933 if (!CONSOLE_TTY_P (c))
934 return;
935
936 OUTPUT1_IF (c, TTY_SD (c).orig_pair);
937 OUTPUT1_IF (c, TTY_SD (c).keypad_off);
938 OUTPUT1_IF (c, TTY_SD (c).cursor_normal);
939 OUTPUT1_IF (c, TTY_SD (c).end_motion);
940 tty_output_end (XDEVICE (CONSOLE_SELECTED_DEVICE (c)));
941 }
942
943 /*****************************************************************************
944 tty_redisplay_shutdown
945
946 Clear the frame and position the cursor properly for exiting.
947 ****************************************************************************/
948 void
949 tty_redisplay_shutdown (struct console *c)
950 {
951 Lisp_Object dev = CONSOLE_SELECTED_DEVICE (c);
952
953 if (!NILP (dev))
954 {
955 Lisp_Object frm = DEVICE_SELECTED_FRAME (XDEVICE (dev));
956
957 if (!NILP (frm))
958 {
959 struct frame *f = XFRAME (frm);
960
961 /* Clear the bottom line of the frame. */
962 redisplay_clear_region (FRAME_SELECTED_WINDOW (f), DEFAULT_INDEX, 0,
963 f->height, f->width, 1);
964
965 /* And then stick the cursor there. */
966 tty_set_final_cursor_coords (f, f->height, 0);
967 tty_output_end (XDEVICE (dev));
968 }
969 }
970 }
971
972
973 /* #### Everything below here is old shit. It should either be moved
974 up or removed. */
975
976
977 /* FLAGS - these don't need to be console local since only one console
978 can be being updated at a time. */
979 static int insert_mode_on; /* nonzero if in insert mode */
980 static int standout_mode_on; /* nonzero if in standout mode */
981 static int underline_mode_on; /* nonzero if in underline mode */
982 static int alternate_mode_on; /* nonzero if in alternate char set */
983 static int attributes_on; /* nonzero if any attributes on */
984
985 #ifdef NOT_YET
986 static void
987 turn_on_insert (struct frame *f)
988 {
989 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
990
991 if (!insert_mode_on)
992 OUTPUT1_IF (c, TTY_SE (c).begin_ins_mode);
993 insert_mode_on = 1;
994 }
995
996 static void
997 turn_off_insert (struct frame *f)
998 {
999 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
1000
1001 if (insert_mode_on)
1002 OUTPUT1 (c, TTY_SE (c).end_ins_mode);
1003 insert_mode_on = 0;
1004 }
1005
1006 static void
1007 internal_cursor_to (struct frame *f, int row, int col)
1008 {
1009 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
1010
1011 if (!TTY_FLAGS (c).insert_mode_motion)
1012 turn_off_insert (f);
1013 if (!TTY_FLAGS (c).standout_motion)
1014 {
1015 turn_off_standout (f);
1016 turn_off_underline (f);
1017 turn_off_alternate (f);
1018 }
1019
1020 cmgoto (f, row, col);
1021 }
1022
1023 static void
1024 clear_to_end (struct frame *f)
1025 {
1026 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
1027
1028 /* assumes cursor is already positioned */
1029 if (TTY_SE (c).clr_from_cursor)
1030 {
1031 OUTPUT1 (c, TTY_SE (c).clr_from_cursor);
1032 }
1033 else
1034 {
1035 int line = FRAME_CURSOR_Y (f);
1036
1037 while (line < FRAME_HEIGHT (f))
1038 {
1039 internal_cursor_to (f, line, 0);
1040 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
1041 }
1042 }
1043 }
1044 #endif /* 0 */
1045
1046 #if 0
1047 /*
1048 * clear from last visible line on window to window end (presumably
1049 * the line above window's modeline
1050 */
1051 static void
1052 tty_clear_window_end (struct window *w, int ystart, int yend)
1053 {
1054 struct console *c = XCONSOLE (WINDOW_CONSOLE (w));
1055 int line;
1056
1057 for (line = ystart; line < yend; line++)
1058 {
1059 cmgoto (XFRAME (w->frame), line, 0);
1060 OUTPUT1 (c, TTY_SE (c).clr_to_eol);
1061 }
1062 }
1063
1064 #endif /* 0 */
1065
1066 static int
1067 tty_flash (struct device *d)
1068 {
1069 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
1070 if (TTY_SD (c).visual_bell)
1071 {
1072 OUTPUT1 (c, TTY_SD (c).visual_bell);
1073 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream));
1074 return 1;
1075 }
1076 else
1077 return 0;
1078 }
1079
1080 /*
1081 * tty_ring_bell - sound an audio beep.
1082 */
1083 static void
1084 tty_ring_bell (struct device *d, int volume, int pitch, int duration)
1085 {
1086 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
1087
1088 if (volume)
1089 {
1090 OUTPUT1 (c, TTY_SD (c).audio_bell);
1091 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream));
1092 }
1093 }
1094
1095
1096 int
1097 init_tty_for_redisplay (struct device *d, char *terminal_type)
1098 {
1099 int status;
1100 char entry_buffer[2044];
1101 /* char temp_buffer[2044]; */
1102 char *bufptr;
1103 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
1104
1105 /* What we should really do is allocate just enough space for
1106 the actual strings that are stored; but this would require
1107 doing this after all the tgetstr()s and adjusting all the
1108 pointers. */
1109 CONSOLE_TTY_DATA (c)->term_entry_buffer = (char *) xmalloc (2044);
1110 bufptr = CONSOLE_TTY_DATA (c)->term_entry_buffer;
1111
1112 #if !defined(WIN32)
1113 /* SIGTT* don't exist under win32 */
1114 EMACS_BLOCK_SIGNAL (SIGTTOU);
1115 #endif
1116 status = tgetent (entry_buffer, terminal_type);
1117 #if !defined(WIN32)
1118 EMACS_UNBLOCK_SIGNAL (SIGTTOU);
1119 #endif
1120 #if 0
1121 if (status < 0)
1122 return TTY_UNABLE_OPEN_DATABASE;
1123 else if (status == 0)
1124 return TTY_TYPE_UNDEFINED;
1125 #endif
1126 /* Under Linux at least, <0 is returned for TTY_TYPE_UNDEFINED. --ben */
1127 if (status <= 0)
1128 return TTY_TYPE_UNDEFINED;
1129
1130 /*
1131 * Establish the terminal size.
1132 */
1133 /* First try to get the info from the system. If that fails, check
1134 the termcap entry. */
1135 get_tty_device_size (d, &CONSOLE_TTY_DATA (c)->width,
1136 &CONSOLE_TTY_DATA (c)->height);
1137
1138 if (CONSOLE_TTY_DATA (c)->width <= 0)
1139 CONSOLE_TTY_DATA (c)->width = tgetnum ("co");
1140 if (CONSOLE_TTY_DATA (c)->height <= 0)
1141 CONSOLE_TTY_DATA (c)->height = tgetnum ("li");
1142
1143 if (CONSOLE_TTY_DATA (c)->width <= 0 || CONSOLE_TTY_DATA (c)->height <= 0)
1144 return TTY_SIZE_UNSPECIFIED;
1145
1146 /*
1147 * Initialize cursor motion information.
1148 */
1149
1150 /* local cursor movement */
1151 TTY_CM (c).up = tgetstr ("up", &bufptr);
1152 TTY_CM (c).down = tgetstr ("do", &bufptr);
1153 TTY_CM (c).left = tgetstr ("le", &bufptr);
1154 TTY_CM (c).right = tgetstr ("nd", &bufptr);
1155 TTY_CM (c).home = tgetstr ("ho", &bufptr);
1156 TTY_CM (c).low_left = tgetstr ("ll", &bufptr);
1157 TTY_CM (c).car_return = tgetstr ("cr", &bufptr);
1158
1159 /* absolute cursor motion */
1160 TTY_CM (c).abs = tgetstr ("cm", &bufptr);
1161 TTY_CM (c).hor_abs = tgetstr ("ch", &bufptr);
1162 TTY_CM (c).ver_abs = tgetstr ("cv", &bufptr);
1163
1164 /* Verify that the terminal is powerful enough to run Emacs */
1165 if (!TTY_CM (c).abs)
1166 {
1167 if (!TTY_CM (c).up || !TTY_CM (c).down
1168 || !TTY_CM (c).left || !TTY_CM (c).right)
1169 return TTY_TYPE_INSUFFICIENT;
1170 }
1171
1172 /* parameterized local cursor movement */
1173 TTY_CM (c).multi_up = tgetstr ("UP", &bufptr);
1174 TTY_CM (c).multi_down = tgetstr ("DO", &bufptr);
1175 TTY_CM (c).multi_left = tgetstr ("LE", &bufptr);
1176 TTY_CM (c).multi_right = tgetstr ("RI", &bufptr);
1177
1178 /* scrolling */
1179 TTY_CM (c).scroll_forw = tgetstr ("sf", &bufptr);
1180 TTY_CM (c).scroll_back = tgetstr ("sr", &bufptr);
1181 TTY_CM (c).multi_scroll_forw = tgetstr ("SF", &bufptr);
1182 TTY_CM (c).multi_scroll_back = tgetstr ("SR", &bufptr);
1183 TTY_CM (c).set_scroll_region = tgetstr ("cs", &bufptr);
1184
1185
1186 /*
1187 * Initialize screen editing information.
1188 */
1189
1190 /* adding to the screen */
1191 TTY_SE (c).ins_line = tgetstr ("al", &bufptr);
1192 TTY_SE (c).multi_ins_line = tgetstr ("AL", &bufptr);
1193 TTY_SE (c).repeat = tgetstr ("rp", &bufptr);
1194 TTY_SE (c).begin_ins_mode = tgetstr ("im", &bufptr);
1195 TTY_SE (c).end_ins_mode = tgetstr ("ei", &bufptr);
1196 TTY_SE (c).ins_char = tgetstr ("ic", &bufptr);
1197 TTY_SE (c).multi_ins_char = tgetstr ("IC", &bufptr);
1198 TTY_SE (c).insert_pad = tgetstr ("ip", &bufptr);
1199
1200 /* deleting from the screen */
1201 TTY_SE (c).clr_frame = tgetstr ("cl", &bufptr);
1202 TTY_SE (c).clr_from_cursor = tgetstr ("cd", &bufptr);
1203 TTY_SE (c).clr_to_eol = tgetstr ("ce", &bufptr);
1204 TTY_SE (c).del_line = tgetstr ("dl", &bufptr);
1205 TTY_SE (c).multi_del_line = tgetstr ("DL", &bufptr);
1206 TTY_SE (c).del_char = tgetstr ("dc", &bufptr);
1207 TTY_SE (c).multi_del_char = tgetstr ("DC", &bufptr);
1208 TTY_SE (c).begin_del_mode = tgetstr ("dm", &bufptr);
1209 TTY_SE (c).end_del_mode = tgetstr ("ed", &bufptr);
1210 TTY_SE (c).erase_at_cursor = tgetstr ("ec", &bufptr);
1211
1212
1213 /*
1214 * Initialize screen display information.
1215 */
1216 TTY_SD (c).begin_standout = tgetstr ("so", &bufptr);
1217 TTY_SD (c).end_standout = tgetstr ("se", &bufptr);
1218 TTY_SD (c).begin_underline = tgetstr ("us", &bufptr);
1219 TTY_SD (c).end_underline = tgetstr ("ue", &bufptr);
1220 TTY_SD (c).begin_alternate = tgetstr ("as", &bufptr);
1221 TTY_SD (c).end_alternate = tgetstr ("ae", &bufptr);
1222 TTY_SD (c).turn_on_reverse = tgetstr ("mr", &bufptr);
1223 TTY_SD (c).turn_on_blinking = tgetstr ("mb", &bufptr);
1224 TTY_SD (c).turn_on_bold = tgetstr ("md", &bufptr);
1225 TTY_SD (c).turn_on_dim = tgetstr ("mh", &bufptr);
1226 TTY_SD (c).turn_off_attributes = tgetstr ("me", &bufptr);
1227 TTY_SD (c).orig_pair = tgetstr ("op", &bufptr);
1228
1229 TTY_SD (c).visual_bell = tgetstr ("vb", &bufptr);
1230 TTY_SD (c).audio_bell = tgetstr ("bl", &bufptr);
1231 if (!TTY_SD (c).audio_bell)
1232 {
1233 /* If audio_bell doesn't get set, then assume C-g. This is gross and
1234 ugly but is what Emacs has done from time immortal. */
1235 TTY_SD (c).audio_bell = "\07";
1236 }
1237
1238 TTY_SD (c).cursor_visible = tgetstr ("ve", &bufptr);
1239 TTY_SD (c).cursor_normal = tgetstr ("vs", &bufptr);
1240 TTY_SD (c).init_motion = tgetstr ("ti", &bufptr);
1241 TTY_SD (c).end_motion = tgetstr ("te", &bufptr);
1242 TTY_SD (c).keypad_on = tgetstr ("ks", &bufptr);
1243 TTY_SD (c).keypad_off = tgetstr ("ke", &bufptr);
1244
1245
1246 /*
1247 * Initialize additional terminal information.
1248 */
1249 TTY_FLAGS (c).must_write_spaces = tgetflag ("in");
1250 TTY_FLAGS (c).insert_mode_motion = tgetflag ("mi");
1251 TTY_FLAGS (c).standout_motion = tgetflag ("ms");
1252 TTY_FLAGS (c).memory_above_frame = tgetflag ("da");
1253 TTY_FLAGS (c).memory_below_frame = tgetflag ("db");
1254 TTY_FLAGS (c).standout_width = tgetnum ("sg");
1255 TTY_FLAGS (c).underline_width = tgetnum ("ug");
1256
1257 if (TTY_FLAGS (c).standout_width == -1)
1258 TTY_FLAGS (c).standout_width = 0;
1259 if (TTY_FLAGS (c).underline_width == -1)
1260 TTY_FLAGS (c).underline_width = 0;
1261
1262 TTY_FLAGS (c).meta_key =
1263 eight_bit_tty (d) ? tgetflag ("km") || tgetflag ("MT") ? 1 : 2 : 0;
1264
1265
1266 /*
1267 * Setup the costs tables for this tty console.
1268 */
1269 cm_cost_init (c);
1270
1271 /*
1272 * Initialize local flags.
1273 */
1274 insert_mode_on = 0;
1275 standout_mode_on = 0;
1276 underline_mode_on = 0;
1277 alternate_mode_on = 0;
1278 attributes_on = 0;
1279
1280 /*
1281 * Attempt to initialize the function_key_map to
1282 * some kind of sensible value
1283 */
1284
1285 term_get_fkeys (c->function_key_map, &bufptr);
1286
1287 {
1288 /* check for ANSI set-foreground and set-background strings,
1289 and assume color if so.
1290
1291 #### we should support the other (non-ANSI) ways of specifying
1292 color, too. */
1293 char foobuf[500];
1294 char *fooptr = foobuf;
1295 if ((tgetstr ("AB", &fooptr) && tgetstr ("AF", &fooptr)) ||
1296 (tgetstr ("Sf", &fooptr) && tgetstr ("Sb", &fooptr)) ||
1297 ((tgetnum ("Co") > 0) && (tgetnum ("pa") > 0)))
1298 DEVICE_CLASS (d) = Qcolor;
1299 else
1300 DEVICE_CLASS (d) = Qmono;
1301 }
1302
1303 return TTY_INIT_SUCCESS;
1304 }
1305
1306 struct fkey_table
1307 {
1308 CONST char *cap;
1309 CONST char *name;
1310 };
1311
1312 /* Termcap capability names that correspond directly to X keysyms.
1313 Some of these (marked "terminfo") aren't supplied by old-style
1314 (Berkeley) termcap entries. They're listed in X keysym order;
1315 except we put the keypad keys first, so that if they clash with
1316 other keys (as on the IBM PC keyboard) they get overridden.
1317 */
1318
1319 static struct fkey_table keys[] =
1320 {
1321 {"kh", "home"}, /* termcap */
1322 {"kl", "left"}, /* termcap */
1323 {"ku", "up"}, /* termcap */
1324 {"kr", "right"}, /* termcap */
1325 {"kd", "down"}, /* termcap */
1326 {"%8", "prior"}, /* terminfo */
1327 {"%5", "next"}, /* terminfo */
1328 {"@7", "end"}, /* terminfo */
1329 {"@1", "begin"}, /* terminfo */
1330 {"*6", "select"}, /* terminfo */
1331 {"%9", "print"}, /* terminfo */
1332 {"@4", "execute"}, /* terminfo --- actually the `command' key */
1333 /*
1334 * "insert" --- see below
1335 */
1336 {"&8", "undo"}, /* terminfo */
1337 {"%0", "redo"}, /* terminfo */
1338 {"%7", "menu"}, /* terminfo --- actually the `options' key */
1339 {"@0", "find"}, /* terminfo */
1340 {"@2", "cancel"}, /* terminfo */
1341 {"%1", "help"}, /* terminfo */
1342 /*
1343 * "break" goes here, but can't be reliably intercepted with termcap
1344 */
1345 {"&4", "reset"}, /* terminfo --- actually `restart' */
1346 /*
1347 * "system" and "user" --- no termcaps
1348 */
1349 {"kE", "clearline"}, /* terminfo */
1350 {"kA", "insertline"}, /* terminfo */
1351 {"kL", "deleteline"}, /* terminfo */
1352 {"kI", "insertchar"}, /* terminfo */
1353 {"kD", "delete"}, /* terminfo */
1354 {"kB", "backtab"}, /* terminfo */
1355 /*
1356 * "kp-backtab", "kp-space", "kp-tab" --- no termcaps
1357 */
1358 {"@8", "kp-enter"}, /* terminfo */
1359 /*
1360 * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
1361 * "kp-multiply", "kp-add", "kp-separator",
1362 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
1363 * --- no termcaps for any of these.
1364 */
1365 {"K4", "kp-1"}, /* terminfo */
1366 /*
1367 * "kp-2" --- no termcap
1368 */
1369 {"K5", "kp-3"}, /* terminfo */
1370 /*
1371 * "kp-4" --- no termcap
1372 */
1373 {"K2", "kp-5"}, /* terminfo */
1374 /*
1375 * "kp-6" --- no termcap
1376 */
1377 {"K1", "kp-7"}, /* terminfo */
1378 /*
1379 * "kp-8" --- no termcap
1380 */
1381 {"K3", "kp-9"}, /* terminfo */
1382 /*
1383 * "kp-equal" --- no termcap
1384 */
1385 {"k1", "f1"},
1386 {"k2", "f2"},
1387 {"k3", "f3"},
1388 {"k4", "f4"},
1389 {"k5", "f5"},
1390 {"k6", "f6"},
1391 {"k7", "f7"},
1392 {"k8", "f8"},
1393 {"k9", "f9"},
1394 };
1395
1396 static char **term_get_fkeys_arg;
1397
1398 static Lisp_Object term_get_fkeys_1 (Lisp_Object keymap);
1399 static Lisp_Object term_get_fkeys_error (Lisp_Object err, Lisp_Object arg);
1400
1401 /* Find the escape codes sent by the function keys for Vfunction_key_map.
1402 This function scans the termcap function key sequence entries, and
1403 adds entries to Vfunction_key_map for each function key it finds. */
1404
1405 static void
1406 term_get_fkeys (Lisp_Object keymap, char **address)
1407 {
1408 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
1409 errors during the call. The only errors should be from Fdefine_key
1410 when given a key sequence containing an invalid prefix key. If the
1411 termcap defines function keys which use a prefix that is already bound
1412 to a command by the default bindings, we should silently ignore that
1413 function key specification, rather than giving the user an error and
1414 refusing to run at all on such a terminal. */
1415
1416 term_get_fkeys_arg = address;
1417
1418 condition_case_1 (Qerror,
1419 term_get_fkeys_1, keymap,
1420 term_get_fkeys_error, Qnil);
1421 }
1422
1423 static Lisp_Object
1424 term_get_fkeys_error (Lisp_Object err, Lisp_Object arg)
1425 {
1426 return arg;
1427 }
1428
1429 static Lisp_Object
1430 term_get_fkeys_1 (Lisp_Object function_key_map)
1431 {
1432 int i;
1433
1434 char **address = term_get_fkeys_arg;
1435
1436 for (i = 0; i < countof (keys); i++)
1437 {
1438 char *sequence = tgetstr (keys[i].cap, address);
1439 if (sequence)
1440 Fdefine_key (function_key_map,
1441 build_ext_string (sequence, FORMAT_BINARY),
1442 vector1 (intern (keys[i].name)));
1443 }
1444
1445 /* The uses of the "k0" capability are inconsistent; sometimes it
1446 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1447 We will attempt to politely accommodate both systems by testing for
1448 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1449 */
1450 {
1451 CONST char *k_semi = tgetstr ("k;", address);
1452 CONST char *k0 = tgetstr ("k0", address);
1453
1454 if (k_semi)
1455 Fdefine_key (function_key_map, build_ext_string (k_semi, FORMAT_BINARY),
1456 vector1 (intern ("f10")));
1457
1458 if (k0)
1459 Fdefine_key (function_key_map, build_ext_string (k0, FORMAT_BINARY),
1460 vector1 (intern (k_semi ? "f0" : "f10")));
1461 }
1462
1463 /* Set up cookies for numbered function keys above f10. */
1464 {
1465 char fcap[3], fkey[4];
1466
1467 fcap[0] = 'F'; fcap[2] = '\0';
1468 for (i = 11; i < 64; i++)
1469 {
1470 if (i <= 19)
1471 fcap[1] = '1' + i - 11;
1472 else if (i <= 45)
1473 fcap[1] = 'A' + i - 20;
1474 else
1475 fcap[1] = 'a' + i - 46;
1476
1477 {
1478 char *sequence = tgetstr (fcap, address);
1479 if (sequence)
1480 {
1481 sprintf (fkey, "f%d", i);
1482 Fdefine_key (function_key_map,
1483 build_ext_string (sequence, FORMAT_BINARY),
1484 vector1 (intern (fkey)));
1485 }
1486 }
1487 }
1488 }
1489
1490 /*
1491 * Various mappings to try and get a better fit.
1492 */
1493 #define CONDITIONAL_REASSIGN(cap1, cap2, keyname) \
1494 if (!tgetstr (cap1, address)) \
1495 { \
1496 char *sequence = tgetstr (cap2, address); \
1497 if (sequence) \
1498 Fdefine_key (function_key_map, \
1499 build_ext_string (sequence, FORMAT_BINARY), \
1500 vector1 (intern (keyname))); \
1501 }
1502
1503 /* if there's no key_next keycap, map key_npage to `next' keysym */
1504 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1505 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1506 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1507 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1508 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1509
1510 /* IBM has their own non-standard dialect of terminfo.
1511 If the standard name isn't found, try the IBM name. */
1512 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1513 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1514 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1515 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1516 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1517 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1518 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1519 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1520 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1521 #undef CONDITIONAL_REASSIGN
1522
1523 return Qnil;
1524 }
1525
1526
1527 /************************************************************************/
1528 /* initialization */
1529 /************************************************************************/
1530
1531 void
1532 console_type_create_redisplay_tty (void)
1533 {
1534 /* redisplay methods */
1535 CONSOLE_HAS_METHOD (tty, text_width);
1536 CONSOLE_HAS_METHOD (tty, output_display_block);
1537 CONSOLE_HAS_METHOD (tty, output_vertical_divider);
1538 CONSOLE_HAS_METHOD (tty, divider_height);
1539 CONSOLE_HAS_METHOD (tty, eol_cursor_width);
1540 CONSOLE_HAS_METHOD (tty, clear_to_window_end);
1541 CONSOLE_HAS_METHOD (tty, clear_region);
1542 CONSOLE_HAS_METHOD (tty, clear_frame);
1543 CONSOLE_HAS_METHOD (tty, output_begin);
1544 CONSOLE_HAS_METHOD (tty, output_end);
1545 CONSOLE_HAS_METHOD (tty, flash);
1546 CONSOLE_HAS_METHOD (tty, ring_bell);
1547 CONSOLE_HAS_METHOD (tty, set_final_cursor_coords);
1548 }