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 ncurses_koi8r_double_line_bug =
273 (strncmp (ncurses_ver, "ncurses ", 8) == 0 && strcmp (ncurses_ver + 8, "6.5.20251115") < 0);
274
275 initscr ();
276
277 #ifdef HAVE_ESCDELAY
278
279
280
281
282
283
284
285
286
287 ESCDELAY = 200;
288 #endif
289
290 tcgetattr (STDIN_FILENO, &mode);
291
292 mode.c_cc[VINTR] = CTRL ('g');
293
294 mode.c_cc[VQUIT] = NULL_VALUE;
295 tcsetattr (STDIN_FILENO, TCSANOW, &mode);
296
297
298 def_prog_mode ();
299
300 tty_start_interrupt_key ();
301
302 if (!mouse_enable)
303 use_mouse_p = MOUSE_DISABLED;
304 tty_init_xterm_support (is_xterm);
305 tty_enter_ca_mode ();
306 tty_raw_mode ();
307 noecho ();
308 keypad (stdscr, TRUE);
309 nodelay (stdscr, FALSE);
310
311 tty_setup_sigwinch (sigwinch_handler);
312 }
313
314
315
316 void
317 tty_shutdown (void)
318 {
319 tty_destroy_winch_pipe ();
320 tty_reset_shell_mode ();
321 tty_noraw_mode ();
322 tty_keypad (FALSE);
323 tty_reset_screen ();
324 tty_exit_ca_mode ();
325 }
326
327
328
329 void
330 tty_enter_ca_mode (void)
331 {
332 if (mc_global.tty.xterm_flag && smcup != NULL)
333 {
334 fprintf (stdout, ESC_STR "7" ESC_STR "[?47h");
335 fflush (stdout);
336 }
337 }
338
339
340
341 void
342 tty_exit_ca_mode (void)
343 {
344 if (mc_global.tty.xterm_flag && rmcup != NULL)
345 {
346 fprintf (stdout, ESC_STR "[?47l" ESC_STR "8" ESC_STR "[m");
347 fflush (stdout);
348 }
349 }
350
351
352
353 void
354 tty_change_screen_size (void)
355 {
356 #if defined(TIOCGWINSZ) && NCURSES_VERSION_MAJOR >= 4
357 struct winsize winsz;
358
359 winsz.ws_col = winsz.ws_row = 0;
360
361 #ifndef NCURSES_VERSION
362 tty_noraw_mode ();
363 tty_reset_screen ();
364 #endif
365
366
367 ioctl (fileno (stdout), TIOCGWINSZ, &winsz);
368 if (winsz.ws_col != 0 && winsz.ws_row != 0)
369 {
370 #if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM)
371 resizeterm (winsz.ws_row, winsz.ws_col);
372 clearok (stdscr, TRUE);
373 #else
374 COLS = winsz.ws_col;
375 LINES = winsz.ws_row;
376 #endif
377 }
378 #endif
379
380 #ifdef ENABLE_SUBSHELL
381 if (mc_global.tty.use_subshell)
382 tty_resize (mc_global.tty.subshell_pty);
383 #endif
384 }
385
386
387
388 void
389 tty_reset_prog_mode (void)
390 {
391 reset_prog_mode ();
392 }
393
394
395
396 void
397 tty_reset_shell_mode (void)
398 {
399 reset_shell_mode ();
400 }
401
402
403
404 void
405 tty_raw_mode (void)
406 {
407 raw ();
408 cbreak ();
409 }
410
411
412
413 void
414 tty_noraw_mode (void)
415 {
416 nocbreak ();
417 noraw ();
418 }
419
420
421
422 void
423 tty_noecho (void)
424 {
425 noecho ();
426 }
427
428
429
430 int
431 tty_flush_input (void)
432 {
433 return flushinp ();
434 }
435
436
437
438 void
439 tty_keypad (gboolean set)
440 {
441 keypad (stdscr, (bool) set);
442 }
443
444
445
446 void
447 tty_nodelay (gboolean set)
448 {
449 nodelay (stdscr, (bool) set);
450 }
451
452
453
454 int
455 tty_baudrate (void)
456 {
457 return baudrate ();
458 }
459
460
461
462 int
463 tty_lowlevel_getch (void)
464 {
465 return getch ();
466 }
467
468
469
470 int
471 tty_reset_screen (void)
472 {
473 return endwin ();
474 }
475
476
477
478 void
479 tty_touch_screen (void)
480 {
481 touchwin (stdscr);
482 }
483
484
485
486 void
487 tty_gotoyx (int y, int x)
488 {
489 mc_curs_row = y;
490 mc_curs_col = x;
491
492 if (y < 0)
493 y = 0;
494 if (y >= LINES)
495 y = LINES - 1;
496
497 if (x < 0)
498 x = 0;
499 if (x >= COLS)
500 x = COLS - 1;
501
502 move (y, x);
503 }
504
505
506
507 void
508 tty_getyx (int *py, int *px)
509 {
510 *py = mc_curs_row;
511 *px = mc_curs_col;
512 }
513
514
515
516 void
517 tty_draw_hline (int y, int x, mc_tty_char_t ch, int len)
518 {
519 int x1;
520
521 if (y < 0 || y >= LINES || x >= COLS)
522 return;
523
524 x1 = x;
525
526 if (x < 0)
527 {
528 len += x;
529 if (len <= 0)
530 return;
531 x = 0;
532 }
533
534 move (y, x);
535 hline_maybe_acs (ch, len);
536 move (y, x1);
537
538 mc_curs_row = y;
539 mc_curs_col = x1;
540 }
541
542
543
544 void
545 tty_draw_vline (int y, int x, mc_tty_char_t ch, int len)
546 {
547 int y1;
548
549 if (x < 0 || x >= COLS || y >= LINES)
550 return;
551
552 y1 = y;
553
554 if (y < 0)
555 {
556 len += y;
557 if (len <= 0)
558 return;
559 y = 0;
560 }
561
562 move (y, x);
563 vline_maybe_acs (ch, len);
564 move (y1, x);
565
566 mc_curs_row = y1;
567 mc_curs_col = x;
568 }
569
570
571
572 void
573 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
574 {
575 int i;
576
577 if (!tty_clip (&y, &x, &rows, &cols))
578 return;
579
580 for (i = 0; i < rows; i++)
581 {
582 move (y + i, x);
583 hline (ch, cols);
584 }
585
586 move (y, x);
587
588 mc_curs_row = y;
589 mc_curs_col = x;
590 }
591
592
593
594 void
595 tty_colorize_area (int y, int x, int rows, int cols, int color)
596 {
597 #ifdef ENABLE_SHADOWS
598 cchar_t *ctext;
599 wchar_t wch[10];
600 attr_t attrs;
601 short color_pair;
602
603 if (!use_colors || !tty_clip (&y, &x, &rows, &cols))
604 return;
605
606 color = tty_maybe_map_color (color);
607 tty_setcolor (color);
608 ctext = g_malloc (sizeof (cchar_t) * (cols + 1));
609
610 for (int row = 0; row < rows; row++)
611 {
612 mvin_wchnstr (y + row, x, ctext, cols);
613
614 for (int col = 0; col < cols; col++)
615 {
616 getcchar (&ctext[col], wch, &attrs, &color_pair, NULL);
617 setcchar (&ctext[col], wch, attrs, color, NULL);
618 }
619
620 mvadd_wchnstr (y + row, x, ctext, cols);
621 }
622
623 g_free (ctext);
624 #else
625 (void) y;
626 (void) x;
627 (void) rows;
628 (void) cols;
629 (void) color;
630 #endif
631 }
632
633
634
635 void
636 tty_display_8bit (gboolean what)
637 {
638 meta (stdscr, (int) what);
639 }
640
641
642
643 void
644 tty_print_char (mc_tty_char_t c)
645 {
646 if (yx_in_screen (mc_curs_row, mc_curs_col))
647 addch_maybe_acs (c);
648 mc_curs_col++;
649 }
650
651
652
653 void
654 tty_print_anychar (mc_tty_char_t c)
655 {
656 if (mc_global.utf8_display || c > 255)
657 {
658 int res;
659 unsigned char str[MB_LEN_MAX + 1];
660
661 res = g_unichar_to_utf8 (c, (char *) str);
662 if (res == 0)
663 {
664 if (yx_in_screen (mc_curs_row, mc_curs_col))
665 addch_maybe_acs ('.');
666 mc_curs_col++;
667 }
668 else
669 {
670 const char *s;
671
672 str[res] = '\0';
673 s = str_term_form ((char *) str);
674
675 if (yx_in_screen (mc_curs_row, mc_curs_col))
676 addstr (s);
677
678 if (g_unichar_iswide (c))
679 mc_curs_col += 2;
680 else if (!g_unichar_iszerowidth (c))
681 mc_curs_col++;
682 }
683 }
684 else
685 {
686 if (yx_in_screen (mc_curs_row, mc_curs_col))
687 addch_maybe_acs (c);
688 mc_curs_col++;
689 }
690 }
691
692
693
694 void
695 tty_print_string (const char *s)
696 {
697 int len;
698 int start = 0;
699
700 s = str_term_form (s);
701 len = str_term_width1 (s);
702
703
704 if (mc_curs_row < 0 || mc_curs_row >= LINES || mc_curs_col + len <= 0 || mc_curs_col >= COLS)
705 {
706 mc_curs_col += len;
707 return;
708 }
709
710
711 if (mc_curs_col < 0)
712 {
713 start = -mc_curs_col;
714 len += mc_curs_col;
715 mc_curs_col = 0;
716 }
717
718 mc_curs_col += len;
719 if (mc_curs_col >= COLS)
720 len = COLS - (mc_curs_col - len);
721
722 addstr (str_term_substring (s, start, len));
723 }
724
725
726
727 void
728 tty_printf (const char *fmt, ...)
729 {
730 va_list args;
731 char buf[BUF_1K];
732
733 va_start (args, fmt);
734 g_vsnprintf (buf, sizeof (buf), fmt, args);
735 va_end (args);
736 tty_print_string (buf);
737 }
738
739
740
741 int
742 tty_tigetflag (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
743 {
744 return tigetflag ((NCURSES_CONST char *) terminfo_cap);
745 }
746
747
748
749 int
750 tty_tigetnum (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
751 {
752 return tigetnum ((NCURSES_CONST char *) terminfo_cap);
753 }
754
755
756
757 char *
758 tty_tigetstr (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
759 {
760 return tigetstr ((NCURSES_CONST char *) terminfo_cap);
761 }
762
763
764
765 void
766 tty_refresh (void)
767 {
768 refresh ();
769 doupdate ();
770 }
771
772
773
774 void
775 tty_beep (void)
776 {
777 beep ();
778 }
779
780