2 Interface to the terminal controlling library.
5 Copyright (C) 2005-2024
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 /*** forward declarations (file scope functions) *************************************************/
79 /*** file scope variables ************************************************************************/
81 /* Various saved termios settings that we control here */
82 static struct termios boot_mode
;
83 static struct termios new_mode
;
85 /* Controls whether we should wait for input in tty_lowlevel_getch */
86 static gboolean no_slang_delay
;
88 static gboolean slsmg_active
= FALSE
;
90 /* This table describes which capabilities we want and which values we
109 { KEY_F (10), "k;" },
110 { KEY_F (11), "F1" },
111 { KEY_F (12), "F2" },
112 { KEY_F (13), "F3" },
113 { KEY_F (14), "F4" },
114 { KEY_F (15), "F5" },
115 { KEY_F (16), "F6" },
116 { KEY_F (17), "F7" },
117 { KEY_F (18), "F8" },
118 { KEY_F (19), "F9" },
119 { KEY_F (20), "FA" },
128 { KEY_BACKSPACE
, "kb" },
135 /* --------------------------------------------------------------------------------------------- */
136 /*** file scope functions ************************************************************************/
137 /* --------------------------------------------------------------------------------------------- */
140 tty_setup_sigwinch (void (*handler
) (int))
142 (void) SLsignal (SIGWINCH
, handler
);
143 tty_create_winch_pipe ();
146 /* --------------------------------------------------------------------------------------------- */
149 sigwinch_handler (int dummy
)
155 n
= write (sigwinch_pipe
[1], "", 1);
158 (void) SLsignal (SIGWINCH
, sigwinch_handler
);
161 /* --------------------------------------------------------------------------------------------- */
163 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
164 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
165 consequence is that function keys don't work in MC sometimes...
166 Unfortunately I don't now the one and only escape sequence to turn off.
167 softkeys (elm uses three different capabilities to turn on softkeys and two.
168 capabilities to turn them off)..
169 Among other things elm uses the pair we already use in slang_keypad. That's.
170 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
171 something better the softkeys are programmed to their defaults from the
172 termcap/terminfo database.
173 The escape sequence to program the softkeys is taken from elm and it is.
174 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this.
179 slang_reset_softkeys (void)
182 static const char display
[] = " ";
185 for (key
= 1; key
< 9; key
++)
189 g_snprintf (tmp
, sizeof (tmp
), "k%d", key
);
190 send
= SLtt_tgetstr (tmp
);
193 g_snprintf (tmp
, sizeof (tmp
), ESC_STR
"&f%dk%dd%dL%s%s", key
,
194 (int) (sizeof (display
) - 1), (int) strlen (send
), display
, send
);
195 SLtt_write_string (tmp
);
200 /* --------------------------------------------------------------------------------------------- */
203 do_define_key (int code
, const char *strcap
)
207 seq
= SLtt_tgetstr ((SLFUTURE_CONST
char *) strcap
);
209 define_sequence (code
, seq
, MCKEY_NOACTION
);
212 /* --------------------------------------------------------------------------------------------- */
215 load_terminfo_keys (void)
219 for (i
= 0; key_table
[i
].key_code
; i
++)
220 do_define_key (key_table
[i
].key_code
, key_table
[i
].key_name
);
223 /* --------------------------------------------------------------------------------------------- */
224 /*** public functions ****************************************************************************/
225 /* --------------------------------------------------------------------------------------------- */
228 mc_tty_normalize_lines_char (const char *str
)
233 struct mc_tty_lines_struct
237 } const lines_codes
[] = {
238 {"\342\224\214", SLSMG_ULCORN_CHAR
},
239 {"\342\224\220", SLSMG_URCORN_CHAR
},
240 {"\342\224\224", SLSMG_LLCORN_CHAR
},
241 {"\342\224\230", SLSMG_LRCORN_CHAR
},
242 {"\342\224\234", SLSMG_LTEE_CHAR
},
243 {"\342\224\244", SLSMG_RTEE_CHAR
},
244 {"\342\224\254", SLSMG_UTEE_CHAR
},
245 {"\342\224\264", SLSMG_DTEE_CHAR
},
246 {"\342\224\200", SLSMG_HLINE_CHAR
},
247 {"\342\224\202", SLSMG_VLINE_CHAR
},
248 {"\342\224\274", SLSMG_PLUS_CHAR
},
256 for (res
= 0; lines_codes
[res
].line
; res
++)
258 if (strcmp (str
, lines_codes
[res
].line
) == 0)
259 return lines_codes
[res
].line_code
;
262 str2
= mc_tty_normalize_from_utf8 (str
);
263 res
= g_utf8_get_char_validated (str2
, -1);
266 res
= (unsigned char) str2
[0];
272 /* --------------------------------------------------------------------------------------------- */
275 tty_init (gboolean mouse_enable
, gboolean is_xterm
)
277 SLtt_Ignore_Beep
= 1;
279 SLutf8_enable (-1); /* has to be called first before any of the other functions. */
280 SLtt_get_terminfo ();
282 * If the terminal in not in terminfo but begins with a well-known
283 * string such as "linux" or "xterm" S-Lang will go on, but the
284 * terminal size and several other variables won't be initialized
285 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
286 * small screen dimensions.
288 if ((COLS
< 10) || (LINES
< 5)
289 #if SLANG_VERSION < 20303
290 /* Beginning from pre2.3.3-8 (55f58798c267d76a1b93d0d916027b71a10ac1ee),
291 these limitations were eliminated. */
292 || (COLS
> SLTT_MAX_SCREEN_COLS
) || (LINES
> SLTT_MAX_SCREEN_ROWS
)
297 _("Screen size %dx%d is not supported.\n"
298 "Check the TERM environment variable.\n"), COLS
, LINES
);
302 tcgetattr (fileno (stdin
), &boot_mode
);
303 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
304 SLang_init_tty (XCTRL ('g'), 1, 0);
306 if (mc_global
.tty
.ugly_line_drawing
)
307 SLtt_Has_Alt_Charset
= 0;
309 tcgetattr (SLang_TT_Read_FD
, &new_mode
);
311 tty_reset_prog_mode ();
312 load_terminfo_keys ();
314 SLtt_Blink_Mode
= (tty_use_256colors (NULL
) || tty_use_truecolors (NULL
)) ? 1 : 0;
316 tty_start_interrupt_key ();
318 /* It's the small part from the previous init_key() */
319 init_key_input_fd ();
321 /* For 8-bit locales, NCurses handles 154 (0x9A) symbol properly, while S-Lang
322 * requires SLsmg_Display_Eight_Bit >= 154 (OR manual filtering if xterm display
323 * detected - but checking TERM would fail under screen, OR running xterm
324 * with allowC1Printable).
326 tty_display_8bit (FALSE
);
331 use_mouse_p
= MOUSE_DISABLED
;
332 tty_init_xterm_support (is_xterm
); /* do it before tty_enter_ca_mode() call */
333 tty_enter_ca_mode ();
337 tty_setup_sigwinch (sigwinch_handler
);
340 /* --------------------------------------------------------------------------------------------- */
347 tty_destroy_winch_pipe ();
348 tty_reset_shell_mode ();
354 slsmg_active
= FALSE
;
356 /* Load the op capability to reset the colors to those that were
357 * active when the program was started up
359 op_cap
= SLtt_tgetstr ((SLFUTURE_CONST
char *) "op");
362 fputs (op_cap
, stdout
);
367 /* --------------------------------------------------------------------------------------------- */
370 tty_enter_ca_mode (void)
372 /* S-Lang handles alternate screen switching and cursor position saving */
375 /* --------------------------------------------------------------------------------------------- */
378 tty_exit_ca_mode (void)
380 /* S-Lang handles alternate screen switching and cursor position restoring */
383 /* --------------------------------------------------------------------------------------------- */
386 tty_change_screen_size (void)
388 SLtt_get_screen_size ();
392 #ifdef ENABLE_SUBSHELL
393 if (mc_global
.tty
.use_subshell
)
394 tty_resize (mc_global
.tty
.subshell_pty
);
398 /* --------------------------------------------------------------------------------------------- */
399 /* Done each time we come back from done mode */
402 tty_reset_prog_mode (void)
404 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
407 SLsmg_touch_lines (0, LINES
);
410 /* --------------------------------------------------------------------------------------------- */
411 /* Called each time we want to shutdown slang screen manager */
414 tty_reset_shell_mode (void)
416 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &boot_mode
);
419 /* --------------------------------------------------------------------------------------------- */
424 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
427 /* --------------------------------------------------------------------------------------------- */
430 tty_noraw_mode (void)
434 /* --------------------------------------------------------------------------------------------- */
441 /* --------------------------------------------------------------------------------------------- */
444 tty_flush_input (void)
449 /* --------------------------------------------------------------------------------------------- */
452 tty_keypad (gboolean set
)
456 keypad_string
= SLtt_tgetstr ((SLFUTURE_CONST
char *) (set
? "ks" : "ke"));
457 if (keypad_string
!= NULL
)
458 SLtt_write_string (keypad_string
);
459 if (set
&& reset_hp_softkeys
)
460 slang_reset_softkeys ();
463 /* --------------------------------------------------------------------------------------------- */
466 tty_nodelay (gboolean set
)
468 no_slang_delay
= set
;
471 /* --------------------------------------------------------------------------------------------- */
476 return SLang_TT_Baud_Rate
;
479 /* --------------------------------------------------------------------------------------------- */
482 tty_lowlevel_getch (void)
486 if (no_slang_delay
&& (SLang_input_pending (0) == 0))
490 if (c
== SLANG_GETKEY_ERROR
)
493 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
494 "Assuming EOF on stdin and exiting\n");
501 /* --------------------------------------------------------------------------------------------- */
504 tty_reset_screen (void)
507 slsmg_active
= FALSE
;
511 /* --------------------------------------------------------------------------------------------- */
514 tty_touch_screen (void)
516 SLsmg_touch_lines (0, LINES
);
519 /* --------------------------------------------------------------------------------------------- */
522 tty_gotoyx (int y
, int x
)
527 /* --------------------------------------------------------------------------------------------- */
530 tty_getyx (int *py
, int *px
)
532 *py
= SLsmg_get_row ();
533 *px
= SLsmg_get_column ();
536 /* --------------------------------------------------------------------------------------------- */
539 tty_draw_hline (int y
, int x
, int ch
, int len
)
543 if (y
< 0 || y
>= LINES
|| x
>= COLS
)
557 ch
= mc_tty_frm
[MC_TTY_FRM_HORIZ
];
564 SLsmg_draw_hline (len
);
569 SLsmg_gotorc (y
, x1
);
572 /* --------------------------------------------------------------------------------------------- */
575 tty_draw_vline (int y
, int x
, int ch
, int len
)
579 if (x
< 0 || x
>= COLS
|| y
>= LINES
)
593 ch
= mc_tty_frm
[MC_TTY_FRM_VERT
];
600 SLsmg_draw_vline (len
);
607 SLsmg_gotorc (y
+ pos
, x
);
613 SLsmg_gotorc (y1
, x
);
616 /* --------------------------------------------------------------------------------------------- */
619 tty_fill_region (int y
, int x
, int rows
, int cols
, unsigned char ch
)
621 SLsmg_fill_region (y
, x
, rows
, cols
, ch
);
624 /* --------------------------------------------------------------------------------------------- */
627 tty_colorize_area (int y
, int x
, int rows
, int cols
, int color
)
630 SLsmg_set_color_in_region (color
, y
, x
, rows
, cols
);
633 /* --------------------------------------------------------------------------------------------- */
636 tty_set_alt_charset (gboolean alt_charset
)
638 SLsmg_set_char_set ((int) alt_charset
);
641 /* --------------------------------------------------------------------------------------------- */
644 tty_display_8bit (gboolean what
)
646 SLsmg_Display_Eight_Bit
= what
? 128 : 160;
649 /* --------------------------------------------------------------------------------------------- */
652 tty_print_char (int c
)
654 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
657 /* --------------------------------------------------------------------------------------------- */
660 tty_print_alt_char (int c
, gboolean single
)
662 #define DRAW(x, y) (x == y) \
663 ? SLsmg_draw_object (SLsmg_get_row(), SLsmg_get_column(), x) \
664 : SLsmg_write_char ((unsigned int) y)
668 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_VERT
: MC_TTY_FRM_DVERT
]);
671 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_HORIZ
: MC_TTY_FRM_DHORIZ
]);
674 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTMIDDLE
: MC_TTY_FRM_DLEFTMIDDLE
]);
677 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTMIDDLE
: MC_TTY_FRM_DRIGHTMIDDLE
]);
680 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_TOPMIDDLE
: MC_TTY_FRM_DTOPMIDDLE
]);
683 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_BOTTOMMIDDLE
: MC_TTY_FRM_DBOTTOMMIDDLE
]);
686 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTTOP
: MC_TTY_FRM_DLEFTTOP
]);
689 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTBOTTOM
: MC_TTY_FRM_DLEFTBOTTOM
]);
692 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTTOP
: MC_TTY_FRM_DRIGHTTOP
]);
695 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTBOTTOM
: MC_TTY_FRM_DRIGHTBOTTOM
]);
698 DRAW (c
, mc_tty_frm
[MC_TTY_FRM_CROSS
]);
701 SLsmg_write_char ((unsigned int) c
);
706 /* --------------------------------------------------------------------------------------------- */
709 tty_print_anychar (int c
)
713 char str
[UTF8_CHAR_LEN
+ 1];
716 res
= g_unichar_to_utf8 (c
, str
);
726 SLsmg_write_string ((char *) str_term_form (str
));
730 if (!is_printable (c
))
732 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
736 /* --------------------------------------------------------------------------------------------- */
739 tty_print_string (const char *s
)
741 SLsmg_write_string ((char *) str_term_form (s
));
744 /* --------------------------------------------------------------------------------------------- */
747 tty_printf (const char *fmt
, ...)
751 va_start (args
, fmt
);
752 SLsmg_vprintf ((char *) fmt
, args
);
756 /* --------------------------------------------------------------------------------------------- */
759 tty_tgetstr (const char *cap
)
761 return SLtt_tgetstr ((SLFUTURE_CONST
char *) cap
);
764 /* --------------------------------------------------------------------------------------------- */
772 /* --------------------------------------------------------------------------------------------- */
780 /* --------------------------------------------------------------------------------------------- */