root/lib/tty/tty.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. sigintr_handler
  2. tty_check_term
  3. tty_start_interrupt_key
  4. tty_enable_interrupt_key
  5. tty_disable_interrupt_key
  6. tty_got_interrupt
  7. tty_got_winch
  8. tty_print_one_hline
  9. tty_print_one_vline
  10. tty_draw_box
  11. mc_tty_normalize_from_utf8
  12. tty_resize
  13. tty_init_xterm_support

   1 /*
   2    Interface to the terminal controlling library.
   3 
   4    Copyright (C) 2005-2019
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Roland Illig <roland.illig@gmx.de>, 2005.
   9    Andrew Borodin <aborodin@vmail.ru>, 2009.
  10 
  11    This file is part of the Midnight Commander.
  12 
  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 3 of the License,
  16    or (at your option) any later version.
  17 
  18    The Midnight Commander is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25  */
  26 
  27 /** \file tty.c
  28  *  \brief Source: %interface to the terminal controlling library
  29  */
  30 
  31 #include <config.h>
  32 
  33 #include <errno.h>
  34 #include <signal.h>
  35 #include <stdarg.h>
  36 #include <stdlib.h>
  37 #include <string.h>             /* memset() */
  38 #include <unistd.h>             /* exit() */
  39 
  40 #ifdef HAVE_SYS_IOCTL_H
  41 #include <sys/ioctl.h>
  42 #endif
  43 
  44 #include "lib/global.h"
  45 #include "lib/strutil.h"
  46 
  47 #include "tty.h"
  48 #include "tty-internal.h"
  49 #include "mouse.h"              /* use_mouse_p */
  50 #include "win.h"
  51 
  52 /*** global variables ****************************************************************************/
  53 
  54 int mc_tty_frm[MC_TTY_FRM_MAX];
  55 
  56 /*** file scope macro definitions ****************************************************************/
  57 
  58 /*** file scope type declarations ****************************************************************/
  59 
  60 /*** file scope variables ************************************************************************/
  61 
  62 static SIG_ATOMIC_VOLATILE_T got_interrupt = 0;
  63 
  64 /*** file scope functions ************************************************************************/
  65 /* --------------------------------------------------------------------------------------------- */
  66 
  67 static void
  68 sigintr_handler (int signo)
     /* [previous][next][first][last][top][bottom][index][help]  */
  69 {
  70     (void) &signo;
  71     got_interrupt = 1;
  72 }
  73 
  74 /* --------------------------------------------------------------------------------------------- */
  75 /*** public functions ****************************************************************************/
  76 /* --------------------------------------------------------------------------------------------- */
  77 
  78 /**
  79  * Check terminal type. If $TERM is not set or value is empty, mc finishes with EXIT_FAILURE.
  80  *
  81  * @param force_xterm Set forced the XTerm type
  82  *
  83  * @return true if @param force_xterm is true or value of $TERM is one of term*, konsole*
  84  *              rxvt*, Eterm or dtterm
  85  */
  86 gboolean
  87 tty_check_term (gboolean force_xterm)
     /* [previous][next][first][last][top][bottom][index][help]  */
  88 {
  89     const char *termvalue;
  90     const char *xdisplay;
  91 
  92     termvalue = getenv ("TERM");
  93     if (termvalue == NULL || *termvalue == '\0')
  94     {
  95         fputs (_("The TERM environment variable is unset!\n"), stderr);
  96         exit (EXIT_FAILURE);
  97     }
  98 
  99     xdisplay = getenv ("DISPLAY");
 100     if (xdisplay != NULL && *xdisplay == '\0')
 101         xdisplay = NULL;
 102 
 103     return force_xterm || strncmp (termvalue, "xterm", 5) == 0
 104         || strncmp (termvalue, "konsole", 7) == 0
 105         || strncmp (termvalue, "rxvt", 4) == 0
 106         || strcmp (termvalue, "Eterm") == 0
 107         || strcmp (termvalue, "dtterm") == 0
 108         || (strncmp (termvalue, "screen", 6) == 0 && xdisplay != NULL);
 109 }
 110 
 111 /* --------------------------------------------------------------------------------------------- */
 112 
 113 extern void
 114 tty_start_interrupt_key (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 115 {
 116     struct sigaction act;
 117 
 118     memset (&act, 0, sizeof (act));
 119     act.sa_handler = sigintr_handler;
 120     sigemptyset (&act.sa_mask);
 121 #ifdef SA_RESTART
 122     act.sa_flags = SA_RESTART;
 123 #endif /* SA_RESTART */
 124     sigaction (SIGINT, &act, NULL);
 125 }
 126 
 127 /* --------------------------------------------------------------------------------------------- */
 128 
 129 extern void
 130 tty_enable_interrupt_key (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 131 {
 132     struct sigaction act;
 133 
 134     memset (&act, 0, sizeof (act));
 135     act.sa_handler = sigintr_handler;
 136     sigemptyset (&act.sa_mask);
 137     sigaction (SIGINT, &act, NULL);
 138     got_interrupt = 0;
 139 }
 140 
 141 /* --------------------------------------------------------------------------------------------- */
 142 
 143 extern void
 144 tty_disable_interrupt_key (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 145 {
 146     struct sigaction act;
 147 
 148     memset (&act, 0, sizeof (act));
 149     act.sa_handler = SIG_IGN;
 150     sigemptyset (&act.sa_mask);
 151     sigaction (SIGINT, &act, NULL);
 152 }
 153 
 154 /* --------------------------------------------------------------------------------------------- */
 155 
 156 extern gboolean
 157 tty_got_interrupt (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 158 {
 159     gboolean rv;
 160 
 161     rv = (got_interrupt != 0);
 162     got_interrupt = 0;
 163     return rv;
 164 }
 165 
 166 /* --------------------------------------------------------------------------------------------- */
 167 
 168 gboolean
 169 tty_got_winch (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 170 {
 171     gboolean ret = FALSE;
 172     ssize_t n;
 173 
 174     /* merge all SIGWINCH events raised to this moment */
 175     do
 176     {
 177         char x[16];
 178 
 179         /* read multiple events at a time  */
 180         n = read (sigwinch_pipe[0], &x, sizeof (x));
 181         if (n > 0)
 182             ret = TRUE;
 183     }
 184     while (n > 0 || (n == -1 && errno == EINTR));
 185 
 186     return ret;
 187 }
 188 
 189 /* --------------------------------------------------------------------------------------------- */
 190 
 191 void
 192 tty_print_one_hline (gboolean single)
     /* [previous][next][first][last][top][bottom][index][help]  */
 193 {
 194     tty_print_alt_char (ACS_HLINE, single);
 195 }
 196 
 197 /* --------------------------------------------------------------------------------------------- */
 198 
 199 void
 200 tty_print_one_vline (gboolean single)
     /* [previous][next][first][last][top][bottom][index][help]  */
 201 {
 202     tty_print_alt_char (ACS_VLINE, single);
 203 }
 204 
 205 /* --------------------------------------------------------------------------------------------- */
 206 
 207 void
 208 tty_draw_box (int y, int x, int ys, int xs, gboolean single)
     /* [previous][next][first][last][top][bottom][index][help]  */
 209 {
 210     int y2, x2;
 211 
 212     if (ys <= 0 || xs <= 0)
 213         return;
 214 
 215     ys--;
 216     xs--;
 217 
 218     y2 = y + ys;
 219     x2 = x + xs;
 220 
 221     tty_draw_vline (y, x, mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT], ys);
 222     tty_draw_vline (y, x2, mc_tty_frm[single ? MC_TTY_FRM_VERT : MC_TTY_FRM_DVERT], ys);
 223     tty_draw_hline (y, x, mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ], xs);
 224     tty_draw_hline (y2, x, mc_tty_frm[single ? MC_TTY_FRM_HORIZ : MC_TTY_FRM_DHORIZ], xs);
 225     tty_gotoyx (y, x);
 226     tty_print_alt_char (ACS_ULCORNER, single);
 227     tty_gotoyx (y2, x);
 228     tty_print_alt_char (ACS_LLCORNER, single);
 229     tty_gotoyx (y, x2);
 230     tty_print_alt_char (ACS_URCORNER, single);
 231     tty_gotoyx (y2, x2);
 232     tty_print_alt_char (ACS_LRCORNER, single);
 233 }
 234 
 235 /* --------------------------------------------------------------------------------------------- */
 236 
 237 char *
 238 mc_tty_normalize_from_utf8 (const char *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 239 {
 240     GIConv conv;
 241     GString *buffer;
 242     const char *_system_codepage = str_detect_termencoding ();
 243 
 244     if (str_isutf8 (_system_codepage))
 245         return g_strdup (str);
 246 
 247     conv = g_iconv_open (_system_codepage, "UTF-8");
 248     if (conv == INVALID_CONV)
 249         return g_strdup (str);
 250 
 251     buffer = g_string_new ("");
 252 
 253     if (str_convert (conv, str, buffer) == ESTR_FAILURE)
 254     {
 255         g_string_free (buffer, TRUE);
 256         str_close_conv (conv);
 257         return g_strdup (str);
 258     }
 259     str_close_conv (conv);
 260 
 261     return g_string_free (buffer, FALSE);
 262 }
 263 
 264 /* --------------------------------------------------------------------------------------------- */
 265 
 266 /** Resize given terminal using TIOCSWINSZ, return ioctl() result */
 267 int
 268 tty_resize (int fd)
     /* [previous][next][first][last][top][bottom][index][help]  */
 269 {
 270 #if defined TIOCSWINSZ
 271     struct winsize tty_size;
 272 
 273     tty_size.ws_row = LINES;
 274     tty_size.ws_col = COLS;
 275     tty_size.ws_xpixel = tty_size.ws_ypixel = 0;
 276 
 277     return ioctl (fd, TIOCSWINSZ, &tty_size);
 278 #else
 279     return 0;
 280 #endif
 281 }
 282 
 283 /* --------------------------------------------------------------------------------------------- */
 284 
 285 void
 286 tty_init_xterm_support (gboolean is_xterm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 287 {
 288     const char *termvalue;
 289 
 290     termvalue = getenv ("TERM");
 291 
 292     /* Check mouse and ca capabilities */
 293     /* terminfo/termcap structures have been already initialized,
 294        in slang_init() or/and init_curses()  */
 295     /* Check terminfo at first, then check termcap */
 296     xmouse_seq = tty_tgetstr ("kmous");
 297     if (xmouse_seq == NULL)
 298         xmouse_seq = tty_tgetstr ("Km");
 299     smcup = tty_tgetstr ("smcup");
 300     if (smcup == NULL)
 301         smcup = tty_tgetstr ("ti");
 302     rmcup = tty_tgetstr ("rmcup");
 303     if (rmcup == NULL)
 304         rmcup = tty_tgetstr ("te");
 305 
 306     if (strcmp (termvalue, "cygwin") == 0)
 307     {
 308         is_xterm = TRUE;
 309         use_mouse_p = MOUSE_DISABLED;
 310     }
 311 
 312     if (is_xterm)
 313     {
 314         /* Default to the standard xterm sequence */
 315         if (xmouse_seq == NULL)
 316             xmouse_seq = ESC_STR "[M";
 317 
 318         /* Enable mouse unless explicitly disabled by --nomouse */
 319         if (use_mouse_p != MOUSE_DISABLED)
 320         {
 321             if (mc_global.tty.old_mouse)
 322                 use_mouse_p = MOUSE_XTERM_NORMAL_TRACKING;
 323             else
 324             {
 325                 /* FIXME: this dirty hack to set supported type of tracking the mouse */
 326                 const char *color_term = getenv ("COLORTERM");
 327                 if (strncmp (termvalue, "rxvt", 4) == 0 ||
 328                     (color_term != NULL && strncmp (color_term, "rxvt", 4) == 0) ||
 329                     strcmp (termvalue, "Eterm") == 0)
 330                     use_mouse_p = MOUSE_XTERM_NORMAL_TRACKING;
 331                 else
 332                     use_mouse_p = MOUSE_XTERM_BUTTON_EVENT_TRACKING;
 333             }
 334         }
 335     }
 336 
 337     /* No termcap for SGR extended mouse (yet), hardcode it for now */
 338     if (xmouse_seq != NULL)
 339         xmouse_extended_seq = ESC_STR "[<";
 340 }
 341 
 342 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */