Fixed memory leak in vfs_free_handle().
[kaloumi3.git] / lib / tty / tty-ncurses.c
blob86d91d120a914d588252e093f9fe6b499d105f29
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 #include "src/main.h"
44 #ifndef WANT_TERM_H
45 # define WANT_TERM_H
46 #endif
48 #include "tty-internal.h" /* slow_tty */
49 #include "tty.h"
50 #include "color-internal.h"
51 #include "win.h"
53 /* include at last !!! */
54 #ifdef WANT_TERM_H
55 #ifdef HAVE_NCURSES_TERM_H
56 # include <ncurses/term.h>
57 #else
58 # include <term.h>
59 #endif /* HAVE_NCURSES_TERM_H */
60 #endif /* WANT_TERM_H */
62 /*** global variables **************************************************/
64 /*** file scope macro definitions **************************************/
66 #if defined(_AIX) && !defined(CTRL)
67 # define CTRL(x) ((x) & 0x1f)
68 #endif
70 /*** global variables **************************************************/
72 /*** file scope type declarations **************************************/
74 /*** file scope variables **********************************************/
76 /*** file scope functions **********************************************/
78 /* --------------------------------------------------------------------------------------------- */
79 /*** public functions **************************************************/
80 /* --------------------------------------------------------------------------------------------- */
82 int
83 mc_tty_normalize_lines_char (const char *ch)
85 char *str2;
86 int res;
88 struct mc_tty_lines_struct {
89 const char *line;
90 int line_code;
91 } const lines_codes[] = {
92 {"\342\224\214", ACS_LRCORNER}, /* ┌ */
93 {"\342\224\220", ACS_LLCORNER}, /* ┐ */
94 {"\342\224\224", ACS_URCORNER}, /* └ */
95 {"\342\224\230", ACS_ULCORNER}, /* ┘ */
96 {"\342\224\234", ACS_LTEE}, /* ├ */
97 {"\342\224\244", ACS_RTEE}, /* ┤ */
98 {"\342\224\254", ACS_TTEE}, /* ┬ */
99 {"\342\224\264", ACS_BTEE}, /* ┴ */
100 {"\342\224\200", ACS_HLINE}, /* ─ */
101 {"\342\224\202", ACS_VLINE}, /* │ */
102 {"\342\224\274", ACS_PLUS}, /* ┼ */
104 {"\342\225\235", ACS_LRCORNER | A_BOLD}, /* ╔ */
105 {"\342\225\232", ACS_LLCORNER | A_BOLD}, /* ╗ */
106 {"\342\225\227", ACS_URCORNER | A_BOLD}, /* ╚ */
107 {"\342\225\224", ACS_ULCORNER | A_BOLD}, /* ╝ */
108 {"\342\225\237", ACS_LTEE | A_BOLD}, /* ╟ */
109 {"\342\225\242", ACS_RTEE | A_BOLD}, /* ╢ */
110 {"\342\225\244", ACS_TTEE | A_BOLD}, /* ╤ */
111 {"\342\225\247", ACS_BTEE | A_BOLD}, /* ╧ */
112 {"\342\225\220", ACS_HLINE | A_BOLD}, /* ═ */
113 {"\342\225\221", ACS_VLINE | A_BOLD}, /* ║ */
115 {NULL, 0}
118 if (ch == NULL)
119 return (int) ' ';
121 for (res = 0; lines_codes[res].line; res++) {
122 if (strcmp (ch, lines_codes[res].line) == 0)
123 return lines_codes[res].line_code;
126 str2 = mc_tty_normalize_from_utf8 (ch);
127 res = g_utf8_get_char_validated (str2, -1);
129 if (res < 0)
130 res = (unsigned char) str2[0];
131 g_free (str2);
133 return res;
136 /* --------------------------------------------------------------------------------------------- */
139 void
140 tty_init (gboolean slow, gboolean ugly_lines)
142 slow_tty = slow;
143 (void) ugly_lines;
145 initscr ();
147 #ifdef HAVE_ESCDELAY
149 * If ncurses exports the ESCDELAY variable, it should be set to
150 * a low value, or you'll experience a delay in processing escape
151 * sequences that are recognized by mc (e.g. Esc-Esc). On the other
152 * hand, making ESCDELAY too small can result in some sequences
153 * (e.g. cursor arrows) being reported as separate keys under heavy
154 * processor load, and this can be a problem if mc hasn't learned
155 * them in the "Learn Keys" dialog. The value is in milliseconds.
157 ESCDELAY = 200;
158 #endif /* HAVE_ESCDELAY */
160 /* use Ctrl-g to generate SIGINT */
161 cur_term->Nttyb.c_cc[VINTR] = CTRL ('g'); /* ^g */
162 /* disable SIGQUIT to allow use Ctrl-\ key */
163 cur_term->Nttyb.c_cc[VQUIT] = NULL_VALUE;
164 tcsetattr (cur_term->Filedes, TCSANOW, &cur_term->Nttyb);
166 tty_start_interrupt_key ();
168 do_enter_ca_mode ();
169 tty_raw_mode ();
170 noecho ();
171 keypad (stdscr, TRUE);
172 nodelay (stdscr, FALSE);
175 void
176 tty_shutdown (void)
178 endwin ();
181 void
182 tty_reset_prog_mode (void)
184 reset_prog_mode ();
187 void
188 tty_reset_shell_mode (void)
190 reset_shell_mode ();
193 void
194 tty_raw_mode (void)
196 raw (); /* FIXME: uneeded? */
197 cbreak ();
200 void
201 tty_noraw_mode (void)
203 nocbreak (); /* FIXME: unneeded? */
204 noraw ();
207 void
208 tty_noecho (void)
210 noecho ();
214 tty_flush_input (void)
216 return flushinp ();
219 void
220 tty_keypad (gboolean set)
222 keypad (stdscr, (bool) set);
225 void
226 tty_nodelay (gboolean set)
228 nodelay (stdscr, (bool) set);
232 tty_baudrate (void)
234 return baudrate ();
238 tty_lowlevel_getch (void)
240 return getch ();
244 tty_reset_screen (void)
246 return endwin ();
249 void
250 tty_touch_screen (void)
252 touchwin (stdscr);
255 void
256 tty_gotoyx (int y, int x)
258 move (y, x);
261 void
262 tty_getyx (int *py, int *px)
264 getyx (stdscr, *py, *px);
267 /* if x < 0 or y < 0, draw line starting from current position */
268 void
269 tty_draw_hline (int y, int x, int ch, int len)
271 if ((chtype) ch == ACS_HLINE)
272 ch = mc_tty_ugly_frm[MC_TTY_FRM_thinhoriz];
274 if ((y >= 0) && (x >= 0))
275 move (y, x);
276 hline (ch, len);
279 /* if x < 0 or y < 0, draw line starting from current position */
280 void
281 tty_draw_vline (int y, int x, int ch, int len)
283 if ((chtype) ch == ACS_VLINE)
284 ch = mc_tty_ugly_frm[MC_TTY_FRM_thinvert];
286 if ((y >= 0) && (x >= 0))
287 move (y, x);
288 vline (ch, len);
291 void
292 tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
294 int i;
296 for (i = 0; i < rows; i++) {
297 move (y + i, x);
298 hline (ch, cols);
301 move (y, x);
304 void
305 tty_set_alt_charset (gboolean alt_charset)
307 (void) alt_charset;
310 void
311 tty_display_8bit (gboolean what)
313 meta (stdscr, (int) what);
316 void
317 tty_print_char (int c)
319 addch (c);
322 void
323 tty_print_anychar (int c)
325 unsigned char str[6 + 1];
327 if (utf8_display || c > 255) {
328 int res = g_unichar_to_utf8 (c, (char *) str);
329 if (res == 0) {
330 str[0] = '.';
331 str[1] = '\0';
332 } else {
333 str[res] = '\0';
335 addstr (str_term_form ((char *) str));
336 } else {
337 addch (c);
342 void
343 tty_print_alt_char (int c)
345 if ((chtype) c == ACS_VLINE)
346 c = mc_tty_ugly_frm[MC_TTY_FRM_thinvert];
347 else if ((chtype) c == ACS_HLINE)
348 c = mc_tty_ugly_frm[MC_TTY_FRM_thinhoriz];
349 else if ((chtype) c == ACS_LTEE)
350 c = mc_tty_ugly_frm[MC_TTY_FRM_leftmiddle];
351 else if ((chtype) c == ACS_RTEE)
352 c = mc_tty_ugly_frm[MC_TTY_FRM_rightmiddle];
353 else if ((chtype) c == ACS_ULCORNER)
354 c = mc_tty_ugly_frm[MC_TTY_FRM_lefttop];
355 else if ((chtype) c == ACS_LLCORNER)
356 c = mc_tty_ugly_frm[MC_TTY_FRM_leftbottom];
357 else if ((chtype) c == ACS_URCORNER)
358 c = mc_tty_ugly_frm[MC_TTY_FRM_righttop];
359 else if ((chtype) c == ACS_LRCORNER)
360 c = mc_tty_ugly_frm[MC_TTY_FRM_rightbottom];
361 else if ((chtype) c == ACS_PLUS)
362 c = mc_tty_ugly_frm[MC_TTY_FRM_centermiddle];
364 addch (c);
367 void
368 tty_print_string (const char *s)
370 addstr (str_term_form (s));
373 void
374 tty_printf (const char *fmt, ...)
376 va_list args;
378 va_start (args, fmt);
379 vw_printw (stdscr, fmt, args);
380 va_end (args);
383 char *
384 tty_tgetstr (const char *cap)
386 char *unused = NULL;
387 return tgetstr ((char *) cap, &unused);
390 void
391 tty_refresh (void)
393 refresh ();
394 doupdate ();
397 void
398 tty_setup_sigwinch (void (*handler) (int))
400 #if (NCURSES_VERSION_MAJOR >= 4) && defined (SIGWINCH)
401 struct sigaction act, oact;
402 act.sa_handler = handler;
403 sigemptyset (&act.sa_mask);
404 act.sa_flags = 0;
405 #ifdef SA_RESTART
406 act.sa_flags |= SA_RESTART;
407 #endif /* SA_RESTART */
408 sigaction (SIGWINCH, &act, &oact);
409 #endif /* SIGWINCH */
412 void
413 tty_beep (void)
415 beep ();