This source file includes following definitions.
- tty_setup_sigwinch
- sigwinch_handler
- 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_clip
- tty_fill_region
- 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 static chtype
126 get_maybe_acs (mc_tty_char_t ch)
127 {
128 switch (ch)
129 {
130 case MC_ACS_HLINE:
131 return ACS_HLINE;
132 case MC_ACS_VLINE:
133 return ACS_VLINE;
134 case MC_ACS_ULCORNER:
135 return ACS_ULCORNER;
136 case MC_ACS_URCORNER:
137 return ACS_URCORNER;
138 case MC_ACS_LLCORNER:
139 return ACS_LLCORNER;
140 case MC_ACS_LRCORNER:
141 return ACS_LRCORNER;
142 case MC_ACS_LTEE:
143 return ACS_LTEE;
144 case MC_ACS_RTEE:
145 return ACS_RTEE;
146 case MC_ACS_TTEE:
147 return ACS_TTEE;
148 case MC_ACS_BTEE:
149 return ACS_BTEE;
150 case MC_ACS_PLUS:
151 return ACS_PLUS;
152
153 default:
154 return ch;
155 }
156 }
157
158
159
160 static inline void
161 addch_maybe_acs (mc_tty_char_t ch)
162 {
163 #ifdef HAVE_NCURSES_WIDECHAR
164 if (mc_global.utf8_display)
165 {
166 wchar_t wch[2] = { ch, 0 };
167 cchar_t ctext;
168
169 setcchar (&ctext, wch, 0, 0, NULL);
170 add_wch (&ctext);
171 }
172 else
173 #endif
174 addch (get_maybe_acs (ch));
175 }
176
177
178
179 static inline void
180 hline_maybe_acs (mc_tty_char_t ch, int len)
181 {
182 #ifdef HAVE_NCURSES_WIDECHAR
183 if (mc_global.utf8_display)
184 {
185 wchar_t wch[2] = { ch, 0 };
186 cchar_t ctext;
187
188 setcchar (&ctext, wch, 0, 0, NULL);
189 hline_set (&ctext, len);
190 }
191 else
192 #endif
193 hline (get_maybe_acs (ch), len);
194 }
195
196
197
198 static inline void
199 vline_maybe_acs (mc_tty_char_t ch, int len)
200 {
201 #ifdef HAVE_NCURSES_WIDECHAR
202 if (mc_global.utf8_display)
203 {
204 wchar_t wch[2] = { ch, 0 };
205 cchar_t ctext;
206
207 setcchar (&ctext, wch, 0, 0, NULL);
208 vline_set (&ctext, len);
209 }
210 else
211 #endif
212 vline (get_maybe_acs (ch), len);
213 }
214
215
216
217
218
219 void
220 tty_init (gboolean mouse_enable, gboolean is_xterm)
221 {
222 struct termios mode;
223
224
225
226 const char *ncurses_ver = curses_version ();
227
228 ncurses_koi8r_double_line_bug =
229 (strncmp (ncurses_ver, "ncurses ", 8) == 0 && strcmp (ncurses_ver + 8, "6.5.20251115") < 0);
230
231 initscr ();
232
233 #ifdef HAVE_ESCDELAY
234
235
236
237
238
239
240
241
242
243 ESCDELAY = 200;
244 #endif
245
246 tcgetattr (STDIN_FILENO, &mode);
247
248 mode.c_cc[VINTR] = CTRL ('g');
249
250 mode.c_cc[VQUIT] = NULL_VALUE;
251 tcsetattr (STDIN_FILENO, TCSANOW, &mode);
252
253
254 def_prog_mode ();
255
256 tty_start_interrupt_key ();
257
258 if (!mouse_enable)
259 use_mouse_p = MOUSE_DISABLED;
260 tty_init_xterm_support (is_xterm);
261 tty_enter_ca_mode ();
262 tty_raw_mode ();
263 noecho ();
264 keypad (stdscr, TRUE);
265 nodelay (stdscr, FALSE);
266
267 tty_setup_sigwinch (sigwinch_handler);
268 }
269
270
271
272 void
273 tty_shutdown (void)
274 {
275 tty_destroy_winch_pipe ();
276 tty_reset_shell_mode ();
277 tty_noraw_mode ();
278 tty_keypad (FALSE);
279 tty_reset_screen ();
280 tty_exit_ca_mode ();
281 }
282
283
284
285 void
286 tty_enter_ca_mode (void)
287 {
288 if (mc_global.tty.xterm_flag && smcup != NULL)
289 {
290 fprintf (stdout, ESC_STR "7" ESC_STR "[?47h");
291 fflush (stdout);
292 }
293 }
294
295
296
297 void
298 tty_exit_ca_mode (void)
299 {
300 if (mc_global.tty.xterm_flag && rmcup != NULL)
301 {
302 fprintf (stdout, ESC_STR "[?47l" ESC_STR "8" ESC_STR "[m");
303 fflush (stdout);
304 }
305 }
306
307
308
309 void
310 tty_change_screen_size (void)
311 {
312 #if defined(TIOCGWINSZ) && NCURSES_VERSION_MAJOR >= 4
313 struct winsize winsz;
314
315 winsz.ws_col = winsz.ws_row = 0;
316
317 #ifndef NCURSES_VERSION
318 tty_noraw_mode ();
319 tty_reset_screen ();
320 #endif
321
322
323 ioctl (fileno (stdout), TIOCGWINSZ, &winsz);
324 if (winsz.ws_col != 0 && winsz.ws_row != 0)
325 {
326 #if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM)
327 resizeterm (winsz.ws_row, winsz.ws_col);
328 clearok (stdscr, TRUE);
329 #else
330 COLS = winsz.ws_col;
331 LINES = winsz.ws_row;
332 #endif
333 }
334 #endif
335
336 #ifdef ENABLE_SUBSHELL
337 if (mc_global.tty.use_subshell)
338 tty_resize (mc_global.tty.subshell_pty);
339 #endif
340 }
341
342
343
344 void
345 tty_reset_prog_mode (void)
346 {
347 reset_prog_mode ();
348 }
349
350
351
352 void
353 tty_reset_shell_mode (void)
354 {
355 reset_shell_mode ();
356 }
357
358
359
360 void
361 tty_raw_mode (void)
362 {
363 raw ();
364 cbreak ();
365 }
366
367
368
369 void
370 tty_noraw_mode (void)
371 {
372 nocbreak ();
373 noraw ();
374 }
375
376
377
378 void
379 tty_noecho (void)
380 {
381 noecho ();
382 }
383
384
385
386 int
387 tty_flush_input (void)
388 {
389 return flushinp ();
390 }
391
392
393
394 void
395 tty_keypad (gboolean set)
396 {
397 keypad (stdscr, (bool) set);
398 }
399
400
401
402 void
403 tty_nodelay (gboolean set)
404 {
405 nodelay (stdscr, (bool) set);
406 }
407
408
409
410 int
411 tty_baudrate (void)
412 {
413 return baudrate ();
414 }
415
416
417
418 int
419 tty_lowlevel_getch (void)
420 {
421 return getch ();
422 }
423
424
425
426 int
427 tty_reset_screen (void)
428 {
429 return endwin ();
430 }
431
432
433
434 void
435 tty_touch_screen (void)
436 {
437 touchwin (stdscr);
438 }
439
440
441
442 void
443 tty_gotoyx (int y, int x)
444 {
445 mc_curs_row = y;
446 mc_curs_col = x;
447
448 if (y < 0)
449 y = 0;
450 if (y >= LINES)
451 y = LINES - 1;
452
453 if (x < 0)
454 x = 0;
455 if (x >= COLS)
456 x = COLS - 1;
457
458 move (y, x);
459 }
460
461
462
463 void
464 tty_getyx (int *py, int *px)
465 {
466 *py = mc_curs_row;
467 *px = mc_curs_col;
468 }
469
470
471
472 void
473 tty_draw_hline (int y, int x, mc_tty_char_t ch, int len)
474 {
475 int x1;
476
477 if (y < 0 || y >= LINES || x >= COLS)
478 return;
479
480 x1 = x;
481
482 if (x < 0)
483 {
484 len += x;
485 if (len <= 0)
486 return;
487 x = 0;
488 }
489
490 move (y, x);
491 hline_maybe_acs (ch, len);
492 move (y, x1);
493
494 mc_curs_row = y;
495 mc_curs_col = x1;
496 }
497
498
499
500 void
501 tty_draw_vline (int y, int x, mc_tty_char_t ch, int len)
502 {
503 int y1;
504
505 if (x < 0 || x >= COLS || y >= LINES)
506 return;
507
508 y1 = y;
509
510 if (y < 0)
511 {
512 len += y;
513 if (len <= 0)
514 return;
515 y = 0;
516 }
517
518 move (y, x);
519 vline_maybe_acs (ch, len);
520 move (y1, x);
521
522 mc_curs_row = y1;
523 mc_curs_col = x;
524 }
525
526
527
528
529
530
531
532
533 gboolean
534 tty_clip (int *y, int *x, int *rows, int *cols)
535 {
536 if (*y < 0)
537 {
538 *rows += *y;
539
540 if (*rows <= 0)
541 return FALSE;
542
543 *y = 0;
544 }
545
546 if (*x < 0)
547 {
548 *cols += *x;
549
550 if (*cols <= 0)
551 return FALSE;
552
553 *x = 0;
554 }
555
556 if (*y + *rows > LINES)
557 *rows = LINES - *y;
558
559 if (*rows <= 0)
560 return FALSE;
561
562 if (*x + *cols > COLS)
563 *cols = COLS - *x;
564
565 if (*cols <= 0)
566 return FALSE;
567
568 return TRUE;
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_display_8bit (gboolean what)
597 {
598 meta (stdscr, (int) what);
599 }
600
601
602
603 void
604 tty_print_char (mc_tty_char_t c)
605 {
606 if (yx_in_screen (mc_curs_row, mc_curs_col))
607 addch_maybe_acs (c);
608 mc_curs_col++;
609 }
610
611
612
613 void
614 tty_print_anychar (mc_tty_char_t c)
615 {
616 if (mc_global.utf8_display || c > 255)
617 {
618 int res;
619 unsigned char str[MB_LEN_MAX + 1];
620
621 res = g_unichar_to_utf8 (c, (char *) str);
622 if (res == 0)
623 {
624 if (yx_in_screen (mc_curs_row, mc_curs_col))
625 addch_maybe_acs ('.');
626 mc_curs_col++;
627 }
628 else
629 {
630 const char *s;
631
632 str[res] = '\0';
633 s = str_term_form ((char *) str);
634
635 if (yx_in_screen (mc_curs_row, mc_curs_col))
636 addstr (s);
637
638 if (g_unichar_iswide (c))
639 mc_curs_col += 2;
640 else if (!g_unichar_iszerowidth (c))
641 mc_curs_col++;
642 }
643 }
644 else
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
654 void
655 tty_print_string (const char *s)
656 {
657 int len;
658 int start = 0;
659
660 s = str_term_form (s);
661 len = str_term_width1 (s);
662
663
664 if (mc_curs_row < 0 || mc_curs_row >= LINES || mc_curs_col + len <= 0 || mc_curs_col >= COLS)
665 {
666 mc_curs_col += len;
667 return;
668 }
669
670
671 if (mc_curs_col < 0)
672 {
673 start = -mc_curs_col;
674 len += mc_curs_col;
675 mc_curs_col = 0;
676 }
677
678 mc_curs_col += len;
679 if (mc_curs_col >= COLS)
680 len = COLS - (mc_curs_col - len);
681
682 addstr (str_term_substring (s, start, len));
683 }
684
685
686
687 void
688 tty_printf (const char *fmt, ...)
689 {
690 va_list args;
691 char buf[BUF_1K];
692
693 va_start (args, fmt);
694 g_vsnprintf (buf, sizeof (buf), fmt, args);
695 va_end (args);
696 tty_print_string (buf);
697 }
698
699
700
701 int
702 tty_tigetflag (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
703 {
704 return tigetflag ((NCURSES_CONST char *) terminfo_cap);
705 }
706
707
708
709 int
710 tty_tigetnum (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
711 {
712 return tigetnum ((NCURSES_CONST char *) terminfo_cap);
713 }
714
715
716
717 char *
718 tty_tigetstr (const char *terminfo_cap, MC_UNUSED const char *termcap_cap)
719 {
720 return tigetstr ((NCURSES_CONST char *) terminfo_cap);
721 }
722
723
724
725 void
726 tty_refresh (void)
727 {
728 refresh ();
729 doupdate ();
730 }
731
732
733
734 void
735 tty_beep (void)
736 {
737 beep ();
738 }
739
740