This source file includes following definitions.
- tty_setup_sigwinch
- sigwinch_handler
- tty_clip
- mc_tty_normalize_lines_char
- 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_set_alt_charset
- tty_display_8bit
- tty_print_char
- tty_print_anychar
- tty_print_alt_char
- tty_print_string
- tty_printf
- tty_tgetstr
- 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
67
68 #if !defined(CTRL)
69 #define CTRL(x) ((x) & 0x1f)
70 #endif
71
72 #define yx_in_screen(y, x) (y >= 0 && y < LINES && x >= 0 && x < COLS)
73
74
75
76
77
78
79
80
81
82
83
84 static int mc_curs_row, mc_curs_col;
85
86
87
88
89
90 static void
91 tty_setup_sigwinch (void (*handler) (int))
92 {
93 #if (NCURSES_VERSION_MAJOR >= 4) && defined(SIGWINCH)
94 struct sigaction act, oact;
95
96 memset (&act, 0, sizeof (act));
97 act.sa_handler = handler;
98 sigemptyset (&act.sa_mask);
99 #ifdef SA_RESTART
100 act.sa_flags = SA_RESTART;
101 #endif
102 my_sigaction (SIGWINCH, &act, &oact);
103 #endif
104
105 tty_create_winch_pipe ();
106 }
107
108
109
110 static void
111 sigwinch_handler (int dummy)
112 {
113 ssize_t n = 0;
114
115 (void) dummy;
116
117 n = write (sigwinch_pipe[1], "", 1);
118 (void) n;
119 }
120
121
122
123
124
125
126
127
128 static gboolean
129 tty_clip (int *y, int *x, int *rows, int *cols)
130 {
131 if (*y < 0)
132 {
133 *rows += *y;
134
135 if (*rows <= 0)
136 return FALSE;
137
138 *y = 0;
139 }
140
141 if (*x < 0)
142 {
143 *cols += *x;
144
145 if (*cols <= 0)
146 return FALSE;
147
148 *x = 0;
149 }
150
151 if (*y + *rows > LINES)
152 *rows = LINES - *y;
153
154 if (*rows <= 0)
155 return FALSE;
156
157 if (*x + *cols > COLS)
158 *cols = COLS - *x;
159
160 if (*cols <= 0)
161 return FALSE;
162
163 return TRUE;
164 }
165
166
167
168
169
170 int
171 mc_tty_normalize_lines_char (const char *str)
172 {
173 char *str2;
174 int res;
175
176 struct mc_tty_lines_struct
177 {
178 const char *line;
179 int line_code;
180 } const lines_codes[] = {
181 { "\342\224\230", ACS_LRCORNER },
182 { "\342\224\224", ACS_LLCORNER },
183 { "\342\224\220", ACS_URCORNER },
184 { "\342\224\214", ACS_ULCORNER },
185 { "\342\224\234", ACS_LTEE },
186 { "\342\224\244", ACS_RTEE },
187 { "\342\224\254", ACS_TTEE },
188 { "\342\224\264", ACS_BTEE },
189 { "\342\224\200", ACS_HLINE },
190 { "\342\224\202", ACS_VLINE },
191 { "\342\224\274", ACS_PLUS },
192
193 { "\342\225\235", ACS_LRCORNER | A_BOLD },
194 { "\342\225\232", ACS_LLCORNER | A_BOLD },
195 { "\342\225\227", ACS_URCORNER | A_BOLD },
196 { "\342\225\224", ACS_ULCORNER | A_BOLD },
197 { "\342\225\237", ACS_LTEE | A_BOLD },
198 { "\342\225\242", ACS_RTEE | A_BOLD },
199 { "\342\225\244", ACS_TTEE | A_BOLD },
200 { "\342\225\247", ACS_BTEE | A_BOLD },
201 { "\342\225\220", ACS_HLINE | A_BOLD },
202 { "\342\225\221", ACS_VLINE | A_BOLD },
203
204 { NULL, 0 },
205 };
206
207 if (str == NULL)
208 return (int) ' ';
209
210 for (res = 0; lines_codes[res].line; res++)
211 if (strcmp (str, lines_codes[res].line) == 0)
212 return lines_codes[res].line_code;
213
214 str2 = mc_tty_normalize_from_utf8 (str);
215 res = g_utf8_get_char_validated (str2, -1);
216
217 if (res < 0)
218 res = (unsigned char) str2[0];
219 g_free (str2);
220
221 return res;
222 }
223
224
225
226 void
227 tty_init (gboolean mouse_enable, gboolean is_xterm)
228 {
229 struct termios mode;
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, int 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 if ((chtype) ch == ACS_HLINE)
491 ch = mc_tty_frm[MC_TTY_FRM_HORIZ];
492
493 move (y, x);
494 hline (ch, len);
495 move (y, x1);
496
497 mc_curs_row = y;
498 mc_curs_col = x1;
499 }
500
501
502
503 void
504 tty_draw_vline (int y, int x, int ch, int len)
505 {
506 int y1;
507
508 if (x < 0 || x >= COLS || y >= LINES)
509 return;
510
511 y1 = y;
512
513 if (y < 0)
514 {
515 len += y;
516 if (len <= 0)
517 return;
518 y = 0;
519 }
520
521 if ((chtype) ch == ACS_VLINE)
522 ch = mc_tty_frm[MC_TTY_FRM_VERT];
523
524 move (y, x);
525 vline (ch, len);
526 move (y1, x);
527
528 mc_curs_row = y1;
529 mc_curs_col = x;
530 }
531
532
533
534 void
535 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
536 {
537 int i;
538
539 if (!tty_clip (&y, &x, &rows, &cols))
540 return;
541
542 for (i = 0; i < rows; i++)
543 {
544 move (y + i, x);
545 hline (ch, cols);
546 }
547
548 move (y, x);
549
550 mc_curs_row = y;
551 mc_curs_col = x;
552 }
553
554
555
556 void
557 tty_colorize_area (int y, int x, int rows, int cols, int color)
558 {
559 #ifdef ENABLE_SHADOWS
560 cchar_t *ctext;
561 wchar_t wch[10];
562 attr_t attrs;
563 short color_pair;
564
565 if (!use_colors || !tty_clip (&y, &x, &rows, &cols))
566 return;
567
568 tty_setcolor (color);
569 ctext = g_malloc (sizeof (cchar_t) * (cols + 1));
570
571 for (int row = 0; row < rows; row++)
572 {
573 mvin_wchnstr (y + row, x, ctext, cols);
574
575 for (int col = 0; col < cols; col++)
576 {
577 getcchar (&ctext[col], wch, &attrs, &color_pair, NULL);
578 setcchar (&ctext[col], wch, attrs, color, NULL);
579 }
580
581 mvadd_wchnstr (y + row, x, ctext, cols);
582 }
583
584 g_free (ctext);
585 #else
586 (void) y;
587 (void) x;
588 (void) rows;
589 (void) cols;
590 (void) color;
591 #endif
592 }
593
594
595
596 void
597 tty_set_alt_charset (gboolean alt_charset)
598 {
599 (void) alt_charset;
600 }
601
602
603
604 void
605 tty_display_8bit (gboolean what)
606 {
607 meta (stdscr, (int) what);
608 }
609
610
611
612 void
613 tty_print_char (int c)
614 {
615 if (yx_in_screen (mc_curs_row, mc_curs_col))
616 addch (c);
617 mc_curs_col++;
618 }
619
620
621
622 void
623 tty_print_anychar (int c)
624 {
625 if (mc_global.utf8_display || c > 255)
626 {
627 int res;
628 unsigned char str[MB_LEN_MAX + 1];
629
630 res = g_unichar_to_utf8 (c, (char *) str);
631 if (res == 0)
632 {
633 if (yx_in_screen (mc_curs_row, mc_curs_col))
634 addch ('.');
635 mc_curs_col++;
636 }
637 else
638 {
639 const char *s;
640
641 str[res] = '\0';
642 s = str_term_form ((char *) str);
643
644 if (yx_in_screen (mc_curs_row, mc_curs_col))
645 addstr (s);
646
647 if (g_unichar_iswide (c))
648 mc_curs_col += 2;
649 else if (!g_unichar_iszerowidth (c))
650 mc_curs_col++;
651 }
652 }
653 else
654 {
655 if (yx_in_screen (mc_curs_row, mc_curs_col))
656 addch (c);
657 mc_curs_col++;
658 }
659 }
660
661
662
663 void
664 tty_print_alt_char (int c, gboolean single)
665 {
666 if (yx_in_screen (mc_curs_row, mc_curs_col))
667 {
668 if ((chtype) c == ACS_VLINE)
669 c = mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT];
670 else if ((chtype) c == ACS_HLINE)
671 c = mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ];
672 else if ((chtype) c == ACS_LTEE)
673 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTMIDDLE : MC_TTY_FRM_DLEFTMIDDLE];
674 else if ((chtype) c == ACS_RTEE)
675 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTMIDDLE : MC_TTY_FRM_DRIGHTMIDDLE];
676 else if ((chtype) c == ACS_ULCORNER)
677 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTTOP : MC_TTY_FRM_DLEFTTOP];
678 else if ((chtype) c == ACS_LLCORNER)
679 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTBOTTOM : MC_TTY_FRM_DLEFTBOTTOM];
680 else if ((chtype) c == ACS_URCORNER)
681 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTTOP : MC_TTY_FRM_DRIGHTTOP];
682 else if ((chtype) c == ACS_LRCORNER)
683 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTBOTTOM : MC_TTY_FRM_DRIGHTBOTTOM];
684 else if ((chtype) c == ACS_PLUS)
685 c = mc_tty_frm[MC_TTY_FRM_CROSS];
686
687 addch (c);
688 }
689
690 mc_curs_col++;
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 char *
743 tty_tgetstr (const char *cap)
744 {
745 char *unused = NULL;
746
747 return tgetstr ((NCURSES_CONST char *) cap, &unused);
748 }
749
750
751
752 void
753 tty_refresh (void)
754 {
755 refresh ();
756 doupdate ();
757 }
758
759
760
761 void
762 tty_beep (void)
763 {
764 beep ();
765 }
766
767