2 Interface to the terminal controlling library.
5 Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011
6 The 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
38 #include <sys/types.h> /* size_t */
42 #include "lib/global.h"
43 #include "lib/strutil.h" /* str_term_form */
44 #include "lib/util.h" /* is_printable() */
46 #include "tty-internal.h" /* mc_tty_normalize_from_utf8() */
49 #include "color-slang.h"
50 #include "color-internal.h"
51 #include "mouse.h" /* Gpm_Event is required in key.h */
52 #include "key.h" /* define_sequence */
56 /*** global variables ****************************************************************************/
58 extern int reset_hp_softkeys
;
60 /*** file scope macro definitions ****************************************************************/
66 #ifndef SLTT_MAX_SCREEN_COLS
67 #define SLTT_MAX_SCREEN_COLS 512
70 #ifndef SLTT_MAX_SCREEN_ROWS
71 #define SLTT_MAX_SCREEN_ROWS 512
74 /*** file scope type declarations ****************************************************************/
76 /*** file scope variables ************************************************************************/
78 /* Various saved termios settings that we control here */
79 static struct termios boot_mode
;
80 static struct termios new_mode
;
82 /* Controls whether we should wait for input in tty_lowlevel_getch */
83 static gboolean no_slang_delay
;
85 /* This table describes which capabilities we want and which values we
105 { KEY_F (10), "k;" },
106 { KEY_F (11), "F1" },
107 { KEY_F (12), "F2" },
108 { KEY_F (13), "F3" },
109 { KEY_F (14), "F4" },
110 { KEY_F (15), "F5" },
111 { KEY_F (16), "F6" },
112 { KEY_F (17), "F7" },
113 { KEY_F (18), "F8" },
114 { KEY_F (19), "F9" },
115 { KEY_F (20), "FA" },
124 { KEY_BACKSPACE
, "kb" },
131 /*** file scope functions ************************************************************************/
132 /* --------------------------------------------------------------------------------------------- */
135 tty_setup_sigwinch (void (*handler
) (int))
138 struct sigaction act
, oact
;
139 act
.sa_handler
= handler
;
140 sigemptyset (&act
.sa_mask
);
143 act
.sa_flags
|= SA_RESTART
;
144 #endif /* SA_RESTART */
145 sigaction (SIGWINCH
, &act
, &oact
);
146 #endif /* SIGWINCH */
149 /* --------------------------------------------------------------------------------------------- */
152 sigwinch_handler (int dummy
)
156 tty_change_screen_size ();
157 mc_global
.tty
.winch_flag
= TRUE
;
160 /* --------------------------------------------------------------------------------------------- */
162 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
163 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
164 consequence is that function keys don't work in MC sometimes...
165 Unfortunately I don't now the one and only escape sequence to turn off.
166 softkeys (elm uses three different capabilities to turn on softkeys and two.
167 capabilities to turn them off)..
168 Among other things elm uses the pair we already use in slang_keypad. That's.
169 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
170 something better the softkeys are programmed to their defaults from the
171 termcap/terminfo database.
172 The escape sequence to program the softkeys is taken from elm and it is.
173 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this.
178 slang_reset_softkeys (void)
182 static const char display
[] = " ";
185 for (key
= 1; key
< 9; key
++)
187 g_snprintf (tmp
, sizeof (tmp
), "k%d", key
);
188 send
= (char *) SLtt_tgetstr (tmp
);
191 g_snprintf (tmp
, sizeof (tmp
), ESC_STR
"&f%dk%dd%dL%s%s", key
,
192 (int) (sizeof (display
) - 1), (int) strlen (send
), display
, send
);
193 SLtt_write_string (tmp
);
198 /* --------------------------------------------------------------------------------------------- */
201 do_define_key (int code
, const char *strcap
)
205 seq
= (char *) SLtt_tgetstr ((char *) strcap
);
207 define_sequence (code
, seq
, MCKEY_NOACTION
);
210 /* --------------------------------------------------------------------------------------------- */
213 load_terminfo_keys (void)
217 for (i
= 0; key_table
[i
].key_code
; i
++)
218 do_define_key (key_table
[i
].key_code
, key_table
[i
].key_name
);
221 /* --------------------------------------------------------------------------------------------- */
222 /*** public functions ****************************************************************************/
223 /* --------------------------------------------------------------------------------------------- */
226 mc_tty_normalize_lines_char (const char *str
)
231 struct mc_tty_lines_struct
235 } const lines_codes
[] = {
236 {"\342\224\214", SLSMG_ULCORN_CHAR
},
237 {"\342\224\220", SLSMG_URCORN_CHAR
},
238 {"\342\224\224", SLSMG_LLCORN_CHAR
},
239 {"\342\224\230", SLSMG_LRCORN_CHAR
},
240 {"\342\224\234", SLSMG_LTEE_CHAR
},
241 {"\342\224\244", SLSMG_RTEE_CHAR
},
242 {"\342\224\254", SLSMG_UTEE_CHAR
},
243 {"\342\224\264", SLSMG_DTEE_CHAR
},
244 {"\342\224\200", SLSMG_HLINE_CHAR
},
245 {"\342\224\202", SLSMG_VLINE_CHAR
},
246 {"\342\224\274", SLSMG_PLUS_CHAR
},
254 for (res
= 0; lines_codes
[res
].line
; res
++)
256 if (strcmp (str
, lines_codes
[res
].line
) == 0)
257 return lines_codes
[res
].line_code
;
260 str2
= mc_tty_normalize_from_utf8 (str
);
261 res
= g_utf8_get_char_validated (str2
, -1);
264 res
= (unsigned char) str2
[0];
270 /* --------------------------------------------------------------------------------------------- */
273 tty_init (gboolean mouse_enable
, gboolean is_xterm
)
275 SLtt_Ignore_Beep
= 1;
277 SLutf8_enable (-1); /* has to be called first before any of the other functions. */
278 SLtt_get_terminfo ();
280 * If the terminal in not in terminfo but begins with a well-known
281 * string such as "linux" or "xterm" S-Lang will go on, but the
282 * terminal size and several other variables won't be initialized
283 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
284 * small, large and negative screen dimensions.
286 if ((COLS
< 10) || (LINES
< 5)
287 || (COLS
> SLTT_MAX_SCREEN_COLS
) || (LINES
> SLTT_MAX_SCREEN_ROWS
))
290 _("Screen size %dx%d is not supported.\n"
291 "Check the TERM environment variable.\n"), COLS
, LINES
);
295 tcgetattr (fileno (stdin
), &boot_mode
);
296 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
297 SLang_init_tty (XCTRL ('g'), 1, 0);
299 if (mc_global
.tty
.ugly_line_drawing
)
300 SLtt_Has_Alt_Charset
= 0;
302 /* If SLang uses fileno(stderr) for terminal input MC will hang
303 if we call SLang_getkey between calls to open_error_pipe and
304 close_error_pipe, e.g. when we do a growing view of an gzipped
306 if (SLang_TT_Read_FD
== fileno (stderr
))
307 SLang_TT_Read_FD
= fileno (stdin
);
309 if (tcgetattr (SLang_TT_Read_FD
, &new_mode
) == 0)
312 new_mode
.c_cc
[VDSUSP
] = NULL_VALUE
; /* to ignore ^Y */
315 new_mode
.c_cc
[VLNEXT
] = NULL_VALUE
; /* to ignore ^V */
317 tcsetattr (SLang_TT_Read_FD
, TCSADRAIN
, &new_mode
);
320 tty_reset_prog_mode ();
321 load_terminfo_keys ();
323 SLtt_Blink_Mode
= tty_use_256colors ()? 1 : 0;
325 tty_start_interrupt_key ();
327 /* It's the small part from the previous init_key() */
328 init_key_input_fd ();
330 /* For 8-bit locales, NCurses handles 154 (0x9A) symbol properly, while S-Lang
331 * requires SLsmg_Display_Eight_Bit >= 154 (OR manual filtering if xterm display
332 * detected - but checking TERM would fail under screen, OR running xterm
333 * with allowC1Printable).
335 tty_display_8bit (FALSE
);
339 use_mouse_p
= MOUSE_DISABLED
;
340 tty_init_xterm_support (is_xterm
); /* do it before do_enter_ca_mode() call */
346 tty_setup_sigwinch (sigwinch_handler
);
349 /* --------------------------------------------------------------------------------------------- */
357 tty_reset_shell_mode ();
364 /* Load the op capability to reset the colors to those that were
365 * active when the program was started up
367 op_cap
= SLtt_tgetstr ((char *) "op");
370 fputs (op_cap
, stdout
);
375 /* --------------------------------------------------------------------------------------------- */
376 /* Done each time we come back from done mode */
379 tty_reset_prog_mode (void)
381 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
383 SLsmg_touch_lines (0, LINES
);
386 /* --------------------------------------------------------------------------------------------- */
387 /* Called each time we want to shutdown slang screen manager */
390 tty_reset_shell_mode (void)
392 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &boot_mode
);
395 /* --------------------------------------------------------------------------------------------- */
400 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
403 /* --------------------------------------------------------------------------------------------- */
406 tty_noraw_mode (void)
410 /* --------------------------------------------------------------------------------------------- */
417 /* --------------------------------------------------------------------------------------------- */
420 tty_flush_input (void)
425 /* --------------------------------------------------------------------------------------------- */
428 tty_keypad (gboolean set
)
432 keypad_string
= (char *) SLtt_tgetstr ((char *) (set
? "ks" : "ke"));
433 if (keypad_string
!= NULL
)
434 SLtt_write_string (keypad_string
);
435 if (set
&& reset_hp_softkeys
)
436 slang_reset_softkeys ();
439 /* --------------------------------------------------------------------------------------------- */
442 tty_nodelay (gboolean set
)
444 no_slang_delay
= set
;
447 /* --------------------------------------------------------------------------------------------- */
452 return SLang_TT_Baud_Rate
;
455 /* --------------------------------------------------------------------------------------------- */
458 tty_lowlevel_getch (void)
462 if (no_slang_delay
&& (SLang_input_pending (0) == 0))
466 if (c
== SLANG_GETKEY_ERROR
)
469 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
470 "Assuming EOF on stdin and exiting\n");
477 /* --------------------------------------------------------------------------------------------- */
480 tty_reset_screen (void)
486 /* --------------------------------------------------------------------------------------------- */
489 tty_touch_screen (void)
491 SLsmg_touch_lines (0, LINES
);
494 /* --------------------------------------------------------------------------------------------- */
497 tty_gotoyx (int y
, int x
)
502 /* --------------------------------------------------------------------------------------------- */
505 tty_getyx (int *py
, int *px
)
507 *py
= SLsmg_get_row ();
508 *px
= SLsmg_get_column ();
511 /* --------------------------------------------------------------------------------------------- */
512 /* if x < 0 or y < 0, draw line staring from current position */
515 tty_draw_hline (int y
, int x
, int ch
, int len
)
518 ch
= mc_tty_frm
[MC_TTY_FRM_HORIZ
];
520 if ((y
< 0) || (x
< 0))
522 y
= SLsmg_get_row ();
523 x
= SLsmg_get_column ();
532 SLsmg_draw_hline (len
);
540 /* --------------------------------------------------------------------------------------------- */
541 /* if x < 0 or y < 0, draw line staring from current position */
544 tty_draw_vline (int y
, int x
, int ch
, int len
)
547 ch
= mc_tty_frm
[MC_TTY_FRM_VERT
];
549 if ((y
< 0) || (x
< 0))
551 y
= SLsmg_get_row ();
552 x
= SLsmg_get_column ();
561 SLsmg_draw_vline (len
);
568 SLsmg_gotorc (y
+ pos
, x
);
577 /* --------------------------------------------------------------------------------------------- */
580 tty_fill_region (int y
, int x
, int rows
, int cols
, unsigned char ch
)
582 SLsmg_fill_region (y
, x
, rows
, cols
, ch
);
585 /* --------------------------------------------------------------------------------------------- */
588 tty_set_alt_charset (gboolean alt_charset
)
590 SLsmg_set_char_set ((int) alt_charset
);
593 /* --------------------------------------------------------------------------------------------- */
596 tty_display_8bit (gboolean what
)
598 SLsmg_Display_Eight_Bit
= what
? 128 : 160;
601 /* --------------------------------------------------------------------------------------------- */
604 tty_print_char (int c
)
606 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
609 /* --------------------------------------------------------------------------------------------- */
612 tty_print_alt_char (int c
, gboolean single
)
614 #define DRAW(x, y) (x == y) \
615 ? SLsmg_draw_object (SLsmg_get_row(), SLsmg_get_column(), x) \
616 : SLsmg_write_char ((unsigned int) y)
620 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_VERT
: MC_TTY_FRM_DVERT
]);
623 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_HORIZ
: MC_TTY_FRM_DHORIZ
]);
626 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTMIDDLE
: MC_TTY_FRM_DLEFTMIDDLE
]);
629 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTMIDDLE
: MC_TTY_FRM_DRIGHTMIDDLE
]);
632 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTTOP
: MC_TTY_FRM_DLEFTTOP
]);
635 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTBOTTOM
: MC_TTY_FRM_DLEFTBOTTOM
]);
638 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTTOP
: MC_TTY_FRM_DRIGHTTOP
]);
641 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTBOTTOM
: MC_TTY_FRM_DRIGHTBOTTOM
]);
644 DRAW (c
, mc_tty_frm
[MC_TTY_FRM_CROSS
]);
647 SLsmg_write_char ((unsigned int) c
);
652 /* --------------------------------------------------------------------------------------------- */
655 tty_print_anychar (int c
)
661 int res
= g_unichar_to_utf8 (c
, str
);
671 SLsmg_write_string ((char *) str_term_form (str
));
675 if (!is_printable (c
))
677 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
681 /* --------------------------------------------------------------------------------------------- */
684 tty_print_string (const char *s
)
686 SLsmg_write_string ((char *) str_term_form (s
));
689 /* --------------------------------------------------------------------------------------------- */
692 tty_printf (const char *fmt
, ...)
696 va_start (args
, fmt
);
697 SLsmg_vprintf ((char *) fmt
, args
);
701 /* --------------------------------------------------------------------------------------------- */
704 tty_tgetstr (const char *cap
)
706 return SLtt_tgetstr ((char *) cap
);
709 /* --------------------------------------------------------------------------------------------- */
717 /* --------------------------------------------------------------------------------------------- */
725 /* --------------------------------------------------------------------------------------------- */