added a new parameter for completion flags to input_new
[midnight-commander.git] / src / slint.c
blobc30fac1b1cdf5a174b6d2208fbc8a542b6f019e2
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 /* Taken from S-Lang's sldisply.c file */
60 #ifndef USE_TERMCAP
61 # define tgetstr(a,b) SLtt_tgetstr (a)
62 #else
63 extern char *tgetstr(char *, char **);
64 #endif
66 #ifndef SA_RESTART
67 # define SA_RESTART 0
68 #endif
70 /* Various saved termios settings that we control here */
71 static struct termios boot_mode;
72 static struct termios new_mode;
74 /* Controls whether we should wait for input in getch */
75 static int no_slang_delay;
77 /* Forward declarations */
78 static void load_terminfo_keys (void);
80 #ifndef HAVE_SLANG_PRIVATE
81 /* Private interfaces have been stripped, so we cannot use them */
82 #define SLang_getkey2() SLang_getkey()
83 #define SLang_input_pending2(s) SLang_input_pending(s)
84 #else
85 /* Copied from ../slang/slgetkey.c, removed the DEC_8Bit_HACK. */
86 extern unsigned char SLang_Input_Buffer [];
87 #if SLANG_VERSION >= 10000
88 extern unsigned int _SLsys_getkey (void);
89 extern int _SLsys_input_pending (int);
90 #else
91 extern unsigned int SLsys_getkey (void);
92 extern int SLsys_input_pending (int);
93 #endif
95 static unsigned int SLang_getkey2 (void)
97 unsigned int imax;
98 unsigned int ch;
100 if (SLang_Input_Buffer_Len)
102 ch = (unsigned int) *SLang_Input_Buffer;
103 SLang_Input_Buffer_Len--;
104 imax = SLang_Input_Buffer_Len;
106 memmove ((char *) SLang_Input_Buffer,
107 (char *) (SLang_Input_Buffer + 1), imax);
108 return(ch);
110 #if SLANG_VERSION >= 10000
111 else return(_SLsys_getkey ());
112 #else
113 else return(SLsys_getkey());
114 #endif
117 static int SLang_input_pending2 (int tsecs)
119 int n, i;
120 unsigned char c;
122 if (SLang_Input_Buffer_Len) return (int) SLang_Input_Buffer_Len;
123 #if SLANG_VERSION >= 10000
124 n = _SLsys_input_pending (tsecs);
125 #else
126 n = SLsys_input_pending (tsecs);
127 #endif
128 if (n <= 0) return 0;
130 i = SLang_getkey2 ();
131 if (i == SLANG_GETKEY_ERROR)
132 return 0; /* don't put crippled error codes into the input buffer */
133 c = (unsigned char)i;
134 SLang_ungetkey_string (&c, 1);
136 return n;
138 #endif /* HAVE_SLANG_PRIVATE */
140 /* Only done the first time */
141 void
142 slang_init (void)
144 SLtt_get_terminfo ();
147 * If the terminal in not in terminfo but begins with a well-known
148 * string such as "linux" or "xterm" S-Lang will go on, but the
149 * terminal size and several other variables won't be initialized
150 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
151 * small, large and negative screen dimensions.
153 if ((COLS < 10) || (LINES < 5) ||
154 (SLang_Version < 10407 && (COLS > 255 || LINES > 255)) ||
155 (SLang_Version >= 10407 && (COLS > 512 || LINES > 512))) {
157 fprintf (stderr,
158 _("Screen size %dx%d is not supported.\n"
159 "Check the TERM environment variable.\n"),
160 COLS, LINES);
161 exit (1);
164 tcgetattr (fileno (stdin), &boot_mode);
165 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
166 SLang_init_tty (XCTRL('c'), 1, 0);
168 /* If SLang uses fileno(stderr) for terminal input MC will hang
169 if we call SLang_getkey between calls to open_error_pipe and
170 close_error_pipe, e.g. when we do a growing view of an gzipped
171 file. */
172 if (SLang_TT_Read_FD == fileno (stderr))
173 SLang_TT_Read_FD = fileno (stdin);
175 if (force_ugly_line_drawing)
176 SLtt_Has_Alt_Charset = 0;
177 if (tcgetattr (SLang_TT_Read_FD, &new_mode) == 0) {
178 #ifdef VDSUSP
179 new_mode.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */
180 #endif
181 #ifdef VLNEXT
182 new_mode.c_cc[VLNEXT] = NULL_VALUE; /* to ignore ^V */
183 #endif
184 tcsetattr (SLang_TT_Read_FD, TCSADRAIN, &new_mode);
186 slang_prog_mode ();
187 load_terminfo_keys ();
188 SLtt_Blink_Mode = 0;
191 void
192 slang_set_raw_mode (void)
194 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
197 /* Done each time we come back from done mode */
198 void
199 slang_prog_mode (void)
201 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
202 SLsmg_init_smg ();
203 SLsmg_touch_lines (0, LINES);
206 /* Called each time we want to shutdown slang screen manager */
207 void
208 slang_shell_mode (void)
210 tcsetattr (SLang_TT_Read_FD, TCSANOW, &boot_mode);
213 void
214 slang_shutdown (void)
216 char *op_cap;
218 slang_shell_mode ();
219 do_exit_ca_mode ();
220 SLang_reset_tty ();
222 /* Load the op capability to reset the colors to those that were
223 * active when the program was started up
225 op_cap = SLtt_tgetstr ("op");
226 if (op_cap){
227 fprintf (stdout, "%s", op_cap);
228 fflush (stdout);
232 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
233 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
234 consequence is that function keys don't work in MC sometimes.
235 Unfortunately I don't now the one and only escape sequence to turn off
236 softkeys (elm uses three different capabilities to turn on softkeys and two
237 capabilities to turn them off).
238 Among other things elm uses the pair we already use in slang_keypad. That's
239 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
240 something better the softkeys are programmed to their defaults from the
241 termcap/terminfo database.
242 The escape sequence to program the softkeys is taken from elm and it is
243 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this
244 sequence. -- Norbert
247 static void
248 slang_reset_softkeys (void)
250 int key;
251 char *send;
252 static const char display[] = " ";
253 char tmp[BUF_SMALL];
255 for (key = 1; key < 9; key++) {
256 g_snprintf (tmp, sizeof (tmp), "k%d", key);
257 send = (char *) SLtt_tgetstr (tmp);
258 if (send) {
259 g_snprintf (tmp, sizeof (tmp), "\033&f%dk%dd%dL%s%s", key,
260 (int) (sizeof (display) - 1), (int) strlen (send),
261 display, send);
262 SLtt_write_string (tmp);
267 /* keypad routines */
268 void
269 slang_keypad (int set)
271 char *keypad_string;
272 extern int reset_hp_softkeys;
274 keypad_string = (char *) SLtt_tgetstr (set ? "ks" : "ke");
275 if (keypad_string)
276 SLtt_write_string (keypad_string);
277 if (set && reset_hp_softkeys)
278 slang_reset_softkeys ();
281 void
282 set_slang_delay (int v)
284 no_slang_delay = v;
287 void
288 hline (int ch, int len)
290 int last_x, last_y;
292 last_x = SLsmg_get_column ();
293 last_y = SLsmg_get_row ();
295 if (ch == 0)
296 ch = ACS_HLINE;
298 if (ch == ACS_HLINE){
299 SLsmg_draw_hline (len);
300 } else {
301 while (len--)
302 addch (ch);
304 move (last_y, last_x);
307 void
308 vline (int character, int len)
310 if (!slow_terminal){
311 SLsmg_draw_vline (len);
312 } else {
313 int last_x, last_y, pos = 0;
315 last_x = SLsmg_get_column ();
316 last_y = SLsmg_get_row ();
318 while (len--){
319 move (last_y + pos++, last_x);
320 addch (' ');
322 move (last_x, last_y);
326 int has_colors (void)
328 const char *terminal = getenv ("TERM");
329 char *cts = color_terminal_string, *s;
330 size_t i;
332 if (force_colors)
333 SLtt_Use_Ansi_Colors = 1;
334 if (NULL != getenv ("COLORTERM"))
335 SLtt_Use_Ansi_Colors = 1;
337 /* We want to allow overwriding */
338 if (!disable_colors){
339 /* check color_terminal_string */
340 if (*cts)
342 while (*cts)
344 while (*cts == ' ' || *cts == '\t') cts++;
346 s = cts;
347 i = 0;
349 while (*cts && *cts != ',')
351 cts++;
352 i++;
354 if (i && i == strlen(terminal) && strncmp(s, terminal, i) == 0)
355 SLtt_Use_Ansi_Colors = 1;
357 if (*cts == ',') cts++;
362 /* Setup emulated colors */
363 if (SLtt_Use_Ansi_Colors){
364 if (use_colors){
365 mc_init_pair (A_REVERSE, "black", "white");
366 mc_init_pair (A_BOLD, "white", "black");
367 } else {
368 mc_init_pair (A_REVERSE, "black", "lightgray");
369 mc_init_pair (A_BOLD, "white", "black");
370 mc_init_pair (A_BOLD_REVERSE, "white", "lightgray");
372 } else {
373 SLtt_set_mono (A_BOLD, NULL, SLTT_BOLD_MASK);
374 SLtt_set_mono (A_REVERSE, NULL, SLTT_REV_MASK);
375 SLtt_set_mono (A_BOLD|A_REVERSE, NULL, SLTT_BOLD_MASK | SLTT_REV_MASK);
377 return SLtt_Use_Ansi_Colors;
380 void
381 attrset (int color)
383 if (!SLtt_Use_Ansi_Colors){
384 SLsmg_set_color (color);
385 return;
388 if (color & A_BOLD){
389 if (color == A_BOLD)
390 SLsmg_set_color (A_BOLD);
391 else
392 SLsmg_set_color ((color & (~A_BOLD)) + 8);
393 return;
396 if (color == A_REVERSE)
397 SLsmg_set_color (A_REVERSE);
398 else
399 SLsmg_set_color (color);
402 /* This table describes which capabilities we want and which values we
403 * assign to them.
405 static const struct {
406 int key_code;
407 const char *key_name;
408 } key_table [] = {
409 { KEY_F(0), "k0" },
410 { KEY_F(1), "k1" },
411 { KEY_F(2), "k2" },
412 { KEY_F(3), "k3" },
413 { KEY_F(4), "k4" },
414 { KEY_F(5), "k5" },
415 { KEY_F(6), "k6" },
416 { KEY_F(7), "k7" },
417 { KEY_F(8), "k8" },
418 { KEY_F(9), "k9" },
419 { KEY_F(10), "k;" },
420 { KEY_F(11), "F1" },
421 { KEY_F(12), "F2" },
422 { KEY_F(13), "F3" },
423 { KEY_F(14), "F4" },
424 { KEY_F(15), "F5" },
425 { KEY_F(16), "F6" },
426 { KEY_F(17), "F7" },
427 { KEY_F(18), "F8" },
428 { KEY_F(19), "F9" },
429 { KEY_F(20), "FA" },
430 { KEY_IC, "kI" },
431 { KEY_NPAGE, "kN" },
432 { KEY_PPAGE, "kP" },
433 { KEY_LEFT, "kl" },
434 { KEY_RIGHT, "kr" },
435 { KEY_UP, "ku" },
436 { KEY_DOWN, "kd" },
437 { KEY_DC, "kD" },
438 { KEY_BACKSPACE, "kb" },
439 { KEY_HOME, "kh" },
440 { KEY_END, "@7" },
441 { 0, 0}
444 static void
445 do_define_key (int code, const char *strcap)
447 char *seq;
449 seq = (char *) SLtt_tgetstr ((char*) strcap);
450 if (seq)
451 define_sequence (code, seq, MCKEY_NOACTION);
454 static void
455 load_terminfo_keys (void)
457 int i;
459 for (i = 0; key_table [i].key_code; i++)
460 do_define_key (key_table [i].key_code, key_table [i].key_name);
464 getch (void)
466 int c;
467 if (no_slang_delay)
468 if (SLang_input_pending2 (0) == 0)
469 return -1;
471 c = SLang_getkey2 ();
472 if (c == SLANG_GETKEY_ERROR) {
473 fprintf (stderr,
474 "SLang_getkey returned SLANG_GETKEY_ERROR\n"
475 "Assuming EOF on stdin and exiting\n");
476 exit (1);
478 return c;
480 #endif /* HAVE_SLANG */
482 void
483 mc_refresh (void)
485 #ifdef WITH_BACKGROUND
486 if (!we_are_background)
487 #endif /* WITH_BACKGROUND */
488 refresh ();