2 Interface to the terminal controlling library.
5 Copyright (C) 2005-2016
6 Free Software Foundation, Inc.
9 Andrew Borodin <aborodin@vmail.ru>, 2009
10 Egmont Koblinger <egmont@gmail.com>, 2010
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/>.
29 * \brief Source: S-Lang-based tty layer of Midnight Commander
37 #include <sys/types.h> /* size_t */
39 #ifdef HAVE_SYS_IOCTL_H
40 #include <sys/ioctl.h>
44 #include "lib/global.h"
45 #include "lib/strutil.h" /* str_term_form */
46 #include "lib/util.h" /* is_printable() */
48 #include "tty-internal.h" /* mc_tty_normalize_from_utf8() */
51 #include "color-slang.h"
52 #include "color-internal.h"
53 #include "mouse.h" /* Gpm_Event is required in key.h */
54 #include "key.h" /* define_sequence */
58 /*** global variables ****************************************************************************/
60 /* If true program softkeys (HP terminals only) on startup and after every
61 command ran in the subshell to the description found in the termcap/terminfo
63 int reset_hp_softkeys
= 0;
65 /*** file scope macro definitions ****************************************************************/
67 #ifndef SLTT_MAX_SCREEN_COLS
68 #define SLTT_MAX_SCREEN_COLS 512
71 #ifndef SLTT_MAX_SCREEN_ROWS
72 #define SLTT_MAX_SCREEN_ROWS 512
75 /*** file scope type declarations ****************************************************************/
77 /*** file scope variables ************************************************************************/
79 /* Various saved termios settings that we control here */
80 static struct termios boot_mode
;
81 static struct termios new_mode
;
83 /* Controls whether we should wait for input in tty_lowlevel_getch */
84 static gboolean no_slang_delay
;
86 static gboolean slsmg_active
= FALSE
;
88 /* This table describes which capabilities we want and which values we
108 { KEY_F (10), "k;" },
109 { KEY_F (11), "F1" },
110 { KEY_F (12), "F2" },
111 { KEY_F (13), "F3" },
112 { KEY_F (14), "F4" },
113 { KEY_F (15), "F5" },
114 { KEY_F (16), "F6" },
115 { KEY_F (17), "F7" },
116 { KEY_F (18), "F8" },
117 { KEY_F (19), "F9" },
118 { KEY_F (20), "FA" },
127 { KEY_BACKSPACE
, "kb" },
134 /* --------------------------------------------------------------------------------------------- */
135 /*** file scope functions ************************************************************************/
136 /* --------------------------------------------------------------------------------------------- */
139 tty_setup_sigwinch (void (*handler
) (int))
141 (void) SLsignal (SIGWINCH
, handler
);
144 /* --------------------------------------------------------------------------------------------- */
147 sigwinch_handler (int dummy
)
151 mc_global
.tty
.winch_flag
= 1;
152 (void) SLsignal (SIGWINCH
, sigwinch_handler
);
155 /* --------------------------------------------------------------------------------------------- */
157 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
158 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
159 consequence is that function keys don't work in MC sometimes...
160 Unfortunately I don't now the one and only escape sequence to turn off.
161 softkeys (elm uses three different capabilities to turn on softkeys and two.
162 capabilities to turn them off)..
163 Among other things elm uses the pair we already use in slang_keypad. That's.
164 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
165 something better the softkeys are programmed to their defaults from the
166 termcap/terminfo database.
167 The escape sequence to program the softkeys is taken from elm and it is.
168 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this.
173 slang_reset_softkeys (void)
176 static const char display
[] = " ";
179 for (key
= 1; key
< 9; key
++)
183 g_snprintf (tmp
, sizeof (tmp
), "k%d", key
);
184 send
= SLtt_tgetstr (tmp
);
187 g_snprintf (tmp
, sizeof (tmp
), ESC_STR
"&f%dk%dd%dL%s%s", key
,
188 (int) (sizeof (display
) - 1), (int) strlen (send
), display
, send
);
189 SLtt_write_string (tmp
);
194 /* --------------------------------------------------------------------------------------------- */
197 do_define_key (int code
, const char *strcap
)
201 seq
= SLtt_tgetstr ((SLFUTURE_CONST
char *) strcap
);
203 define_sequence (code
, seq
, MCKEY_NOACTION
);
206 /* --------------------------------------------------------------------------------------------- */
209 load_terminfo_keys (void)
213 for (i
= 0; key_table
[i
].key_code
; i
++)
214 do_define_key (key_table
[i
].key_code
, key_table
[i
].key_name
);
217 /* --------------------------------------------------------------------------------------------- */
218 /*** public functions ****************************************************************************/
219 /* --------------------------------------------------------------------------------------------- */
222 mc_tty_normalize_lines_char (const char *str
)
227 struct mc_tty_lines_struct
231 } const lines_codes
[] = {
232 {"\342\224\214", SLSMG_ULCORN_CHAR
},
233 {"\342\224\220", SLSMG_URCORN_CHAR
},
234 {"\342\224\224", SLSMG_LLCORN_CHAR
},
235 {"\342\224\230", SLSMG_LRCORN_CHAR
},
236 {"\342\224\234", SLSMG_LTEE_CHAR
},
237 {"\342\224\244", SLSMG_RTEE_CHAR
},
238 {"\342\224\254", SLSMG_UTEE_CHAR
},
239 {"\342\224\264", SLSMG_DTEE_CHAR
},
240 {"\342\224\200", SLSMG_HLINE_CHAR
},
241 {"\342\224\202", SLSMG_VLINE_CHAR
},
242 {"\342\224\274", SLSMG_PLUS_CHAR
},
250 for (res
= 0; lines_codes
[res
].line
; res
++)
252 if (strcmp (str
, lines_codes
[res
].line
) == 0)
253 return lines_codes
[res
].line_code
;
256 str2
= mc_tty_normalize_from_utf8 (str
);
257 res
= g_utf8_get_char_validated (str2
, -1);
260 res
= (unsigned char) str2
[0];
266 /* --------------------------------------------------------------------------------------------- */
269 tty_init (gboolean mouse_enable
, gboolean is_xterm
)
271 SLtt_Ignore_Beep
= 1;
273 SLutf8_enable (-1); /* has to be called first before any of the other functions. */
274 SLtt_get_terminfo ();
276 * If the terminal in not in terminfo but begins with a well-known
277 * string such as "linux" or "xterm" S-Lang will go on, but the
278 * terminal size and several other variables won't be initialized
279 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
280 * small, large and negative screen dimensions.
282 if ((COLS
< 10) || (LINES
< 5)
283 || (COLS
> SLTT_MAX_SCREEN_COLS
) || (LINES
> SLTT_MAX_SCREEN_ROWS
))
286 _("Screen size %dx%d is not supported.\n"
287 "Check the TERM environment variable.\n"), COLS
, LINES
);
291 tcgetattr (fileno (stdin
), &boot_mode
);
292 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
293 SLang_init_tty (XCTRL ('g'), 1, 0);
295 if (mc_global
.tty
.ugly_line_drawing
)
296 SLtt_Has_Alt_Charset
= 0;
298 /* If SLang uses fileno(stderr) for terminal input MC will hang
299 if we call SLang_getkey between calls to open_error_pipe and
300 close_error_pipe, e.g. when we do a growing view of an gzipped
302 if (SLang_TT_Read_FD
== fileno (stderr
))
303 SLang_TT_Read_FD
= fileno (stdin
);
305 if (tcgetattr (SLang_TT_Read_FD
, &new_mode
) == 0)
308 new_mode
.c_cc
[VDSUSP
] = NULL_VALUE
; /* to ignore ^Y */
311 new_mode
.c_cc
[VLNEXT
] = NULL_VALUE
; /* to ignore ^V */
313 tcsetattr (SLang_TT_Read_FD
, TCSADRAIN
, &new_mode
);
316 tty_reset_prog_mode ();
317 load_terminfo_keys ();
319 SLtt_Blink_Mode
= tty_use_256colors ()? 1 : 0;
321 tty_start_interrupt_key ();
323 /* It's the small part from the previous init_key() */
324 init_key_input_fd ();
326 /* For 8-bit locales, NCurses handles 154 (0x9A) symbol properly, while S-Lang
327 * requires SLsmg_Display_Eight_Bit >= 154 (OR manual filtering if xterm display
328 * detected - but checking TERM would fail under screen, OR running xterm
329 * with allowC1Printable).
331 tty_display_8bit (FALSE
);
336 use_mouse_p
= MOUSE_DISABLED
;
337 tty_init_xterm_support (is_xterm
); /* do it before tty_enter_ca_mode() call */
338 tty_enter_ca_mode ();
342 tty_setup_sigwinch (sigwinch_handler
);
345 /* --------------------------------------------------------------------------------------------- */
352 tty_reset_shell_mode ();
358 slsmg_active
= FALSE
;
360 /* Load the op capability to reset the colors to those that were
361 * active when the program was started up
363 op_cap
= SLtt_tgetstr ((SLFUTURE_CONST
char *) "op");
366 fputs (op_cap
, stdout
);
371 /* --------------------------------------------------------------------------------------------- */
374 tty_enter_ca_mode (void)
376 /* S-Lang handles alternate screen switching and cursor position saving */
379 /* --------------------------------------------------------------------------------------------- */
382 tty_exit_ca_mode (void)
384 /* S-Lang handles alternate screen switching and cursor position restoring */
387 /* --------------------------------------------------------------------------------------------- */
390 tty_change_screen_size (void)
392 SLtt_get_screen_size ();
396 #ifdef ENABLE_SUBSHELL
397 if (mc_global
.tty
.use_subshell
)
398 tty_resize (mc_global
.tty
.subshell_pty
);
402 /* --------------------------------------------------------------------------------------------- */
403 /* Done each time we come back from done mode */
406 tty_reset_prog_mode (void)
408 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
411 SLsmg_touch_lines (0, LINES
);
414 /* --------------------------------------------------------------------------------------------- */
415 /* Called each time we want to shutdown slang screen manager */
418 tty_reset_shell_mode (void)
420 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &boot_mode
);
423 /* --------------------------------------------------------------------------------------------- */
428 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
431 /* --------------------------------------------------------------------------------------------- */
434 tty_noraw_mode (void)
438 /* --------------------------------------------------------------------------------------------- */
445 /* --------------------------------------------------------------------------------------------- */
448 tty_flush_input (void)
453 /* --------------------------------------------------------------------------------------------- */
456 tty_keypad (gboolean set
)
460 keypad_string
= SLtt_tgetstr ((SLFUTURE_CONST
char *) (set
? "ks" : "ke"));
461 if (keypad_string
!= NULL
)
462 SLtt_write_string (keypad_string
);
463 if (set
&& reset_hp_softkeys
)
464 slang_reset_softkeys ();
467 /* --------------------------------------------------------------------------------------------- */
470 tty_nodelay (gboolean set
)
472 no_slang_delay
= set
;
475 /* --------------------------------------------------------------------------------------------- */
480 return SLang_TT_Baud_Rate
;
483 /* --------------------------------------------------------------------------------------------- */
486 tty_lowlevel_getch (void)
490 if (no_slang_delay
&& (SLang_input_pending (0) == 0))
494 if (c
== SLANG_GETKEY_ERROR
)
497 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
498 "Assuming EOF on stdin and exiting\n");
505 /* --------------------------------------------------------------------------------------------- */
508 tty_reset_screen (void)
511 slsmg_active
= FALSE
;
515 /* --------------------------------------------------------------------------------------------- */
518 tty_touch_screen (void)
520 SLsmg_touch_lines (0, LINES
);
523 /* --------------------------------------------------------------------------------------------- */
526 tty_gotoyx (int y
, int x
)
531 /* --------------------------------------------------------------------------------------------- */
534 tty_getyx (int *py
, int *px
)
536 *py
= SLsmg_get_row ();
537 *px
= SLsmg_get_column ();
540 /* --------------------------------------------------------------------------------------------- */
543 tty_draw_hline (int y
, int x
, int ch
, int len
)
547 if (y
< 0 || y
>= LINES
|| x
>= COLS
)
561 ch
= mc_tty_frm
[MC_TTY_FRM_HORIZ
];
568 SLsmg_draw_hline (len
);
573 SLsmg_gotorc (y
, x1
);
576 /* --------------------------------------------------------------------------------------------- */
579 tty_draw_vline (int y
, int x
, int ch
, int len
)
583 if (x
< 0 || x
>= COLS
|| y
>= LINES
)
597 ch
= mc_tty_frm
[MC_TTY_FRM_VERT
];
604 SLsmg_draw_vline (len
);
611 SLsmg_gotorc (y
+ pos
, x
);
617 SLsmg_gotorc (y1
, x
);
620 /* --------------------------------------------------------------------------------------------- */
623 tty_fill_region (int y
, int x
, int rows
, int cols
, unsigned char ch
)
625 SLsmg_fill_region (y
, x
, rows
, cols
, ch
);
628 /* --------------------------------------------------------------------------------------------- */
631 tty_set_alt_charset (gboolean alt_charset
)
633 SLsmg_set_char_set ((int) alt_charset
);
636 /* --------------------------------------------------------------------------------------------- */
639 tty_display_8bit (gboolean what
)
641 SLsmg_Display_Eight_Bit
= what
? 128 : 160;
644 /* --------------------------------------------------------------------------------------------- */
647 tty_print_char (int c
)
649 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
652 /* --------------------------------------------------------------------------------------------- */
655 tty_print_alt_char (int c
, gboolean single
)
657 #define DRAW(x, y) (x == y) \
658 ? SLsmg_draw_object (SLsmg_get_row(), SLsmg_get_column(), x) \
659 : SLsmg_write_char ((unsigned int) y)
663 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_VERT
: MC_TTY_FRM_DVERT
]);
666 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_HORIZ
: MC_TTY_FRM_DHORIZ
]);
669 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTMIDDLE
: MC_TTY_FRM_DLEFTMIDDLE
]);
672 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTMIDDLE
: MC_TTY_FRM_DRIGHTMIDDLE
]);
675 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_TOPMIDDLE
: MC_TTY_FRM_DTOPMIDDLE
]);
678 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_BOTTOMMIDDLE
: MC_TTY_FRM_DBOTTOMMIDDLE
]);
681 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTTOP
: MC_TTY_FRM_DLEFTTOP
]);
684 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTBOTTOM
: MC_TTY_FRM_DLEFTBOTTOM
]);
687 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTTOP
: MC_TTY_FRM_DRIGHTTOP
]);
690 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTBOTTOM
: MC_TTY_FRM_DRIGHTBOTTOM
]);
693 DRAW (c
, mc_tty_frm
[MC_TTY_FRM_CROSS
]);
696 SLsmg_write_char ((unsigned int) c
);
701 /* --------------------------------------------------------------------------------------------- */
704 tty_print_anychar (int c
)
708 char str
[UTF8_CHAR_LEN
+ 1];
711 res
= g_unichar_to_utf8 (c
, str
);
721 SLsmg_write_string ((char *) str_term_form (str
));
725 if (!is_printable (c
))
727 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
731 /* --------------------------------------------------------------------------------------------- */
734 tty_print_string (const char *s
)
736 SLsmg_write_string ((char *) str_term_form (s
));
739 /* --------------------------------------------------------------------------------------------- */
742 tty_printf (const char *fmt
, ...)
746 va_start (args
, fmt
);
747 SLsmg_vprintf ((char *) fmt
, args
);
751 /* --------------------------------------------------------------------------------------------- */
754 tty_tgetstr (const char *cap
)
756 return SLtt_tgetstr ((SLFUTURE_CONST
char *) cap
);
759 /* --------------------------------------------------------------------------------------------- */
767 /* --------------------------------------------------------------------------------------------- */
775 /* --------------------------------------------------------------------------------------------- */