comparison src/redisplay-tty.c @ 0:376386a54a3c r19-14

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