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 tty_setcolor (color);
607 ctext = g_malloc (sizeof (cchar_t) * (cols + 1));
608
609 for (int row = 0; row < rows; row++)
610 {
611 mvin_wchnstr (y + row, x, ctext, cols);
612
613 for (int col = 0; col < cols; col++)
614 {
615 getcchar (&ctext[col], wch, &attrs, &color_pair, NULL);
616 setcchar (&ctext[col], wch, attrs, color, NULL);
617 }
618
619 mvadd_wchnstr (y + row, x, ctext, cols);
620 }
621
622 g_free (ctext);
623 #else
624 (void) y;
625 (void) x;
626 (void) rows;
627 (void) cols;
628 (void) color;
629 #endif
630 }
631
632
633
634 void
635 tty_display_8bit (gboolean what)
636 {
637 meta (stdscr, (int) what);
638 }
639
640
641
642 void
643 tty_print_char (mc_tty_char_t c)
644 {
645 if (yx_in_screen (mc_curs_row, mc_curs_col))
646 addch_maybe_acs (c);
647 mc_curs_col++;
648 }
649
650
651
652 void
653 tty_print_anychar (mc_tty_char_t c)
654 {
655 if (mc_global.utf8_display || c > 255)
656 {
657 int res;
658 unsigned char str[MB_LEN_MAX + 1];
659
660 res = g_unichar_to_utf8 (c, (char *) str);
661 if (res == 0)
662 {
663 if (yx_in_screen (mc_curs_row, mc_curs_col))
664 addch_maybe_acs ('.');
665 mc_curs_col++;
666 }
667 else
668 {
669 const char *s;
670
671 str[res] = '\0';
672 s = str_term_form ((char *) str);
673
674 if (yx_in_screen (mc_curs_row, mc_curs_col))
675 addstr (s);
676
677 if (g_unichar_iswide (c))
678 mc_curs_col += 2;
679 else if (!g_unichar_iszerowidth (c))
680 mc_curs_col++;
681 }
682 }
683 else
684 {
685 if (yx_in_screen (mc_curs_row, mc_curs_col))
686 addch_maybe_acs (c);
687 mc_curs_col++;
688 }
689 }
690
691
692
693 void
694 tty_print_string (const char *s)
695 {
696 int len;
697 int start = 0;
698
699 s = str_term_form (s);
700 len = str_term_width1 (s);
701
702
703 if (mc_curs_row < 0 || mc_curs_row >= LINES || mc_curs_col + len <= 0 || mc_curs_col >= COLS)
704 {
705 mc_curs_col += len;
706 return;
707 }
708
709
710 if (mc_curs_col < 0)
711 {
712 start = -mc_curs_col;
713 len += mc_curs_col;
714 mc_curs_col = 0;
715 }
716
717 mc_curs_col += len;
718 if (mc_curs_col >= COLS)
719 len = COLS - (mc_curs_col - len);
720
721 addstr (str_term_substring (s, start, len));
722 }
723
724
725
726 void
727 tty_printf (const char *fmt, ...)
728 {
729 va_list args;
730 char buf[BUF_1K];
731
732 va_start (args, fmt);
733 g_vsnprintf (buf, sizeof (buf), fmt, args);
734 va_end (args);
735 tty_print_string (buf);
736 }
737
738
739
740 int
741 tty_tigetflag (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
742 {
743 return tigetflag ((NCURSES_CONST char *) terminfo_cap);
744 }
745
746
747
748 int
749 tty_tigetnum (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
750 {
751 return tigetnum ((NCURSES_CONST char *) terminfo_cap);
752 }
753
754
755
756 char *
757 tty_tigetstr (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
758 {
759 return tigetstr ((NCURSES_CONST char *) terminfo_cap);
760 }
761
762
763
764 void
765 tty_refresh (void)
766 {
767 refresh ();
768 doupdate ();
769 }
770
771
772
773 void
774 tty_beep (void)
775 {
776 beep ();
777 }
778
779