Some fixups with wrongly highlighted words
[midnight-commander.git] / src / slint.c
blobc296164a9a5e9427d7b52868cdf263c8895b5ae9
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 /** \file slint.c
25 * \brief Source: slang %interface to the Midnight Commander
26 * \warning This module will be removed soon
29 #include <config.h>
31 #include <signal.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
36 #ifdef HAVE_TERMIOS_H
37 #include <termios.h>
38 #endif
39 #include <unistd.h>
41 #include "global.h"
42 #include "tty.h"
43 #include "color.h"
44 #include "mouse.h" /* Gpm_Event is required in key.h */
45 #include "key.h" /* define_sequence */
46 #include "main.h" /* extern: force_colors */
47 #include "win.h" /* do_exit_ca_mode */
48 #include "setup.h"
49 #include "background.h" /* we_are_background */
51 #ifdef HAVE_SLANG
53 /* Taken from S-Lang's slutty.c */
54 #ifdef ultrix /* Ultrix gets _POSIX_VDISABLE wrong! */
55 # define NULL_VALUE -1
56 #else
57 # ifdef _POSIX_VDISABLE
58 # define NULL_VALUE _POSIX_VDISABLE
59 # else
60 # define NULL_VALUE 255
61 # endif
62 #endif
64 #ifndef SA_RESTART
65 # define SA_RESTART 0
66 #endif
68 /* Various saved termios settings that we control here */
69 static struct termios boot_mode;
70 static struct termios new_mode;
72 /* Controls whether we should wait for input in getch */
73 static int no_slang_delay;
75 /* Forward declarations */
76 static void load_terminfo_keys (void);
78 #ifndef HAVE_SLANG_PRIVATE
79 /* Private interfaces have been stripped, so we cannot use them */
80 #define SLang_getkey2() SLang_getkey()
81 #define SLang_input_pending2(s) SLang_input_pending(s)
82 #else
83 /* Copied from ../slang/slgetkey.c, removed the DEC_8Bit_HACK. */
84 extern unsigned char SLang_Input_Buffer [];
85 #if SLANG_VERSION >= 10000
86 extern unsigned int _SLsys_getkey (void);
87 extern int _SLsys_input_pending (int);
88 #else
89 extern unsigned int SLsys_getkey (void);
90 extern int SLsys_input_pending (int);
91 #endif
93 static unsigned int SLang_getkey2 (void)
95 unsigned int imax;
96 unsigned int ch;
98 if (SLang_Input_Buffer_Len)
100 ch = (unsigned int) *SLang_Input_Buffer;
101 SLang_Input_Buffer_Len--;
102 imax = SLang_Input_Buffer_Len;
104 memmove ((char *) SLang_Input_Buffer,
105 (char *) (SLang_Input_Buffer + 1), imax);
106 return(ch);
108 #if SLANG_VERSION >= 10000
109 else return(_SLsys_getkey ());
110 #else
111 else return(SLsys_getkey());
112 #endif
115 static int SLang_input_pending2 (int tsecs)
117 int n, i;
118 unsigned char c;
120 if (SLang_Input_Buffer_Len) return (int) SLang_Input_Buffer_Len;
121 #if SLANG_VERSION >= 10000
122 n = _SLsys_input_pending (tsecs);
123 #else
124 n = SLsys_input_pending (tsecs);
125 #endif
126 if (n <= 0) return 0;
128 i = SLang_getkey2 ();
129 if (i == SLANG_GETKEY_ERROR)
130 return 0; /* don't put crippled error codes into the input buffer */
131 c = (unsigned char)i;
132 SLang_ungetkey_string (&c, 1);
134 return n;
136 #endif /* HAVE_SLANG_PRIVATE */
138 /* Only done the first time */
139 void
140 slang_init (void)
142 SLtt_get_terminfo ();
145 * If the terminal in not in terminfo but begins with a well-known
146 * string such as "linux" or "xterm" S-Lang will go on, but the
147 * terminal size and several other variables won't be initialized
148 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
149 * small, large and negative screen dimensions.
151 if ((COLS < 10) || (LINES < 5) ||
152 (SLang_Version < 10407 && (COLS > 255 || LINES > 255)) ||
153 (SLang_Version >= 10407 && (COLS > 512 || LINES > 512))) {
155 fprintf (stderr,
156 _("Screen size %dx%d is not supported.\n"
157 "Check the TERM environment variable.\n"),
158 COLS, LINES);
159 exit (1);
162 tcgetattr (fileno (stdin), &boot_mode);
163 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
164 SLang_init_tty (XCTRL('c'), 1, 0);
166 /* If SLang uses fileno(stderr) for terminal input MC will hang
167 if we call SLang_getkey between calls to open_error_pipe and
168 close_error_pipe, e.g. when we do a growing view of an gzipped
169 file. */
170 if (SLang_TT_Read_FD == fileno (stderr))
171 SLang_TT_Read_FD = fileno (stdin);
173 if (force_ugly_line_drawing)
174 SLtt_Has_Alt_Charset = 0;
175 if (tcgetattr (SLang_TT_Read_FD, &new_mode) == 0) {
176 #ifdef VDSUSP
177 new_mode.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */
178 #endif
179 #ifdef VLNEXT
180 new_mode.c_cc[VLNEXT] = NULL_VALUE; /* to ignore ^V */
181 #endif
182 tcsetattr (SLang_TT_Read_FD, TCSADRAIN, &new_mode);
184 slang_prog_mode ();
185 load_terminfo_keys ();
186 SLtt_Blink_Mode = 0;
189 void
190 slang_set_raw_mode (void)
192 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
195 /* Done each time we come back from done mode */
196 void
197 slang_prog_mode (void)
199 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
200 SLsmg_init_smg ();
201 SLsmg_touch_lines (0, LINES);
204 /* Called each time we want to shutdown slang screen manager */
205 void
206 slang_shell_mode (void)
208 tcsetattr (SLang_TT_Read_FD, TCSANOW, &boot_mode);
211 void
212 slang_shutdown (void)
214 char *op_cap;
216 slang_shell_mode ();
217 do_exit_ca_mode ();
218 SLang_reset_tty ();
220 /* Load the op capability to reset the colors to those that were
221 * active when the program was started up
223 op_cap = SLtt_tgetstr ("op");
224 if (op_cap){
225 fprintf (stdout, "%s", op_cap);
226 fflush (stdout);
230 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
231 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
232 consequence is that function keys don't work in MC sometimes.
233 Unfortunately I don't now the one and only escape sequence to turn off
234 softkeys (elm uses three different capabilities to turn on softkeys and two
235 capabilities to turn them off).
236 Among other things elm uses the pair we already use in slang_keypad. That's
237 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
238 something better the softkeys are programmed to their defaults from the
239 termcap/terminfo database.
240 The escape sequence to program the softkeys is taken from elm and it is
241 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this
242 sequence. -- Norbert
245 static void
246 slang_reset_softkeys (void)
248 int key;
249 char *send;
250 static const char display[] = " ";
251 char tmp[BUF_SMALL];
253 for (key = 1; key < 9; key++) {
254 g_snprintf (tmp, sizeof (tmp), "k%d", key);
255 send = (char *) SLtt_tgetstr (tmp);
256 if (send) {
257 g_snprintf (tmp, sizeof (tmp), "\033&f%dk%dd%dL%s%s", key,
258 (int) (sizeof (display) - 1), (int) strlen (send),
259 display, send);
260 SLtt_write_string (tmp);
265 /* keypad routines */
266 void
267 slang_keypad (int set)
269 char *keypad_string;
270 extern int reset_hp_softkeys;
272 keypad_string = (char *) SLtt_tgetstr (set ? "ks" : "ke");
273 if (keypad_string)
274 SLtt_write_string (keypad_string);
275 if (set && reset_hp_softkeys)
276 slang_reset_softkeys ();
279 void
280 set_slang_delay (int v)
282 no_slang_delay = v;
285 void
286 hline (int ch, int len)
288 int last_x, last_y;
290 last_x = SLsmg_get_column ();
291 last_y = SLsmg_get_row ();
293 if (ch == 0)
294 ch = ACS_HLINE;
296 if (ch == ACS_HLINE){
297 SLsmg_draw_hline (len);
298 } else {
299 while (len--)
300 addch (ch);
302 move (last_y, last_x);
305 void
306 vline (int character, int len)
308 if (!slow_terminal){
309 SLsmg_draw_vline (len);
310 } else {
311 int last_x, last_y, pos = 0;
313 last_x = SLsmg_get_column ();
314 last_y = SLsmg_get_row ();
316 while (len--){
317 move (last_y + pos++, last_x);
318 addch (' ');
320 move (last_x, last_y);
324 int has_colors (void)
326 const char *terminal = getenv ("TERM");
327 char *cts = color_terminal_string, *s;
328 size_t i;
330 if (force_colors)
331 SLtt_Use_Ansi_Colors = 1;
332 if (NULL != getenv ("COLORTERM"))
333 SLtt_Use_Ansi_Colors = 1;
335 /* We want to allow overwriding */
336 if (!disable_colors){
337 /* check color_terminal_string */
338 if (*cts)
340 while (*cts)
342 while (*cts == ' ' || *cts == '\t') cts++;
344 s = cts;
345 i = 0;
347 while (*cts && *cts != ',')
349 cts++;
350 i++;
352 if (i && i == strlen(terminal) && strncmp(s, terminal, i) == 0)
353 SLtt_Use_Ansi_Colors = 1;
355 if (*cts == ',') cts++;
360 /* Setup emulated colors */
361 if (SLtt_Use_Ansi_Colors){
362 if (use_colors){
363 mc_init_pair (A_REVERSE, "black", "white");
364 mc_init_pair (A_BOLD, "white", "black");
365 } else {
366 mc_init_pair (A_REVERSE, "black", "lightgray");
367 mc_init_pair (A_BOLD, "white", "black");
368 mc_init_pair (A_BOLD_REVERSE, "white", "lightgray");
370 } else {
371 SLtt_set_mono (A_BOLD, NULL, SLTT_BOLD_MASK);
372 SLtt_set_mono (A_REVERSE, NULL, SLTT_REV_MASK);
373 SLtt_set_mono (A_BOLD|A_REVERSE, NULL, SLTT_BOLD_MASK | SLTT_REV_MASK);
375 return SLtt_Use_Ansi_Colors;
378 void
379 attrset (int color)
381 if (!SLtt_Use_Ansi_Colors){
382 SLsmg_set_color (color);
383 return;
386 if (color & A_BOLD){
387 if (color == A_BOLD)
388 SLsmg_set_color (A_BOLD);
389 else
390 SLsmg_set_color ((color & (~A_BOLD)) + 8);
391 return;
394 if (color == A_REVERSE)
395 SLsmg_set_color (A_REVERSE);
396 else
397 SLsmg_set_color (color);
400 /* This table describes which capabilities we want and which values we
401 * assign to them.
403 static const struct {
404 int key_code;
405 const char *key_name;
406 } key_table [] = {
407 { KEY_F(0), "k0" },
408 { KEY_F(1), "k1" },
409 { KEY_F(2), "k2" },
410 { KEY_F(3), "k3" },
411 { KEY_F(4), "k4" },
412 { KEY_F(5), "k5" },
413 { KEY_F(6), "k6" },
414 { KEY_F(7), "k7" },
415 { KEY_F(8), "k8" },
416 { KEY_F(9), "k9" },
417 { KEY_F(10), "k;" },
418 { KEY_F(11), "F1" },
419 { KEY_F(12), "F2" },
420 { KEY_F(13), "F3" },
421 { KEY_F(14), "F4" },
422 { KEY_F(15), "F5" },
423 { KEY_F(16), "F6" },
424 { KEY_F(17), "F7" },
425 { KEY_F(18), "F8" },
426 { KEY_F(19), "F9" },
427 { KEY_F(20), "FA" },
428 { KEY_IC, "kI" },
429 { KEY_NPAGE, "kN" },
430 { KEY_PPAGE, "kP" },
431 { KEY_LEFT, "kl" },
432 { KEY_RIGHT, "kr" },
433 { KEY_UP, "ku" },
434 { KEY_DOWN, "kd" },
435 { KEY_DC, "kD" },
436 { KEY_BACKSPACE, "kb" },
437 { KEY_HOME, "kh" },
438 { KEY_END, "@7" },
439 { 0, 0}
442 static void
443 do_define_key (int code, const char *strcap)
445 char *seq;
447 seq = (char *) SLtt_tgetstr ((char*) strcap);
448 if (seq)
449 define_sequence (code, seq, MCKEY_NOACTION);
452 static void
453 load_terminfo_keys (void)
455 int i;
457 for (i = 0; key_table [i].key_code; i++)
458 do_define_key (key_table [i].key_code, key_table [i].key_name);
462 getch (void)
464 int c;
465 if (no_slang_delay)
466 if (SLang_input_pending2 (0) == 0)
467 return -1;
469 c = SLang_getkey2 ();
470 if (c == SLANG_GETKEY_ERROR) {
471 fprintf (stderr,
472 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
473 "Assuming EOF on stdin and exiting\n");
474 exit (1);
476 return c;
478 #endif /* HAVE_SLANG */
480 void
481 mc_refresh (void)
483 #ifdef WITH_BACKGROUND
484 if (!we_are_background)
485 #endif /* WITH_BACKGROUND */
486 refresh ();