Merge branch '2621_path_encoding_and_extfs'
[midnight-commander.git] / lib / tty / tty.c
blobc2b2fcda66625389cf9671c6e464590038150e58
1 /*
2 Interface to the terminal controlling library.
4 Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
6 Written by:
7 Roland Illig <roland.illig@gmx.de>, 2005.
8 Andrew Borodin <aborodin@vmail.ru>, 2009.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software; you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be
18 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
19 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 MA 02110-1301, USA.
28 /** \file tty.c
29 * \brief Source: %interface to the terminal controlling library
32 #include <config.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <unistd.h> /* exit() */
39 #ifdef HAVE_SYS_IOCTL_H
40 #include <sys/ioctl.h>
41 #endif
43 #include "lib/global.h"
44 #include "lib/strutil.h"
46 #include "tty.h"
47 #include "tty-internal.h"
48 #include "mouse.h" /* use_mouse_p */
49 #include "win.h"
51 /*** global variables ****************************************************************************/
53 /* If true program softkeys (HP terminals only) on startup and after every
54 command ran in the subshell to the description found in the termcap/terminfo
55 database */
56 int reset_hp_softkeys = 0;
58 int mc_tty_frm[MC_TTY_FRM_MAX];
60 /*** file scope macro definitions ****************************************************************/
62 /*** file scope type declarations ****************************************************************/
64 /*** file scope variables ************************************************************************/
66 static volatile sig_atomic_t got_interrupt = 0;
68 /*** file scope functions ************************************************************************/
69 /* --------------------------------------------------------------------------------------------- */
71 static void
72 sigintr_handler (int signo)
74 (void) &signo;
75 got_interrupt = 1;
78 /* --------------------------------------------------------------------------------------------- */
79 /*** public functions ****************************************************************************/
80 /* --------------------------------------------------------------------------------------------- */
82 /**
83 * Check terminal type. If $TERM is not set or value is empty, mc finishes with EXIT_FAILURE.
85 * @param force_xterm Set forced the XTerm type
87 * @return true if @param force_xterm is true or value of $TERM is one of term*, konsole*
88 * rxvt*, Eterm or dtterm
90 gboolean
91 tty_check_term (gboolean force_xterm)
93 const char *termvalue;
95 termvalue = getenv ("TERM");
96 if (termvalue == NULL || *termvalue == '\0')
98 fputs (_("The TERM environment variable is unset!\n"), stderr);
99 exit (EXIT_FAILURE);
102 return force_xterm || strncmp (termvalue, "xterm", 5) == 0
103 || strncmp (termvalue, "konsole", 7) == 0
104 || strncmp (termvalue, "rxvt", 4) == 0
105 || strcmp (termvalue, "Eterm") == 0 || strcmp (termvalue, "dtterm") == 0;
108 /* --------------------------------------------------------------------------------------------- */
110 extern void
111 tty_start_interrupt_key (void)
113 struct sigaction act;
115 act.sa_handler = sigintr_handler;
116 sigemptyset (&act.sa_mask);
117 act.sa_flags = SA_RESTART;
118 sigaction (SIGINT, &act, NULL);
121 /* --------------------------------------------------------------------------------------------- */
123 extern void
124 tty_enable_interrupt_key (void)
126 struct sigaction act;
128 act.sa_handler = sigintr_handler;
129 sigemptyset (&act.sa_mask);
130 act.sa_flags = 0;
131 sigaction (SIGINT, &act, NULL);
132 got_interrupt = 0;
135 /* --------------------------------------------------------------------------------------------- */
137 extern void
138 tty_disable_interrupt_key (void)
140 struct sigaction act;
142 act.sa_handler = SIG_IGN;
143 sigemptyset (&act.sa_mask);
144 act.sa_flags = 0;
145 sigaction (SIGINT, &act, NULL);
148 /* --------------------------------------------------------------------------------------------- */
150 extern gboolean
151 tty_got_interrupt (void)
153 gboolean rv;
155 rv = (got_interrupt != 0);
156 got_interrupt = 0;
157 return rv;
160 /* --------------------------------------------------------------------------------------------- */
162 void
163 tty_print_one_hline (gboolean single)
165 tty_print_alt_char (ACS_HLINE, single);
168 /* --------------------------------------------------------------------------------------------- */
170 void
171 tty_print_one_vline (gboolean single)
173 tty_print_alt_char (ACS_VLINE, single);
176 /* --------------------------------------------------------------------------------------------- */
178 void
179 tty_draw_box (int y, int x, int ys, int xs, gboolean single)
181 ys--;
182 xs--;
184 tty_draw_vline (y, x, mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT], ys);
185 tty_draw_vline (y, x + xs, mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT], ys);
186 tty_draw_hline (y, x, mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ], xs);
187 tty_draw_hline (y + ys, x, mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ], xs);
188 tty_gotoyx (y, x);
189 tty_print_alt_char (ACS_ULCORNER, single);
190 tty_gotoyx (y + ys, x);
191 tty_print_alt_char (ACS_LLCORNER, single);
192 tty_gotoyx (y, x + xs);
193 tty_print_alt_char (ACS_URCORNER, single);
194 tty_gotoyx (y + ys, x + xs);
195 tty_print_alt_char (ACS_LRCORNER, single);
198 /* --------------------------------------------------------------------------------------------- */
200 char *
201 mc_tty_normalize_from_utf8 (const char *str)
203 GIConv conv;
204 GString *buffer;
205 const char *_system_codepage = str_detect_termencoding ();
207 if (str_isutf8 (_system_codepage))
208 return g_strdup (str);
210 conv = g_iconv_open (_system_codepage, "UTF-8");
211 if (conv == INVALID_CONV)
212 return g_strdup (str);
214 buffer = g_string_new ("");
216 if (str_convert (conv, str, buffer) == ESTR_FAILURE)
218 g_string_free (buffer, TRUE);
219 str_close_conv (conv);
220 return g_strdup (str);
222 str_close_conv (conv);
224 return g_string_free (buffer, FALSE);
227 /* --------------------------------------------------------------------------------------------- */
229 /** Resize given terminal using TIOCSWINSZ, return ioctl() result */
231 tty_resize (int fd)
233 #if defined TIOCSWINSZ
234 struct winsize tty_size;
236 tty_size.ws_row = LINES;
237 tty_size.ws_col = COLS;
238 tty_size.ws_xpixel = tty_size.ws_ypixel = 0;
240 return ioctl (fd, TIOCSWINSZ, &tty_size);
241 #else
242 return 0;
243 #endif
246 /* --------------------------------------------------------------------------------------------- */
248 void
249 tty_change_screen_size (void)
251 #if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4
252 #if defined TIOCGWINSZ
253 struct winsize winsz;
255 winsz.ws_col = winsz.ws_row = 0;
256 /* Ioctl on the STDIN_FILENO */
257 ioctl (0, TIOCGWINSZ, &winsz);
258 if (winsz.ws_col && winsz.ws_row)
260 #if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM)
261 resizeterm (winsz.ws_row, winsz.ws_col);
262 clearok (stdscr, TRUE); /* sigwinch's should use a semaphore! */
263 #else
264 COLS = winsz.ws_col;
265 LINES = winsz.ws_row;
266 #endif
267 #ifdef HAVE_SUBSHELL_SUPPORT
268 if (!mc_global.tty.use_subshell)
269 return;
271 tty_resize (mc_global.tty.subshell_pty);
272 #endif
274 #endif /* TIOCGWINSZ */
275 #endif /* defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 */
278 /* --------------------------------------------------------------------------------------------- */
280 void
281 tty_init_xterm_support (gboolean is_xterm)
283 const char *termvalue;
285 termvalue = getenv ("TERM");
287 /* Check mouse and ca capabilities */
288 /* terminfo/termcap structures have been already initialized,
289 in slang_init() or/and init_curses() */
290 /* Check terminfo at first, then check termcap */
291 xmouse_seq = tty_tgetstr ("kmous");
292 if (xmouse_seq == NULL)
293 xmouse_seq = tty_tgetstr ("Km");
294 smcup = tty_tgetstr ("smcup");
295 if (smcup == NULL)
296 smcup = tty_tgetstr ("ti");
297 rmcup = tty_tgetstr ("rmcup");
298 if (rmcup == NULL)
299 rmcup = tty_tgetstr ("te");
301 if (strcmp (termvalue, "cygwin") == 0)
303 is_xterm = TRUE;
304 use_mouse_p = MOUSE_DISABLED;
307 if (is_xterm)
309 /* Default to the standard xterm sequence */
310 if (xmouse_seq == NULL)
311 xmouse_seq = ESC_STR "[M";
313 /* Enable mouse unless explicitly disabled by --nomouse */
314 if (use_mouse_p != MOUSE_DISABLED)
316 if (mc_global.tty.old_mouse)
317 use_mouse_p = MOUSE_XTERM_NORMAL_TRACKING;
318 else
320 /* FIXME: this dirty hack to set supported type of tracking the mouse */
321 const char *color_term = getenv ("COLORTERM");
322 if (strncmp (termvalue, "rxvt", 4) == 0 ||
323 (color_term != NULL && strncmp (color_term, "rxvt", 4) == 0) ||
324 strcmp (termvalue, "Eterm") == 0)
325 use_mouse_p = MOUSE_XTERM_NORMAL_TRACKING;
326 else
327 use_mouse_p = MOUSE_XTERM_BUTTON_EVENT_TRACKING;
333 /* --------------------------------------------------------------------------------------------- */