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
), ESC_STR
"&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
, gboolean mouse_enable
, gboolean is_xterm
)
247 ugly_line_drawing
= ugly_lines
;
249 SLtt_Ignore_Beep
= 1;
251 SLutf8_enable (-1); /* has to be called first before any of the other functions. */
252 SLtt_get_terminfo ();
254 * If the terminal in not in terminfo but begins with a well-known
255 * string such as "linux" or "xterm" S-Lang will go on, but the
256 * terminal size and several other variables won't be initialized
257 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
258 * small, large and negative screen dimensions.
260 if ((COLS
< 10) || (LINES
< 5)
261 || (COLS
> SLTT_MAX_SCREEN_COLS
) || (LINES
> SLTT_MAX_SCREEN_ROWS
))
264 _("Screen size %dx%d is not supported.\n"
265 "Check the TERM environment variable.\n"), COLS
, LINES
);
269 tcgetattr (fileno (stdin
), &boot_mode
);
270 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
271 SLang_init_tty (XCTRL ('g'), 1, 0);
274 SLtt_Has_Alt_Charset
= 0;
276 /* If SLang uses fileno(stderr) for terminal input MC will hang
277 if we call SLang_getkey between calls to open_error_pipe and
278 close_error_pipe, e.g. when we do a growing view of an gzipped
280 if (SLang_TT_Read_FD
== fileno (stderr
))
281 SLang_TT_Read_FD
= fileno (stdin
);
283 if (tcgetattr (SLang_TT_Read_FD
, &new_mode
) == 0)
286 new_mode
.c_cc
[VDSUSP
] = NULL_VALUE
; /* to ignore ^Y */
289 new_mode
.c_cc
[VLNEXT
] = NULL_VALUE
; /* to ignore ^V */
291 tcsetattr (SLang_TT_Read_FD
, TCSADRAIN
, &new_mode
);
294 tty_reset_prog_mode ();
295 load_terminfo_keys ();
298 tty_start_interrupt_key ();
300 /* It's the small part from the previous init_key() */
301 init_key_input_fd ();
303 /* For 8-bit locales, NCurses handles 154 (0x9A) symbol properly, while S-Lang
304 * requires SLsmg_Display_Eight_Bit >= 154 (OR manual filtering if xterm display
305 * detected - but checking TERM would fail under screen, OR running xterm
306 * with allowC1Printable).
308 tty_display_8bit (FALSE
);
312 use_mouse_p
= MOUSE_DISABLED
;
313 tty_init_xterm_support (is_xterm
); /* do it before do_enter_ca_mode() call */
320 /* --------------------------------------------------------------------------------------------- */
328 tty_reset_shell_mode ();
335 /* Load the op capability to reset the colors to those that were
336 * active when the program was started up
338 op_cap
= SLtt_tgetstr ((char *) "op");
341 fputs (op_cap
, stdout
);
346 /* --------------------------------------------------------------------------------------------- */
347 /* Done each time we come back from done mode */
350 tty_reset_prog_mode (void)
352 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
354 SLsmg_touch_lines (0, LINES
);
357 /* --------------------------------------------------------------------------------------------- */
358 /* Called each time we want to shutdown slang screen manager */
361 tty_reset_shell_mode (void)
363 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &boot_mode
);
366 /* --------------------------------------------------------------------------------------------- */
371 tcsetattr (SLang_TT_Read_FD
, TCSANOW
, &new_mode
);
374 /* --------------------------------------------------------------------------------------------- */
377 tty_noraw_mode (void)
381 /* --------------------------------------------------------------------------------------------- */
388 /* --------------------------------------------------------------------------------------------- */
391 tty_flush_input (void)
396 /* --------------------------------------------------------------------------------------------- */
399 tty_keypad (gboolean set
)
403 keypad_string
= (char *) SLtt_tgetstr ((char *) (set
? "ks" : "ke"));
404 if (keypad_string
!= NULL
)
405 SLtt_write_string (keypad_string
);
406 if (set
&& reset_hp_softkeys
)
407 slang_reset_softkeys ();
410 /* --------------------------------------------------------------------------------------------- */
413 tty_nodelay (gboolean set
)
415 no_slang_delay
= set
;
418 /* --------------------------------------------------------------------------------------------- */
423 return SLang_TT_Baud_Rate
;
426 /* --------------------------------------------------------------------------------------------- */
429 tty_lowlevel_getch (void)
433 if (no_slang_delay
&& (SLang_input_pending (0) == 0))
437 if (c
== SLANG_GETKEY_ERROR
)
440 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
441 "Assuming EOF on stdin and exiting\n");
448 /* --------------------------------------------------------------------------------------------- */
451 tty_reset_screen (void)
457 /* --------------------------------------------------------------------------------------------- */
460 tty_touch_screen (void)
462 SLsmg_touch_lines (0, LINES
);
465 /* --------------------------------------------------------------------------------------------- */
468 tty_gotoyx (int y
, int x
)
473 /* --------------------------------------------------------------------------------------------- */
476 tty_getyx (int *py
, int *px
)
478 *py
= SLsmg_get_row ();
479 *px
= SLsmg_get_column ();
482 /* --------------------------------------------------------------------------------------------- */
483 /* if x < 0 or y < 0, draw line staring from current position */
486 tty_draw_hline (int y
, int x
, int ch
, int len
)
489 ch
= mc_tty_frm
[MC_TTY_FRM_HORIZ
];
491 if ((y
< 0) || (x
< 0))
493 y
= SLsmg_get_row ();
494 x
= SLsmg_get_column ();
503 SLsmg_draw_hline (len
);
511 /* --------------------------------------------------------------------------------------------- */
512 /* if x < 0 or y < 0, draw line staring from current position */
515 tty_draw_vline (int y
, int x
, int ch
, int len
)
518 ch
= mc_tty_frm
[MC_TTY_FRM_VERT
];
520 if ((y
< 0) || (x
< 0))
522 y
= SLsmg_get_row ();
523 x
= SLsmg_get_column ();
532 SLsmg_draw_vline (len
);
539 SLsmg_gotorc (y
+ pos
, x
);
548 /* --------------------------------------------------------------------------------------------- */
551 tty_fill_region (int y
, int x
, int rows
, int cols
, unsigned char ch
)
553 SLsmg_fill_region (y
, x
, rows
, cols
, ch
);
556 /* --------------------------------------------------------------------------------------------- */
559 tty_set_alt_charset (gboolean alt_charset
)
561 SLsmg_set_char_set ((int) alt_charset
);
564 /* --------------------------------------------------------------------------------------------- */
567 tty_display_8bit (gboolean what
)
569 SLsmg_Display_Eight_Bit
= what
? 128 : 160;
572 /* --------------------------------------------------------------------------------------------- */
575 tty_print_char (int c
)
577 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
580 /* --------------------------------------------------------------------------------------------- */
583 tty_print_alt_char (int c
, gboolean single
)
585 #define DRAW(x, y) (x == y) \
586 ? SLsmg_draw_object (SLsmg_get_row(), SLsmg_get_column(), x) \
587 : SLsmg_write_char ((unsigned int) y)
591 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_VERT
: MC_TTY_FRM_DVERT
]);
594 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_HORIZ
: MC_TTY_FRM_DHORIZ
]);
597 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTMIDDLE
: MC_TTY_FRM_DLEFTMIDDLE
]);
600 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTMIDDLE
: MC_TTY_FRM_DRIGHTMIDDLE
]);
603 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTTOP
: MC_TTY_FRM_DLEFTTOP
]);
606 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_LEFTBOTTOM
: MC_TTY_FRM_DLEFTBOTTOM
]);
609 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTTOP
: MC_TTY_FRM_DRIGHTTOP
]);
612 DRAW (c
, mc_tty_frm
[single
? MC_TTY_FRM_RIGHTBOTTOM
: MC_TTY_FRM_DRIGHTBOTTOM
]);
615 DRAW (c
, mc_tty_frm
[MC_TTY_FRM_CROSS
]);
618 SLsmg_write_char ((unsigned int) c
);
623 /* --------------------------------------------------------------------------------------------- */
626 tty_print_anychar (int c
)
632 int res
= g_unichar_to_utf8 (c
, str
);
642 SLsmg_write_string ((char *) str_term_form (str
));
646 if (!is_printable (c
))
648 SLsmg_write_char ((SLwchar_Type
) ((unsigned int) c
));
652 /* --------------------------------------------------------------------------------------------- */
655 tty_print_string (const char *s
)
657 SLsmg_write_string ((char *) str_term_form (s
));
660 /* --------------------------------------------------------------------------------------------- */
663 tty_printf (const char *fmt
, ...)
667 va_start (args
, fmt
);
668 SLsmg_vprintf ((char *) fmt
, args
);
672 /* --------------------------------------------------------------------------------------------- */
675 tty_tgetstr (const char *cap
)
677 return SLtt_tgetstr ((char *) cap
);
680 /* --------------------------------------------------------------------------------------------- */
688 /* --------------------------------------------------------------------------------------------- */
691 tty_setup_sigwinch (void (*handler
) (int))
694 struct sigaction act
, oact
;
695 act
.sa_handler
= handler
;
696 sigemptyset (&act
.sa_mask
);
699 act
.sa_flags
|= SA_RESTART
;
700 #endif /* SA_RESTART */
701 sigaction (SIGWINCH
, &act
, &oact
);
702 #endif /* SIGWINCH */
705 /* --------------------------------------------------------------------------------------------- */
713 /* --------------------------------------------------------------------------------------------- */