2 Interface to the terminal controlling library.
5 Copyright (C) 2005, 2006, 2007, 2009, 2011
6 The Free Software Foundation, Inc.
9 Andrew Borodin <aborodin@vmail.ru>, 2009.
10 Ilia Maslakov <il.smind@gmail.com>, 2009.
12 This file is part of the Midnight Commander.
14 The Midnight Commander is free software: you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation, either version 3 of the License,
17 or (at your option) any later version.
19 The Midnight Commander is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 * \brief Source: NCurses-based tty layer of Midnight-commander
37 #ifdef HAVE_SYS_IOCTL_H
38 #include <sys/ioctl.h>
42 #include "lib/global.h"
43 #include "lib/strutil.h" /* str_term_form */
49 #include "tty-internal.h" /* mc_tty_normalize_from_utf8() */
51 #include "color-internal.h"
55 /* include at last !!! */
57 #ifdef HAVE_NCURSES_TERM_H
58 #include <ncurses/term.h>
61 #endif /* HAVE_NCURSES_TERM_H */
62 #endif /* WANT_TERM_H */
64 /*** global variables ****************************************************************************/
66 /*** file scope macro definitions ****************************************************************/
68 #if defined(_AIX) && !defined(CTRL)
69 #define CTRL(x) ((x) & 0x1f)
72 #define yx_in_screen(y, x) \
73 (y >= 0 && y < LINES && x >= 0 && x < COLS)
75 /*** global variables ****************************************************************************/
77 /*** file scope type declarations ****************************************************************/
79 /*** file scope variables ************************************************************************/
81 /* ncurses supports cursor positions only within window */
82 /* We use our own cursor coordibates to support partially visible widgets */
83 static int mc_curs_row
, mc_curs_col
;
85 /*** file scope functions ************************************************************************/
86 /* --------------------------------------------------------------------------------------------- */
88 /* --------------------------------------------------------------------------------------------- */
91 tty_setup_sigwinch (void (*handler
) (int))
93 #if (NCURSES_VERSION_MAJOR >= 4) && defined (SIGWINCH)
94 struct sigaction act
, oact
;
95 act
.sa_handler
= handler
;
96 sigemptyset (&act
.sa_mask
);
99 act
.sa_flags
|= SA_RESTART
;
100 #endif /* SA_RESTART */
101 sigaction (SIGWINCH
, &act
, &oact
);
102 #endif /* SIGWINCH */
105 /* --------------------------------------------------------------------------------------------- */
108 sigwinch_handler (int dummy
)
112 mc_global
.tty
.winch_flag
= 1;
115 /* --------------------------------------------------------------------------------------------- */
116 /*** public functions ****************************************************************************/
117 /* --------------------------------------------------------------------------------------------- */
120 mc_tty_normalize_lines_char (const char *ch
)
125 struct mc_tty_lines_struct
129 } const lines_codes
[] = {
130 {"\342\224\230", ACS_LRCORNER
}, /* ┌ */
131 {"\342\224\224", ACS_LLCORNER
}, /* └ */
132 {"\342\224\220", ACS_URCORNER
}, /* ┐ */
133 {"\342\224\214", ACS_ULCORNER
}, /* ┘ */
134 {"\342\224\234", ACS_LTEE
}, /* ├ */
135 {"\342\224\244", ACS_RTEE
}, /* ┤ */
136 {"\342\224\254", ACS_TTEE
}, /* ┬ */
137 {"\342\224\264", ACS_BTEE
}, /* ┴ */
138 {"\342\224\200", ACS_HLINE
}, /* ─ */
139 {"\342\224\202", ACS_VLINE
}, /* │ */
140 {"\342\224\274", ACS_PLUS
}, /* ┼ */
142 {"\342\225\235", ACS_LRCORNER
| A_BOLD
}, /* ╔ */
143 {"\342\225\232", ACS_LLCORNER
| A_BOLD
}, /* ╚ */
144 {"\342\225\227", ACS_URCORNER
| A_BOLD
}, /* ╗ */
145 {"\342\225\224", ACS_ULCORNER
| A_BOLD
}, /* ╝ */
146 {"\342\225\237", ACS_LTEE
| A_BOLD
}, /* ╟ */
147 {"\342\225\242", ACS_RTEE
| A_BOLD
}, /* ╢ */
148 {"\342\225\244", ACS_TTEE
| A_BOLD
}, /* ╤ */
149 {"\342\225\247", ACS_BTEE
| A_BOLD
}, /* ╧ */
150 {"\342\225\220", ACS_HLINE
| A_BOLD
}, /* ═ */
151 {"\342\225\221", ACS_VLINE
| A_BOLD
}, /* ║ */
159 for (res
= 0; lines_codes
[res
].line
; res
++)
161 if (strcmp (ch
, lines_codes
[res
].line
) == 0)
162 return lines_codes
[res
].line_code
;
165 str2
= mc_tty_normalize_from_utf8 (ch
);
166 res
= g_utf8_get_char_validated (str2
, -1);
169 res
= (unsigned char) str2
[0];
175 /* --------------------------------------------------------------------------------------------- */
178 tty_init (gboolean mouse_enable
, gboolean is_xterm
)
184 * If ncurses exports the ESCDELAY variable, it should be set to
185 * a low value, or you'll experience a delay in processing escape
186 * sequences that are recognized by mc (e.g. Esc-Esc). On the other
187 * hand, making ESCDELAY too small can result in some sequences
188 * (e.g. cursor arrows) being reported as separate keys under heavy
189 * processor load, and this can be a problem if mc hasn't learned
190 * them in the "Learn Keys" dialog. The value is in milliseconds.
193 #endif /* HAVE_ESCDELAY */
195 /* use Ctrl-g to generate SIGINT */
196 cur_term
->Nttyb
.c_cc
[VINTR
] = CTRL ('g'); /* ^g */
197 /* disable SIGQUIT to allow use Ctrl-\ key */
198 cur_term
->Nttyb
.c_cc
[VQUIT
] = NULL_VALUE
;
199 tcsetattr (cur_term
->Filedes
, TCSANOW
, &cur_term
->Nttyb
);
201 tty_start_interrupt_key ();
204 use_mouse_p
= MOUSE_DISABLED
;
205 tty_init_xterm_support (is_xterm
); /* do it before do_enter_ca_mode() call */
209 keypad (stdscr
, TRUE
);
210 nodelay (stdscr
, FALSE
);
212 tty_setup_sigwinch (sigwinch_handler
);
215 /* --------------------------------------------------------------------------------------------- */
221 tty_reset_shell_mode ();
228 /* --------------------------------------------------------------------------------------------- */
231 tty_change_screen_size (void)
233 #if defined(TIOCGWINSZ) && NCURSES_VERSION_MAJOR >= 4
234 struct winsize winsz
;
236 winsz
.ws_col
= winsz
.ws_row
= 0;
238 #ifndef NCURSES_VERSION
243 /* Ioctl on the STDIN_FILENO */
244 ioctl (fileno (stdout
), TIOCGWINSZ
, &winsz
);
245 if (winsz
.ws_col
!= 0 && winsz
.ws_row
!= 0)
247 #if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM)
248 resizeterm (winsz
.ws_row
, winsz
.ws_col
);
249 clearok (stdscr
, TRUE
); /* sigwinch's should use a semaphore! */
252 LINES
= winsz
.ws_row
;
255 #endif /* defined(TIOCGWINSZ) || NCURSES_VERSION_MAJOR >= 4 */
257 #ifdef ENABLE_SUBSHELL
258 if (mc_global
.tty
.use_subshell
)
259 tty_resize (mc_global
.tty
.subshell_pty
);
263 /* --------------------------------------------------------------------------------------------- */
266 tty_reset_prog_mode (void)
271 /* --------------------------------------------------------------------------------------------- */
274 tty_reset_shell_mode (void)
279 /* --------------------------------------------------------------------------------------------- */
284 raw (); /* FIXME: uneeded? */
288 /* --------------------------------------------------------------------------------------------- */
291 tty_noraw_mode (void)
293 nocbreak (); /* FIXME: unneeded? */
297 /* --------------------------------------------------------------------------------------------- */
305 /* --------------------------------------------------------------------------------------------- */
308 tty_flush_input (void)
313 /* --------------------------------------------------------------------------------------------- */
316 tty_keypad (gboolean set
)
318 keypad (stdscr
, (bool) set
);
321 /* --------------------------------------------------------------------------------------------- */
324 tty_nodelay (gboolean set
)
326 nodelay (stdscr
, (bool) set
);
329 /* --------------------------------------------------------------------------------------------- */
337 /* --------------------------------------------------------------------------------------------- */
340 tty_lowlevel_getch (void)
345 /* --------------------------------------------------------------------------------------------- */
348 tty_reset_screen (void)
353 /* --------------------------------------------------------------------------------------------- */
356 tty_touch_screen (void)
361 /* --------------------------------------------------------------------------------------------- */
364 tty_gotoyx (int y
, int x
)
382 /* --------------------------------------------------------------------------------------------- */
385 tty_getyx (int *py
, int *px
)
391 /* --------------------------------------------------------------------------------------------- */
394 tty_draw_hline (int y
, int x
, int ch
, int len
)
398 if (y
< 0 || y
>= LINES
|| x
>= COLS
)
411 if ((chtype
) ch
== ACS_HLINE
)
412 ch
= mc_tty_frm
[MC_TTY_FRM_HORIZ
];
422 /* --------------------------------------------------------------------------------------------- */
425 tty_draw_vline (int y
, int x
, int ch
, int len
)
429 if (x
< 0 || x
>= COLS
|| y
>= LINES
)
442 if ((chtype
) ch
== ACS_VLINE
)
443 ch
= mc_tty_frm
[MC_TTY_FRM_VERT
];
453 /* --------------------------------------------------------------------------------------------- */
456 tty_fill_region (int y
, int x
, int rows
, int cols
, unsigned char ch
)
480 if (y
+ rows
> LINES
)
485 for (i
= 0; i
< rows
; i
++)
497 /* --------------------------------------------------------------------------------------------- */
500 tty_set_alt_charset (gboolean alt_charset
)
505 /* --------------------------------------------------------------------------------------------- */
508 tty_display_8bit (gboolean what
)
510 meta (stdscr
, (int) what
);
513 /* --------------------------------------------------------------------------------------------- */
516 tty_print_char (int c
)
518 if (yx_in_screen (mc_curs_row
, mc_curs_col
))
523 /* --------------------------------------------------------------------------------------------- */
526 tty_print_anychar (int c
)
528 unsigned char str
[6 + 1];
530 if (mc_global
.utf8_display
|| c
> 255)
534 res
= g_unichar_to_utf8 (c
, (char *) str
);
537 if (yx_in_screen (mc_curs_row
, mc_curs_col
))
546 s
= str_term_form ((char *) str
);
548 if (yx_in_screen (mc_curs_row
, mc_curs_col
))
551 if (g_unichar_iswide (c
))
553 else if (!g_unichar_iszerowidth (c
))
559 if (yx_in_screen (mc_curs_row
, mc_curs_col
))
565 /* --------------------------------------------------------------------------------------------- */
568 tty_print_alt_char (int c
, gboolean single
)
570 if (yx_in_screen (mc_curs_row
, mc_curs_col
))
572 if ((chtype
) c
== ACS_VLINE
)
573 c
= mc_tty_frm
[single
? MC_TTY_FRM_VERT
: MC_TTY_FRM_DVERT
];
574 else if ((chtype
) c
== ACS_HLINE
)
575 c
= mc_tty_frm
[single
? MC_TTY_FRM_HORIZ
: MC_TTY_FRM_DHORIZ
];
576 else if ((chtype
) c
== ACS_LTEE
)
577 c
= mc_tty_frm
[single
? MC_TTY_FRM_LEFTMIDDLE
: MC_TTY_FRM_DLEFTMIDDLE
];
578 else if ((chtype
) c
== ACS_RTEE
)
579 c
= mc_tty_frm
[single
? MC_TTY_FRM_RIGHTMIDDLE
: MC_TTY_FRM_DRIGHTMIDDLE
];
580 else if ((chtype
) c
== ACS_ULCORNER
)
581 c
= mc_tty_frm
[single
? MC_TTY_FRM_LEFTTOP
: MC_TTY_FRM_DLEFTTOP
];
582 else if ((chtype
) c
== ACS_LLCORNER
)
583 c
= mc_tty_frm
[single
? MC_TTY_FRM_LEFTBOTTOM
: MC_TTY_FRM_DLEFTBOTTOM
];
584 else if ((chtype
) c
== ACS_URCORNER
)
585 c
= mc_tty_frm
[single
? MC_TTY_FRM_RIGHTTOP
: MC_TTY_FRM_DRIGHTTOP
];
586 else if ((chtype
) c
== ACS_LRCORNER
)
587 c
= mc_tty_frm
[single
? MC_TTY_FRM_RIGHTBOTTOM
: MC_TTY_FRM_DRIGHTBOTTOM
];
588 else if ((chtype
) c
== ACS_PLUS
)
589 c
= mc_tty_frm
[MC_TTY_FRM_CROSS
];
597 /* --------------------------------------------------------------------------------------------- */
600 tty_print_string (const char *s
)
605 s
= str_term_form (s
);
606 len
= str_term_width1 (s
);
608 /* line is upper or below the screen or entire line is before or after scrren */
609 if (mc_curs_row
< 0 || mc_curs_row
>= LINES
|| mc_curs_col
+ len
<= 0 || mc_curs_col
>= COLS
)
615 /* skip invisible left part */
618 start
= -mc_curs_col
;
624 if (mc_curs_col
>= COLS
)
625 len
= COLS
- (mc_curs_col
- len
);
627 addstr (str_term_substring (s
, start
, len
));
630 /* --------------------------------------------------------------------------------------------- */
633 tty_printf (const char *fmt
, ...)
636 char buf
[BUF_1K
]; /* FIXME: is it enough? */
638 va_start (args
, fmt
);
639 g_vsnprintf (buf
, sizeof (buf
), fmt
, args
);
641 tty_print_string (buf
);
644 /* --------------------------------------------------------------------------------------------- */
647 tty_tgetstr (const char *cap
)
650 return tgetstr ((char *) cap
, &unused
);
653 /* --------------------------------------------------------------------------------------------- */
662 /* --------------------------------------------------------------------------------------------- */
670 /* --------------------------------------------------------------------------------------------- */