2 Interface to the terminal controlling library.
5 Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
8 Andrew Borodin <aborodin@vmail.ru>, 2009.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software; you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be
18 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
19 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
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" /* slow_tty */
48 #include "color-slang.h"
49 #include "color-internal.h"
50 #include "mouse.h" /* Gpm_Event is required in key.h */
51 #include "key.h" /* define_sequence */
55 /*** global variables ****************************************************************************/
57 extern int reset_hp_softkeys
;
59 /*** file scope macro definitions ****************************************************************/
65 #ifndef SLTT_MAX_SCREEN_COLS
66 #define SLTT_MAX_SCREEN_COLS 512
69 #ifndef SLTT_MAX_SCREEN_ROWS
70 #define SLTT_MAX_SCREEN_ROWS 512
73 /*** file scope type declarations ****************************************************************/
75 /*** file scope variables ************************************************************************/
77 /* Various saved termios settings that we control here */
78 static struct termios boot_mode
;
79 static struct termios new_mode
;
81 /* Controls whether we should wait for input in tty_lowlevel_getch */
82 static gboolean no_slang_delay
;
84 /* This table describes which capabilities we want and which values we
104 { KEY_F (10), "k;" },
105 { KEY_F (11), "F1" },
106 { KEY_F (12), "F2" },
107 { KEY_F (13), "F3" },
108 { KEY_F (14), "F4" },
109 { KEY_F (15), "F5" },
110 { KEY_F (16), "F6" },
111 { KEY_F (17), "F7" },
112 { KEY_F (18), "F8" },
113 { KEY_F (19), "F9" },
114 { KEY_F (20), "FA" },
123 { KEY_BACKSPACE
, "kb" },
130 /*** file scope functions ************************************************************************/
131 /* --------------------------------------------------------------------------------------------- */
133 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
134 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
135 consequence is that function keys don't work in MC sometimes...
136 Unfortunately I don't now the one and only escape sequence to turn off.
137 softkeys (elm uses three different capabilities to turn on softkeys and two.
138 capabilities to turn them off)..
139 Among other things elm uses the pair we already use in slang_keypad. That's.
140 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
141 something better the softkeys are programmed to their defaults from the
142 termcap/terminfo database.
143 The escape sequence to program the softkeys is taken from elm and it is.
144 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this.
149 slang_reset_softkeys (void)
153 static const char display
[] = " ";
156 for (key
= 1; key
< 9; key
++)
158 g_snprintf (tmp
, sizeof (tmp
), "k%d", key
);
159 send
= (char *) SLtt_tgetstr (tmp
);
162 g_snprintf (tmp
, sizeof (tmp
), "\033&f%dk%dd%dL%s%s", key
,
163 (int) (sizeof (display
) - 1), (int) strlen (send
), display
, send
);
164 SLtt_write_string (tmp
);
169 /* --------------------------------------------------------------------------------------------- */
172 do_define_key (int code
, const char *strcap
)
176 seq
= (char *) SLtt_tgetstr ((char *) strcap
);
178 define_sequence (code
, seq
, MCKEY_NOACTION
);
181 /* --------------------------------------------------------------------------------------------- */
184 load_terminfo_keys (void)
188 for (i
= 0; key_table
[i
].key_code
; i
++)
189 do_define_key (key_table
[i
].key_code
, key_table
[i
].key_name
);
192 /* --------------------------------------------------------------------------------------------- */
193 /*** public functions ****************************************************************************/
194 /* --------------------------------------------------------------------------------------------- */
197 mc_tty_normalize_lines_char (const char *str
)
202 struct mc_tty_lines_struct
206 } const lines_codes
[] = {
207 {"\342\224\214", SLSMG_ULCORN_CHAR
},
208 {"\342\224\220", SLSMG_URCORN_CHAR
},
209 {"\342\224\224", SLSMG_LLCORN_CHAR
},
210 {"\342\224\230", SLSMG_LRCORN_CHAR
},
211 {"\342\224\234", SLSMG_LTEE_CHAR
},
212 {"\342\224\244", SLSMG_RTEE_CHAR
},
213 {"\342\224\254", SLSMG_UTEE_CHAR
},
214 {"\342\224\264", SLSMG_DTEE_CHAR
},
215 {"\342\224\200", SLSMG_HLINE_CHAR
},
216 {"\342\224\202", SLSMG_VLINE_CHAR
},
217 {"\342\224\274", SLSMG_PLUS_CHAR
},
225 for (res
= 0; lines_codes
[res
].line
; res
++)
227 if (strcmp (str
, lines_codes
[res
].line
) == 0)
228 return lines_codes
[res
].line_code
;
231 str2
= mc_tty_normalize_from_utf8 (str
);
232 res
= g_utf8_get_char_validated (str2
, -1);
235 res
= (unsigned char) str2
[0];
241 /* --------------------------------------------------------------------------------------------- */
244 tty_init (gboolean slow
, gboolean ugly_lines
)
247 ugly_line_drawing
= ugly_lines
;
249 SLtt_Ignore_Beep
= 1;
250 SLtt_get_terminfo ();
253 * If the terminal in not in terminfo but begins with a well-known
254 * string such as "linux" or "xterm" S-Lang will go on, but the
255 * terminal size and several other variables won't be initialized
256 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
257 * small, large and negative screen dimensions.
259 if ((COLS
< 10) || (LINES
< 5)
260 || (COLS
> SLTT_MAX_SCREEN_COLS
) || (LINES
> SLTT_MAX_SCREEN_ROWS
))
263 _("Screen size %dx%d is not supported.\n"
264 "Check the TERM environment variable.\n"), COLS
, LINES
);
268 tcgetattr (fileno (stdin
), &boot_mode
);
269 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
270 SLang_init_tty (XCTRL ('g'), 1, 0);
273 SLtt_Has_Alt_Charset
= 0;
275 /* If SLang uses fileno(stderr) for terminal input MC will hang
276 if we call SLang_getkey between calls to open_error_pipe and
277 close_error_pipe, e.g. when we do a growing view of an gzipped
279 if (SLang_TT_Read_FD
== fileno (stderr
))
280 SLang_TT_Read_FD
= fileno (stdin
);
282 if (tcgetattr (SLang_TT_Read_FD
, &new_mode
) == 0)
285 new_mode
.c_cc
[VDSUSP
] = NULL_VALUE
; /* to ignore ^Y */
288 new_mode
.c_cc
[VLNEXT
] = NULL_VALUE
; /* to ignore ^V */
290 tcsetattr (SLang_TT_Read_FD
, TCSADRAIN
, &new_mode
);
293 tty_reset_prog_mode ();
294 load_terminfo_keys ();
297 tty_start_interrupt_key ();
299 /* It's the small part from the previous init_key() */
300 init_key_input_fd ();
308 /* --------------------------------------------------------------------------------------------- */
316 tty_reset_shell_mode ();
320 /* Load the op capability to reset the colors to those that were
321 * active when the program was started up
323 op_cap
= SLtt_tgetstr ((char *) "op");
326 fputs (op_cap
, stdout
);
331 /* --------------------------------------------------------------------------------------------- */
332 /* Done each time we come back from done mode */
335 tty_reset_prog_mode (void)
337 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
339 SLsmg_touch_lines (0, LINES
);
342 /* --------------------------------------------------------------------------------------------- */
343 /* Called each time we want to shutdown slang screen manager */
346 tty_reset_shell_mode (void)
348 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &boot_mode
);
351 /* --------------------------------------------------------------------------------------------- */
356 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
359 /* --------------------------------------------------------------------------------------------- */
362 tty_noraw_mode (void)
366 /* --------------------------------------------------------------------------------------------- */
373 /* --------------------------------------------------------------------------------------------- */
376 tty_flush_input (void)
381 /* --------------------------------------------------------------------------------------------- */
384 tty_keypad (gboolean set
)
388 keypad_string
= (char *) SLtt_tgetstr ((char *) (set
? "ks" : "ke"));
389 if (keypad_string
!= NULL
)
390 SLtt_write_string (keypad_string
);
391 if (set
&& reset_hp_softkeys
)
392 slang_reset_softkeys ();
395 /* --------------------------------------------------------------------------------------------- */
398 tty_nodelay (gboolean set
)
400 no_slang_delay
= set
;
403 /* --------------------------------------------------------------------------------------------- */
408 return SLang_TT_Baud_Rate
;
411 /* --------------------------------------------------------------------------------------------- */
414 tty_lowlevel_getch (void)
418 if (no_slang_delay
&& (SLang_input_pending (0) == 0))
422 if (c
== SLANG_GETKEY_ERROR
)
425 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
426 "Assuming EOF on stdin and exiting\n");
433 /* --------------------------------------------------------------------------------------------- */
436 tty_reset_screen (void)
442 /* --------------------------------------------------------------------------------------------- */
445 tty_touch_screen (void)
447 SLsmg_touch_lines (0, LINES
);
450 /* --------------------------------------------------------------------------------------------- */
453 tty_gotoyx (int y
, int x
)
458 /* --------------------------------------------------------------------------------------------- */
461 tty_getyx (int *py
, int *px
)
463 *py
= SLsmg_get_row ();
464 *px
= SLsmg_get_column ();
467 /* --------------------------------------------------------------------------------------------- */
468 /* if x < 0 or y < 0, draw line staring from current position */
471 tty_draw_hline (int y
, int x
, int ch
, int len
)
474 ch
= mc_tty_frm
[MC_TTY_FRM_HORIZ
];
476 if ((y
< 0) || (x
< 0))
478 y
= SLsmg_get_row ();
479 x
= SLsmg_get_column ();
488 SLsmg_draw_hline (len
);
496 /* --------------------------------------------------------------------------------------------- */
497 /* if x < 0 or y < 0, draw line staring from current position */
500 tty_draw_vline (int y
, int x
, int ch
, int len
)
503 ch
= mc_tty_frm
[MC_TTY_FRM_VERT
];
505 if ((y
< 0) || (x
< 0))
507 y
= SLsmg_get_row ();
508 x
= SLsmg_get_column ();
517 SLsmg_draw_vline (len
);
524 SLsmg_gotorc (y
+ pos
, x
);
533 /* --------------------------------------------------------------------------------------------- */
536 tty_fill_region (int y
, int x
, int rows
, int cols
, unsigned char ch
)
538 SLsmg_fill_region (y
, x
, rows
, cols
, ch
);
541 /* --------------------------------------------------------------------------------------------- */
544 tty_set_alt_charset (gboolean alt_charset
)
546 SLsmg_set_char_set ((int) alt_charset
);
549 /* --------------------------------------------------------------------------------------------- */
552 tty_display_8bit (gboolean what
)
554 SLsmg_Display_Eight_Bit
= what
? 128 : 160;
557 /* --------------------------------------------------------------------------------------------- */
560 tty_print_char (int c
)
562 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
565 /* --------------------------------------------------------------------------------------------- */
568 tty_print_alt_char (int c
, gboolean single
)
570 #define DRAW(x, y) (x == y) \
571 ? SLsmg_draw_object (SLsmg_get_row(), SLsmg_get_column(), x) \
572 : SLsmg_write_char ((unsigned int) y)
576 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_VERT
: MC_TTY_FRM_DVERT
]);
579 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_HORIZ
: MC_TTY_FRM_DHORIZ
]);
582 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTMIDDLE
: MC_TTY_FRM_DLEFTMIDDLE
]);
585 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTMIDDLE
: MC_TTY_FRM_DRIGHTMIDDLE
]);
588 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTTOP
: MC_TTY_FRM_DLEFTTOP
]);
591 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTBOTTOM
: MC_TTY_FRM_DLEFTBOTTOM
]);
594 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTTOP
: MC_TTY_FRM_DRIGHTTOP
]);
597 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTBOTTOM
: MC_TTY_FRM_DRIGHTBOTTOM
]);
600 DRAW (c
, mc_tty_frm
[MC_TTY_FRM_CROSS
]);
603 SLsmg_write_char ((unsigned int) c
);
608 /* --------------------------------------------------------------------------------------------- */
611 tty_print_anychar (int c
)
617 int res
= g_unichar_to_utf8 (c
, str
);
627 SLsmg_write_string ((char *) str_term_form (str
));
631 if (!is_printable (c
))
633 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
637 /* --------------------------------------------------------------------------------------------- */
640 tty_print_string (const char *s
)
642 SLsmg_write_string ((char *) str_term_form (s
));
645 /* --------------------------------------------------------------------------------------------- */
648 tty_printf (const char *fmt
, ...)
652 va_start (args
, fmt
);
653 SLsmg_vprintf ((char *) fmt
, args
);
657 /* --------------------------------------------------------------------------------------------- */
660 tty_tgetstr (const char *cap
)
662 return SLtt_tgetstr ((char *) cap
);
665 /* --------------------------------------------------------------------------------------------- */
673 /* --------------------------------------------------------------------------------------------- */
676 tty_setup_sigwinch (void (*handler
) (int))
679 struct sigaction act
, oact
;
680 act
.sa_handler
= handler
;
681 sigemptyset (&act
.sa_mask
);
684 act
.sa_flags
|= SA_RESTART
;
685 #endif /* SA_RESTART */
686 sigaction (SIGWINCH
, &act
, &oact
);
687 #endif /* SIGWINCH */
690 /* --------------------------------------------------------------------------------------------- */
698 /* --------------------------------------------------------------------------------------------- */