Define winch_flag as volatile sig_atomic_t.
[midnight-commander.git] / lib / tty / tty-ncurses.c
blobfe2d4cca02ad08ba22d29cebb8ecf787f1b80c5c
1 /*
2 Interface to the terminal controlling library.
3 Ncurses wrapper.
5 Copyright (C) 2005, 2006, 2007, 2009, 2011
6 The Free Software Foundation, Inc.
8 Written by:
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/>.
28 /** \file
29 * \brief Source: NCurses-based tty layer of Midnight-commander
32 #include <config.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <signal.h>
38 #include "lib/global.h"
39 #include "lib/strutil.h" /* str_term_form */
41 #ifndef WANT_TERM_H
42 #define WANT_TERM_H
43 #endif
45 #include "tty-internal.h" /* mc_tty_normalize_from_utf8() */
46 #include "tty.h"
47 #include "color-internal.h"
48 #include "mouse.h"
49 #include "win.h"
51 /* include at last !!! */
52 #ifdef WANT_TERM_H
53 #ifdef HAVE_NCURSES_TERM_H
54 #include <ncurses/term.h>
55 #else
56 #include <term.h>
57 #endif /* HAVE_NCURSES_TERM_H */
58 #endif /* WANT_TERM_H */
60 /*** global variables ****************************************************************************/
62 /*** file scope macro definitions ****************************************************************/
64 #if defined(_AIX) && !defined(CTRL)
65 #define CTRL(x) ((x) & 0x1f)
66 #endif
68 /*** global variables ****************************************************************************/
70 /*** file scope type declarations ****************************************************************/
72 /*** file scope variables ************************************************************************/
74 /*** file scope functions ************************************************************************/
75 /* --------------------------------------------------------------------------------------------- */
77 /* --------------------------------------------------------------------------------------------- */
79 static void
80 tty_setup_sigwinch (void (*handler) (int))
82 #if (NCURSES_VERSION_MAJOR >= 4) && defined (SIGWINCH)
83 struct sigaction act, oact;
84 act.sa_handler = handler;
85 sigemptyset (&act.sa_mask);
86 act.sa_flags = 0;
87 #ifdef SA_RESTART
88 act.sa_flags |= SA_RESTART;
89 #endif /* SA_RESTART */
90 sigaction (SIGWINCH, &act, &oact);
91 #endif /* SIGWINCH */
94 /* --------------------------------------------------------------------------------------------- */
96 static void
97 sigwinch_handler (int dummy)
99 (void) dummy;
101 mc_global.tty.winch_flag = 1;
104 /* --------------------------------------------------------------------------------------------- */
105 /*** public functions ****************************************************************************/
106 /* --------------------------------------------------------------------------------------------- */
109 mc_tty_normalize_lines_char (const char *ch)
111 char *str2;
112 int res;
114 struct mc_tty_lines_struct
116 const char *line;
117 int line_code;
118 } const lines_codes[] = {
119 {"\342\224\230", ACS_LRCORNER}, /* ┌ */
120 {"\342\224\224", ACS_LLCORNER}, /* └ */
121 {"\342\224\220", ACS_URCORNER}, /* ┐ */
122 {"\342\224\214", ACS_ULCORNER}, /* ┘ */
123 {"\342\224\234", ACS_LTEE}, /* ├ */
124 {"\342\224\244", ACS_RTEE}, /* ┤ */
125 {"\342\224\254", ACS_TTEE}, /* ┬ */
126 {"\342\224\264", ACS_BTEE}, /* ┴ */
127 {"\342\224\200", ACS_HLINE}, /* ─ */
128 {"\342\224\202", ACS_VLINE}, /* │ */
129 {"\342\224\274", ACS_PLUS}, /* ┼ */
131 {"\342\225\235", ACS_LRCORNER | A_BOLD}, /* ╔ */
132 {"\342\225\232", ACS_LLCORNER | A_BOLD}, /* ╚ */
133 {"\342\225\227", ACS_URCORNER | A_BOLD}, /* ╗ */
134 {"\342\225\224", ACS_ULCORNER | A_BOLD}, /* ╝ */
135 {"\342\225\237", ACS_LTEE | A_BOLD}, /* ╟ */
136 {"\342\225\242", ACS_RTEE | A_BOLD}, /* ╢ */
137 {"\342\225\244", ACS_TTEE | A_BOLD}, /* ╤ */
138 {"\342\225\247", ACS_BTEE | A_BOLD}, /* ╧ */
139 {"\342\225\220", ACS_HLINE | A_BOLD}, /* ═ */
140 {"\342\225\221", ACS_VLINE | A_BOLD}, /* ║ */
142 {NULL, 0}
145 if (ch == NULL)
146 return (int) ' ';
148 for (res = 0; lines_codes[res].line; res++)
150 if (strcmp (ch, lines_codes[res].line) == 0)
151 return lines_codes[res].line_code;
154 str2 = mc_tty_normalize_from_utf8 (ch);
155 res = g_utf8_get_char_validated (str2, -1);
157 if (res < 0)
158 res = (unsigned char) str2[0];
159 g_free (str2);
161 return res;
164 /* --------------------------------------------------------------------------------------------- */
166 void
167 tty_init (gboolean mouse_enable, gboolean is_xterm)
169 initscr ();
171 #ifdef HAVE_ESCDELAY
173 * If ncurses exports the ESCDELAY variable, it should be set to
174 * a low value, or you'll experience a delay in processing escape
175 * sequences that are recognized by mc (e.g. Esc-Esc). On the other
176 * hand, making ESCDELAY too small can result in some sequences
177 * (e.g. cursor arrows) being reported as separate keys under heavy
178 * processor load, and this can be a problem if mc hasn't learned
179 * them in the "Learn Keys" dialog. The value is in milliseconds.
181 ESCDELAY = 200;
182 #endif /* HAVE_ESCDELAY */
184 /* use Ctrl-g to generate SIGINT */
185 cur_term->Nttyb.c_cc[VINTR] = CTRL ('g'); /* ^g */
186 /* disable SIGQUIT to allow use Ctrl-\ key */
187 cur_term->Nttyb.c_cc[VQUIT] = NULL_VALUE;
188 tcsetattr (cur_term->Filedes, TCSANOW, &cur_term->Nttyb);
190 tty_start_interrupt_key ();
192 if (!mouse_enable)
193 use_mouse_p = MOUSE_DISABLED;
194 tty_init_xterm_support (is_xterm); /* do it before do_enter_ca_mode() call */
195 init_mouse ();
196 do_enter_ca_mode ();
197 tty_raw_mode ();
198 noecho ();
199 keypad (stdscr, TRUE);
200 nodelay (stdscr, FALSE);
202 tty_setup_sigwinch (sigwinch_handler);
205 /* --------------------------------------------------------------------------------------------- */
207 void
208 tty_shutdown (void)
210 disable_mouse ();
211 tty_reset_shell_mode ();
212 tty_noraw_mode ();
213 tty_keypad (FALSE);
214 tty_reset_screen ();
215 do_exit_ca_mode ();
218 /* --------------------------------------------------------------------------------------------- */
220 void
221 tty_reset_prog_mode (void)
223 reset_prog_mode ();
226 /* --------------------------------------------------------------------------------------------- */
228 void
229 tty_reset_shell_mode (void)
231 reset_shell_mode ();
234 /* --------------------------------------------------------------------------------------------- */
236 void
237 tty_raw_mode (void)
239 raw (); /* FIXME: uneeded? */
240 cbreak ();
243 /* --------------------------------------------------------------------------------------------- */
245 void
246 tty_noraw_mode (void)
248 nocbreak (); /* FIXME: unneeded? */
249 noraw ();
252 /* --------------------------------------------------------------------------------------------- */
254 void
255 tty_noecho (void)
257 noecho ();
260 /* --------------------------------------------------------------------------------------------- */
263 tty_flush_input (void)
265 return flushinp ();
268 /* --------------------------------------------------------------------------------------------- */
270 void
271 tty_keypad (gboolean set)
273 keypad (stdscr, (bool) set);
276 /* --------------------------------------------------------------------------------------------- */
278 void
279 tty_nodelay (gboolean set)
281 nodelay (stdscr, (bool) set);
284 /* --------------------------------------------------------------------------------------------- */
287 tty_baudrate (void)
289 return baudrate ();
292 /* --------------------------------------------------------------------------------------------- */
295 tty_lowlevel_getch (void)
297 return getch ();
300 /* --------------------------------------------------------------------------------------------- */
303 tty_reset_screen (void)
305 return endwin ();
308 /* --------------------------------------------------------------------------------------------- */
310 void
311 tty_touch_screen (void)
313 touchwin (stdscr);
316 /* --------------------------------------------------------------------------------------------- */
318 void
319 tty_gotoyx (int y, int x)
321 move (y, x);
324 /* --------------------------------------------------------------------------------------------- */
326 void
327 tty_getyx (int *py, int *px)
329 getyx (stdscr, *py, *px);
332 /* --------------------------------------------------------------------------------------------- */
333 /* if x < 0 or y < 0, draw line starting from current position */
335 void
336 tty_draw_hline (int y, int x, int ch, int len)
338 if ((chtype) ch == ACS_HLINE)
339 ch = mc_tty_frm[MC_TTY_FRM_HORIZ];
341 if ((y >= 0) && (x >= 0))
342 move (y, x);
343 hline (ch, len);
346 /* --------------------------------------------------------------------------------------------- */
347 /* if x < 0 or y < 0, draw line starting from current position */
349 void
350 tty_draw_vline (int y, int x, int ch, int len)
352 if ((chtype) ch == ACS_VLINE)
353 ch = mc_tty_frm[MC_TTY_FRM_VERT];
355 if ((y >= 0) && (x >= 0))
356 move (y, x);
357 vline (ch, len);
360 /* --------------------------------------------------------------------------------------------- */
362 void
363 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
365 int i;
367 if (y < 0)
369 rows += y;
371 if (rows <= 0)
372 return;
374 y = 0;
377 if (x < 0)
379 cols += x;
381 if (cols <= 0)
382 return;
384 x = 0;
387 if (y + rows > LINES)
388 rows = LINES - y;
389 if (x + cols > COLS)
390 cols = COLS - x;
392 for (i = 0; i < rows; i++)
394 move (y + i, x);
395 hline (ch, cols);
398 move (y, x);
401 /* --------------------------------------------------------------------------------------------- */
403 void
404 tty_set_alt_charset (gboolean alt_charset)
406 (void) alt_charset;
409 /* --------------------------------------------------------------------------------------------- */
411 void
412 tty_display_8bit (gboolean what)
414 meta (stdscr, (int) what);
417 /* --------------------------------------------------------------------------------------------- */
419 void
420 tty_print_char (int c)
422 addch (c);
425 /* --------------------------------------------------------------------------------------------- */
427 void
428 tty_print_anychar (int c)
430 unsigned char str[6 + 1];
432 if (mc_global.utf8_display || c > 255)
434 int res = g_unichar_to_utf8 (c, (char *) str);
435 if (res == 0)
437 str[0] = '.';
438 str[1] = '\0';
440 else
441 str[res] = '\0';
442 addstr (str_term_form ((char *) str));
444 else
445 addch (c);
449 /* --------------------------------------------------------------------------------------------- */
451 void
452 tty_print_alt_char (int c, gboolean single)
454 if ((chtype) c == ACS_VLINE)
455 c = mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT];
456 else if ((chtype) c == ACS_HLINE)
457 c = mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ];
458 else if ((chtype) c == ACS_LTEE)
459 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTMIDDLE : MC_TTY_FRM_DLEFTMIDDLE];
460 else if ((chtype) c == ACS_RTEE)
461 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTMIDDLE : MC_TTY_FRM_DRIGHTMIDDLE];
462 else if ((chtype) c == ACS_ULCORNER)
463 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTTOP : MC_TTY_FRM_DLEFTTOP];
464 else if ((chtype) c == ACS_LLCORNER)
465 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTBOTTOM : MC_TTY_FRM_DLEFTBOTTOM];
466 else if ((chtype) c == ACS_URCORNER)
467 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTTOP : MC_TTY_FRM_DRIGHTTOP];
468 else if ((chtype) c == ACS_LRCORNER)
469 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTBOTTOM : MC_TTY_FRM_DRIGHTBOTTOM];
470 else if ((chtype) c == ACS_PLUS)
471 c = mc_tty_frm[MC_TTY_FRM_CROSS];
473 addch (c);
476 /* --------------------------------------------------------------------------------------------- */
478 void
479 tty_print_string (const char *s)
481 addstr (str_term_form (s));
484 /* --------------------------------------------------------------------------------------------- */
486 void
487 tty_printf (const char *fmt, ...)
489 va_list args;
491 va_start (args, fmt);
492 vw_printw (stdscr, fmt, args);
493 va_end (args);
496 /* --------------------------------------------------------------------------------------------- */
498 char *
499 tty_tgetstr (const char *cap)
501 char *unused = NULL;
502 return tgetstr ((char *) cap, &unused);
505 /* --------------------------------------------------------------------------------------------- */
507 void
508 tty_refresh (void)
510 refresh ();
511 doupdate ();
514 /* --------------------------------------------------------------------------------------------- */
516 void
517 tty_beep (void)
519 beep ();
522 /* --------------------------------------------------------------------------------------------- */