This source file includes following definitions.
- tty_setup_sigwinch
- sigwinch_handler
- tty_clip
- get_maybe_acs
- addch_maybe_acs
- hline_maybe_acs
- vline_maybe_acs
- tty_init
- tty_shutdown
- tty_enter_ca_mode
- tty_exit_ca_mode
- tty_change_screen_size
- tty_reset_prog_mode
- tty_reset_shell_mode
- tty_raw_mode
- tty_noraw_mode
- tty_noecho
- tty_flush_input
- tty_keypad
- tty_nodelay
- tty_baudrate
- tty_lowlevel_getch
- tty_reset_screen
- tty_touch_screen
- tty_gotoyx
- tty_getyx
- tty_draw_hline
- tty_draw_vline
- tty_fill_region
- tty_colorize_area
- tty_display_8bit
- tty_print_char
- tty_print_anychar
- tty_print_string
- tty_printf
- tty_tigetflag
- tty_tigetnum
- tty_tigetstr
- tty_refresh
- tty_beep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include <config.h>
33
34 #include <limits.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <signal.h>
38 #ifdef HAVE_SYS_IOCTL_H
39 #include <sys/ioctl.h>
40 #endif
41 #include <termios.h>
42
43 #include "lib/global.h"
44 #include "lib/strutil.h"
45 #include "lib/util.h"
46
47 #include "tty-internal.h"
48 #include "tty.h"
49 #include "color.h"
50 #include "color-internal.h"
51 #include "key.h"
52 #include "mouse.h"
53 #include "win.h"
54
55
56 #ifdef HAVE_NCURSESW_TERM_H
57 #include <ncursesw/term.h>
58 #elif defined HAVE_NCURSES_TERM_H
59 #include <ncurses/term.h>
60 #else
61 #include <term.h>
62 #endif
63
64
65
66 gboolean ncurses_koi8r_double_line_bug;
67
68
69
70 #if !defined(CTRL)
71 #define CTRL(x) ((x) & 0x1f)
72 #endif
73
74 #define yx_in_screen(y, x) (y >= 0 && y < LINES && x >= 0 && x < COLS)
75
76
77
78
79
80
81
82
83
84
85
86 static int mc_curs_row, mc_curs_col;
87
88
89
90
91
92 static void
93 tty_setup_sigwinch (void (*handler) (int))
94 {
95 #if (NCURSES_VERSION_MAJOR >= 4) && defined(SIGWINCH)
96 struct sigaction act, oact;
97
98 memset (&act, 0, sizeof (act));
99 act.sa_handler = handler;
100 sigemptyset (&act.sa_mask);
101 #ifdef SA_RESTART
102 act.sa_flags = SA_RESTART;
103 #endif
104 my_sigaction (SIGWINCH, &act, &oact);
105 #endif
106
107 tty_create_winch_pipe ();
108 }
109
110
111
112 static void
113 sigwinch_handler (int dummy)
114 {
115 ssize_t n = 0;
116
117 (void) dummy;
118
119 n = write (sigwinch_pipe[1], "", 1);
120 (void) n;
121 }
122
123
124
125
126
127
128
129
130 static gboolean
131 tty_clip (int *y, int *x, int *rows, int *cols)
132 {
133 if (*y < 0)
134 {
135 *rows += *y;
136
137 if (*rows <= 0)
138 return FALSE;
139
140 *y = 0;
141 }
142
143 if (*x < 0)
144 {
145 *cols += *x;
146
147 if (*cols <= 0)
148 return FALSE;
149
150 *x = 0;
151 }
152
153 if (*y + *rows > LINES)
154 *rows = LINES - *y;
155
156 if (*rows <= 0)
157 return FALSE;
158
159 if (*x + *cols > COLS)
160 *cols = COLS - *x;
161
162 if (*cols <= 0)
163 return FALSE;
164
165 return TRUE;
166 }
167
168
169
170 static chtype
171 get_maybe_acs (mc_tty_char_t ch)
172 {
173 switch (ch)
174 {
175 case MC_ACS_HLINE:
176 return ACS_HLINE;
177 case MC_ACS_VLINE:
178 return ACS_VLINE;
179 case MC_ACS_ULCORNER:
180 return ACS_ULCORNER;
181 case MC_ACS_URCORNER:
182 return ACS_URCORNER;
183 case MC_ACS_LLCORNER:
184 return ACS_LLCORNER;
185 case MC_ACS_LRCORNER:
186 return ACS_LRCORNER;
187 case MC_ACS_LTEE:
188 return ACS_LTEE;
189 case MC_ACS_RTEE:
190 return ACS_RTEE;
191 case MC_ACS_TTEE:
192 return ACS_TTEE;
193 case MC_ACS_BTEE:
194 return ACS_BTEE;
195 case MC_ACS_PLUS:
196 return ACS_PLUS;
197
198 default:
199 return ch;
200 }
201 }
202
203
204
205 static inline void
206 addch_maybe_acs (mc_tty_char_t ch)
207 {
208 #ifdef HAVE_NCURSES_WIDECHAR
209 if (mc_global.utf8_display)
210 {
211 wchar_t wch[2] = { ch, 0 };
212 cchar_t ctext;
213
214 setcchar (&ctext, wch, 0, 0, NULL);
215 add_wch (&ctext);
216 }
217 else
218 #endif
219 addch (get_maybe_acs (ch));
220 }
221
222
223
224 static inline void
225 hline_maybe_acs (mc_tty_char_t ch, int len)
226 {
227 #ifdef HAVE_NCURSES_WIDECHAR
228 if (mc_global.utf8_display)
229 {
230 wchar_t wch[2] = { ch, 0 };
231 cchar_t ctext;
232
233 setcchar (&ctext, wch, 0, 0, NULL);
234 hline_set (&ctext, len);
235 }
236 else
237 #endif
238 hline (get_maybe_acs (ch), len);
239 }
240
241
242
243 static inline void
244 vline_maybe_acs (mc_tty_char_t ch, int len)
245 {
246 #ifdef HAVE_NCURSES_WIDECHAR
247 if (mc_global.utf8_display)
248 {
249 wchar_t wch[2] = { ch, 0 };
250 cchar_t ctext;
251
252 setcchar (&ctext, wch, 0, 0, NULL);
253 vline_set (&ctext, len);
254 }
255 else
256 #endif
257 vline (get_maybe_acs (ch), len);
258 }
259
260
261
262
263
264 void
265 tty_init (gboolean mouse_enable, gboolean is_xterm)
266 {
267 struct termios mode;
268
269
270
271 const char *ncurses_ver = curses_version ();
272
273 ncurses_koi8r_double_line_bug =
274 (strncmp (ncurses_ver, "ncurses ", 8) == 0 && strcmp (ncurses_ver + 8, "6.5.20251115") < 0);
275
276 initscr ();
277
278 #ifdef HAVE_ESCDELAY
279
280
281
282
283
284
285
286
287
288 ESCDELAY = 200;
289 #endif
290
291 tcgetattr (STDIN_FILENO, &mode);
292
293 mode.c_cc[VINTR] = CTRL ('g');
294
295 mode.c_cc[VQUIT] = NULL_VALUE;
296 tcsetattr (STDIN_FILENO, TCSANOW, &mode);
297
298
299 def_prog_mode ();
300
301 tty_start_interrupt_key ();
302
303 if (!mouse_enable)
304 use_mouse_p = MOUSE_DISABLED;
305 tty_init_xterm_support (is_xterm);
306 tty_enter_ca_mode ();
307 tty_raw_mode ();
308 noecho ();
309 keypad (stdscr, TRUE);
310 nodelay (stdscr, FALSE);
311
312 tty_setup_sigwinch (sigwinch_handler);
313 }
314
315
316
317 void
318 tty_shutdown (void)
319 {
320 tty_destroy_winch_pipe ();
321 tty_reset_shell_mode ();
322 tty_noraw_mode ();
323 tty_keypad (FALSE);
324 tty_reset_screen ();
325 tty_exit_ca_mode ();
326 }
327
328
329
330 void
331 tty_enter_ca_mode (void)
332 {
333 if (mc_global.tty.xterm_flag && smcup != NULL)
334 {
335 fprintf (stdout, ESC_STR "7" ESC_STR "[?47h");
336 fflush (stdout);
337 }
338 }
339
340
341
342 void
343 tty_exit_ca_mode (void)
344 {
345 if (mc_global.tty.xterm_flag && rmcup != NULL)
346 {
347 fprintf (stdout, ESC_STR "[?47l" ESC_STR "8" ESC_STR "[m");
348 fflush (stdout);
349 }
350 }
351
352
353
354 void
355 tty_change_screen_size (void)
356 {
357 #if defined(TIOCGWINSZ) && NCURSES_VERSION_MAJOR >= 4
358 struct winsize winsz;
359
360 winsz.ws_col = winsz.ws_row = 0;
361
362 #ifndef NCURSES_VERSION
363 tty_noraw_mode ();
364 tty_reset_screen ();
365 #endif
366
367
368 ioctl (fileno (stdout), TIOCGWINSZ, &winsz);
369 if (winsz.ws_col != 0 && winsz.ws_row != 0)
370 {
371 #if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM)
372 resizeterm (winsz.ws_row, winsz.ws_col);
373 clearok (stdscr, TRUE);
374 #else
375 COLS = winsz.ws_col;
376 LINES = winsz.ws_row;
377 #endif
378 }
379 #endif
380
381 #ifdef ENABLE_SUBSHELL
382 if (mc_global.tty.use_subshell)
383 tty_resize (mc_global.tty.subshell_pty);
384 #endif
385 }
386
387
388
389 void
390 tty_reset_prog_mode (void)
391 {
392 reset_prog_mode ();
393 }
394
395
396
397 void
398 tty_reset_shell_mode (void)
399 {
400 reset_shell_mode ();
401 }
402
403
404
405 void
406 tty_raw_mode (void)
407 {
408 raw ();
409 cbreak ();
410 }
411
412
413
414 void
415 tty_noraw_mode (void)
416 {
417 nocbreak ();
418 noraw ();
419 }
420
421
422
423 void
424 tty_noecho (void)
425 {
426 noecho ();
427 }
428
429
430
431 int
432 tty_flush_input (void)
433 {
434 return flushinp ();
435 }
436
437
438
439 void
440 tty_keypad (gboolean set)
441 {
442 keypad (stdscr, (bool) set);
443 }
444
445
446
447 void
448 tty_nodelay (gboolean set)
449 {
450 nodelay (stdscr, (bool) set);
451 }
452
453
454
455 int
456 tty_baudrate (void)
457 {
458 return baudrate ();
459 }
460
461
462
463 int
464 tty_lowlevel_getch (void)
465 {
466 return getch ();
467 }
468
469
470
471 int
472 tty_reset_screen (void)
473 {
474 return endwin ();
475 }
476
477
478
479 void
480 tty_touch_screen (void)
481 {
482 touchwin (stdscr);
483 }
484
485
486
487 void
488 tty_gotoyx (int y, int x)
489 {
490 mc_curs_row = y;
491 mc_curs_col = x;
492
493 if (y < 0)
494 y = 0;
495 if (y >= LINES)
496 y = LINES - 1;
497
498 if (x < 0)
499 x = 0;
500 if (x >= COLS)
501 x = COLS - 1;
502
503 move (y, x);
504 }
505
506
507
508 void
509 tty_getyx (int *py, int *px)
510 {
511 *py = mc_curs_row;
512 *px = mc_curs_col;
513 }
514
515
516
517 void
518 tty_draw_hline (int y, int x, mc_tty_char_t ch, int len)
519 {
520 int x1;
521
522 if (y < 0 || y >= LINES || x >= COLS)
523 return;
524
525 x1 = x;
526
527 if (x < 0)
528 {
529 len += x;
530 if (len <= 0)
531 return;
532 x = 0;
533 }
534
535 move (y, x);
536 hline_maybe_acs (ch, len);
537 move (y, x1);
538
539 mc_curs_row = y;
540 mc_curs_col = x1;
541 }
542
543
544
545 void
546 tty_draw_vline (int y, int x, mc_tty_char_t ch, int len)
547 {
548 int y1;
549
550 if (x < 0 || x >= COLS || y >= LINES)
551 return;
552
553 y1 = y;
554
555 if (y < 0)
556 {
557 len += y;
558 if (len <= 0)
559 return;
560 y = 0;
561 }
562
563 move (y, x);
564 vline_maybe_acs (ch, len);
565 move (y1, x);
566
567 mc_curs_row = y1;
568 mc_curs_col = x;
569 }
570
571
572
573 void
574 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
575 {
576 int i;
577
578 if (!tty_clip (&y, &x, &rows, &cols))
579 return;
580
581 for (i = 0; i < rows; i++)
582 {
583 move (y + i, x);
584 hline (ch, cols);
585 }
586
587 move (y, x);
588
589 mc_curs_row = y;
590 mc_curs_col = x;
591 }
592
593
594
595 void
596 tty_colorize_area (int y, int x, int rows, int cols, int color)
597 {
598 #ifdef ENABLE_SHADOWS
599 cchar_t *ctext;
600 wchar_t wch[10];
601 attr_t attrs;
602 short color_pair;
603
604 if (!use_colors || !tty_clip (&y, &x, &rows, &cols))
605 return;
606
607 color = tty_maybe_map_color (color);
608 tty_setcolor (color);
609 ctext = g_malloc (sizeof (cchar_t) * (cols + 1));
610
611 for (int row = 0; row < rows; row++)
612 {
613 mvin_wchnstr (y + row, x, ctext, cols);
614
615 for (int col = 0; col < cols; col++)
616 {
617 getcchar (&ctext[col], wch, &attrs, &color_pair, NULL);
618 setcchar (&ctext[col], wch, attrs, color, NULL);
619 }
620
621 mvadd_wchnstr (y + row, x, ctext, cols);
622 }
623
624 g_free (ctext);
625 #else
626 (void) y;
627 (void) x;
628 (void) rows;
629 (void) cols;
630 (void) color;
631 #endif
632 }
633
634
635
636 void
637 tty_display_8bit (gboolean what)
638 {
639 meta (stdscr, (int) what);
640 }
641
642
643
644 void
645 tty_print_char (mc_tty_char_t c)
646 {
647 if (yx_in_screen (mc_curs_row, mc_curs_col))
648 addch_maybe_acs (c);
649 mc_curs_col++;
650 }
651
652
653
654 void
655 tty_print_anychar (mc_tty_char_t c)
656 {
657 if (mc_global.utf8_display || c > 255)
658 {
659 int res;
660 unsigned char str[MB_LEN_MAX + 1];
661
662 res = g_unichar_to_utf8 (c, (char *) str);
663 if (res == 0)
664 {
665 if (yx_in_screen (mc_curs_row, mc_curs_col))
666 addch_maybe_acs ('.');
667 mc_curs_col++;
668 }
669 else
670 {
671 const char *s;
672
673 str[res] = '\0';
674 s = str_term_form ((char *) str);
675
676 if (yx_in_screen (mc_curs_row, mc_curs_col))
677 addstr (s);
678
679 if (g_unichar_iswide (c))
680 mc_curs_col += 2;
681 else if (!g_unichar_iszerowidth (c))
682 mc_curs_col++;
683 }
684 }
685 else
686 {
687 if (yx_in_screen (mc_curs_row, mc_curs_col))
688 addch_maybe_acs (c);
689 mc_curs_col++;
690 }
691 }
692
693
694
695 void
696 tty_print_string (const char *s)
697 {
698 int len;
699 int start = 0;
700
701 s = str_term_form (s);
702 len = str_term_width1 (s);
703
704
705 if (mc_curs_row < 0 || mc_curs_row >= LINES || mc_curs_col + len <= 0 || mc_curs_col >= COLS)
706 {
707 mc_curs_col += len;
708 return;
709 }
710
711
712 if (mc_curs_col < 0)
713 {
714 start = -mc_curs_col;
715 len += mc_curs_col;
716 mc_curs_col = 0;
717 }
718
719 mc_curs_col += len;
720 if (mc_curs_col >= COLS)
721 len = COLS - (mc_curs_col - len);
722
723 addstr (str_term_substring (s, start, len));
724 }
725
726
727
728 void
729 tty_printf (const char *fmt, ...)
730 {
731 va_list args;
732 char buf[BUF_1K];
733
734 va_start (args, fmt);
735 g_vsnprintf (buf, sizeof (buf), fmt, args);
736 va_end (args);
737 tty_print_string (buf);
738 }
739
740
741
742 int
743 tty_tigetflag (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
744 {
745 return tigetflag ((NCURSES_CONST char *) terminfo_cap);
746 }
747
748
749
750 int
751 tty_tigetnum (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
752 {
753 return tigetnum ((NCURSES_CONST char *) terminfo_cap);
754 }
755
756
757
758 char *
759 tty_tigetstr (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
760 {
761 return tigetstr ((NCURSES_CONST char *) terminfo_cap);
762 }
763
764
765
766 void
767 tty_refresh (void)
768 {
769 refresh ();
770 doupdate ();
771 }
772
773
774
775 void
776 tty_beep (void)
777 {
778 beep ();
779 }
780
781