Merge branch '2621_path_encoding_and_extfs'
[midnight-commander.git] / lib / tty / tty-ncurses.c
blob922fdedfbf2e865eb0ab6cfdaf031b7f1daf4abe
1 /*
2 Interface to the terminal controlling library.
3 Ncurses wrapper.
5 Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
7 Written by:
8 Andrew Borodin <aborodin@vmail.ru>, 2009.
9 Ilia Maslakov <il.smind@gmail.com>, 2009.
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software; you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be
19 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
20 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 MA 02110-1301, USA.
29 /** \file
30 * \brief Source: NCurses-based tty layer of Midnight-commander
33 #include <config.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <signal.h>
39 #include "lib/global.h"
40 #include "lib/strutil.h" /* str_term_form */
42 #ifndef WANT_TERM_H
43 #define WANT_TERM_H
44 #endif
46 #include "tty-internal.h" /* mc_tty_normalize_from_utf8() */
47 #include "tty.h"
48 #include "color-internal.h"
49 #include "mouse.h"
50 #include "win.h"
52 /* include at last !!! */
53 #ifdef WANT_TERM_H
54 #ifdef HAVE_NCURSES_TERM_H
55 #include <ncurses/term.h>
56 #else
57 #include <term.h>
58 #endif /* HAVE_NCURSES_TERM_H */
59 #endif /* WANT_TERM_H */
61 /*** global variables ****************************************************************************/
63 /*** file scope macro definitions ****************************************************************/
65 #if defined(_AIX) && !defined(CTRL)
66 #define CTRL(x) ((x) & 0x1f)
67 #endif
69 /*** global variables ****************************************************************************/
71 /*** file scope type declarations ****************************************************************/
73 /*** file scope variables ************************************************************************/
75 /*** file scope functions ************************************************************************/
76 /* --------------------------------------------------------------------------------------------- */
78 /* --------------------------------------------------------------------------------------------- */
80 static void
81 tty_setup_sigwinch (void (*handler) (int))
83 #if (NCURSES_VERSION_MAJOR >= 4) && defined (SIGWINCH)
84 struct sigaction act, oact;
85 act.sa_handler = handler;
86 sigemptyset (&act.sa_mask);
87 act.sa_flags = 0;
88 #ifdef SA_RESTART
89 act.sa_flags |= SA_RESTART;
90 #endif /* SA_RESTART */
91 sigaction (SIGWINCH, &act, &oact);
92 #endif /* SIGWINCH */
95 /* --------------------------------------------------------------------------------------------- */
97 void
98 sigwinch_handler (int dummy)
100 (void) dummy;
102 mc_global.tty.winch_flag = TRUE;
105 /* --------------------------------------------------------------------------------------------- */
106 /*** public functions ****************************************************************************/
107 /* --------------------------------------------------------------------------------------------- */
110 mc_tty_normalize_lines_char (const char *ch)
112 char *str2;
113 int res;
115 struct mc_tty_lines_struct
117 const char *line;
118 int line_code;
119 } const lines_codes[] = {
120 {"\342\224\230", ACS_LRCORNER}, /* ┌ */
121 {"\342\224\224", ACS_LLCORNER}, /* └ */
122 {"\342\224\220", ACS_URCORNER}, /* ┐ */
123 {"\342\224\214", ACS_ULCORNER}, /* ┘ */
124 {"\342\224\234", ACS_LTEE}, /* ├ */
125 {"\342\224\244", ACS_RTEE}, /* ┤ */
126 {"\342\224\254", ACS_TTEE}, /* ┬ */
127 {"\342\224\264", ACS_BTEE}, /* ┴ */
128 {"\342\224\200", ACS_HLINE}, /* ─ */
129 {"\342\224\202", ACS_VLINE}, /* │ */
130 {"\342\224\274", ACS_PLUS}, /* ┼ */
132 {"\342\225\235", ACS_LRCORNER | A_BOLD}, /* ╔ */
133 {"\342\225\232", ACS_LLCORNER | A_BOLD}, /* ╚ */
134 {"\342\225\227", ACS_URCORNER | A_BOLD}, /* ╗ */
135 {"\342\225\224", ACS_ULCORNER | A_BOLD}, /* ╝ */
136 {"\342\225\237", ACS_LTEE | A_BOLD}, /* ╟ */
137 {"\342\225\242", ACS_RTEE | A_BOLD}, /* ╢ */
138 {"\342\225\244", ACS_TTEE | A_BOLD}, /* ╤ */
139 {"\342\225\247", ACS_BTEE | A_BOLD}, /* ╧ */
140 {"\342\225\220", ACS_HLINE | A_BOLD}, /* ═ */
141 {"\342\225\221", ACS_VLINE | A_BOLD}, /* ║ */
143 {NULL, 0}
146 if (ch == NULL)
147 return (int) ' ';
149 for (res = 0; lines_codes[res].line; res++)
151 if (strcmp (ch, lines_codes[res].line) == 0)
152 return lines_codes[res].line_code;
155 str2 = mc_tty_normalize_from_utf8 (ch);
156 res = g_utf8_get_char_validated (str2, -1);
158 if (res < 0)
159 res = (unsigned char) str2[0];
160 g_free (str2);
162 return res;
165 /* --------------------------------------------------------------------------------------------- */
167 void
168 tty_init (gboolean mouse_enable, gboolean is_xterm)
170 initscr ();
172 #ifdef HAVE_ESCDELAY
174 * If ncurses exports the ESCDELAY variable, it should be set to
175 * a low value, or you'll experience a delay in processing escape
176 * sequences that are recognized by mc (e.g. Esc-Esc). On the other
177 * hand, making ESCDELAY too small can result in some sequences
178 * (e.g. cursor arrows) being reported as separate keys under heavy
179 * processor load, and this can be a problem if mc hasn't learned
180 * them in the "Learn Keys" dialog. The value is in milliseconds.
182 ESCDELAY = 200;
183 #endif /* HAVE_ESCDELAY */
185 /* use Ctrl-g to generate SIGINT */
186 cur_term->Nttyb.c_cc[VINTR] = CTRL ('g'); /* ^g */
187 /* disable SIGQUIT to allow use Ctrl-\ key */
188 cur_term->Nttyb.c_cc[VQUIT] = NULL_VALUE;
189 tcsetattr (cur_term->Filedes, TCSANOW, &cur_term->Nttyb);
191 tty_start_interrupt_key ();
193 if (!mouse_enable)
194 use_mouse_p = MOUSE_DISABLED;
195 tty_init_xterm_support (is_xterm); /* do it before do_enter_ca_mode() call */
196 init_mouse ();
197 do_enter_ca_mode ();
198 tty_raw_mode ();
199 noecho ();
200 keypad (stdscr, TRUE);
201 nodelay (stdscr, FALSE);
203 tty_setup_sigwinch (sigwinch_handler);
206 /* --------------------------------------------------------------------------------------------- */
208 void
209 tty_shutdown (void)
211 disable_mouse ();
212 tty_reset_shell_mode ();
213 tty_noraw_mode ();
214 tty_keypad (FALSE);
215 tty_reset_screen ();
216 do_exit_ca_mode ();
219 /* --------------------------------------------------------------------------------------------- */
221 void
222 tty_reset_prog_mode (void)
224 reset_prog_mode ();
227 /* --------------------------------------------------------------------------------------------- */
229 void
230 tty_reset_shell_mode (void)
232 reset_shell_mode ();
235 /* --------------------------------------------------------------------------------------------- */
237 void
238 tty_raw_mode (void)
240 raw (); /* FIXME: uneeded? */
241 cbreak ();
244 /* --------------------------------------------------------------------------------------------- */
246 void
247 tty_noraw_mode (void)
249 nocbreak (); /* FIXME: unneeded? */
250 noraw ();
253 /* --------------------------------------------------------------------------------------------- */
255 void
256 tty_noecho (void)
258 noecho ();
261 /* --------------------------------------------------------------------------------------------- */
264 tty_flush_input (void)
266 return flushinp ();
269 /* --------------------------------------------------------------------------------------------- */
271 void
272 tty_keypad (gboolean set)
274 keypad (stdscr, (bool) set);
277 /* --------------------------------------------------------------------------------------------- */
279 void
280 tty_nodelay (gboolean set)
282 nodelay (stdscr, (bool) set);
285 /* --------------------------------------------------------------------------------------------- */
288 tty_baudrate (void)
290 return baudrate ();
293 /* --------------------------------------------------------------------------------------------- */
296 tty_lowlevel_getch (void)
298 return getch ();
301 /* --------------------------------------------------------------------------------------------- */
304 tty_reset_screen (void)
306 return endwin ();
309 /* --------------------------------------------------------------------------------------------- */
311 void
312 tty_touch_screen (void)
314 touchwin (stdscr);
317 /* --------------------------------------------------------------------------------------------- */
319 void
320 tty_gotoyx (int y, int x)
322 move (y, x);
325 /* --------------------------------------------------------------------------------------------- */
327 void
328 tty_getyx (int *py, int *px)
330 getyx (stdscr, *py, *px);
333 /* --------------------------------------------------------------------------------------------- */
334 /* if x < 0 or y < 0, draw line starting from current position */
336 void
337 tty_draw_hline (int y, int x, int ch, int len)
339 if ((chtype) ch == ACS_HLINE)
340 ch = mc_tty_frm[MC_TTY_FRM_HORIZ];
342 if ((y >= 0) && (x >= 0))
343 move (y, x);
344 hline (ch, len);
347 /* --------------------------------------------------------------------------------------------- */
348 /* if x < 0 or y < 0, draw line starting from current position */
350 void
351 tty_draw_vline (int y, int x, int ch, int len)
353 if ((chtype) ch == ACS_VLINE)
354 ch = mc_tty_frm[MC_TTY_FRM_VERT];
356 if ((y >= 0) && (x >= 0))
357 move (y, x);
358 vline (ch, len);
361 /* --------------------------------------------------------------------------------------------- */
363 void
364 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
366 int i;
368 if (y < 0)
370 rows += y;
372 if (rows <= 0)
373 return;
375 y = 0;
378 if (x < 0)
380 cols += x;
382 if (cols <= 0)
383 return;
385 x = 0;
388 if (y + rows > LINES)
389 rows = LINES - y;
390 if (x + cols > COLS)
391 cols = COLS - x;
393 for (i = 0; i < rows; i++)
395 move (y + i, x);
396 hline (ch, cols);
399 move (y, x);
402 /* --------------------------------------------------------------------------------------------- */
404 void
405 tty_set_alt_charset (gboolean alt_charset)
407 (void) alt_charset;
410 /* --------------------------------------------------------------------------------------------- */
412 void
413 tty_display_8bit (gboolean what)
415 meta (stdscr, (int) what);
418 /* --------------------------------------------------------------------------------------------- */
420 void
421 tty_print_char (int c)
423 addch (c);
426 /* --------------------------------------------------------------------------------------------- */
428 void
429 tty_print_anychar (int c)
431 unsigned char str[6 + 1];
433 if (mc_global.utf8_display || c > 255)
435 int res = g_unichar_to_utf8 (c, (char *) str);
436 if (res == 0)
438 str[0] = '.';
439 str[1] = '\0';
441 else
442 str[res] = '\0';
443 addstr (str_term_form ((char *) str));
445 else
446 addch (c);
450 /* --------------------------------------------------------------------------------------------- */
452 void
453 tty_print_alt_char (int c, gboolean single)
455 if ((chtype) c == ACS_VLINE)
456 c = mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT];
457 else if ((chtype) c == ACS_HLINE)
458 c = mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ];
459 else if ((chtype) c == ACS_LTEE)
460 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTMIDDLE : MC_TTY_FRM_DLEFTMIDDLE];
461 else if ((chtype) c == ACS_RTEE)
462 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTMIDDLE : MC_TTY_FRM_DRIGHTMIDDLE];
463 else if ((chtype) c == ACS_ULCORNER)
464 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTTOP : MC_TTY_FRM_DLEFTTOP];
465 else if ((chtype) c == ACS_LLCORNER)
466 c = mc_tty_frm[single ? MC_TTY_FRM_LEFTBOTTOM : MC_TTY_FRM_DLEFTBOTTOM];
467 else if ((chtype) c == ACS_URCORNER)
468 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTTOP : MC_TTY_FRM_DRIGHTTOP];
469 else if ((chtype) c == ACS_LRCORNER)
470 c = mc_tty_frm[single ? MC_TTY_FRM_RIGHTBOTTOM : MC_TTY_FRM_DRIGHTBOTTOM];
471 else if ((chtype) c == ACS_PLUS)
472 c = mc_tty_frm[MC_TTY_FRM_CROSS];
474 addch (c);
477 /* --------------------------------------------------------------------------------------------- */
479 void
480 tty_print_string (const char *s)
482 addstr (str_term_form (s));
485 /* --------------------------------------------------------------------------------------------- */
487 void
488 tty_printf (const char *fmt, ...)
490 va_list args;
492 va_start (args, fmt);
493 vw_printw (stdscr, fmt, args);
494 va_end (args);
497 /* --------------------------------------------------------------------------------------------- */
499 char *
500 tty_tgetstr (const char *cap)
502 char *unused = NULL;
503 return tgetstr ((char *) cap, &unused);
506 /* --------------------------------------------------------------------------------------------- */
508 void
509 tty_refresh (void)
511 refresh ();
512 doupdate ();
515 /* --------------------------------------------------------------------------------------------- */
517 void
518 tty_beep (void)
520 beep ();
523 /* --------------------------------------------------------------------------------------------- */