Added functions to convert GError messages (which are in UTF-8 charset)
[midnight-commander.git] / src / slint.c
blob87ca88a7f536eb0e0263200918b692a3335e5fa5
1 /* Slang interface to the Midnight Commander
2 This emulates some features of ncurses on top of slang
4 Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5 2005, 2007 Free Software Foundation, Inc.
7 Author Miguel de Icaza
8 Norbert Warmuth
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
24 #include <config.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
31 #ifdef HAVE_TERMIOS_H
32 #include <termios.h>
33 #endif
34 #include <unistd.h>
36 #include "global.h"
37 #include "tty.h"
38 #include "color.h"
39 #include "mouse.h" /* Gpm_Event is required in key.h */
40 #include "key.h" /* define_sequence */
41 #include "main.h" /* extern: force_colors */
42 #include "win.h" /* do_exit_ca_mode */
43 #include "setup.h"
44 #include "background.h" /* we_are_background */
46 #ifdef HAVE_SLANG
48 /* Taken from S-Lang's slutty.c */
49 #ifdef ultrix /* Ultrix gets _POSIX_VDISABLE wrong! */
50 # define NULL_VALUE -1
51 #else
52 # ifdef _POSIX_VDISABLE
53 # define NULL_VALUE _POSIX_VDISABLE
54 # else
55 # define NULL_VALUE 255
56 # endif
57 #endif
59 #ifndef SA_RESTART
60 # define SA_RESTART 0
61 #endif
63 /* Various saved termios settings that we control here */
64 static struct termios boot_mode;
65 static struct termios new_mode;
67 /* Controls whether we should wait for input in getch */
68 static int no_slang_delay;
70 /* Forward declarations */
71 static void load_terminfo_keys (void);
73 #ifndef HAVE_SLANG_PRIVATE
74 /* Private interfaces have been stripped, so we cannot use them */
75 #define SLang_getkey2() SLang_getkey()
76 #define SLang_input_pending2(s) SLang_input_pending(s)
77 #else
78 /* Copied from ../slang/slgetkey.c, removed the DEC_8Bit_HACK. */
79 extern unsigned char SLang_Input_Buffer [];
80 #if SLANG_VERSION >= 10000
81 extern unsigned int _SLsys_getkey (void);
82 extern int _SLsys_input_pending (int);
83 #else
84 extern unsigned int SLsys_getkey (void);
85 extern int SLsys_input_pending (int);
86 #endif
88 static unsigned int SLang_getkey2 (void)
90 unsigned int imax;
91 unsigned int ch;
93 if (SLang_Input_Buffer_Len)
95 ch = (unsigned int) *SLang_Input_Buffer;
96 SLang_Input_Buffer_Len--;
97 imax = SLang_Input_Buffer_Len;
99 memmove ((char *) SLang_Input_Buffer,
100 (char *) (SLang_Input_Buffer + 1), imax);
101 return(ch);
103 #if SLANG_VERSION >= 10000
104 else return(_SLsys_getkey ());
105 #else
106 else return(SLsys_getkey());
107 #endif
110 static int SLang_input_pending2 (int tsecs)
112 int n, i;
113 unsigned char c;
115 if (SLang_Input_Buffer_Len) return (int) SLang_Input_Buffer_Len;
116 #if SLANG_VERSION >= 10000
117 n = _SLsys_input_pending (tsecs);
118 #else
119 n = SLsys_input_pending (tsecs);
120 #endif
121 if (n <= 0) return 0;
123 i = SLang_getkey2 ();
124 if (i == SLANG_GETKEY_ERROR)
125 return 0; /* don't put crippled error codes into the input buffer */
126 c = (unsigned char)i;
127 SLang_ungetkey_string (&c, 1);
129 return n;
131 #endif /* HAVE_SLANG_PRIVATE */
133 /* Only done the first time */
134 void
135 slang_init (void)
137 SLtt_get_terminfo ();
138 #if SLANG_VERSION >= 20000
139 SLutf8_enable (-1);
140 #endif
142 * If the terminal in not in terminfo but begins with a well-known
143 * string such as "linux" or "xterm" S-Lang will go on, but the
144 * terminal size and several other variables won't be initialized
145 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
146 * small, large and negative screen dimensions.
148 if ((COLS < 10) || (LINES < 5) ||
149 (SLang_Version < 10407 && (COLS > 255 || LINES > 255)) ||
150 (SLang_Version >= 10407 && (COLS > 512 || LINES > 512))) {
152 fprintf (stderr,
153 _("Screen size %dx%d is not supported.\n"
154 "Check the TERM environment variable.\n"),
155 COLS, LINES);
156 exit (1);
159 tcgetattr (fileno (stdin), &boot_mode);
160 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
161 SLang_init_tty (XCTRL('c'), 1, 0);
163 /* If SLang uses fileno(stderr) for terminal input MC will hang
164 if we call SLang_getkey between calls to open_error_pipe and
165 close_error_pipe, e.g. when we do a growing view of an gzipped
166 file. */
167 if (SLang_TT_Read_FD == fileno (stderr))
168 SLang_TT_Read_FD = fileno (stdin);
170 if (force_ugly_line_drawing)
171 SLtt_Has_Alt_Charset = 0;
172 if (tcgetattr (SLang_TT_Read_FD, &new_mode) == 0) {
173 #ifdef VDSUSP
174 new_mode.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */
175 #endif
176 #ifdef VLNEXT
177 new_mode.c_cc[VLNEXT] = NULL_VALUE; /* to ignore ^V */
178 #endif
179 tcsetattr (SLang_TT_Read_FD, TCSADRAIN, &new_mode);
181 slang_prog_mode ();
182 load_terminfo_keys ();
183 SLtt_Blink_Mode = 0;
186 void
187 slang_set_raw_mode (void)
189 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
192 /* Done each time we come back from done mode */
193 void
194 slang_prog_mode (void)
196 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
197 SLsmg_init_smg ();
198 SLsmg_touch_lines (0, LINES);
201 /* Called each time we want to shutdown slang screen manager */
202 void
203 slang_shell_mode (void)
205 tcsetattr (SLang_TT_Read_FD, TCSANOW, &boot_mode);
208 void
209 slang_shutdown (void)
211 char *op_cap;
213 slang_shell_mode ();
214 do_exit_ca_mode ();
215 SLang_reset_tty ();
217 /* Load the op capability to reset the colors to those that were
218 * active when the program was started up
220 op_cap = SLtt_tgetstr ("op");
221 if (op_cap){
222 fprintf (stdout, "%s", op_cap);
223 fflush (stdout);
227 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
228 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
229 consequence is that function keys don't work in MC sometimes.
230 Unfortunately I don't now the one and only escape sequence to turn off
231 softkeys (elm uses three different capabilities to turn on softkeys and two
232 capabilities to turn them off).
233 Among other things elm uses the pair we already use in slang_keypad. That's
234 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
235 something better the softkeys are programmed to their defaults from the
236 termcap/terminfo database.
237 The escape sequence to program the softkeys is taken from elm and it is
238 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this
239 sequence. -- Norbert
242 static void
243 slang_reset_softkeys (void)
245 int key;
246 char *send;
247 static const char display[] = " ";
248 char tmp[BUF_SMALL];
250 for (key = 1; key < 9; key++) {
251 g_snprintf (tmp, sizeof (tmp), "k%d", key);
252 send = (char *) SLtt_tgetstr (tmp);
253 if (send) {
254 g_snprintf (tmp, sizeof (tmp), "\033&f%dk%dd%dL%s%s", key,
255 (int) (sizeof (display) - 1), (int) strlen (send),
256 display, send);
257 SLtt_write_string (tmp);
262 /* keypad routines */
263 void
264 slang_keypad (int set)
266 char *keypad_string;
267 extern int reset_hp_softkeys;
269 keypad_string = (char *) SLtt_tgetstr (set ? "ks" : "ke");
270 if (keypad_string)
271 SLtt_write_string (keypad_string);
272 if (set && reset_hp_softkeys)
273 slang_reset_softkeys ();
276 void
277 set_slang_delay (int v)
279 no_slang_delay = v;
282 void
283 hline (int ch, int len)
285 int last_x, last_y;
287 last_x = SLsmg_get_column ();
288 last_y = SLsmg_get_row ();
290 if (ch == 0)
291 ch = ACS_HLINE;
293 if (ch == ACS_HLINE){
294 SLsmg_draw_hline (len);
295 } else {
296 while (len--)
297 addch (ch);
299 move (last_y, last_x);
302 void
303 vline (int character, int len)
305 (void) character;
306 if (!slow_terminal){
307 SLsmg_draw_vline (len);
308 } else {
309 int last_x, last_y, pos = 0;
311 last_x = SLsmg_get_column ();
312 last_y = SLsmg_get_row ();
314 while (len--){
315 move (last_y + pos++, last_x);
316 addch (' ');
318 move (last_x, last_y);
322 int has_colors (void)
324 const char *terminal = getenv ("TERM");
325 char *cts = color_terminal_string, *s;
326 size_t i;
328 if (force_colors)
329 SLtt_Use_Ansi_Colors = 1;
330 if (NULL != getenv ("COLORTERM"))
331 SLtt_Use_Ansi_Colors = 1;
333 /* We want to allow overwriding */
334 if (!disable_colors){
335 /* check color_terminal_string */
336 if (*cts)
338 while (*cts)
340 while (*cts == ' ' || *cts == '\t') cts++;
342 s = cts;
343 i = 0;
345 while (*cts && *cts != ',')
347 cts++;
348 i++;
350 if (i && i == strlen(terminal) && strncmp(s, terminal, i) == 0)
351 SLtt_Use_Ansi_Colors = 1;
353 if (*cts == ',') cts++;
358 /* Setup emulated colors */
359 if (SLtt_Use_Ansi_Colors){
360 if (use_colors){
361 mc_init_pair (A_REVERSE, "black", "white");
362 mc_init_pair (A_BOLD, "white", "black");
363 } else {
364 mc_init_pair (A_REVERSE, "black", "lightgray");
365 mc_init_pair (A_BOLD, "white", "black");
366 mc_init_pair (A_BOLD_REVERSE, "white", "lightgray");
368 } else {
369 SLtt_set_mono (A_BOLD, NULL, SLTT_BOLD_MASK);
370 SLtt_set_mono (A_REVERSE, NULL, SLTT_REV_MASK);
371 SLtt_set_mono (A_BOLD|A_REVERSE, NULL, SLTT_BOLD_MASK | SLTT_REV_MASK);
373 return SLtt_Use_Ansi_Colors;
376 void
377 attrset (int color)
379 if (!SLtt_Use_Ansi_Colors){
380 SLsmg_set_color (color);
381 return;
384 if (color & A_BOLD){
385 if (color == A_BOLD)
386 SLsmg_set_color (A_BOLD);
387 else
388 SLsmg_set_color ((color & (~A_BOLD)) + 8);
389 return;
392 if (color == A_REVERSE)
393 SLsmg_set_color (A_REVERSE);
394 else
395 SLsmg_set_color (color);
398 /* This table describes which capabilities we want and which values we
399 * assign to them.
401 static const struct {
402 int key_code;
403 const char *key_name;
404 } key_table [] = {
405 { KEY_F(0), "k0" },
406 { KEY_F(1), "k1" },
407 { KEY_F(2), "k2" },
408 { KEY_F(3), "k3" },
409 { KEY_F(4), "k4" },
410 { KEY_F(5), "k5" },
411 { KEY_F(6), "k6" },
412 { KEY_F(7), "k7" },
413 { KEY_F(8), "k8" },
414 { KEY_F(9), "k9" },
415 { KEY_F(10), "k;" },
416 { KEY_F(11), "F1" },
417 { KEY_F(12), "F2" },
418 { KEY_F(13), "F3" },
419 { KEY_F(14), "F4" },
420 { KEY_F(15), "F5" },
421 { KEY_F(16), "F6" },
422 { KEY_F(17), "F7" },
423 { KEY_F(18), "F8" },
424 { KEY_F(19), "F9" },
425 { KEY_F(20), "FA" },
426 { KEY_IC, "kI" },
427 { KEY_NPAGE, "kN" },
428 { KEY_PPAGE, "kP" },
429 { KEY_LEFT, "kl" },
430 { KEY_RIGHT, "kr" },
431 { KEY_UP, "ku" },
432 { KEY_DOWN, "kd" },
433 { KEY_DC, "kD" },
434 { KEY_BACKSPACE, "kb" },
435 { KEY_HOME, "kh" },
436 { KEY_END, "@7" },
437 { 0, 0}
440 static void
441 do_define_key (int code, const char *strcap)
443 char *seq;
445 seq = (char *) SLtt_tgetstr ((char*) strcap);
446 if (seq)
447 define_sequence (code, seq, MCKEY_NOACTION);
450 static void
451 load_terminfo_keys (void)
453 int i;
455 for (i = 0; key_table [i].key_code; i++)
456 do_define_key (key_table [i].key_code, key_table [i].key_name);
460 getch (void)
462 int c;
463 if (no_slang_delay)
464 if (SLang_input_pending2 (0) == 0)
465 return -1;
467 c = SLang_getkey2 ();
468 if (c == SLANG_GETKEY_ERROR) {
469 fprintf (stderr,
470 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
471 "Assuming EOF on stdin and exiting\n");
472 exit (1);
474 return c;
476 #endif /* HAVE_SLANG */
478 void
479 mc_refresh (void)
481 #ifdef WITH_BACKGROUND
482 if (!we_are_background)
483 #endif /* WITH_BACKGROUND */
484 refresh ();