This source file includes following definitions.
- tty_ring_bell
- tty_send_additional_strings
- tty_set_terminal_modes
- tty_reset_terminal_modes
- tty_update_end
- tty_set_terminal_window
- tty_set_scroll_region
- tty_turn_on_insert
- tty_turn_off_insert
- tty_turn_off_highlight
- tty_turn_on_highlight
- tty_toggle_highlight
- tty_hide_cursor
- tty_show_cursor
- tty_background_highlight
- tty_highlight_if_desired
- tty_cursor_to
- tty_raw_cursor_to
- tty_clear_to_end
- tty_clear_frame
- tty_clear_end_of_line
- encode_terminal_code
- encode_terminal_code
- tty_write_glyphs
- tty_write_glyphs_with_face
- tty_insert_glyphs
- tty_delete_glyphs
- tty_ins_del_lines
- string_cost
- string_cost_one_line
- per_line_cost
- calculate_ins_del_char_costs
- calculate_costs
- term_get_fkeys
- term_get_fkeys_1
- append_glyph
- tty_append_glyph
- produce_glyphs
- append_composite_glyph
- produce_composite_glyph
- append_glyphless_glyph
- produce_glyphless_glyph
- turn_on_face
- turn_off_face
- tty_capable_p
- DEFUN
- DEFUN
- tty_default_color_capabilities
- tty_setup_colors
- set_tty_color_mode
- tty_type_name
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- tty_draw_row_with_mouse_face
- term_mouse_moveto
- current_Time
- term_mouse_position
- term_mouse_click
- handle_one_term_event
- DEFUN
- close_gpm
- DEFUN
- tty_menu_create
- tty_menu_make_room
- tty_menu_search_pane
- tty_menu_calc_size
- mouse_get_xy
- tty_menu_display
- tty_menu_add_pane
- tty_menu_add_selection
- tty_menu_locate
- save_and_enable_current_matrix
- restore_desired_matrix
- free_saved_screen
- screen_update
- read_menu_input
- tty_menu_activate
- tty_menu_destroy
- tty_menu_help_callback
- tty_pop_down_menu
- tty_menu_last_menubar_item
- tty_menu_new_item_coords
- tty_menu_show
- create_tty_output
- tty_free_frame_resources
- tty_free_frame_resources
- clear_tty_hooks
- set_tty_hooks
- dissociate_if_controlling_tty
- init_tty
- vfatal
- maybe_fatal
- fatal
- delete_tty
- syms_of_term
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <config.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <sys/file.h>
27 #include <sys/time.h>
28 #include <unistd.h>
29
30 #include "lisp.h"
31 #include "termchar.h"
32 #include "tparam.h"
33 #include "character.h"
34 #include "buffer.h"
35 #include "charset.h"
36 #include "coding.h"
37 #include "composite.h"
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "disptab.h"
41 #include "termhooks.h"
42 #include "dispextern.h"
43 #include "window.h"
44 #include "keymap.h"
45 #include "blockinput.h"
46 #include "syssignal.h"
47 #include "sysstdio.h"
48 #ifdef MSDOS
49 #include "msdos.h"
50 static int been_here = -1;
51 #endif
52
53 #ifdef USE_X_TOOLKIT
54 #include "../lwlib/lwlib.h"
55 #endif
56
57 #include "cm.h"
58 #include "menu.h"
59
60
61 #ifdef WINDOWSNT
62 #include "w32term.h"
63 #endif
64
65 #ifndef HAVE_ANDROID
66
67 static void tty_set_scroll_region (struct frame *f, int start, int stop);
68 static void turn_on_face (struct frame *, int face_id);
69 static void turn_off_face (struct frame *, int face_id);
70 static void tty_turn_off_highlight (struct tty_display_info *);
71 static void tty_show_cursor (struct tty_display_info *);
72 static void tty_hide_cursor (struct tty_display_info *);
73 static void tty_background_highlight (struct tty_display_info *tty);
74 static void clear_tty_hooks (struct terminal *terminal);
75 static void set_tty_hooks (struct terminal *terminal);
76 static void dissociate_if_controlling_tty (int fd);
77 static void delete_tty (struct terminal *);
78
79 #endif
80
81 static AVOID maybe_fatal (bool, struct terminal *, const char *, const char *,
82 ...)
83 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
84 static AVOID vfatal (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
85
86 #ifndef HAVE_ANDROID
87
88 #define OUTPUT(tty, a) \
89 emacs_tputs ((tty), a, \
90 FRAME_TOTAL_LINES (XFRAME (selected_frame)) - curY (tty), \
91 cmputc)
92
93 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
94 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
95
96 #define OUTPUT_IF(tty, a) \
97 do { \
98 if (a) \
99 OUTPUT (tty, a); \
100 } while (0)
101
102 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
103
104 #endif
105
106
107
108
109 struct tty_display_info *tty_list;
110
111
112
113
114 enum no_color_bit
115 {
116 NC_STANDOUT = 1 << 0,
117 NC_UNDERLINE = 1 << 1,
118 NC_REVERSE = 1 << 2,
119 NC_ITALIC = 1 << 3,
120 NC_DIM = 1 << 4,
121 NC_BOLD = 1 << 5,
122 NC_STRIKE_THROUGH = 1 << 6,
123 NC_PROTECT = 1 << 7
124 };
125
126
127
128 #ifndef HAVE_ANDROID
129
130
131
132 static int max_frame_cols;
133
134 #endif
135
136
137
138 #ifdef HAVE_GPM
139 #include <sys/fcntl.h>
140
141
142 struct tty_display_info *gpm_tty = NULL;
143
144
145 static int last_mouse_x, last_mouse_y;
146 #endif
147
148 #ifndef HAVE_ANDROID
149
150
151
152 static void
153 tty_ring_bell (struct frame *f)
154 {
155 struct tty_display_info *tty = FRAME_TTY (f);
156
157 if (tty->output)
158 {
159 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
160 ? tty->TS_visible_bell
161 : tty->TS_bell));
162 fflush (tty->output);
163 }
164 }
165
166
167
168 static void
169 tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym)
170 {
171
172
173
174
175 if (! terminal->name)
176 return;
177 struct tty_display_info *tty = terminal->display_info.tty;
178
179 for (Lisp_Object extra_codes
180 = CDR_SAFE (assq_no_quit (sym, terminal->param_alist));
181 CONSP (extra_codes);
182 extra_codes = XCDR (extra_codes))
183 {
184 Lisp_Object string = XCAR (extra_codes);
185 if (STRINGP (string))
186 {
187 fwrite (SDATA (string), 1, SBYTES (string), tty->output);
188 if (tty->termscript)
189 fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
190 }
191 }
192 }
193
194 static void
195 tty_set_terminal_modes (struct terminal *terminal)
196 {
197 struct tty_display_info *tty = terminal->display_info.tty;
198
199 if (tty->output)
200 {
201 if (tty->TS_termcap_modes)
202 OUTPUT (tty, tty->TS_termcap_modes);
203 else
204 {
205
206
207 int i;
208 current_tty = tty;
209 for (i = 0; i < FRAME_TOTAL_LINES (XFRAME (selected_frame)); i++)
210 cmputc ('\n');
211 }
212
213 OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
214 OUTPUT_IF (tty, tty->TS_keypad_mode);
215 losecursor (tty);
216 tty_send_additional_strings (terminal, Qtty_mode_set_strings);
217 fflush (tty->output);
218 }
219 }
220
221
222
223 static void
224 tty_reset_terminal_modes (struct terminal *terminal)
225 {
226 struct tty_display_info *tty = terminal->display_info.tty;
227
228 if (tty->output)
229 {
230 tty_send_additional_strings (terminal, Qtty_mode_reset_strings);
231 tty_turn_off_highlight (tty);
232 tty_turn_off_insert (tty);
233 OUTPUT_IF (tty, tty->TS_end_keypad_mode);
234 OUTPUT_IF (tty, tty->TS_cursor_normal);
235 OUTPUT_IF (tty, tty->TS_end_termcap_modes);
236 OUTPUT_IF (tty, tty->TS_orig_pair);
237
238 current_tty = tty;
239 cmputc ('\r');
240 fflush (tty->output);
241 }
242 }
243
244
245
246 static void
247 tty_update_end (struct frame *f)
248 {
249 struct tty_display_info *tty = FRAME_TTY (f);
250
251 if (!XWINDOW (selected_window)->cursor_off_p)
252 tty_show_cursor (tty);
253 tty_turn_off_insert (tty);
254 tty_background_highlight (tty);
255 fflush (tty->output);
256 }
257
258
259
260 static void
261 tty_set_terminal_window (struct frame *f, int size)
262 {
263 struct tty_display_info *tty = FRAME_TTY (f);
264
265 tty->specified_window = size ? size : FRAME_TOTAL_LINES (f);
266 if (FRAME_SCROLL_REGION_OK (f))
267 tty_set_scroll_region (f, 0, tty->specified_window);
268 }
269
270 static void
271 tty_set_scroll_region (struct frame *f, int start, int stop)
272 {
273 char *buf;
274 struct tty_display_info *tty = FRAME_TTY (f);
275
276 if (tty->TS_set_scroll_region)
277 buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1, 0, 0);
278 else if (tty->TS_set_scroll_region_1)
279 buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
280 FRAME_TOTAL_LINES (f), start,
281 FRAME_TOTAL_LINES (f) - stop,
282 FRAME_TOTAL_LINES (f));
283 else
284 buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
285
286 OUTPUT (tty, buf);
287 xfree (buf);
288 losecursor (tty);
289 }
290
291
292 static void
293 tty_turn_on_insert (struct tty_display_info *tty)
294 {
295 if (!tty->insert_mode)
296 OUTPUT (tty, tty->TS_insert_mode);
297 tty->insert_mode = 1;
298 }
299
300 void
301 tty_turn_off_insert (struct tty_display_info *tty)
302 {
303 if (tty->insert_mode)
304 OUTPUT (tty, tty->TS_end_insert_mode);
305 tty->insert_mode = 0;
306 }
307
308
309
310 static void
311 tty_turn_off_highlight (struct tty_display_info *tty)
312 {
313 if (tty->standout_mode)
314 OUTPUT_IF (tty, tty->TS_end_standout_mode);
315 tty->standout_mode = 0;
316 }
317
318 static void
319 tty_turn_on_highlight (struct tty_display_info *tty)
320 {
321 if (!tty->standout_mode)
322 OUTPUT_IF (tty, tty->TS_standout_mode);
323 tty->standout_mode = 1;
324 }
325
326 static void
327 tty_toggle_highlight (struct tty_display_info *tty)
328 {
329 if (tty->standout_mode)
330 tty_turn_off_highlight (tty);
331 else
332 tty_turn_on_highlight (tty);
333 }
334
335
336
337
338 static void
339 tty_hide_cursor (struct tty_display_info *tty)
340 {
341 if (tty->cursor_hidden == 0)
342 {
343 tty->cursor_hidden = 1;
344 #ifdef WINDOWSNT
345 w32con_hide_cursor ();
346 #else
347 OUTPUT_IF (tty, tty->TS_cursor_invisible);
348 #endif
349 }
350 }
351
352
353
354
355 static void
356 tty_show_cursor (struct tty_display_info *tty)
357 {
358 if (tty->cursor_hidden)
359 {
360 tty->cursor_hidden = 0;
361 #ifdef WINDOWSNT
362 w32con_show_cursor ();
363 #else
364 OUTPUT_IF (tty, tty->TS_cursor_normal);
365 if (visible_cursor)
366 OUTPUT_IF (tty, tty->TS_cursor_visible);
367 #endif
368 }
369 }
370
371
372
373
374
375
376 static void
377 tty_background_highlight (struct tty_display_info *tty)
378 {
379 if (inverse_video)
380 tty_turn_on_highlight (tty);
381 else
382 tty_turn_off_highlight (tty);
383 }
384
385
386
387 static void
388 tty_highlight_if_desired (struct tty_display_info *tty)
389 {
390 if (inverse_video)
391 tty_turn_on_highlight (tty);
392 else
393 tty_turn_off_highlight (tty);
394 }
395
396
397
398
399
400 static void
401 tty_cursor_to (struct frame *f, int vpos, int hpos)
402 {
403 struct tty_display_info *tty = FRAME_TTY (f);
404
405
406
407 if (! tty->costs_set)
408 return;
409
410 if (curY (tty) == vpos
411 && curX (tty) == hpos)
412 return;
413 if (!tty->TF_standout_motion)
414 tty_background_highlight (tty);
415 if (!tty->TF_insmode_motion)
416 tty_turn_off_insert (tty);
417 cmgoto (tty, vpos, hpos);
418 }
419
420
421
422 static void
423 tty_raw_cursor_to (struct frame *f, int row, int col)
424 {
425 struct tty_display_info *tty = FRAME_TTY (f);
426
427 if (curY (tty) == row
428 && curX (tty) == col)
429 return;
430 if (!tty->TF_standout_motion)
431 tty_background_highlight (tty);
432 if (!tty->TF_insmode_motion)
433 tty_turn_off_insert (tty);
434 cmgoto (tty, row, col);
435 }
436
437
438
439
440
441 static void
442 tty_clear_to_end (struct frame *f)
443 {
444 register int i;
445 struct tty_display_info *tty = FRAME_TTY (f);
446
447 if (tty->TS_clr_to_bottom)
448 {
449 tty_background_highlight (tty);
450 OUTPUT (tty, tty->TS_clr_to_bottom);
451 }
452 else
453 {
454 for (i = curY (tty); i < FRAME_TOTAL_LINES (f); i++)
455 {
456 cursor_to (f, i, 0);
457 clear_end_of_line (f, FRAME_COLS (f));
458 }
459 }
460 }
461
462
463
464 static void
465 tty_clear_frame (struct frame *f)
466 {
467 struct tty_display_info *tty = FRAME_TTY (f);
468
469 if (tty->TS_clr_frame)
470 {
471 tty_background_highlight (tty);
472 OUTPUT (tty, tty->TS_clr_frame);
473 cmat (tty, 0, 0);
474 }
475 else
476 {
477 cursor_to (f, 0, 0);
478 clear_to_end (f);
479 }
480 }
481
482
483
484
485
486 static void
487 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
488 {
489 register int i;
490 struct tty_display_info *tty = FRAME_TTY (f);
491
492
493
494 if (! tty->costs_set)
495 return;
496
497 if (curX (tty) >= first_unused_hpos)
498 return;
499 tty_background_highlight (tty);
500 if (tty->TS_clr_line)
501 {
502 OUTPUT1 (tty, tty->TS_clr_line);
503 }
504 else
505 {
506 tty_turn_off_insert (tty);
507
508
509 if (AutoWrap (tty)
510 && curY (tty) == FrameRows (tty) - 1
511 && first_unused_hpos == FrameCols (tty))
512 first_unused_hpos--;
513
514 for (i = curX (tty); i < first_unused_hpos; i++)
515 {
516 if (tty->termscript)
517 putc (' ', tty->termscript);
518 putc (' ', tty->output);
519 }
520 cmplus (tty, first_unused_hpos - curX (tty));
521 }
522 }
523
524
525 static unsigned char *encode_terminal_src;
526 static unsigned char *encode_terminal_dst;
527
528 static ptrdiff_t encode_terminal_src_size;
529 static ptrdiff_t encode_terminal_dst_size;
530
531
532
533
534
535 unsigned char *
536 encode_terminal_code (struct glyph *src, int src_len,
537 struct coding_system *coding)
538 {
539 struct glyph *src_end = src + src_len;
540 unsigned char *buf;
541 ptrdiff_t nchars, nbytes, required;
542 ptrdiff_t tlen = GLYPH_TABLE_LENGTH;
543 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
544 Lisp_Object charset_list;
545
546
547
548
549
550 if (ckd_mul (&required, src_len, MAX_MULTIBYTE_LENGTH))
551 memory_full (SIZE_MAX);
552 if (encode_terminal_src_size < required)
553 encode_terminal_src = xpalloc (encode_terminal_src,
554 &encode_terminal_src_size,
555 required - encode_terminal_src_size,
556 -1, sizeof *encode_terminal_src);
557
558 charset_list = coding_charset_list (coding);
559
560 buf = encode_terminal_src;
561 nchars = 0;
562 while (src < src_end)
563 {
564 if (src->type == COMPOSITE_GLYPH)
565 {
566 struct composition *cmp;
567 Lisp_Object gstring UNINIT;
568 int i;
569
570 nbytes = buf - encode_terminal_src;
571 if (src->u.cmp.automatic)
572 {
573 cmp = NULL;
574 gstring = composition_gstring_from_id (src->u.cmp.id);
575 required = src->slice.cmp.to - src->slice.cmp.from + 1;
576 }
577 else
578 {
579 cmp = composition_table[src->u.cmp.id];
580 required = cmp->glyph_len;
581 }
582 required *= MAX_MULTIBYTE_LENGTH;
583
584 if (encode_terminal_src_size - nbytes < required)
585 {
586 encode_terminal_src =
587 xpalloc (encode_terminal_src, &encode_terminal_src_size,
588 required - (encode_terminal_src_size - nbytes),
589 -1, 1);
590 buf = encode_terminal_src + nbytes;
591 }
592
593 if (!cmp)
594 for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
595 {
596 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
597 int c = LGLYPH_CHAR (g);
598
599 if (! char_charset (c, charset_list, NULL))
600 c = '?';
601 buf += CHAR_STRING (c, buf);
602 nchars++;
603 }
604 else
605 for (i = 0; i < cmp->glyph_len; i++)
606 {
607 int c = COMPOSITION_GLYPH (cmp, i);
608
609
610
611 if (c == '\t')
612 continue;
613 if (char_charset (c, charset_list, NULL))
614 {
615 if (CHARACTER_WIDTH (c) == 0
616 && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
617
618 {
619 buf += CHAR_STRING (' ', buf);
620 nchars++;
621 }
622 }
623 else
624 c = '?';
625 buf += CHAR_STRING (c, buf);
626 nchars++;
627 }
628 }
629
630 else if (! CHAR_GLYPH_PADDING_P (*src))
631 {
632 GLYPH g;
633 int c UNINIT;
634 Lisp_Object string;
635
636 string = Qnil;
637 SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
638
639 if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
640 {
641
642 c = src->u.ch;
643 }
644 else
645 {
646
647
648 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
649
650 if (GLYPH_SIMPLE_P (tbase, tlen, g))
651
652
653 c = GLYPH_CHAR (g);
654 else
655
656 string = tbase[GLYPH_CHAR (g)];
657 }
658
659 if (NILP (string))
660 {
661 nbytes = buf - encode_terminal_src;
662 if (encode_terminal_src_size - nbytes < MAX_MULTIBYTE_LENGTH)
663 {
664 encode_terminal_src =
665 xpalloc (encode_terminal_src, &encode_terminal_src_size,
666 MAX_MULTIBYTE_LENGTH, -1, 1);
667 buf = encode_terminal_src + nbytes;
668 }
669 if (CHAR_BYTE8_P (c)
670 || char_charset (c, charset_list, NULL))
671 {
672
673 buf += CHAR_STRING (c, buf);
674 nchars++;
675 }
676 else
677 {
678
679 *buf++ = '?';
680 nchars++;
681 while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
682 {
683 *buf++ = '?';
684 nchars++;
685 src++;
686 }
687 }
688 }
689 else
690 {
691 if (! STRING_MULTIBYTE (string))
692 string = string_to_multibyte (string);
693 nbytes = buf - encode_terminal_src;
694 if (encode_terminal_src_size - nbytes < SBYTES (string))
695 {
696 encode_terminal_src =
697 xpalloc (encode_terminal_src, &encode_terminal_src_size,
698 (SBYTES (string)
699 - (encode_terminal_src_size - nbytes)),
700 -1, 1);
701 buf = encode_terminal_src + nbytes;
702 }
703 memcpy (buf, SDATA (string), SBYTES (string));
704 buf += SBYTES (string);
705 nchars += SCHARS (string);
706 }
707 }
708 src++;
709 }
710
711 if (nchars == 0)
712 {
713 coding->produced = 0;
714 return NULL;
715 }
716
717 nbytes = buf - encode_terminal_src;
718 coding->source = encode_terminal_src;
719 if (encode_terminal_dst_size == 0)
720 {
721 encode_terminal_dst = xrealloc (encode_terminal_dst,
722 encode_terminal_src_size);
723 encode_terminal_dst_size = encode_terminal_src_size;
724 }
725 coding->destination = encode_terminal_dst;
726 coding->dst_bytes = encode_terminal_dst_size;
727 encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
728
729 encode_terminal_dst = coding->destination;
730 encode_terminal_dst_size = coding->dst_bytes;
731
732 return (encode_terminal_dst);
733 }
734
735 #else
736
737 unsigned char *
738 encode_terminal_code (struct glyph *src, int src_len,
739 struct coding_system *coding)
740 {
741
742 coding->produced = 0;
743 return NULL;
744 }
745
746 #endif
747
748 #ifndef HAVE_ANDROID
749
750
751
752 static void
753 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
754 {
755 unsigned char *conversion_buffer;
756 struct coding_system *coding;
757 int n, stringlen;
758
759 struct tty_display_info *tty = FRAME_TTY (f);
760
761 tty_turn_off_insert (tty);
762 tty_hide_cursor (tty);
763
764
765
766
767 if (AutoWrap (tty)
768 && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
769 && (curX (tty) + len) == FRAME_COLS (f))
770 len --;
771 if (len <= 0)
772 return;
773
774 cmplus (tty, len);
775
776
777
778
779 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
780 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
781
782
783 coding->mode &= ~CODING_MODE_LAST_BLOCK;
784
785 for (stringlen = len; stringlen != 0; stringlen -= n)
786 {
787
788 int face_id = string->face_id;
789
790 for (n = 1; n < stringlen; ++n)
791 if (string[n].face_id != face_id)
792 break;
793
794
795 tty_highlight_if_desired (tty);
796 turn_on_face (f, face_id);
797
798 if (n == stringlen)
799
800 coding->mode |= CODING_MODE_LAST_BLOCK;
801 conversion_buffer = encode_terminal_code (string, n, coding);
802 if (coding->produced > 0)
803 {
804 block_input ();
805 fwrite (conversion_buffer, 1, coding->produced, tty->output);
806 clearerr (tty->output);
807 if (tty->termscript)
808 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
809 unblock_input ();
810 }
811 string += n;
812
813
814 turn_off_face (f, face_id);
815 tty_turn_off_highlight (tty);
816 }
817
818 cmcheckmagic (tty);
819 }
820
821 #ifndef DOS_NT
822
823 static void
824 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
825 register int len, register int face_id)
826 {
827 unsigned char *conversion_buffer;
828 struct coding_system *coding;
829
830 struct tty_display_info *tty = FRAME_TTY (f);
831
832 tty_turn_off_insert (tty);
833 tty_hide_cursor (tty);
834
835
836
837
838 if (AutoWrap (tty)
839 && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
840 && (curX (tty) + len) == FRAME_COLS (f))
841 len --;
842 if (len <= 0)
843 return;
844
845 cmplus (tty, len);
846
847
848
849
850 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
851 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
852
853
854 coding->mode &= ~CODING_MODE_LAST_BLOCK;
855
856
857 tty_highlight_if_desired (tty);
858 turn_on_face (f, face_id);
859
860 coding->mode |= CODING_MODE_LAST_BLOCK;
861 conversion_buffer = encode_terminal_code (string, len, coding);
862 if (coding->produced > 0)
863 {
864 block_input ();
865 fwrite (conversion_buffer, 1, coding->produced, tty->output);
866 clearerr (tty->output);
867 if (tty->termscript)
868 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
869 unblock_input ();
870 }
871
872
873 turn_off_face (f, face_id);
874 tty_turn_off_highlight (tty);
875
876 cmcheckmagic (tty);
877 }
878
879 #endif
880
881
882
883 static void
884 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
885 {
886 char *buf;
887 struct glyph *glyph = NULL;
888 unsigned char *conversion_buffer;
889 unsigned char space[1];
890 struct coding_system *coding;
891
892 struct tty_display_info *tty = FRAME_TTY (f);
893
894 if (tty->TS_ins_multi_chars)
895 {
896 buf = tparam (tty->TS_ins_multi_chars, 0, 0, len, 0, 0, 0);
897 OUTPUT1 (tty, buf);
898 xfree (buf);
899 if (start)
900 write_glyphs (f, start, len);
901 return;
902 }
903
904 tty_turn_on_insert (tty);
905 cmplus (tty, len);
906
907 if (! start)
908 space[0] = SPACEGLYPH;
909
910
911
912
913 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
914 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
915
916
917 coding->mode &= ~CODING_MODE_LAST_BLOCK;
918
919 while (len-- > 0)
920 {
921 OUTPUT1_IF (tty, tty->TS_ins_char);
922 if (!start)
923 {
924 conversion_buffer = space;
925 coding->produced = 1;
926 }
927 else
928 {
929 tty_highlight_if_desired (tty);
930 turn_on_face (f, start->face_id);
931 glyph = start;
932 ++start;
933
934
935 while (len && CHAR_GLYPH_PADDING_P (*start))
936 {
937 OUTPUT1_IF (tty, tty->TS_ins_char);
938 start++, len--;
939 }
940
941 if (len <= 0)
942
943 coding->mode |= CODING_MODE_LAST_BLOCK;
944
945 conversion_buffer = encode_terminal_code (glyph, 1, coding);
946 }
947
948 if (coding->produced > 0)
949 {
950 block_input ();
951 fwrite (conversion_buffer, 1, coding->produced, tty->output);
952 clearerr (tty->output);
953 if (tty->termscript)
954 fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
955 unblock_input ();
956 }
957
958 OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
959 if (start)
960 {
961 turn_off_face (f, glyph->face_id);
962 tty_turn_off_highlight (tty);
963 }
964 }
965
966 cmcheckmagic (tty);
967 }
968
969
970
971 static void
972 tty_delete_glyphs (struct frame *f, int n)
973 {
974 char *buf;
975 register int i;
976
977 struct tty_display_info *tty = FRAME_TTY (f);
978
979 if (tty->delete_in_insert_mode)
980 {
981 tty_turn_on_insert (tty);
982 }
983 else
984 {
985 tty_turn_off_insert (tty);
986 OUTPUT_IF (tty, tty->TS_delete_mode);
987 }
988
989 if (tty->TS_del_multi_chars)
990 {
991 buf = tparam (tty->TS_del_multi_chars, 0, 0, n, 0, 0, 0);
992 OUTPUT1 (tty, buf);
993 xfree (buf);
994 }
995 else
996 for (i = 0; i < n; i++)
997 OUTPUT1 (tty, tty->TS_del_char);
998 if (!tty->delete_in_insert_mode)
999 OUTPUT_IF (tty, tty->TS_end_delete_mode);
1000 }
1001
1002
1003
1004 static void
1005 tty_ins_del_lines (struct frame *f, int vpos, int n)
1006 {
1007 struct tty_display_info *tty = FRAME_TTY (f);
1008 const char *multi =
1009 n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
1010 const char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
1011 const char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
1012
1013 int i = eabs (n);
1014 char *buf;
1015
1016
1017
1018
1019
1020
1021
1022
1023 if (FRAME_SCROLL_REGION_OK (f)
1024 && vpos + i >= tty->specified_window)
1025 return;
1026 if (!FRAME_MEMORY_BELOW_FRAME (f)
1027 && vpos + i >= FRAME_TOTAL_LINES (f))
1028 return;
1029
1030 if (multi)
1031 {
1032 raw_cursor_to (f, vpos, 0);
1033 tty_background_highlight (tty);
1034 buf = tparam (multi, 0, 0, i, 0, 0, 0);
1035 OUTPUT (tty, buf);
1036 xfree (buf);
1037 }
1038 else if (single)
1039 {
1040 raw_cursor_to (f, vpos, 0);
1041 tty_background_highlight (tty);
1042 while (--i >= 0)
1043 OUTPUT (tty, single);
1044 if (tty->TF_teleray)
1045 curX (tty) = 0;
1046 }
1047 else
1048 {
1049 tty_set_scroll_region (f, vpos, tty->specified_window);
1050 if (n < 0)
1051 raw_cursor_to (f, tty->specified_window - 1, 0);
1052 else
1053 raw_cursor_to (f, vpos, 0);
1054 tty_background_highlight (tty);
1055 while (--i >= 0)
1056 OUTPUTL (tty, scroll, tty->specified_window - vpos);
1057 tty_set_scroll_region (f, 0, tty->specified_window);
1058 }
1059
1060 if (!FRAME_SCROLL_REGION_OK (f)
1061 && FRAME_MEMORY_BELOW_FRAME (f)
1062 && n < 0)
1063 {
1064 cursor_to (f, FRAME_TOTAL_LINES (f) + n, 0);
1065 clear_to_end (f);
1066 }
1067 }
1068
1069
1070
1071
1072 int
1073 string_cost (const char *str)
1074 {
1075 cost = 0;
1076 #ifndef HAVE_ANDROID
1077 if (str)
1078 tputs (str, 0, evalcost);
1079 #endif
1080 return cost;
1081 }
1082
1083
1084
1085
1086 static int
1087 string_cost_one_line (const char *str)
1088 {
1089 cost = 0;
1090 #ifndef HAVE_ANDROID
1091 if (str)
1092 tputs (str, 1, evalcost);
1093 #endif
1094 return cost;
1095 }
1096
1097
1098
1099
1100 int
1101 per_line_cost (const char *str)
1102 {
1103 cost = 0;
1104 #ifndef HAVE_ANDROID
1105 if (str)
1106 tputs (str, 0, evalcost);
1107 cost = - cost;
1108 if (str)
1109 tputs (str, 10, evalcost);
1110 #endif
1111 return cost;
1112 }
1113
1114
1115
1116
1117
1118 int *char_ins_del_vector;
1119
1120 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
1121
1122 static void
1123 calculate_ins_del_char_costs (struct frame *f)
1124 {
1125 struct tty_display_info *tty = FRAME_TTY (f);
1126 int ins_startup_cost, del_startup_cost;
1127 int ins_cost_per_char, del_cost_per_char;
1128 register int i;
1129 register int *p;
1130
1131 if (tty->TS_ins_multi_chars)
1132 {
1133 ins_cost_per_char = 0;
1134 ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
1135 }
1136 else if (tty->TS_ins_char || tty->TS_pad_inserted_char
1137 || (tty->TS_insert_mode && tty->TS_end_insert_mode))
1138 {
1139 ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
1140 + string_cost (tty->TS_end_insert_mode))) / 100;
1141 ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
1142 + string_cost_one_line (tty->TS_pad_inserted_char));
1143 }
1144 else
1145 {
1146 ins_startup_cost = 9999;
1147 ins_cost_per_char = 0;
1148 }
1149
1150 if (tty->TS_del_multi_chars)
1151 {
1152 del_cost_per_char = 0;
1153 del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
1154 }
1155 else if (tty->TS_del_char)
1156 {
1157 del_startup_cost = (string_cost (tty->TS_delete_mode)
1158 + string_cost (tty->TS_end_delete_mode));
1159 if (tty->delete_in_insert_mode)
1160 del_startup_cost /= 2;
1161 del_cost_per_char = string_cost_one_line (tty->TS_del_char);
1162 }
1163 else
1164 {
1165 del_startup_cost = 9999;
1166 del_cost_per_char = 0;
1167 }
1168
1169
1170 p = &char_ins_del_cost (f)[0];
1171 for (i = FRAME_COLS (f); --i >= 0;)
1172 *--p = (del_startup_cost += del_cost_per_char);
1173
1174
1175 p = &char_ins_del_cost (f)[0];
1176 *p++ = 0;
1177
1178
1179 for (i = FRAME_COLS (f); --i >= 0;)
1180 *p++ = (ins_startup_cost += ins_cost_per_char);
1181 }
1182
1183 #endif
1184
1185 void
1186 calculate_costs (struct frame *frame)
1187 {
1188 FRAME_COST_BAUD_RATE (frame) = baud_rate;
1189
1190 #ifndef HAVE_ANDROID
1191 if (FRAME_TERMCAP_P (frame))
1192 {
1193 struct tty_display_info *tty = FRAME_TTY (frame);
1194 register const char *f = (tty->TS_set_scroll_region
1195 ? tty->TS_set_scroll_region
1196 : tty->TS_set_scroll_region_1);
1197
1198 FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
1199
1200 tty->costs_set = 1;
1201
1202
1203
1204
1205
1206
1207
1208
1209 max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
1210 if ((min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) - 1) / 2
1211 < max_frame_cols)
1212 memory_full (SIZE_MAX);
1213
1214 char_ins_del_vector =
1215 xrealloc (char_ins_del_vector,
1216 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1217
1218 memset (char_ins_del_vector, 0,
1219 (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
1220
1221
1222 if (f && (!tty->TS_ins_line && !tty->TS_del_line))
1223 do_line_insertion_deletion_costs (frame,
1224 tty->TS_rev_scroll, tty->TS_ins_multi_lines,
1225 tty->TS_fwd_scroll, tty->TS_del_multi_lines,
1226 f, f, 1);
1227 else
1228 do_line_insertion_deletion_costs (frame,
1229 tty->TS_ins_line, tty->TS_ins_multi_lines,
1230 tty->TS_del_line, tty->TS_del_multi_lines,
1231 0, 0, 1);
1232
1233 calculate_ins_del_char_costs (frame);
1234
1235
1236 if (tty->TS_repeat
1237 && (baud_rate <= 0
1238 || per_line_cost (tty->TS_repeat) < 9000 / baud_rate))
1239 tty->RPov = string_cost (tty->TS_repeat);
1240 else
1241 tty->RPov = FRAME_COLS (frame) * 2;
1242
1243 cmcostinit (FRAME_TTY (frame));
1244 }
1245 #endif
1246 }
1247
1248 struct fkey_table
1249 {
1250 const char *cap, *name;
1251 };
1252
1253 #if !defined DOS_NT && !defined HAVE_ANDROID
1254
1255
1256
1257
1258
1259
1260
1261 static const struct fkey_table keys[] =
1262 {
1263 {"kh", "home"},
1264 {"kl", "left"},
1265 {"ku", "up"},
1266 {"kr", "right"},
1267 {"kd", "down"},
1268 {"%8", "prior"},
1269 {"%5", "next"},
1270 {"@7", "end"},
1271 {"@1", "begin"},
1272 {"*6", "select"},
1273 {"%9", "print"},
1274 {"@4", "execute"},
1275
1276
1277
1278 {"&8", "undo"},
1279 {"%0", "redo"},
1280 {"%7", "menu"},
1281 {"@0", "find"},
1282 {"@2", "cancel"},
1283 {"%1", "help"},
1284
1285
1286
1287 {"&4", "reset"},
1288
1289
1290
1291 {"kE", "clearline"},
1292 {"kA", "insertline"},
1293 {"kL", "deleteline"},
1294 {"kI", "insertchar"},
1295 {"kD", "deletechar"},
1296 {"kB", "backtab"},
1297
1298
1299
1300 {"@8", "kp-enter"},
1301
1302
1303
1304
1305
1306
1307 {"K4", "kp-1"},
1308
1309
1310
1311 {"K5", "kp-3"},
1312
1313
1314
1315 {"K2", "kp-5"},
1316
1317
1318
1319 {"K1", "kp-7"},
1320
1321
1322
1323 {"K3", "kp-9"},
1324
1325
1326
1327 {"k1", "f1"},
1328 {"k2", "f2"},
1329 {"k3", "f3"},
1330 {"k4", "f4"},
1331 {"k5", "f5"},
1332 {"k6", "f6"},
1333 {"k7", "f7"},
1334 {"k8", "f8"},
1335 {"k9", "f9"},
1336
1337 {"&0", "S-cancel"},
1338 {"&9", "S-begin"},
1339 {"*0", "S-find"},
1340 {"*1", "S-execute"},
1341 {"*4", "S-delete"},
1342 {"*7", "S-end"},
1343 {"*8", "S-clearline"},
1344 {"#1", "S-help"},
1345 {"#2", "S-home"},
1346 {"#3", "S-insert"},
1347 {"#4", "S-left"},
1348 {"%d", "S-menu"},
1349 {"%c", "S-next"},
1350 {"%e", "S-prior"},
1351 {"%f", "S-print"},
1352 {"%g", "S-redo"},
1353 {"%i", "S-right"},
1354 {"!3", "S-undo"}
1355 };
1356
1357 static char **term_get_fkeys_address;
1358 static KBOARD *term_get_fkeys_kboard;
1359 static Lisp_Object term_get_fkeys_1 (void);
1360
1361
1362
1363
1364
1365 static void
1366 term_get_fkeys (char **address, KBOARD *kboard)
1367 {
1368
1369
1370
1371
1372
1373
1374
1375
1376 term_get_fkeys_address = address;
1377 term_get_fkeys_kboard = kboard;
1378 internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
1379 }
1380
1381 static Lisp_Object
1382 term_get_fkeys_1 (void)
1383 {
1384 int i;
1385
1386 char **address = term_get_fkeys_address;
1387 KBOARD *kboard = term_get_fkeys_kboard;
1388
1389
1390
1391 if (!KEYMAPP (KVAR (kboard, Vinput_decode_map)))
1392 kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil));
1393
1394 for (i = 0; i < ARRAYELTS (keys); i++)
1395 {
1396 char *sequence = tgetstr (keys[i].cap, address);
1397 if (sequence)
1398 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
1399 make_vector (1, intern (keys[i].name)), Qnil);
1400 }
1401
1402
1403
1404
1405
1406
1407 {
1408 const char *k_semi = tgetstr ("k;", address);
1409 const char *k0 = tgetstr ("k0", address);
1410 const char *k0_name = "f10";
1411
1412 if (k_semi)
1413 {
1414 if (k0)
1415
1416
1417 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1418 make_vector (1, intern ("f0")), Qnil);
1419 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k_semi),
1420 make_vector (1, intern ("f10")), Qnil);
1421 }
1422 else if (k0)
1423 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
1424 make_vector (1, intern (k0_name)), Qnil);
1425 }
1426
1427
1428 {
1429 char fcap[3], fkey[4];
1430
1431 fcap[0] = 'F'; fcap[2] = '\0';
1432 for (i = 11; i < 64; i++)
1433 {
1434 if (i <= 19)
1435 fcap[1] = '1' + i - 11;
1436 else if (i <= 45)
1437 fcap[1] = 'A' + i - 20;
1438 else
1439 fcap[1] = 'a' + i - 46;
1440
1441 {
1442 char *sequence = tgetstr (fcap, address);
1443 if (sequence)
1444 {
1445 sprintf (fkey, "f%d", i);
1446 Fdefine_key (KVAR (kboard, Vinput_decode_map),
1447 build_string (sequence),
1448 make_vector (1, intern (fkey)),
1449 Qnil);
1450 }
1451 }
1452 }
1453 }
1454
1455
1456
1457
1458 {
1459 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1460 if (!tgetstr (cap1, address)) \
1461 { \
1462 char *sequence = tgetstr (cap2, address); \
1463 if (sequence) \
1464 Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
1465 make_vector (1, intern (sym)), Qnil); \
1466 }
1467
1468
1469 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1470
1471 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1472
1473 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1474
1475 CONDITIONAL_REASSIGN ("@7", "kH", "end");
1476 #undef CONDITIONAL_REASSIGN
1477 }
1478
1479 return Qnil;
1480 }
1481 #endif
1482
1483
1484
1485 #ifndef HAVE_ANDROID
1486
1487
1488
1489
1490 static void append_glyph (struct it *);
1491 static void append_composite_glyph (struct it *);
1492 static void produce_composite_glyph (struct it *);
1493 static void append_glyphless_glyph (struct it *, int, const char *);
1494 static void produce_glyphless_glyph (struct it *, Lisp_Object);
1495
1496
1497
1498
1499
1500
1501
1502 static void
1503 append_glyph (struct it *it)
1504 {
1505 struct glyph *glyph, *end;
1506 int i;
1507
1508 eassert (it->glyph_row);
1509 glyph = (it->glyph_row->glyphs[it->area]
1510 + it->glyph_row->used[it->area]);
1511 end = it->glyph_row->glyphs[1 + it->area];
1512
1513
1514
1515 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1516 {
1517 struct glyph *g;
1518 int move_by = it->pixel_width;
1519
1520
1521 if (move_by > end - glyph)
1522 move_by = end - glyph;
1523 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1524 g[move_by] = *g;
1525 glyph = it->glyph_row->glyphs[it->area];
1526 end = glyph + move_by;
1527 }
1528
1529
1530
1531
1532
1533 for (i = 0;
1534 i < it->pixel_width && glyph < end;
1535 ++i)
1536 {
1537 glyph->type = CHAR_GLYPH;
1538 glyph->pixel_width = 1;
1539 glyph->u.ch = it->char_to_display;
1540 glyph->face_id = it->face_id;
1541 glyph->avoid_cursor_p = it->avoid_cursor_p;
1542 glyph->multibyte_p = it->multibyte_p;
1543 glyph->padding_p = i > 0;
1544 glyph->charpos = CHARPOS (it->position);
1545 glyph->object = it->object;
1546 if (it->bidi_p)
1547 {
1548 glyph->resolved_level = it->bidi_it.resolved_level;
1549 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
1550 glyph->bidi_type = it->bidi_it.type;
1551 }
1552 else
1553 {
1554 glyph->resolved_level = 0;
1555 glyph->bidi_type = UNKNOWN_BT;
1556 }
1557
1558 ++it->glyph_row->used[it->area];
1559 ++glyph;
1560 }
1561 }
1562
1563 #endif
1564
1565
1566 void
1567 tty_append_glyph (struct it *it)
1568 {
1569 #ifndef HAVE_ANDROID
1570 append_glyph (it);
1571 #endif
1572 }
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593 void
1594 produce_glyphs (struct it *it)
1595 {
1596 #ifndef HAVE_ANDROID
1597
1598
1599
1600 eassert (it->what == IT_CHARACTER
1601 || it->what == IT_COMPOSITION
1602 || it->what == IT_STRETCH
1603 || it->what == IT_GLYPHLESS);
1604
1605 if (it->what == IT_STRETCH)
1606 {
1607 produce_stretch_glyph (it);
1608 goto done;
1609 }
1610
1611 if (it->what == IT_COMPOSITION)
1612 {
1613 produce_composite_glyph (it);
1614 goto done;
1615 }
1616
1617 if (it->what == IT_GLYPHLESS)
1618 {
1619 produce_glyphless_glyph (it, Qnil);
1620 goto done;
1621 }
1622
1623 if (it->char_to_display >= 040 && it->char_to_display < 0177)
1624 {
1625 it->pixel_width = it->nglyphs = 1;
1626 if (it->glyph_row)
1627 append_glyph (it);
1628 }
1629 else if (it->char_to_display == '\n')
1630 it->pixel_width = it->nglyphs = 0;
1631 else if (it->char_to_display == '\t')
1632 {
1633 int absolute_x = (it->current_x
1634 + it->continuation_lines_width);
1635 int x0 = absolute_x;
1636
1637 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
1638 absolute_x -= it->lnum_pixel_width;
1639 int next_tab_x
1640 = (((1 + absolute_x + it->tab_width - 1)
1641 / it->tab_width)
1642 * it->tab_width);
1643 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
1644 next_tab_x += it->lnum_pixel_width;
1645 int nspaces;
1646
1647
1648
1649
1650
1651
1652 nspaces = next_tab_x - x0;
1653
1654 if (it->glyph_row)
1655 {
1656 int n = nspaces;
1657
1658 it->char_to_display = ' ';
1659 it->pixel_width = it->len = 1;
1660
1661 while (n--)
1662 append_glyph (it);
1663 }
1664
1665 it->pixel_width = nspaces;
1666 it->nglyphs = nspaces;
1667 }
1668 else if (CHAR_BYTE8_P (it->char_to_display))
1669 {
1670
1671
1672
1673
1674 it->pixel_width = it->nglyphs = 1;
1675 if (it->glyph_row)
1676 append_glyph (it);
1677 }
1678 else
1679 {
1680 struct terminal *t = FRAME_TERMINAL (it->f);
1681 Lisp_Object charset_list = t->charset_list, char_glyph;
1682
1683 if (char_charset (it->char_to_display, charset_list, NULL)
1684 && (char_glyph = terminal_glyph_code (t, it->char_to_display),
1685 NILP (char_glyph)
1686 || (FIXNUMP (char_glyph) && XFIXNUM (char_glyph) >= 0)))
1687 {
1688 it->pixel_width = CHARACTER_WIDTH (it->char_to_display);
1689 it->nglyphs = it->pixel_width;
1690 if (it->glyph_row)
1691 append_glyph (it);
1692 }
1693 else
1694 {
1695 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1696
1697 eassert (it->what == IT_GLYPHLESS);
1698 produce_glyphless_glyph (it, acronym);
1699 }
1700 }
1701
1702 done:
1703
1704
1705 if (it->area == TEXT_AREA)
1706 it->current_x += it->pixel_width;
1707 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1708 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1709 #endif
1710 }
1711
1712 #ifndef HAVE_ANDROID
1713
1714
1715
1716
1717
1718
1719 static void
1720 append_composite_glyph (struct it *it)
1721 {
1722 struct glyph *glyph;
1723
1724 eassert (it->glyph_row);
1725 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1726 if (glyph < it->glyph_row->glyphs[1 + it->area])
1727 {
1728
1729
1730 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1731 {
1732 struct glyph *g;
1733
1734
1735 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1736 g[1] = *g;
1737 glyph = it->glyph_row->glyphs[it->area];
1738 }
1739 glyph->type = COMPOSITE_GLYPH;
1740 eassert (it->pixel_width <= SHRT_MAX);
1741 glyph->pixel_width = it->pixel_width;
1742 glyph->u.cmp.id = it->cmp_it.id;
1743 if (it->cmp_it.ch < 0)
1744 {
1745 glyph->u.cmp.automatic = 0;
1746 glyph->u.cmp.id = it->cmp_it.id;
1747 }
1748 else
1749 {
1750 glyph->u.cmp.automatic = 1;
1751 glyph->u.cmp.id = it->cmp_it.id;
1752 glyph->slice.cmp.from = it->cmp_it.from;
1753 glyph->slice.cmp.to = it->cmp_it.to - 1;
1754 }
1755
1756 glyph->avoid_cursor_p = it->avoid_cursor_p;
1757 glyph->multibyte_p = it->multibyte_p;
1758 glyph->face_id = it->face_id;
1759 glyph->padding_p = false;
1760 glyph->charpos = CHARPOS (it->position);
1761 glyph->object = it->object;
1762 if (it->bidi_p)
1763 {
1764 glyph->resolved_level = it->bidi_it.resolved_level;
1765 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
1766 glyph->bidi_type = it->bidi_it.type;
1767 }
1768 else
1769 {
1770 glyph->resolved_level = 0;
1771 glyph->bidi_type = UNKNOWN_BT;
1772 }
1773
1774 ++it->glyph_row->used[it->area];
1775 ++glyph;
1776 }
1777 }
1778
1779
1780
1781
1782
1783
1784
1785 static void
1786 produce_composite_glyph (struct it *it)
1787 {
1788 if (it->cmp_it.ch < 0)
1789 {
1790 struct composition *cmp = composition_table[it->cmp_it.id];
1791
1792 it->pixel_width = cmp->width;
1793 }
1794 else
1795 {
1796 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
1797
1798 it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
1799 it->cmp_it.to, NULL);
1800 }
1801 it->nglyphs = 1;
1802 if (it->glyph_row)
1803 append_composite_glyph (it);
1804 }
1805
1806
1807
1808
1809
1810
1811
1812 static void
1813 append_glyphless_glyph (struct it *it, int face_id, const char *str)
1814 {
1815 struct glyph *glyph, *end;
1816 int i;
1817
1818 eassert (it->glyph_row);
1819 glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
1820 end = it->glyph_row->glyphs[1 + it->area];
1821
1822
1823
1824 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
1825 {
1826 struct glyph *g;
1827 int move_by = it->pixel_width;
1828
1829
1830 if (move_by > end - glyph)
1831 move_by = end - glyph;
1832 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
1833 g[move_by] = *g;
1834 glyph = it->glyph_row->glyphs[it->area];
1835 end = glyph + move_by;
1836 }
1837
1838 if (glyph >= end)
1839 return;
1840 glyph->type = CHAR_GLYPH;
1841 glyph->pixel_width = 1;
1842 glyph->avoid_cursor_p = it->avoid_cursor_p;
1843 glyph->multibyte_p = it->multibyte_p;
1844 glyph->face_id = face_id;
1845 glyph->padding_p = false;
1846 glyph->charpos = CHARPOS (it->position);
1847 glyph->object = it->object;
1848 if (it->bidi_p)
1849 {
1850 glyph->resolved_level = it->bidi_it.resolved_level;
1851 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
1852 glyph->bidi_type = it->bidi_it.type;
1853 }
1854 else
1855 {
1856 glyph->resolved_level = 0;
1857 glyph->bidi_type = UNKNOWN_BT;
1858 }
1859
1860
1861
1862
1863 for (i = 0; i < it->nglyphs && glyph < end; ++i)
1864 {
1865 if (i > 0)
1866 glyph[0] = glyph[-1];
1867 glyph->u.ch = str[i];
1868 ++it->glyph_row->used[it->area];
1869 ++glyph;
1870 }
1871 }
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882 static void
1883 produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
1884 {
1885 int len, face_id = merge_glyphless_glyph_face (it);
1886 char buf[sizeof "\\x" + max (6, (INT_WIDTH + 3) / 4)];
1887 char const *str = " ";
1888
1889 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
1890 {
1891
1892
1893 len = 1;
1894 }
1895 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
1896 {
1897 len = CHARACTER_WIDTH (it->c);
1898 if (len == 0)
1899 len = 1;
1900 else if (len > 4)
1901 len = 4;
1902 len = sprintf (buf, "[%.*s]", len, str);
1903 str = buf;
1904 }
1905 else
1906 {
1907 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
1908 {
1909 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
1910 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
1911 if (CONSP (acronym))
1912 acronym = XCDR (acronym);
1913 str = STRINGP (acronym) ? SSDATA (acronym) : "";
1914
1915
1916
1917 if (STRINGP (acronym) && SCHARS (acronym) == 1)
1918 {
1919 buf[0] = str[0];
1920 len = 1;
1921 }
1922 else
1923 {
1924 buf[0] = '[';
1925 for (len = 0;
1926 len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++)
1927 buf[1 + len] = str[len];
1928 buf[1 + len] = ']';
1929 len += 2;
1930 }
1931 }
1932 else
1933 {
1934 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
1935 len = sprintf (buf,
1936 (it->c < 0x10000 ? "\\u%04X"
1937 : it->c <= MAX_UNICODE_CHAR ? "\\U%06X"
1938 : "\\x%06X"),
1939 it->c + 0u);
1940 }
1941 str = buf;
1942 }
1943
1944 it->pixel_width = len;
1945 it->nglyphs = len;
1946 if (it->glyph_row)
1947 append_glyphless_glyph (it, face_id, str);
1948 }
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960 #define MAY_USE_WITH_COLORS_P(tty, ATTR) \
1961 (tty->TN_max_colors > 0 \
1962 ? (tty->TN_no_color_video & (ATTR)) == 0 \
1963 : 1)
1964
1965
1966
1967
1968 static void
1969 turn_on_face (struct frame *f, int face_id)
1970 {
1971 struct face *face = FACE_FROM_ID (f, face_id);
1972 unsigned long fg = face->foreground;
1973 unsigned long bg = face->background;
1974 struct tty_display_info *tty = FRAME_TTY (f);
1975
1976
1977
1978
1979 if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE)
1980 && (inverse_video
1981 ? fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR
1982 : fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR))
1983 tty_toggle_highlight (tty);
1984
1985 if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
1986 OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
1987
1988 if (face->tty_italic_p && MAY_USE_WITH_COLORS_P (tty, NC_ITALIC))
1989 {
1990 if (tty->TS_enter_italic_mode)
1991 OUTPUT1 (tty, tty->TS_enter_italic_mode);
1992 else
1993
1994
1995
1996 OUTPUT1 (tty, tty->TS_enter_dim_mode);
1997 }
1998
1999 if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
2000 OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
2001
2002 if (face->tty_strike_through_p
2003 && MAY_USE_WITH_COLORS_P (tty, NC_STRIKE_THROUGH))
2004 OUTPUT1_IF (tty, tty->TS_enter_strike_through_mode);
2005
2006 if (tty->TN_max_colors > 0)
2007 {
2008 const char *ts;
2009 char *p;
2010
2011 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
2012 if (face_tty_specified_color (fg) && ts)
2013 {
2014 p = tparam (ts, NULL, 0, fg, 0, 0, 0);
2015 OUTPUT (tty, p);
2016 xfree (p);
2017 }
2018
2019 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
2020 if (face_tty_specified_color (bg) && ts)
2021 {
2022 p = tparam (ts, NULL, 0, bg, 0, 0, 0);
2023 OUTPUT (tty, p);
2024 xfree (p);
2025 }
2026 }
2027 }
2028
2029
2030
2031
2032 static void
2033 turn_off_face (struct frame *f, int face_id)
2034 {
2035 struct face *face = FACE_FROM_ID (f, face_id);
2036 struct tty_display_info *tty = FRAME_TTY (f);
2037
2038 if (tty->TS_exit_attribute_mode)
2039 {
2040
2041
2042
2043 if (face->tty_bold_p
2044 || face->tty_italic_p
2045 || face->tty_reverse_p
2046 || face->tty_underline_p
2047 || face->tty_strike_through_p)
2048 {
2049 OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
2050 if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
2051 tty->standout_mode = 0;
2052 }
2053 }
2054 else
2055 {
2056
2057
2058 if (face->tty_underline_p)
2059 OUTPUT_IF (tty, tty->TS_exit_underline_mode);
2060 }
2061
2062
2063 if (tty->TN_max_colors > 0
2064 && ((face->foreground != FACE_TTY_DEFAULT_COLOR
2065 && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
2066 || (face->background != FACE_TTY_DEFAULT_COLOR
2067 && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
2068 OUTPUT1_IF (tty, tty->TS_orig_pair);
2069 }
2070
2071 #endif
2072
2073
2074
2075
2076 bool
2077 tty_capable_p (struct tty_display_info *tty, unsigned int caps)
2078 {
2079 #ifndef HAVE_ANDROID
2080 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
2081 if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P (tty, NC_bit))) \
2082 return 0;
2083
2084 TTY_CAPABLE_P_TRY (tty,
2085 TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE);
2086 TTY_CAPABLE_P_TRY (tty,
2087 TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode,
2088 NC_UNDERLINE);
2089 TTY_CAPABLE_P_TRY (tty,
2090 TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD);
2091 TTY_CAPABLE_P_TRY (tty,
2092 TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM);
2093 TTY_CAPABLE_P_TRY (tty,
2094 TTY_CAP_ITALIC, tty->TS_enter_italic_mode, NC_ITALIC);
2095 TTY_CAPABLE_P_TRY (tty,
2096 TTY_CAP_STRIKE_THROUGH, tty->TS_enter_strike_through_mode,
2097 NC_STRIKE_THROUGH);
2098
2099
2100 return 1;
2101 #else
2102 return false;
2103 #endif
2104 }
2105
2106
2107
2108 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
2109 0, 1, 0,
2110 doc:
2111
2112
2113
2114 )
2115 (Lisp_Object terminal)
2116 {
2117 struct terminal *t = decode_tty_terminal (terminal);
2118
2119 return (t && t->display_info.tty->TN_max_colors > 0) ? Qt : Qnil;
2120 }
2121
2122
2123 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
2124 Stty_display_color_cells, 0, 1, 0,
2125 doc:
2126
2127
2128
2129 )
2130 (Lisp_Object terminal)
2131 {
2132 struct terminal *t = decode_tty_terminal (terminal);
2133
2134 return make_fixnum (t ? t->display_info.tty->TN_max_colors : 0);
2135 }
2136
2137 #if !defined DOS_NT && !defined HAVE_ANDROID
2138
2139
2140
2141
2142 static int default_max_colors;
2143 static int default_no_color_video;
2144 static char *default_orig_pair;
2145 static char *default_set_foreground;
2146 static char *default_set_background;
2147
2148
2149
2150 static void
2151 tty_default_color_capabilities (struct tty_display_info *tty, bool save)
2152 {
2153
2154 if (save)
2155 {
2156 dupstring (&default_orig_pair, tty->TS_orig_pair);
2157 dupstring (&default_set_foreground, tty->TS_set_foreground);
2158 dupstring (&default_set_background, tty->TS_set_background);
2159 default_max_colors = tty->TN_max_colors;
2160 default_no_color_video = tty->TN_no_color_video;
2161 }
2162 else
2163 {
2164 tty->TS_orig_pair = default_orig_pair;
2165 tty->TS_set_foreground = default_set_foreground;
2166 tty->TS_set_background = default_set_background;
2167 tty->TN_max_colors = default_max_colors;
2168 tty->TN_no_color_video = default_no_color_video;
2169 }
2170 }
2171
2172
2173
2174
2175
2176 static void
2177 tty_setup_colors (struct tty_display_info *tty, int mode)
2178 {
2179
2180 if (mode < -1)
2181 mode = -1;
2182
2183 switch (mode)
2184 {
2185 case -1:
2186 tty->TN_max_colors = 0;
2187 tty->TN_no_color_video = 0;
2188 tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
2189 break;
2190 case 0:
2191 default:
2192 tty_default_color_capabilities (tty, 0);
2193 break;
2194 case 8:
2195 tty->TS_orig_pair = "\033[0m";
2196 #ifdef TERMINFO
2197 tty->TS_set_foreground = "\033[3%p1%dm";
2198 tty->TS_set_background = "\033[4%p1%dm";
2199 #else
2200 tty->TS_set_foreground = "\033[3%dm";
2201 tty->TS_set_background = "\033[4%dm";
2202 #endif
2203 tty->TN_max_colors = 8;
2204 tty->TN_no_color_video = 0;
2205 break;
2206 }
2207 }
2208
2209 void
2210 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2211 {
2212 Lisp_Object tem, val;
2213 Lisp_Object color_mode;
2214 int mode;
2215 Lisp_Object tty_color_mode_alist
2216 = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
2217
2218 tem = assq_no_quit (Qtty_color_mode, f->param_alist);
2219 val = CONSP (tem) ? XCDR (tem) : Qnil;
2220
2221 if (FIXNUMP (val))
2222 color_mode = val;
2223 else if (SYMBOLP (tty_color_mode_alist))
2224 {
2225 tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
2226 color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
2227 }
2228 else
2229 color_mode = Qnil;
2230
2231 mode = TYPE_RANGED_FIXNUMP (int, color_mode) ? XFIXNUM (color_mode) : 0;
2232
2233 if (mode != tty->previous_color_mode)
2234 {
2235 tty->previous_color_mode = mode;
2236 tty_setup_colors (tty , mode);
2237
2238 safe_call (1, intern ("tty-set-up-initial-frame-faces"));
2239 }
2240 }
2241
2242 #endif
2243
2244 char *
2245 tty_type_name (Lisp_Object terminal)
2246 {
2247 struct terminal *t = decode_tty_terminal (terminal);
2248
2249 return t? t->display_info.tty->type: NULL;
2250 }
2251
2252 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
2253 doc:
2254
2255
2256
2257 )
2258 (Lisp_Object terminal)
2259 {
2260 char *name = tty_type_name (terminal);
2261
2262 return (name? build_string (name) : Qnil);
2263 }
2264
2265 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
2266 doc:
2267
2268
2269
2270 )
2271 (Lisp_Object terminal)
2272 {
2273 struct terminal *t = decode_tty_terminal (terminal);
2274
2275 return (t && !strcmp (t->display_info.tty->name, DEV_TTY) ? Qt : Qnil);
2276 }
2277
2278 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
2279 doc:
2280
2281
2282
2283
2284
2285
2286 )
2287 (Lisp_Object terminal)
2288 {
2289 struct terminal *t = decode_live_terminal (terminal);
2290
2291 if (t->type == output_termcap)
2292 t->display_info.tty->TS_enter_underline_mode = 0;
2293 return Qnil;
2294 }
2295
2296 DEFUN ("tty-top-frame", Ftty_top_frame, Stty_top_frame, 0, 1, 0,
2297 doc:
2298
2299
2300
2301 )
2302 (Lisp_Object terminal)
2303 {
2304 struct terminal *t = decode_live_terminal (terminal);
2305
2306 if (t->type == output_termcap)
2307 return t->display_info.tty->top_frame;
2308 return Qnil;
2309 }
2310
2311
2312
2313 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
2314 doc:
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331 )
2332 (Lisp_Object tty)
2333 {
2334 #ifndef HAVE_ANDROID
2335 struct terminal *t = decode_tty_terminal (tty);
2336 FILE *f;
2337
2338 if (!t)
2339 error ("Attempt to suspend a non-text terminal device");
2340
2341 f = t->display_info.tty->input;
2342
2343 if (f)
2344 {
2345
2346
2347
2348 Lisp_Object term;
2349 XSETTERMINAL (term, t);
2350 CALLN (Frun_hook_with_args, intern ("suspend-tty-functions"), term);
2351
2352 reset_sys_modes (t->display_info.tty);
2353 delete_keyboard_wait_descriptor (fileno (f));
2354
2355 #ifndef MSDOS
2356 if (f != t->display_info.tty->output)
2357 emacs_fclose (t->display_info.tty->output);
2358 emacs_fclose (f);
2359 #endif
2360
2361 t->display_info.tty->input = 0;
2362 t->display_info.tty->output = 0;
2363
2364 if (FRAMEP (t->display_info.tty->top_frame))
2365 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
2366
2367 }
2368
2369
2370 clear_tty_hooks (t);
2371 #else
2372
2373 decode_tty_terminal (tty);
2374 #endif
2375
2376 return Qnil;
2377 }
2378
2379 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
2380 doc:
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395 )
2396 (Lisp_Object tty)
2397 {
2398 #ifndef HAVE_ANDROID
2399 struct terminal *t;
2400 int fd;
2401
2402 t = decode_tty_terminal (tty);
2403
2404 if (!t)
2405 error ("Attempt to resume a non-text terminal device");
2406
2407 if (!t->display_info.tty->input)
2408 {
2409 if (get_named_terminal (t->display_info.tty->name))
2410 error ("Cannot resume display while another display is active on the same device");
2411
2412 #ifdef MSDOS
2413 t->display_info.tty->output = stdout;
2414 t->display_info.tty->input = stdin;
2415 #else
2416 fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
2417 t->display_info.tty->input = t->display_info.tty->output
2418 = fd < 0 ? 0 : emacs_fdopen (fd, "w+");
2419
2420 if (! t->display_info.tty->input)
2421 {
2422 int open_errno = errno;
2423 emacs_close (fd);
2424 report_file_errno ("Cannot reopen tty device",
2425 build_string (t->display_info.tty->name),
2426 open_errno);
2427 }
2428
2429 if (!O_IGNORE_CTTY && strcmp (t->display_info.tty->name, DEV_TTY) != 0)
2430 dissociate_if_controlling_tty (fd);
2431 #endif
2432
2433 add_keyboard_wait_descriptor (fd);
2434
2435 if (FRAMEP (t->display_info.tty->top_frame))
2436 {
2437 struct frame *f = XFRAME (t->display_info.tty->top_frame);
2438 int width, height;
2439 int old_height = FRAME_COLS (f);
2440 int old_width = FRAME_TOTAL_LINES (f);
2441
2442
2443
2444 get_tty_size (fileno (t->display_info.tty->input), &width, &height);
2445 if (width != old_width || height != old_height)
2446 change_frame_size (f, width, height, false, false, false);
2447 SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
2448 }
2449
2450 set_tty_hooks (t);
2451 init_sys_modes (t->display_info.tty);
2452
2453
2454 Lisp_Object term;
2455 XSETTERMINAL (term, t);
2456 CALLN (Frun_hook_with_args, intern ("resume-tty-functions"), term);
2457 }
2458
2459 set_tty_hooks (t);
2460 #else
2461 decode_tty_terminal (tty);
2462 #endif
2463
2464 return Qnil;
2465 }
2466
2467 #ifndef HAVE_ANDROID
2468
2469 DEFUN ("tty--set-output-buffer-size", Ftty__set_output_buffer_size,
2470 Stty__set_output_buffer_size, 1, 2, 0, doc:
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480 )
2481 (Lisp_Object size, Lisp_Object tty)
2482 {
2483 if (!TYPE_RANGED_FIXNUMP (size_t, size))
2484 error ("Invalid output buffer size");
2485 Fsuspend_tty (tty);
2486 struct terminal *terminal = decode_tty_terminal (tty);
2487 terminal->display_info.tty->output_buffer_size = XFIXNUM (size);
2488 return Fresume_tty (tty);
2489 }
2490
2491 DEFUN ("tty--output-buffer-size", Ftty__output_buffer_size,
2492 Stty__output_buffer_size, 0, 1, 0, doc:
2493
2494
2495
2496
2497
2498 )
2499 (Lisp_Object tty)
2500 {
2501 struct terminal *terminal = decode_tty_terminal (tty);
2502 if (terminal)
2503 return make_fixnum (terminal->display_info.tty->output_buffer_size);
2504 error ("Not a tty terminal");
2505 }
2506
2507 #endif
2508
2509
2510
2511
2512
2513
2514 #if !defined DOS_NT && !defined HAVE_ANDROID
2515
2516
2517 void
2518 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2519 int start_hpos, int end_hpos,
2520 enum draw_glyphs_face draw)
2521 {
2522 int nglyphs = end_hpos - start_hpos;
2523 struct frame *f = XFRAME (WINDOW_FRAME (w));
2524 struct tty_display_info *tty = FRAME_TTY (f);
2525 int face_id = tty->mouse_highlight.mouse_face_face_id;
2526 int save_x, save_y, pos_x, pos_y;
2527
2528 if (end_hpos >= row->used[TEXT_AREA])
2529 nglyphs = row->used[TEXT_AREA] - start_hpos;
2530
2531 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2532 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2533
2534
2535 save_y = curY (tty);
2536 save_x = curX (tty);
2537 cursor_to (f, pos_y, pos_x);
2538
2539 if (draw == DRAW_MOUSE_FACE)
2540 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2541 nglyphs, face_id);
2542 else if (draw == DRAW_NORMAL_TEXT)
2543 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2544
2545 cursor_to (f, save_y, save_x);
2546 }
2547
2548 #endif
2549
2550 #ifdef HAVE_GPM
2551
2552 void
2553 term_mouse_moveto (int x, int y)
2554 {
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564 }
2565
2566
2567 static Time
2568 current_Time (void)
2569 {
2570 struct timespec now = current_timespec ();
2571 Time s_1000 = now.tv_sec;
2572 s_1000 *= 1000;
2573 Time ms = now.tv_nsec / 1000000;
2574 return s_1000 + ms;
2575 }
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590 static void
2591 term_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
2592 enum scroll_bar_part *part, Lisp_Object *x,
2593 Lisp_Object *y, Time *timeptr)
2594 {
2595 *fp = SELECTED_FRAME ();
2596 (*fp)->mouse_moved = 0;
2597
2598 *bar_window = Qnil;
2599 *part = scroll_bar_above_handle;
2600
2601 XSETINT (*x, last_mouse_x);
2602 XSETINT (*y, last_mouse_y);
2603 *timeptr = current_Time ();
2604 }
2605
2606
2607
2608
2609
2610
2611 static Lisp_Object
2612 term_mouse_click (struct input_event *result, Gpm_Event *event,
2613 struct frame *f)
2614 {
2615 int i, j;
2616
2617 result->kind = MOUSE_CLICK_EVENT;
2618 for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
2619 {
2620 if (event->buttons & j) {
2621 result->code = i;
2622 break;
2623 }
2624 }
2625 result->timestamp = current_Time ();
2626
2627 if (event->type & GPM_UP)
2628 result->modifiers = up_modifier;
2629 else if (event->type & GPM_DOWN)
2630 result->modifiers = down_modifier;
2631 else
2632 result->modifiers = 0;
2633
2634 if (event->type & GPM_SINGLE)
2635 result->modifiers |= click_modifier;
2636
2637 if (event->type & GPM_DOUBLE)
2638 result->modifiers |= double_modifier;
2639
2640 if (event->type & GPM_TRIPLE)
2641 result->modifiers |= triple_modifier;
2642
2643 if (event->type & GPM_DRAG)
2644 result->modifiers |= drag_modifier;
2645
2646 if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
2647
2648
2649 if (event->modifiers & (1 << 0))
2650 result->modifiers |= shift_modifier;
2651
2652
2653 if (event->modifiers & (1 << 2))
2654 result->modifiers |= ctrl_modifier;
2655
2656
2657 if (event->modifiers & (1 << 3)
2658 || event->modifiers & (1 << 1))
2659 result->modifiers |= meta_modifier;
2660 }
2661
2662 XSETINT (result->x, event->x);
2663 XSETINT (result->y, event->y);
2664 XSETFRAME (result->frame_or_window, f);
2665 result->arg = Qnil;
2666 return Qnil;
2667 }
2668
2669 int
2670 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event)
2671 {
2672 struct frame *f = XFRAME (tty->top_frame);
2673 struct input_event ie;
2674 int count = 0;
2675
2676 EVENT_INIT (ie);
2677 ie.kind = NO_EVENT;
2678 ie.arg = Qnil;
2679
2680 if (event->type & (GPM_MOVE | GPM_DRAG))
2681 {
2682 Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
2683
2684
2685
2686 if (event->x != last_mouse_x || event->y != last_mouse_y)
2687 {
2688
2689
2690
2691
2692 last_mouse_x = event->x;
2693 last_mouse_y = event->y;
2694 f->mouse_moved = 1;
2695
2696 count += update_mouse_position (f, event->x, event->y);
2697 }
2698 }
2699 else
2700 {
2701 f->mouse_moved = 0;
2702 term_mouse_click (&ie, event, f);
2703 ie.arg = tty_handle_tab_bar_click (f, event->x, event->y,
2704 (ie.modifiers & down_modifier) != 0, &ie);
2705 kbd_buffer_store_event (&ie);
2706 count++;
2707 }
2708
2709 return count;
2710 }
2711
2712 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
2713 0, 0, 0,
2714 doc:
2715 )
2716 (void)
2717 {
2718 struct frame *f = SELECTED_FRAME ();
2719 struct tty_display_info *tty
2720 = ((f)->output_method == output_termcap
2721 ? (f)->terminal->display_info.tty : NULL);
2722 Gpm_Connect connection;
2723
2724 if (!tty)
2725 error ("Gpm-mouse only works in the GNU/Linux console");
2726 if (gpm_tty == tty)
2727 return Qnil;
2728 if (gpm_tty)
2729 error ("Gpm-mouse can only be activated for one tty at a time");
2730
2731 connection.eventMask = ~0;
2732 connection.defaultMask = ~GPM_HARD;
2733 connection.maxMod = ~0;
2734 connection.minMod = 0;
2735 gpm_zerobased = 1;
2736
2737 if (Gpm_Open (&connection, 0) < 0)
2738 error ("Gpm-mouse failed to connect to the gpm daemon");
2739 else
2740 {
2741 gpm_tty = tty;
2742
2743
2744
2745 reset_sys_modes (tty);
2746 init_sys_modes (tty);
2747 add_gpm_wait_descriptor (gpm_fd);
2748 return Qnil;
2749 }
2750 }
2751
2752 void
2753 close_gpm (int fd)
2754 {
2755 if (fd >= 0)
2756 delete_gpm_wait_descriptor (fd);
2757 while (Gpm_Close());
2758 gpm_tty = NULL;
2759 }
2760
2761 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2762 0, 0, 0,
2763 doc: )
2764 (void)
2765 {
2766 struct frame *f = SELECTED_FRAME ();
2767 struct tty_display_info *tty
2768 = ((f)->output_method == output_termcap
2769 ? (f)->terminal->display_info.tty : NULL);
2770
2771 if (!tty || gpm_tty != tty)
2772 return Qnil;
2773
2774 close_gpm (gpm_fd);
2775 return Qnil;
2776 }
2777 #endif
2778
2779
2780
2781
2782
2783
2784 #if !defined (MSDOS) && !defined HAVE_ANDROID
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800 #define TTYM_FAILURE -1
2801 #define TTYM_SUCCESS 1
2802 #define TTYM_NO_SELECT 2
2803 #define TTYM_IA_SELECT 3
2804 #define TTYM_NEXT 4
2805 #define TTYM_PREV 5
2806
2807
2808 static const char *menu_help_message, *prev_menu_help_message;
2809
2810
2811 static int menu_help_paneno, menu_help_itemno;
2812
2813 typedef struct tty_menu_struct
2814 {
2815 int count;
2816 char **text;
2817 struct tty_menu_struct **submenu;
2818 int *panenumber;
2819 ptrdiff_t allocated;
2820 int panecount;
2821 int width;
2822 const char **help_text;
2823 } tty_menu;
2824
2825
2826
2827 static tty_menu * ATTRIBUTE_MALLOC
2828 tty_menu_create (void)
2829 {
2830 return xzalloc (sizeof *tty_menu_create ());
2831 }
2832
2833
2834
2835
2836 static void
2837 tty_menu_make_room (tty_menu *menu)
2838 {
2839 if (menu->allocated == menu->count)
2840 {
2841 ptrdiff_t allocated = menu->allocated;
2842 menu->text = xpalloc (menu->text, &allocated, 1, -1, sizeof *menu->text);
2843 menu->text = xrealloc (menu->text, allocated * sizeof *menu->text);
2844 menu->submenu = xrealloc (menu->submenu,
2845 allocated * sizeof *menu->submenu);
2846 menu->panenumber = xrealloc (menu->panenumber,
2847 allocated * sizeof *menu->panenumber);
2848 menu->help_text = xrealloc (menu->help_text,
2849 allocated * sizeof *menu->help_text);
2850 menu->allocated = allocated;
2851 }
2852 }
2853
2854
2855
2856 static tty_menu *
2857 tty_menu_search_pane (tty_menu *menu, int pane)
2858 {
2859 int i;
2860 tty_menu *try;
2861
2862 for (i = 0; i < menu->count; i++)
2863 if (menu->submenu[i])
2864 {
2865 if (pane == menu->panenumber[i])
2866 return menu->submenu[i];
2867 try = tty_menu_search_pane (menu->submenu[i], pane);
2868 if (try)
2869 return try;
2870 }
2871 return (tty_menu *) 0;
2872 }
2873
2874
2875
2876 static void
2877 tty_menu_calc_size (tty_menu *menu, int *width, int *height)
2878 {
2879 int i, h2, w2, maxsubwidth, maxheight;
2880
2881 maxsubwidth = menu->width;
2882 maxheight = menu->count;
2883 for (i = 0; i < menu->count; i++)
2884 {
2885 if (menu->submenu[i])
2886 {
2887 tty_menu_calc_size (menu->submenu[i], &w2, &h2);
2888 if (w2 > maxsubwidth) maxsubwidth = w2;
2889 if (i + h2 > maxheight) maxheight = i + h2;
2890 }
2891 }
2892 *width = maxsubwidth;
2893 *height = maxheight;
2894 }
2895
2896 static void
2897 mouse_get_xy (int *x, int *y)
2898 {
2899 Lisp_Object lmx = Qnil, lmy = Qnil;
2900 Lisp_Object mouse = mouse_position (tty_menu_calls_mouse_position_function);
2901
2902 if (EQ (selected_frame, XCAR (mouse)))
2903 {
2904 lmx = XCAR (XCDR (mouse));
2905 lmy = XCDR (XCDR (mouse));
2906 }
2907
2908 if (!NILP (lmx))
2909 {
2910 *x = XFIXNUM (lmx);
2911 *y = XFIXNUM (lmy);
2912 }
2913 }
2914
2915
2916
2917
2918 static void
2919 tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
2920 int mx, int my, int first_item, bool disp_help)
2921 {
2922 int i, face, width, enabled, mousehere, row, col;
2923 struct frame *sf = SELECTED_FRAME ();
2924 struct tty_display_info *tty = FRAME_TTY (sf);
2925
2926
2927
2928 int max_items = min (menu->count - first_item, FRAME_TOTAL_LINES (sf) - 1 - y);
2929
2930 menu_help_message = NULL;
2931
2932 width = menu->width;
2933 col = cursorX (tty);
2934 row = cursorY (tty);
2935 for (i = 0; i < max_items; i++)
2936 {
2937 int max_width = width + 2;
2938 int j = i + first_item;
2939
2940 if (menu->submenu[j])
2941 max_width += 2;
2942 enabled
2943 = (!menu->submenu[j] && menu->panenumber[j]) || (menu->submenu[j]);
2944 mousehere = (y + i == my && x <= mx && mx < x + max_width);
2945 face = faces[enabled + mousehere * 2];
2946
2947
2948
2949 if (disp_help && enabled + mousehere * 2 >= 2)
2950 {
2951 menu_help_message = menu->help_text[j];
2952 menu_help_paneno = pn - 1;
2953 menu_help_itemno = j;
2954 }
2955
2956
2957 if (mousehere)
2958 {
2959 row = y + i;
2960 col = x;
2961 }
2962 display_tty_menu_item (menu->text[j], max_width, face, x, y + i,
2963 menu->submenu[j] != NULL);
2964 }
2965 update_frame_with_menu (sf, row, col);
2966 }
2967
2968
2969
2970
2971
2972 static int
2973 tty_menu_add_pane (tty_menu *menu, const char *txt)
2974 {
2975 int len;
2976
2977 tty_menu_make_room (menu);
2978 menu->submenu[menu->count] = tty_menu_create ();
2979 menu->text[menu->count] = (char *)txt;
2980 menu->panenumber[menu->count] = ++menu->panecount;
2981 menu->help_text[menu->count] = NULL;
2982 menu->count++;
2983
2984
2985 len = menu_item_width ((const unsigned char *) txt);
2986 if (len > menu->width)
2987 menu->width = len;
2988
2989 return menu->panecount;
2990 }
2991
2992
2993
2994 static bool
2995 tty_menu_add_selection (tty_menu *menu, int pane,
2996 char *txt, bool enable, char const *help_text)
2997 {
2998 int len;
2999
3000 if (pane)
3001 {
3002 menu = tty_menu_search_pane (menu, pane);
3003 if (! menu)
3004 return 0;
3005 }
3006 tty_menu_make_room (menu);
3007 menu->submenu[menu->count] = (tty_menu *) 0;
3008 menu->text[menu->count] = txt;
3009 menu->panenumber[menu->count] = enable;
3010 menu->help_text[menu->count] = help_text;
3011 menu->count++;
3012
3013
3014 len = menu_item_width ((const unsigned char *) txt);
3015 if (len > menu->width)
3016 menu->width = len;
3017
3018 return 1;
3019 }
3020
3021
3022
3023 static void
3024 tty_menu_locate (tty_menu *menu, int x, int y,
3025 int *ulx, int *uly, int *width, int *height)
3026 {
3027 tty_menu_calc_size (menu, width, height);
3028 *ulx = x + 1;
3029 *uly = y;
3030 *width += 2;
3031 }
3032
3033 struct tty_menu_state
3034 {
3035 struct glyph_matrix *screen_behind;
3036 tty_menu *menu;
3037 int pane;
3038 int x, y;
3039 };
3040
3041
3042
3043
3044
3045 static struct glyph_matrix *
3046 save_and_enable_current_matrix (struct frame *f)
3047 {
3048 int i;
3049 struct glyph_matrix *saved = xzalloc (sizeof *saved);
3050 saved->nrows = f->current_matrix->nrows;
3051 saved->rows = xzalloc (saved->nrows * sizeof *saved->rows);
3052
3053 for (i = 0; i < saved->nrows; ++i)
3054 {
3055 struct glyph_row *from = f->current_matrix->rows + i;
3056 struct glyph_row *to = saved->rows + i;
3057 ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
3058
3059 to->glyphs[TEXT_AREA] = xmalloc (nbytes);
3060 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
3061 to->used[TEXT_AREA] = from->used[TEXT_AREA];
3062
3063
3064
3065 to->enabled_p = true;
3066 to->hash = from->hash;
3067 }
3068
3069 return saved;
3070 }
3071
3072
3073
3074
3075 static void
3076 restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
3077 {
3078 int i;
3079
3080 for (i = 0; i < saved->nrows; ++i)
3081 {
3082 struct glyph_row *from = saved->rows + i;
3083 struct glyph_row *to = f->desired_matrix->rows + i;
3084 ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
3085
3086 eassert (to->glyphs[TEXT_AREA] != from->glyphs[TEXT_AREA]);
3087 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
3088 to->used[TEXT_AREA] = from->used[TEXT_AREA];
3089 to->enabled_p = from->enabled_p;
3090 to->hash = from->hash;
3091 }
3092 }
3093
3094 static void
3095 free_saved_screen (struct glyph_matrix *saved)
3096 {
3097 int i;
3098
3099 if (!saved)
3100 return;
3101
3102 for (i = 0; i < saved->nrows; ++i)
3103 {
3104 struct glyph_row *from = saved->rows + i;
3105
3106 xfree (from->glyphs[TEXT_AREA]);
3107 }
3108
3109 xfree (saved->rows);
3110 xfree (saved);
3111 }
3112
3113
3114 static void
3115 screen_update (struct frame *f, struct glyph_matrix *mtx)
3116 {
3117 restore_desired_matrix (f, mtx);
3118 update_frame_with_menu (f, -1, -1);
3119 }
3120
3121 typedef enum {
3122 MI_QUIT_MENU = -1,
3123 MI_CONTINUE = 0,
3124 MI_ITEM_SELECTED = 1,
3125 MI_NEXT_ITEM = 2,
3126 MI_PREV_ITEM = 3,
3127 MI_SCROLL_FORWARD = 4,
3128 MI_SCROLL_BACK = 5
3129 } mi_result;
3130
3131
3132
3133
3134 static mi_result
3135 read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
3136 bool *first_time)
3137 {
3138 if (*first_time)
3139 {
3140 *first_time = false;
3141 sf->mouse_moved = 1;
3142 }
3143 else
3144 {
3145 Lisp_Object cmd;
3146 bool usable_input = 1;
3147 mi_result st = MI_CONTINUE;
3148 struct tty_display_info *tty = FRAME_TTY (sf);
3149 Lisp_Object old_track_mouse = track_mouse;
3150
3151
3152
3153 tty->showing_menu = 1;
3154
3155 track_mouse = Qt;
3156 do {
3157 cmd = read_menu_command ();
3158 } while (NILP (cmd));
3159 tty->showing_menu = 0;
3160 track_mouse = old_track_mouse;
3161
3162 if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit)
3163
3164
3165
3166 || sf != SELECTED_FRAME ())
3167 return MI_QUIT_MENU;
3168 if (EQ (cmd, Qtty_menu_mouse_movement))
3169 mouse_get_xy (x, y);
3170 else if (EQ (cmd, Qtty_menu_next_menu))
3171 {
3172 usable_input = 0;
3173 st = MI_NEXT_ITEM;
3174 }
3175 else if (EQ (cmd, Qtty_menu_prev_menu))
3176 {
3177 usable_input = 0;
3178 st = MI_PREV_ITEM;
3179 }
3180 else if (EQ (cmd, Qtty_menu_next_item))
3181 {
3182 if (*y < max_y)
3183 *y += 1;
3184 else
3185 st = MI_SCROLL_FORWARD;
3186 }
3187 else if (EQ (cmd, Qtty_menu_prev_item))
3188 {
3189 if (*y > min_y)
3190 *y -= 1;
3191 else
3192 st = MI_SCROLL_BACK;
3193 }
3194 else if (EQ (cmd, Qtty_menu_select))
3195 st = MI_ITEM_SELECTED;
3196 else if (!EQ (cmd, Qtty_menu_ignore))
3197 usable_input = 0;
3198 if (usable_input)
3199 sf->mouse_moved = 1;
3200 return st;
3201 }
3202 return MI_CONTINUE;
3203 }
3204
3205
3206 static int
3207 tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3208 int x0, int y0, char **txt,
3209 void (*help_callback)(char const *, int, int),
3210 bool kbd_navigation)
3211 {
3212 struct tty_menu_state *state;
3213 int statecount, x, y, i;
3214 bool leave, onepane;
3215 int result UNINIT;
3216 int title_faces[4];
3217 int faces[4], buffers_num_deleted = 0;
3218 struct frame *sf = SELECTED_FRAME ();
3219 struct tty_display_info *tty = FRAME_TTY (sf);
3220 bool first_time;
3221 Lisp_Object selectface;
3222 int first_item = 0;
3223 int col, row;
3224 Lisp_Object prev_inhibit_redisplay = Vinhibit_redisplay;
3225 USE_SAFE_ALLOCA;
3226
3227
3228
3229 if (x0 <= 0)
3230 x0 = 1;
3231 if (y0 <= 0)
3232 y0 = 1;
3233
3234 SAFE_NALLOCA (state, 1, menu->panecount);
3235 memset (state, 0, sizeof (*state));
3236 faces[0]
3237 = lookup_derived_face (NULL, sf, intern ("tty-menu-disabled-face"),
3238 DEFAULT_FACE_ID, 1);
3239 faces[1]
3240 = lookup_derived_face (NULL, sf, intern ("tty-menu-enabled-face"),
3241 DEFAULT_FACE_ID, 1);
3242 selectface = intern ("tty-menu-selected-face");
3243 faces[2] = lookup_derived_face (NULL, sf, selectface,
3244 faces[0], 1);
3245 faces[3] = lookup_derived_face (NULL, sf, selectface,
3246 faces[1], 1);
3247
3248
3249
3250 for (i = 0; i < 4; i++)
3251 title_faces[i] = faces[3];
3252
3253 statecount = 1;
3254
3255
3256
3257
3258
3259
3260
3261 if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
3262 {
3263 menu->text[0][7] = '\0';
3264 buffers_num_deleted = 1;
3265 }
3266
3267
3268
3269
3270 Vinhibit_redisplay = Qt;
3271
3272
3273
3274 update_frame_with_menu (sf, -1, -1);
3275 state[0].menu = menu;
3276 state[0].screen_behind = save_and_enable_current_matrix (sf);
3277
3278
3279
3280
3281
3282 tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0, 0);
3283
3284
3285
3286 col = cursorX (tty);
3287 row = cursorY (tty);
3288 tty_hide_cursor (tty);
3289
3290 if (buffers_num_deleted)
3291 menu->text[0][7] = ' ';
3292 onepane = menu->count == 1 && menu->submenu[0];
3293 if (onepane)
3294 {
3295 menu->width = menu->submenu[0]->width;
3296 state[0].menu = menu->submenu[0];
3297 }
3298 else
3299 {
3300 state[0].menu = menu;
3301 }
3302 state[0].x = x0 - 1;
3303 state[0].y = y0;
3304 state[0].pane = onepane;
3305
3306 x = state[0].x;
3307 y = state[0].y;
3308 first_time = true;
3309
3310 leave = 0;
3311 while (!leave)
3312 {
3313 mi_result input_status;
3314 int min_y = state[0].y;
3315 int max_y = min (min_y + state[0].menu->count, FRAME_TOTAL_LINES (sf) - 1) - 1;
3316
3317 input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
3318 if (input_status)
3319 {
3320 leave = 1;
3321 switch (input_status)
3322 {
3323 case MI_QUIT_MENU:
3324
3325
3326 show_help_echo (Qnil, Qnil, Qnil, Qnil);
3327 result = TTYM_NO_SELECT;
3328 break;
3329 case MI_NEXT_ITEM:
3330 if (kbd_navigation)
3331 result = TTYM_NEXT;
3332 else
3333 leave = 0;
3334 break;
3335 case MI_PREV_ITEM:
3336 if (kbd_navigation)
3337 result = TTYM_PREV;
3338 else
3339 leave = 0;
3340 break;
3341 case MI_SCROLL_FORWARD:
3342 if (y - min_y == state[0].menu->count - 1 - first_item)
3343 {
3344 y = min_y;
3345 first_item = 0;
3346 }
3347 else
3348 first_item++;
3349 leave = 0;
3350 break;
3351 case MI_SCROLL_BACK:
3352 if (first_item == 0)
3353 {
3354 y = max_y;
3355 first_item = state[0].menu->count - 1 - (y - min_y);
3356 }
3357 else
3358 first_item--;
3359 leave = 0;
3360 break;
3361 default:
3362
3363 break;
3364 }
3365 }
3366 if (sf->mouse_moved && input_status != MI_QUIT_MENU)
3367 {
3368 sf->mouse_moved = 0;
3369 result = TTYM_IA_SELECT;
3370 for (i = 0; i < statecount; i++)
3371 if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
3372 {
3373 int dy = y - state[i].y + first_item;
3374 if (0 <= dy && dy < state[i].menu->count)
3375 {
3376 if (!state[i].menu->submenu[dy])
3377 {
3378 if (state[i].menu->panenumber[dy])
3379 result = TTYM_SUCCESS;
3380 else
3381 result = TTYM_IA_SELECT;
3382 }
3383 *pane = state[i].pane - 1;
3384 *selidx = dy;
3385
3386
3387
3388 if (i != statecount - 2
3389 || state[i].menu->submenu[dy] != state[i + 1].menu)
3390 while (i < statecount - 1)
3391 {
3392 statecount--;
3393 screen_update (sf, state[statecount].screen_behind);
3394 state[statecount].screen_behind = NULL;
3395 }
3396 if (i == statecount - 1 && state[i].menu->submenu[dy])
3397 {
3398 tty_menu_display (state[i].menu,
3399 state[i].x,
3400 state[i].y,
3401 state[i].pane,
3402 faces, x, y, first_item, 1);
3403 state[statecount].menu = state[i].menu->submenu[dy];
3404 state[statecount].pane = state[i].menu->panenumber[dy];
3405 state[statecount].screen_behind
3406 = save_and_enable_current_matrix (sf);
3407 state[statecount].x
3408 = state[i].x + state[i].menu->width + 2;
3409 state[statecount].y = y;
3410 statecount++;
3411 }
3412 }
3413 }
3414 tty_menu_display (state[statecount - 1].menu,
3415 state[statecount - 1].x,
3416 state[statecount - 1].y,
3417 state[statecount - 1].pane,
3418 faces, x, y, first_item, 1);
3419
3420
3421
3422 col = cursorX (tty);
3423 row = cursorY (tty);
3424 }
3425
3426
3427
3428 if ((menu_help_message || prev_menu_help_message)
3429 && menu_help_message != prev_menu_help_message)
3430 {
3431 help_callback (menu_help_message,
3432 menu_help_paneno, menu_help_itemno);
3433
3434
3435
3436 cursor_to (sf, row, col);
3437 prev_menu_help_message = menu_help_message;
3438 }
3439
3440
3441
3442 tty_hide_cursor (tty);
3443 fflush (tty->output);
3444 }
3445
3446 sf->mouse_moved = 0;
3447 screen_update (sf, state[0].screen_behind);
3448 while (statecount--)
3449 free_saved_screen (state[statecount].screen_behind);
3450 tty_show_cursor (tty);
3451 fflush (tty->output);
3452
3453
3454
3455
3456
3457
3458 discard_mouse_events ();
3459 if (!kbd_buffer_events_waiting ())
3460 clear_input_pending ();
3461 SAFE_FREE ();
3462 Vinhibit_redisplay = prev_inhibit_redisplay;
3463 return result;
3464 }
3465
3466
3467
3468 static void
3469 tty_menu_destroy (tty_menu *menu)
3470 {
3471 int i;
3472 if (menu->allocated)
3473 {
3474 for (i = 0; i < menu->count; i++)
3475 if (menu->submenu[i])
3476 tty_menu_destroy (menu->submenu[i]);
3477 xfree (menu->text);
3478 xfree (menu->submenu);
3479 xfree (menu->panenumber);
3480 xfree (menu->help_text);
3481 }
3482 xfree (menu);
3483 menu_help_message = prev_menu_help_message = NULL;
3484 }
3485
3486
3487
3488
3489
3490
3491 static void
3492 tty_menu_help_callback (char const *help_string, int pane, int item)
3493 {
3494 Lisp_Object *first_item;
3495 Lisp_Object pane_name;
3496 Lisp_Object menu_object;
3497
3498 first_item = XVECTOR (menu_items)->contents;
3499 if (EQ (first_item[0], Qt))
3500 pane_name = first_item[MENU_ITEMS_PANE_NAME];
3501 else if (EQ (first_item[0], Qquote))
3502
3503 pane_name = empty_unibyte_string;
3504 else
3505 pane_name = first_item[MENU_ITEMS_ITEM_NAME];
3506
3507
3508 menu_object = list3 (Qmenu_item, pane_name, make_fixnum (pane));
3509 show_help_echo (help_string ? build_string (help_string) : Qnil,
3510 Qnil, menu_object, make_fixnum (item));
3511 }
3512
3513 struct tty_pop_down_menu
3514 {
3515 tty_menu *menu;
3516 struct buffer *buffer;
3517 };
3518
3519 static void
3520 tty_pop_down_menu (void *arg)
3521 {
3522 struct tty_pop_down_menu *data = arg;
3523
3524 block_input ();
3525 tty_menu_destroy (data->menu);
3526 set_buffer_internal (data->buffer);
3527 unblock_input ();
3528 }
3529
3530
3531 static int
3532 tty_menu_last_menubar_item (struct frame *f)
3533 {
3534 int i = 0;
3535
3536 eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
3537 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
3538 {
3539 Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
3540
3541 while (i < ASIZE (items))
3542 {
3543 Lisp_Object str;
3544
3545 str = AREF (items, i + 1);
3546 if (NILP (str))
3547 break;
3548 i += 4;
3549 }
3550 i -= 4;
3551 }
3552 return i;
3553 }
3554
3555
3556
3557
3558
3559
3560 static void
3561 tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y)
3562 {
3563 eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
3564 if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
3565 {
3566 Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
3567 int last_i = tty_menu_last_menubar_item (f);
3568 int i, prev_x;
3569
3570
3571
3572
3573 for (i = 0, prev_x = -1; i < ASIZE (items); i += 4)
3574 {
3575 Lisp_Object pos, str;
3576 int ix;
3577
3578 str = AREF (items, i + 1);
3579 pos = AREF (items, i + 3);
3580 if (NILP (str))
3581 return;
3582 ix = XFIXNUM (pos);
3583 if (ix <= *x
3584
3585
3586 && *x <= ix + menu_item_width (SDATA (str)))
3587 {
3588
3589
3590 if (which == TTYM_NEXT)
3591 {
3592 if (i < last_i)
3593 *x = XFIXNUM (AREF (items, i + 4 + 3));
3594 else
3595 *x = 0;
3596 }
3597 else if (prev_x < 0)
3598 {
3599
3600 *x = XFIXNUM (AREF (items, last_i + 3));
3601 }
3602 else
3603 *x = prev_x;
3604 return;
3605 }
3606 prev_x = ix;
3607 }
3608 }
3609 }
3610
3611
3612 Lisp_Object
3613 tty_menu_show (struct frame *f, int x, int y, int menuflags,
3614 Lisp_Object title, const char **error_name)
3615 {
3616 tty_menu *menu;
3617 int pane, selidx, lpane, status;
3618 Lisp_Object entry, pane_prefix;
3619 char *datap;
3620 int ulx, uly, width, height;
3621 int item_x, item_y;
3622 int dispwidth, dispheight;
3623 int i, j, lines, maxlines;
3624 int maxwidth;
3625 specpdl_ref specpdl_count;
3626
3627 eassert (FRAME_TERMCAP_P (f));
3628
3629 *error_name = 0;
3630 if (menu_items_n_panes == 0)
3631 return Qnil;
3632
3633 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
3634 {
3635 *error_name = "Empty menu";
3636 return Qnil;
3637 }
3638
3639
3640 menu = tty_menu_create ();
3641
3642
3643
3644 specpdl_count = inhibit_garbage_collection ();
3645
3646
3647
3648 temporarily_switch_to_single_kboard (f);
3649
3650
3651 item_x = x += f->left_pos;
3652 item_y = y += f->top_pos;
3653
3654
3655 USE_SAFE_ALLOCA;
3656 maxwidth = maxlines = lines = i = 0;
3657 lpane = TTYM_FAILURE;
3658 while (i < menu_items_used)
3659 {
3660 if (EQ (AREF (menu_items, i), Qt))
3661 {
3662
3663 Lisp_Object pane_name, prefix;
3664 const char *pane_string;
3665
3666 maxlines = max (maxlines, lines);
3667 lines = 0;
3668 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
3669 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
3670 pane_string = (NILP (pane_name)
3671 ? "" : SSDATA (pane_name));
3672 if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
3673 pane_string++;
3674
3675 lpane = tty_menu_add_pane (menu, pane_string);
3676 if (lpane == TTYM_FAILURE)
3677 {
3678 tty_menu_destroy (menu);
3679 *error_name = "Can't create pane";
3680 entry = Qnil;
3681 goto tty_menu_end;
3682 }
3683 i += MENU_ITEMS_PANE_LENGTH;
3684
3685
3686 j = i;
3687 while (j < menu_items_used)
3688 {
3689 Lisp_Object item;
3690 item = AREF (menu_items, j);
3691 if (EQ (item, Qt))
3692 break;
3693 if (NILP (item))
3694 {
3695 j++;
3696 continue;
3697 }
3698 width = SBYTES (item);
3699 if (width > maxwidth)
3700 maxwidth = width;
3701
3702 j += MENU_ITEMS_ITEM_LENGTH;
3703 }
3704 }
3705
3706
3707 else if (EQ (AREF (menu_items, i), Qquote))
3708 i += 1;
3709 else
3710 {
3711
3712 Lisp_Object item_name, enable, descrip, help;
3713 char *item_data;
3714 char const *help_string;
3715
3716 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
3717 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
3718 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
3719 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
3720 help_string = STRINGP (help) ? SSDATA (help) : NULL;
3721
3722 if (!NILP (descrip))
3723 {
3724 item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
3725 memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
3726 for (j = SCHARS (item_name); j < maxwidth; j++)
3727 item_data[j] = ' ';
3728 memcpy (item_data + j, SSDATA (descrip), SBYTES (descrip));
3729 item_data[j + SBYTES (descrip)] = 0;
3730 }
3731 else
3732 item_data = SSDATA (item_name);
3733
3734 if (lpane == TTYM_FAILURE
3735 || (! tty_menu_add_selection (menu, lpane, item_data,
3736 !NILP (enable), help_string)))
3737 {
3738 tty_menu_destroy (menu);
3739 *error_name = "Can't add selection to menu";
3740 entry = Qnil;
3741 goto tty_menu_end;
3742 }
3743 i += MENU_ITEMS_ITEM_LENGTH;
3744 lines++;
3745 }
3746 }
3747
3748 maxlines = max (maxlines, lines);
3749
3750
3751 dispwidth = f->text_cols;
3752 dispheight = f->text_lines;
3753 x = min (x, dispwidth);
3754 y = min (y, dispheight);
3755 x = max (x, 1);
3756 y = max (y, 1);
3757 tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
3758 if (ulx + width > dispwidth)
3759 {
3760 x -= (ulx + width) - dispwidth;
3761 ulx = dispwidth - width;
3762 }
3763 if (uly + height > dispheight)
3764 {
3765 y -= (uly + height) - dispheight;
3766 uly = dispheight - height;
3767 }
3768
3769 if (FRAME_HAS_MINIBUF_P (f) && uly + height > dispheight - 2)
3770 {
3771
3772
3773 if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
3774 {
3775 y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
3776 uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
3777 }
3778 else
3779 {
3780 y -= 2;
3781 uly -= 2;
3782 }
3783 }
3784
3785 if (ulx < 0) x -= ulx;
3786 if (uly < 0) y -= uly;
3787
3788 #if 0
3789
3790
3791
3792
3793 if (! for_click)
3794 {
3795
3796
3797
3798 x += width / 2;
3799 y += 1.5 * height / (maxlines + 2);
3800 }
3801 #endif
3802
3803 pane = selidx = 0;
3804
3805
3806
3807 record_unwind_protect_ptr (tty_pop_down_menu,
3808 &((struct tty_pop_down_menu)
3809 {menu, current_buffer}));
3810
3811 specbind (Qoverriding_terminal_local_map,
3812 Fsymbol_value (Qtty_menu_navigation_map));
3813 status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
3814 tty_menu_help_callback,
3815 menuflags & MENU_KBD_NAVIGATION);
3816 entry = pane_prefix = Qnil;
3817
3818 switch (status)
3819 {
3820 case TTYM_SUCCESS:
3821
3822 i = 0;
3823 while (i < menu_items_used)
3824 {
3825 if (EQ (AREF (menu_items, i), Qt))
3826 {
3827 if (pane == 0)
3828 pane_prefix
3829 = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
3830 pane--;
3831 i += MENU_ITEMS_PANE_LENGTH;
3832 }
3833 else
3834 {
3835 if (pane == -1)
3836 {
3837 if (selidx == 0)
3838 {
3839 entry
3840 = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
3841 if (menuflags & MENU_KEYMAPS)
3842 {
3843 entry = Fcons (entry, Qnil);
3844 if (!NILP (pane_prefix))
3845 entry = Fcons (pane_prefix, entry);
3846 }
3847 break;
3848 }
3849 selidx--;
3850 }
3851 i += MENU_ITEMS_ITEM_LENGTH;
3852 }
3853 }
3854 break;
3855
3856 case TTYM_NEXT:
3857 case TTYM_PREV:
3858 tty_menu_new_item_coords (f, status, &item_x, &item_y);
3859 entry = Fcons (make_fixnum (item_x), make_fixnum (item_y));
3860 break;
3861
3862 case TTYM_FAILURE:
3863 *error_name = "Can't activate menu";
3864 case TTYM_IA_SELECT:
3865 break;
3866 case TTYM_NO_SELECT:
3867
3868
3869
3870 if (f != SELECTED_FRAME ())
3871 Ftop_level ();
3872
3873
3874 if (!(menuflags & MENU_FOR_CLICK))
3875 quit ();
3876 break;
3877 }
3878
3879 tty_menu_end:
3880
3881 return SAFE_FREE_UNBIND_TO (specpdl_count, entry);
3882 }
3883
3884 #endif
3885
3886
3887
3888 #if !defined MSDOS && !defined HAVE_ANDROID
3889
3890
3891
3892
3893
3894
3895
3896
3897 void
3898 create_tty_output (struct frame *f)
3899 {
3900 struct tty_output *t = xzalloc (sizeof *t);
3901
3902 eassert (FRAME_TERMCAP_P (f));
3903
3904 t->display_info = FRAME_TERMINAL (f)->display_info.tty;
3905
3906 f->output_data.tty = t;
3907 }
3908
3909
3910
3911 static void
3912 tty_free_frame_resources (struct frame *f)
3913 {
3914 eassert (FRAME_TERMCAP_P (f));
3915 free_frame_faces (f);
3916 xfree (f->output_data.tty);
3917 }
3918
3919 #elif defined MSDOS
3920
3921
3922
3923 static void
3924 tty_free_frame_resources (struct frame *f)
3925 {
3926 eassert (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
3927 free_frame_faces (f);
3928 }
3929
3930 #endif
3931
3932
3933
3934 #ifndef HAVE_ANDROID
3935
3936
3937
3938 static void
3939 clear_tty_hooks (struct terminal *terminal)
3940 {
3941 terminal->rif = 0;
3942 terminal->cursor_to_hook = 0;
3943 terminal->raw_cursor_to_hook = 0;
3944 terminal->clear_to_end_hook = 0;
3945 terminal->clear_frame_hook = 0;
3946 terminal->clear_end_of_line_hook = 0;
3947 terminal->ins_del_lines_hook = 0;
3948 terminal->insert_glyphs_hook = 0;
3949 terminal->write_glyphs_hook = 0;
3950 terminal->delete_glyphs_hook = 0;
3951 terminal->ring_bell_hook = 0;
3952 terminal->reset_terminal_modes_hook = 0;
3953 terminal->set_terminal_modes_hook = 0;
3954 terminal->update_begin_hook = 0;
3955 terminal->update_end_hook = 0;
3956 terminal->set_terminal_window_hook = 0;
3957
3958
3959
3960 terminal->mouse_position_hook = 0;
3961 terminal->frame_rehighlight_hook = 0;
3962 terminal->frame_raise_lower_hook = 0;
3963 terminal->fullscreen_hook = 0;
3964 terminal->menu_show_hook = 0;
3965 terminal->set_vertical_scroll_bar_hook = 0;
3966 terminal->set_horizontal_scroll_bar_hook = 0;
3967 terminal->condemn_scroll_bars_hook = 0;
3968 terminal->redeem_scroll_bar_hook = 0;
3969 terminal->judge_scroll_bars_hook = 0;
3970 terminal->read_socket_hook = 0;
3971 terminal->frame_up_to_date_hook = 0;
3972
3973
3974
3975 terminal->delete_frame_hook = &tty_free_frame_resources;
3976 terminal->delete_terminal_hook = &delete_tty;
3977 }
3978
3979
3980
3981 static void
3982 set_tty_hooks (struct terminal *terminal)
3983 {
3984 terminal->cursor_to_hook = &tty_cursor_to;
3985 terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
3986 terminal->clear_to_end_hook = &tty_clear_to_end;
3987 terminal->clear_frame_hook = &tty_clear_frame;
3988 terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
3989 terminal->ins_del_lines_hook = &tty_ins_del_lines;
3990 terminal->insert_glyphs_hook = &tty_insert_glyphs;
3991 terminal->write_glyphs_hook = &tty_write_glyphs;
3992 terminal->delete_glyphs_hook = &tty_delete_glyphs;
3993 terminal->ring_bell_hook = &tty_ring_bell;
3994 terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
3995 terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
3996 terminal->update_end_hook = &tty_update_end;
3997 #ifdef MSDOS
3998 terminal->menu_show_hook = &x_menu_show;
3999 #else
4000 terminal->menu_show_hook = &tty_menu_show;
4001 #endif
4002 terminal->set_terminal_window_hook = &tty_set_terminal_window;
4003 terminal->defined_color_hook = &tty_defined_color;
4004 terminal->read_socket_hook = &tty_read_avail_input;
4005 terminal->delete_frame_hook = &tty_free_frame_resources;
4006 terminal->delete_terminal_hook = &delete_tty;
4007
4008 }
4009
4010
4011 static void
4012 dissociate_if_controlling_tty (int fd)
4013 {
4014
4015
4016 if (tcgetpgrp (fd) >= 0 && setsid () < 0)
4017 {
4018 #ifdef TIOCNOTTY
4019
4020
4021
4022 sigset_t oldset;
4023 block_tty_out_signal (&oldset);
4024 ioctl (fd, TIOCNOTTY, 0);
4025 unblock_tty_out_signal (&oldset);
4026 #endif
4027 }
4028 }
4029
4030 #endif
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046 #ifdef HAVE_ANDROID
4047 _Noreturn
4048 #endif
4049
4050 struct terminal *
4051 init_tty (const char *name, const char *terminal_type, bool must_succeed)
4052 {
4053 #ifdef HAVE_ANDROID
4054 maybe_fatal (must_succeed, 0, "Text terminals are not supported"
4055 " under Android", "Text terminals are not supported"
4056 " under Android");
4057 #else
4058 struct tty_display_info *tty = NULL;
4059 struct terminal *terminal = NULL;
4060 #ifndef DOS_NT
4061 char *area;
4062 char **address = &area;
4063 int status;
4064 sigset_t oldset;
4065 bool ctty = false;
4066 #endif
4067
4068 if (!terminal_type)
4069 maybe_fatal (must_succeed, 0,
4070 "Unknown terminal type",
4071 "Unknown terminal type");
4072
4073 if (name == NULL)
4074 name = DEV_TTY;
4075 #ifndef DOS_NT
4076 if (!strcmp (name, DEV_TTY))
4077 ctty = 1;
4078 #endif
4079
4080
4081
4082
4083
4084
4085 terminal = get_named_terminal (name);
4086 if (terminal)
4087 return terminal;
4088
4089 terminal = create_terminal (output_termcap, NULL);
4090 #ifdef MSDOS
4091 if (been_here > 0)
4092 maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
4093 name, "");
4094 been_here = 1;
4095 tty = &the_only_display_info;
4096 #else
4097 tty = xzalloc (sizeof *tty);
4098 #endif
4099 tty->top_frame = Qnil;
4100 tty->next = tty_list;
4101 tty_list = tty;
4102
4103 terminal->display_info.tty = tty;
4104 tty->terminal = terminal;
4105
4106 tty->Wcm = xmalloc (sizeof *tty->Wcm);
4107 Wcm_clear (tty);
4108
4109 encode_terminal_src_size = 0;
4110 encode_terminal_dst_size = 0;
4111
4112
4113 #ifndef DOS_NT
4114 set_tty_hooks (terminal);
4115
4116 {
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126 int flags = O_RDWR | O_NOCTTY | (ctty ? 0 : O_IGNORE_CTTY);
4127 int fd = emacs_open (name, flags, 0);
4128 tty->input = tty->output
4129 = ((fd < 0 || ! isatty (fd))
4130 ? NULL
4131 : emacs_fdopen (fd, "w+"));
4132
4133 if (! tty->input)
4134 {
4135 char const *diagnostic
4136 = (fd < 0) ? "Could not open file: %s" : "Not a tty device: %s";
4137 emacs_close (fd);
4138 delete_terminal_internal (terminal);
4139 maybe_fatal (must_succeed, terminal, diagnostic, diagnostic, name);
4140 }
4141
4142 tty->name = xstrdup (name);
4143 terminal->name = xstrdup (name);
4144
4145 if (!O_IGNORE_CTTY && !ctty)
4146 dissociate_if_controlling_tty (fd);
4147 }
4148
4149 tty->type = xstrdup (terminal_type);
4150
4151 add_keyboard_wait_descriptor (fileno (tty->input));
4152
4153 Wcm_clear (tty);
4154
4155
4156
4157 block_tty_out_signal (&oldset);
4158 status = tgetent (tty->termcap_term_buffer, terminal_type);
4159 if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1])
4160 emacs_abort ();
4161 unblock_tty_out_signal (&oldset);
4162
4163 if (status < 0)
4164 {
4165 #ifdef TERMINFO
4166 maybe_fatal (must_succeed, terminal,
4167 "Cannot open terminfo database file",
4168 "Cannot open terminfo database file");
4169 #else
4170 maybe_fatal (must_succeed, terminal,
4171 "Cannot open termcap database file",
4172 "Cannot open termcap database file");
4173 #endif
4174 }
4175 if (status == 0)
4176 {
4177 maybe_fatal (must_succeed, terminal,
4178 "Terminal type %s is not defined",
4179 "Terminal type %s is not defined.\n\
4180 If that is not the actual type of terminal you have,\n\
4181 use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
4182 'setenv TERM ...') to specify the correct type. It may be necessary\n"
4183 #ifdef TERMINFO
4184 "to do 'unset TERMINFO' (C-shell: 'unsetenv TERMINFO') as well.",
4185 #else
4186 "to do 'unset TERMCAP' (C-shell: 'unsetenv TERMCAP') as well.",
4187 #endif
4188 terminal_type);
4189 }
4190
4191 area = tty->termcap_strings_buffer;
4192 tty->TS_ins_line = tgetstr ("al", address);
4193 tty->TS_ins_multi_lines = tgetstr ("AL", address);
4194 tty->TS_bell = tgetstr ("bl", address);
4195 BackTab (tty) = tgetstr ("bt", address);
4196 tty->TS_clr_to_bottom = tgetstr ("cd", address);
4197 tty->TS_clr_line = tgetstr ("ce", address);
4198 tty->TS_clr_frame = tgetstr ("cl", address);
4199 ColPosition (tty) = NULL;
4200 AbsPosition (tty) = tgetstr ("cm", address);
4201 CR (tty) = tgetstr ("cr", address);
4202 tty->TS_set_scroll_region = tgetstr ("cs", address);
4203 tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
4204 RowPosition (tty) = tgetstr ("cv", address);
4205 tty->TS_del_char = tgetstr ("dc", address);
4206 tty->TS_del_multi_chars = tgetstr ("DC", address);
4207 tty->TS_del_line = tgetstr ("dl", address);
4208 tty->TS_del_multi_lines = tgetstr ("DL", address);
4209 tty->TS_delete_mode = tgetstr ("dm", address);
4210 tty->TS_end_delete_mode = tgetstr ("ed", address);
4211 tty->TS_end_insert_mode = tgetstr ("ei", address);
4212 Home (tty) = tgetstr ("ho", address);
4213 tty->TS_ins_char = tgetstr ("ic", address);
4214 tty->TS_ins_multi_chars = tgetstr ("IC", address);
4215 tty->TS_insert_mode = tgetstr ("im", address);
4216 tty->TS_pad_inserted_char = tgetstr ("ip", address);
4217 tty->TS_end_keypad_mode = tgetstr ("ke", address);
4218 tty->TS_keypad_mode = tgetstr ("ks", address);
4219 LastLine (tty) = tgetstr ("ll", address);
4220 Right (tty) = tgetstr ("nd", address);
4221 Down (tty) = tgetstr ("do", address);
4222 if (!Down (tty))
4223 Down (tty) = tgetstr ("nl", address);
4224 if (tgetflag ("bs"))
4225 Left (tty) = "\b";
4226 else
4227 Left (tty) = tgetstr ("le", address);
4228 if (!Left (tty))
4229 Left (tty) = tgetstr ("bc", address);
4230 tty->TS_pad_char = tgetstr ("pc", address);
4231 tty->TS_repeat = tgetstr ("rp", address);
4232 tty->TS_end_standout_mode = tgetstr ("se", address);
4233 tty->TS_fwd_scroll = tgetstr ("sf", address);
4234 tty->TS_standout_mode = tgetstr ("so", address);
4235 tty->TS_rev_scroll = tgetstr ("sr", address);
4236 tty->Wcm->cm_tab = tgetstr ("ta", address);
4237 tty->TS_end_termcap_modes = tgetstr ("te", address);
4238 tty->TS_termcap_modes = tgetstr ("ti", address);
4239 Up (tty) = tgetstr ("up", address);
4240 tty->TS_visible_bell = tgetstr ("vb", address);
4241 tty->TS_cursor_normal = tgetstr ("ve", address);
4242 tty->TS_cursor_visible = tgetstr ("vs", address);
4243 tty->TS_cursor_invisible = tgetstr ("vi", address);
4244 tty->TS_set_window = tgetstr ("wi", address);
4245
4246 tty->TS_enter_underline_mode = tgetstr ("us", address);
4247 tty->TS_exit_underline_mode = tgetstr ("ue", address);
4248 tty->TS_enter_bold_mode = tgetstr ("md", address);
4249 tty->TS_enter_italic_mode = tgetstr ("ZH", address);
4250 tty->TS_enter_dim_mode = tgetstr ("mh", address);
4251 tty->TS_enter_reverse_mode = tgetstr ("mr", address);
4252 tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
4253 tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
4254 tty->TS_exit_attribute_mode = tgetstr ("me", address);
4255 #ifdef TERMINFO
4256 tty->TS_enter_strike_through_mode = tigetstr ("smxx");
4257 if (tty->TS_enter_strike_through_mode == (char *) (intptr_t) -1)
4258 tty->TS_enter_strike_through_mode = NULL;
4259 #else
4260
4261
4262 tty->TS_enter_strike_through_mode = tgetstr ("smxx", address);
4263 #endif
4264
4265 MultiUp (tty) = tgetstr ("UP", address);
4266 MultiDown (tty) = tgetstr ("DO", address);
4267 MultiLeft (tty) = tgetstr ("LE", address);
4268 MultiRight (tty) = tgetstr ("RI", address);
4269
4270
4271
4272
4273 tty->TS_orig_pair = tgetstr ("op", address);
4274 if (tty->TS_orig_pair)
4275 {
4276 tty->TS_set_foreground = tgetstr ("AF", address);
4277 tty->TS_set_background = tgetstr ("AB", address);
4278 if (!tty->TS_set_foreground)
4279 {
4280
4281 tty->TS_set_foreground = tgetstr ("Sf", address);
4282 tty->TS_set_background = tgetstr ("Sb", address);
4283 }
4284
4285 tty->TN_max_colors = tgetnum ("Co");
4286
4287 #ifdef TERMINFO
4288 {
4289 const char *fg = tigetstr ("setf24");
4290 const char *bg = tigetstr ("setb24");
4291
4292 if (fg && bg
4293 && fg != (char *) (intptr_t) -1
4294 && bg != (char *) (intptr_t) -1)
4295 {
4296 tty->TS_set_foreground = fg;
4297 tty->TS_set_background = bg;
4298 tty->TN_max_colors = 16777216;
4299 }
4300
4301 else if (tigetflag ("RGB") > 0)
4302 {
4303
4304
4305
4306 tty->TN_max_colors = 16777216;
4307 }
4308
4309
4310
4311 else if ((tigetflag ("Tc") > 0)
4312 || ((bg = getenv ("COLORTERM")) != NULL
4313 && strcasecmp (bg, "truecolor") == 0))
4314 {
4315 tty->TS_set_foreground = "\033[%?%p1%{8}%<%t3%p1%d%e38;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m";
4316 tty->TS_set_background = "\033[%?%p1%{8}%<%t4%p1%d%e48;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m";
4317 tty->TN_max_colors = 16777216;
4318 }
4319 }
4320 #endif
4321
4322 tty->TN_no_color_video = tgetnum ("NC");
4323 if (tty->TN_no_color_video == -1)
4324 tty->TN_no_color_video = 0;
4325 }
4326
4327 tty_default_color_capabilities (tty, 1);
4328
4329 MagicWrap (tty) = tgetflag ("xn");
4330
4331
4332 AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
4333 tty->memory_below_frame = tgetflag ("db");
4334 tty->TF_hazeltine = tgetflag ("hz");
4335 tty->must_write_spaces = tgetflag ("in");
4336 tty->meta_key = tgetflag ("km") || tgetflag ("MT");
4337 tty->TF_insmode_motion = tgetflag ("mi");
4338 tty->TF_standout_motion = tgetflag ("ms");
4339 tty->TF_underscore = tgetflag ("ul");
4340 tty->TF_teleray = tgetflag ("xt");
4341
4342 #else
4343 #ifdef WINDOWSNT
4344 {
4345 struct frame *f = XFRAME (selected_frame);
4346 int height, width;
4347
4348 initialize_w32_display (terminal, &width, &height);
4349
4350 FrameRows (tty) = height;
4351 FrameCols (tty) = width;
4352 tty->specified_window = height;
4353
4354 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
4355 FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) = 0;
4356 tty->char_ins_del_ok = 1;
4357 baud_rate = 19200;
4358 }
4359 #else
4360 {
4361 int height, width;
4362 if (strcmp (terminal_type, "internal") == 0)
4363 terminal->type = output_msdos_raw;
4364 initialize_msdos_display (terminal);
4365
4366 get_tty_size (fileno (tty->input), &width, &height);
4367 FrameCols (tty) = width;
4368 FrameRows (tty) = height;
4369 tty->char_ins_del_ok = 0;
4370 init_baud_rate (fileno (tty->input));
4371 }
4372 #endif
4373 tty->output = stdout;
4374 tty->input = stdin;
4375
4376 terminal->delete_frame_hook = &tty_free_frame_resources;
4377 terminal->delete_terminal_hook = &delete_tty;
4378
4379 tty->name = xstrdup (name);
4380 terminal->name = xstrdup (name);
4381 tty->type = xstrdup (terminal_type);
4382
4383 add_keyboard_wait_descriptor (0);
4384
4385 tty->delete_in_insert_mode = 1;
4386
4387 UseTabs (tty) = 0;
4388 tty->scroll_region_ok = 0;
4389
4390
4391
4392
4393 tty->line_ins_del_ok = 0;
4394
4395 tty->TN_max_colors = 16;
4396 #endif
4397
4398 #ifdef HAVE_GPM
4399 terminal->mouse_position_hook = term_mouse_position;
4400 #endif
4401 tty->mouse_highlight.mouse_face_window = Qnil;
4402
4403 terminal->kboard = allocate_kboard (Qnil);
4404 terminal->kboard->reference_count++;
4405
4406
4407
4408 if (current_kboard == initial_kboard)
4409 current_kboard = terminal->kboard;
4410 #ifndef DOS_NT
4411 term_get_fkeys (address, terminal->kboard);
4412
4413
4414 {
4415 int height, width;
4416 get_tty_size (fileno (tty->input), &width, &height);
4417 FrameCols (tty) = width;
4418 FrameRows (tty) = height;
4419 }
4420
4421 if (FrameCols (tty) <= 0)
4422 FrameCols (tty) = tgetnum ("co");
4423 if (FrameRows (tty) <= 0)
4424 FrameRows (tty) = tgetnum ("li");
4425
4426 if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
4427 maybe_fatal (must_succeed, terminal,
4428 "Screen size %dx%d is too small",
4429 "Screen size %dx%d is too small",
4430 FrameCols (tty), FrameRows (tty));
4431
4432 TabWidth (tty) = tgetnum ("tw");
4433
4434 if (!tty->TS_bell)
4435 tty->TS_bell = "\07";
4436
4437 if (!tty->TS_fwd_scroll)
4438 tty->TS_fwd_scroll = Down (tty);
4439
4440 PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
4441
4442 if (TabWidth (tty) < 0)
4443 TabWidth (tty) = 8;
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453 if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
4454 {
4455 tty->TS_standout_mode = 0;
4456 tty->TS_end_standout_mode = 0;
4457 }
4458 if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
4459 {
4460 tty->TS_enter_underline_mode = 0;
4461 tty->TS_exit_underline_mode = 0;
4462 }
4463
4464
4465 if (tty->TS_standout_mode == 0)
4466 {
4467 tty->TS_standout_mode = tty->TS_enter_underline_mode;
4468 tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
4469 }
4470
4471
4472
4473 if (tty->TS_end_standout_mode == 0)
4474 {
4475 char *s = tgetstr ("me", address);
4476 if (s != 0)
4477 tty->TS_end_standout_mode = s;
4478 else
4479 tty->TS_standout_mode = 0;
4480 }
4481
4482 if (tty->TF_teleray)
4483 {
4484 tty->Wcm->cm_tab = 0;
4485
4486 tty->TS_standout_mode = 0;
4487
4488 CR (tty) = 0;
4489
4490
4491 Down (tty) = 0;
4492 }
4493
4494 tty->specified_window = FrameRows (tty);
4495
4496 if (Wcm_init (tty) == -1)
4497 {
4498 maybe_fatal (must_succeed, terminal,
4499 "Terminal type \"%s\" is not powerful enough to run Emacs",
4500 "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
4501 It lacks the ability to position the cursor.\n\
4502 If that is not the actual type of terminal you have,\n\
4503 use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
4504 'setenv TERM ...') to specify the correct type. It may be necessary\n"
4505 # ifdef TERMINFO
4506 "to do 'unset TERMINFO' (C-shell: 'unsetenv TERMINFO') as well.",
4507 # else
4508 "to do 'unset TERMCAP' (C-shell: 'unsetenv TERMCAP') as well.",
4509 # endif
4510 terminal_type);
4511 }
4512
4513 if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
4514 maybe_fatal (must_succeed, terminal,
4515 "Could not determine the frame size",
4516 "Could not determine the frame size");
4517
4518 tty->delete_in_insert_mode
4519 = tty->TS_delete_mode && tty->TS_insert_mode
4520 && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
4521
4522 UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
4523
4524 tty->scroll_region_ok
4525 = (tty->Wcm->cm_abs
4526 && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
4527
4528 tty->line_ins_del_ok
4529 = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
4530 && (tty->TS_del_line || tty->TS_del_multi_lines))
4531 || (tty->scroll_region_ok
4532 && tty->TS_fwd_scroll && tty->TS_rev_scroll));
4533
4534 tty->char_ins_del_ok
4535 = ((tty->TS_ins_char || tty->TS_insert_mode
4536 || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
4537 && (tty->TS_del_char || tty->TS_del_multi_chars));
4538
4539 init_baud_rate (fileno (tty->input));
4540
4541 #endif
4542
4543
4544 init_sys_modes (tty);
4545
4546 return terminal;
4547 #endif
4548 }
4549
4550
4551 static void
4552 vfatal (const char *str, va_list ap)
4553 {
4554 fputs ("emacs: ", stderr);
4555 vfprintf (stderr, str, ap);
4556 if (! (str[0] && str[strlen (str) - 1] == '\n'))
4557 putc ('\n', stderr);
4558 exit (1);
4559 }
4560
4561
4562
4563
4564
4565
4566 static void
4567 maybe_fatal (bool must_succeed, struct terminal *terminal,
4568 const char *str1, const char *str2, ...)
4569 {
4570 va_list ap;
4571 va_start (ap, str2);
4572
4573 #ifndef HAVE_ANDROID
4574 if (terminal)
4575 delete_tty (terminal);
4576 #else
4577 eassert (terminal == NULL);
4578 #endif
4579
4580 if (must_succeed)
4581 vfatal (str2, ap);
4582 else
4583 verror (str1, ap);
4584 }
4585
4586 void
4587 fatal (const char *str, ...)
4588 {
4589 va_list ap;
4590 va_start (ap, str);
4591 vfatal (str, ap);
4592 }
4593
4594
4595
4596 #ifndef HAVE_ANDROID
4597
4598
4599
4600 static void
4601 delete_tty (struct terminal *terminal)
4602 {
4603 struct tty_display_info *tty;
4604
4605
4606
4607 if (!terminal->name)
4608 return;
4609
4610 eassert (terminal->type == output_termcap);
4611
4612 tty = terminal->display_info.tty;
4613
4614 if (tty == tty_list)
4615 tty_list = tty->next;
4616 else
4617 {
4618 struct tty_display_info *p;
4619 for (p = tty_list; p && p->next != tty; p = p->next)
4620 ;
4621
4622 if (! p)
4623
4624 emacs_abort ();
4625
4626 p->next = tty->next;
4627 tty->next = 0;
4628 }
4629
4630
4631
4632 reset_sys_modes (tty);
4633
4634 delete_terminal (terminal);
4635
4636 xfree (tty->name);
4637 xfree (tty->type);
4638
4639 if (tty->input)
4640 {
4641 delete_keyboard_wait_descriptor (fileno (tty->input));
4642 if (tty->input != stdin)
4643 emacs_fclose (tty->input);
4644 }
4645 if (tty->output && tty->output != stdout && tty->output != tty->input)
4646 emacs_fclose (tty->output);
4647 if (tty->termscript)
4648 emacs_fclose (tty->termscript);
4649
4650 xfree (tty->old_tty);
4651 xfree (tty->Wcm);
4652 xfree (tty);
4653 }
4654
4655 #endif
4656
4657 void
4658 syms_of_term (void)
4659 {
4660 DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
4661 doc:
4662 );
4663 #if defined TERMINFO || (defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
4664 system_uses_terminfo = 1;
4665 #else
4666 system_uses_terminfo = 0;
4667 #endif
4668
4669 DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions,
4670 doc:
4671
4672 );
4673 Vsuspend_tty_functions = Qnil;
4674
4675
4676 DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions,
4677 doc:
4678
4679 );
4680 Vresume_tty_functions = Qnil;
4681
4682 DEFVAR_BOOL ("visible-cursor", visible_cursor,
4683 doc:
4684
4685
4686 );
4687 visible_cursor = 1;
4688
4689 DEFVAR_BOOL ("tty-menu-calls-mouse-position-function",
4690 tty_menu_calls_mouse_position_function,
4691 doc:
4692
4693 );
4694 tty_menu_calls_mouse_position_function = 0;
4695
4696 defsubr (&Stty_display_color_p);
4697 defsubr (&Stty_display_color_cells);
4698 defsubr (&Stty_no_underline);
4699 defsubr (&Stty_type);
4700 defsubr (&Scontrolling_tty_p);
4701 defsubr (&Stty_top_frame);
4702 defsubr (&Ssuspend_tty);
4703 defsubr (&Sresume_tty);
4704 #ifndef HAVE_ANDROID
4705 defsubr (&Stty__set_output_buffer_size);
4706 defsubr (&Stty__output_buffer_size);
4707 #endif
4708 #ifdef HAVE_GPM
4709 defsubr (&Sgpm_mouse_start);
4710 defsubr (&Sgpm_mouse_stop);
4711 #endif
4712
4713 #if !defined DOS_NT && !defined HAVE_ANDROID
4714 default_orig_pair = NULL;
4715 default_set_foreground = NULL;
4716 default_set_background = NULL;
4717 #endif
4718
4719 #ifndef HAVE_ANDROID
4720 encode_terminal_src = NULL;
4721 encode_terminal_dst = NULL;
4722 #endif
4723
4724 DEFSYM (Qtty_mode_set_strings, "tty-mode-set-strings");
4725 DEFSYM (Qtty_mode_reset_strings, "tty-mode-reset-strings");
4726
4727 #ifndef MSDOS
4728 DEFSYM (Qtty_menu_next_item, "tty-menu-next-item");
4729 DEFSYM (Qtty_menu_prev_item, "tty-menu-prev-item");
4730 DEFSYM (Qtty_menu_next_menu, "tty-menu-next-menu");
4731 DEFSYM (Qtty_menu_prev_menu, "tty-menu-prev-menu");
4732 DEFSYM (Qtty_menu_select, "tty-menu-select");
4733 DEFSYM (Qtty_menu_ignore, "tty-menu-ignore");
4734 DEFSYM (Qtty_menu_exit, "tty-menu-exit");
4735 DEFSYM (Qtty_menu_mouse_movement, "tty-menu-mouse-movement");
4736 DEFSYM (Qtty_menu_navigation_map, "tty-menu-navigation-map");
4737 #endif
4738 }