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
110 { KEY_F (10), "k;" },
111 { KEY_F (11), "F1" },
112 { KEY_F (12), "F2" },
113 { KEY_F (13), "F3" },
114 { KEY_F (14), "F4" },
115 { KEY_F (15), "F5" },
116 { KEY_F (16), "F6" },
117 { KEY_F (17), "F7" },
118 { KEY_F (18), "F8" },
119 { KEY_F (19), "F9" },
120 { KEY_F (20), "FA" },
129 { KEY_BACKSPACE
, "kb" },
136 /* --------------------------------------------------------------------------------------------- */
137 /*** file scope functions ************************************************************************/
138 /* --------------------------------------------------------------------------------------------- */
141 tty_setup_sigwinch (void (*handler
) (int))
143 (void) SLsignal (SIGWINCH
, handler
);
144 tty_create_winch_pipe ();
147 /* --------------------------------------------------------------------------------------------- */
150 sigwinch_handler (int dummy
)
156 n
= write (sigwinch_pipe
[1], "", 1);
159 (void) SLsignal (SIGWINCH
, sigwinch_handler
);
162 /* --------------------------------------------------------------------------------------------- */
164 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
165 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
166 consequence is that function keys don't work in MC sometimes...
167 Unfortunately I don't now the one and only escape sequence to turn off.
168 softkeys (elm uses three different capabilities to turn on softkeys and two.
169 capabilities to turn them off)..
170 Among other things elm uses the pair we already use in slang_keypad. That's.
171 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
172 something better the softkeys are programmed to their defaults from the
173 termcap/terminfo database.
174 The escape sequence to program the softkeys is taken from elm and it is.
175 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this.
180 slang_reset_softkeys (void)
183 static const char display
[] = " ";
186 for (key
= 1; key
< 9; key
++)
190 g_snprintf (tmp
, sizeof (tmp
), "k%d", key
);
191 send
= SLtt_tgetstr (tmp
);
194 g_snprintf (tmp
, sizeof (tmp
), ESC_STR
"&f%dk%dd%dL%s%s", key
,
195 (int) (sizeof (display
) - 1), (int) strlen (send
), display
, send
);
196 SLtt_write_string (tmp
);
201 /* --------------------------------------------------------------------------------------------- */
204 do_define_key (int code
, const char *strcap
)
208 seq
= SLtt_tgetstr ((SLFUTURE_CONST
char *) strcap
);
210 define_sequence (code
, seq
, MCKEY_NOACTION
);
213 /* --------------------------------------------------------------------------------------------- */
216 load_terminfo_keys (void)
220 for (i
= 0; key_table
[i
].key_code
; i
++)
221 do_define_key (key_table
[i
].key_code
, key_table
[i
].key_name
);
224 /* --------------------------------------------------------------------------------------------- */
225 /*** public functions ****************************************************************************/
226 /* --------------------------------------------------------------------------------------------- */
229 mc_tty_normalize_lines_char (const char *str
)
234 struct mc_tty_lines_struct
238 } const lines_codes
[] = {
239 {"\342\224\214", SLSMG_ULCORN_CHAR
},
240 {"\342\224\220", SLSMG_URCORN_CHAR
},
241 {"\342\224\224", SLSMG_LLCORN_CHAR
},
242 {"\342\224\230", SLSMG_LRCORN_CHAR
},
243 {"\342\224\234", SLSMG_LTEE_CHAR
},
244 {"\342\224\244", SLSMG_RTEE_CHAR
},
245 {"\342\224\254", SLSMG_UTEE_CHAR
},
246 {"\342\224\264", SLSMG_DTEE_CHAR
},
247 {"\342\224\200", SLSMG_HLINE_CHAR
},
248 {"\342\224\202", SLSMG_VLINE_CHAR
},
249 {"\342\224\274", SLSMG_PLUS_CHAR
},
257 for (res
= 0; lines_codes
[res
].line
; res
++)
259 if (strcmp (str
, lines_codes
[res
].line
) == 0)
260 return lines_codes
[res
].line_code
;
263 str2
= mc_tty_normalize_from_utf8 (str
);
264 res
= g_utf8_get_char_validated (str2
, -1);
267 res
= (unsigned char) str2
[0];
273 /* --------------------------------------------------------------------------------------------- */
276 tty_init (gboolean mouse_enable
, gboolean is_xterm
)
278 SLtt_Ignore_Beep
= 1;
280 SLutf8_enable (-1); /* has to be called first before any of the other functions. */
281 SLtt_get_terminfo ();
283 * If the terminal in not in terminfo but begins with a well-known
284 * string such as "linux" or "xterm" S-Lang will go on, but the
285 * terminal size and several other variables won't be initialized
286 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
287 * small screen dimensions.
289 if ((COLS
< 10) || (LINES
< 5)
290 #if SLANG_VERSION < 20303
291 /* Beginning from pre2.3.3-8 (55f58798c267d76a1b93d0d916027b71a10ac1ee),
292 these limitations were eliminated. */
293 || (COLS
> SLTT_MAX_SCREEN_COLS
) || (LINES
> SLTT_MAX_SCREEN_ROWS
)
298 _("Screen size %dx%d is not supported.\n"
299 "Check the TERM environment variable.\n"), COLS
, LINES
);
303 tcgetattr (fileno (stdin
), &boot_mode
);
304 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
305 SLang_init_tty (XCTRL ('g'), 1, 0);
307 if (mc_global
.tty
.ugly_line_drawing
)
308 SLtt_Has_Alt_Charset
= 0;
310 tcgetattr (SLang_TT_Read_FD
, &new_mode
);
312 tty_reset_prog_mode ();
313 load_terminfo_keys ();
315 SLtt_Blink_Mode
= (tty_use_256colors (NULL
) || tty_use_truecolors (NULL
)) ? 1 : 0;
317 tty_start_interrupt_key ();
319 /* It's the small part from the previous init_key() */
320 init_key_input_fd ();
322 /* For 8-bit locales, NCurses handles 154 (0x9A) symbol properly, while S-Lang
323 * requires SLsmg_Display_Eight_Bit >= 154 (OR manual filtering if xterm display
324 * detected - but checking TERM would fail under screen, OR running xterm
325 * with allowC1Printable).
327 tty_display_8bit (FALSE
);
332 use_mouse_p
= MOUSE_DISABLED
;
333 tty_init_xterm_support (is_xterm
); /* do it before tty_enter_ca_mode() call */
334 tty_enter_ca_mode ();
338 tty_setup_sigwinch (sigwinch_handler
);
341 /* --------------------------------------------------------------------------------------------- */
348 tty_destroy_winch_pipe ();
349 tty_reset_shell_mode ();
355 slsmg_active
= FALSE
;
357 /* Load the op capability to reset the colors to those that were
358 * active when the program was started up
360 op_cap
= SLtt_tgetstr ((SLFUTURE_CONST
char *) "op");
363 fputs (op_cap
, stdout
);
368 /* --------------------------------------------------------------------------------------------- */
371 tty_enter_ca_mode (void)
373 /* S-Lang handles alternate screen switching and cursor position saving */
376 /* --------------------------------------------------------------------------------------------- */
379 tty_exit_ca_mode (void)
381 /* S-Lang handles alternate screen switching and cursor position restoring */
384 /* --------------------------------------------------------------------------------------------- */
387 tty_change_screen_size (void)
389 SLtt_get_screen_size ();
393 #ifdef ENABLE_SUBSHELL
394 if (mc_global
.tty
.use_subshell
)
395 tty_resize (mc_global
.tty
.subshell_pty
);
399 /* --------------------------------------------------------------------------------------------- */
400 /* Done each time we come back from done mode */
403 tty_reset_prog_mode (void)
405 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
408 SLsmg_touch_lines (0, LINES
);
411 /* --------------------------------------------------------------------------------------------- */
412 /* Called each time we want to shutdown slang screen manager */
415 tty_reset_shell_mode (void)
417 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &boot_mode
);
420 /* --------------------------------------------------------------------------------------------- */
425 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
428 /* --------------------------------------------------------------------------------------------- */
431 tty_noraw_mode (void)
435 /* --------------------------------------------------------------------------------------------- */
442 /* --------------------------------------------------------------------------------------------- */
445 tty_flush_input (void)
450 /* --------------------------------------------------------------------------------------------- */
453 tty_keypad (gboolean set
)
457 keypad_string
= SLtt_tgetstr ((SLFUTURE_CONST
char *) (set
? "ks" : "ke"));
458 if (keypad_string
!= NULL
)
459 SLtt_write_string (keypad_string
);
460 if (set
&& reset_hp_softkeys
)
461 slang_reset_softkeys ();
464 /* --------------------------------------------------------------------------------------------- */
467 tty_nodelay (gboolean set
)
469 no_slang_delay
= set
;
472 /* --------------------------------------------------------------------------------------------- */
477 return SLang_TT_Baud_Rate
;
480 /* --------------------------------------------------------------------------------------------- */
483 tty_lowlevel_getch (void)
487 if (no_slang_delay
&& (SLang_input_pending (0) == 0))
491 if (c
== SLANG_GETKEY_ERROR
)
494 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
495 "Assuming EOF on stdin and exiting\n");
502 /* --------------------------------------------------------------------------------------------- */
505 tty_reset_screen (void)
508 slsmg_active
= FALSE
;
512 /* --------------------------------------------------------------------------------------------- */
515 tty_touch_screen (void)
517 SLsmg_touch_lines (0, LINES
);
520 /* --------------------------------------------------------------------------------------------- */
523 tty_gotoyx (int y
, int x
)
528 /* --------------------------------------------------------------------------------------------- */
531 tty_getyx (int *py
, int *px
)
533 *py
= SLsmg_get_row ();
534 *px
= SLsmg_get_column ();
537 /* --------------------------------------------------------------------------------------------- */
540 tty_draw_hline (int y
, int x
, int ch
, int len
)
544 if (y
< 0 || y
>= LINES
|| x
>= COLS
)
558 ch
= mc_tty_frm
[MC_TTY_FRM_HORIZ
];
565 SLsmg_draw_hline (len
);
570 SLsmg_gotorc (y
, x1
);
573 /* --------------------------------------------------------------------------------------------- */
576 tty_draw_vline (int y
, int x
, int ch
, int len
)
580 if (x
< 0 || x
>= COLS
|| y
>= LINES
)
594 ch
= mc_tty_frm
[MC_TTY_FRM_VERT
];
601 SLsmg_draw_vline (len
);
608 SLsmg_gotorc (y
+ pos
, x
);
614 SLsmg_gotorc (y1
, x
);
617 /* --------------------------------------------------------------------------------------------- */
620 tty_fill_region (int y
, int x
, int rows
, int cols
, unsigned char ch
)
622 SLsmg_fill_region (y
, x
, rows
, cols
, ch
);
625 /* --------------------------------------------------------------------------------------------- */
628 tty_colorize_area (int y
, int x
, int rows
, int cols
, int color
)
631 SLsmg_set_color_in_region (color
, y
, x
, rows
, cols
);
634 /* --------------------------------------------------------------------------------------------- */
637 tty_set_alt_charset (gboolean alt_charset
)
639 SLsmg_set_char_set ((int) alt_charset
);
642 /* --------------------------------------------------------------------------------------------- */
645 tty_display_8bit (gboolean what
)
647 SLsmg_Display_Eight_Bit
= what
? 128 : 160;
650 /* --------------------------------------------------------------------------------------------- */
653 tty_print_char (int c
)
655 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
658 /* --------------------------------------------------------------------------------------------- */
661 tty_print_alt_char (int c
, gboolean single
)
663 #define DRAW(x, y) (x == y) \
664 ? SLsmg_draw_object (SLsmg_get_row(), SLsmg_get_column(), x) \
665 : SLsmg_write_char ((unsigned int) y)
669 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_VERT
: MC_TTY_FRM_DVERT
]);
672 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_HORIZ
: MC_TTY_FRM_DHORIZ
]);
675 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTMIDDLE
: MC_TTY_FRM_DLEFTMIDDLE
]);
678 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTMIDDLE
: MC_TTY_FRM_DRIGHTMIDDLE
]);
681 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_TOPMIDDLE
: MC_TTY_FRM_DTOPMIDDLE
]);
684 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_BOTTOMMIDDLE
: MC_TTY_FRM_DBOTTOMMIDDLE
]);
687 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTTOP
: MC_TTY_FRM_DLEFTTOP
]);
690 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTBOTTOM
: MC_TTY_FRM_DLEFTBOTTOM
]);
693 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTTOP
: MC_TTY_FRM_DRIGHTTOP
]);
696 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTBOTTOM
: MC_TTY_FRM_DRIGHTBOTTOM
]);
699 DRAW (c
, mc_tty_frm
[MC_TTY_FRM_CROSS
]);
702 SLsmg_write_char ((unsigned int) c
);
707 /* --------------------------------------------------------------------------------------------- */
710 tty_print_anychar (int c
)
714 char str
[UTF8_CHAR_LEN
+ 1];
717 res
= g_unichar_to_utf8 (c
, str
);
727 SLsmg_write_string ((char *) str_term_form (str
));
731 if (!is_printable (c
))
733 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
737 /* --------------------------------------------------------------------------------------------- */
740 tty_print_string (const char *s
)
742 SLsmg_write_string ((char *) str_term_form (s
));
745 /* --------------------------------------------------------------------------------------------- */
748 tty_printf (const char *fmt
, ...)
752 va_start (args
, fmt
);
753 SLsmg_vprintf ((char *) fmt
, args
);
757 /* --------------------------------------------------------------------------------------------- */
760 tty_tgetstr (const char *cap
)
762 return SLtt_tgetstr ((SLFUTURE_CONST
char *) cap
);
765 /* --------------------------------------------------------------------------------------------- */
773 /* --------------------------------------------------------------------------------------------- */
781 /* --------------------------------------------------------------------------------------------- */