small typo
[midnight-commander.git] / src / slint.c
blobe27827a3b5eff4f2ca8f4bb8cf60ae227bab1134
1 /* Slang interface to the Midnight Commander
2 This emulates some features of ncurses on top of slang
4 Copyright (C) 1995, 1996 The Free Software Foundation.
6 Author Miguel de Icaza
7 Norbert Warmuth
9 $Id$
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #include <config.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <termios.h>
29 #include <signal.h>
30 #include <string.h>
32 #include "global.h"
33 #include "tty.h"
34 #include "color.h"
35 #include "mouse.h" /* Gpm_Event is required in key.h */
36 #include "key.h" /* define_sequence */
37 #include "main.h" /* extern: force_colors */
38 #include "win.h" /* do_exit_ca_mode */
39 #include "setup.h"
41 #ifdef HAVE_SLANG
43 /* Taken from S-Lang's slutty.c */
44 #ifdef ultrix /* Ultrix gets _POSIX_VDISABLE wrong! */
45 # define NULL_VALUE -1
46 #else
47 # ifdef _POSIX_VDISABLE
48 # define NULL_VALUE _POSIX_VDISABLE
49 # else
50 # define NULL_VALUE 255
51 # endif
52 #endif
54 /* Taken from S-Lang's sldisply.c file */
55 #ifndef USE_TERMCAP
56 # define tgetstr(a,b) SLtt_tgetstr (a)
57 #else
58 extern char *tgetstr(char *, char **);
59 #endif
61 #ifndef SA_RESTART
62 # define SA_RESTART 0
63 #endif
65 /* Various saved termios settings that we control here */
66 static struct termios boot_mode;
67 static struct termios new_mode;
69 /* Set if we get an interrupt */
70 static int slinterrupt;
72 /* Controls whether we should wait for input in getch */
73 static int no_slang_delay;
75 /* {{{ Copied from ../slang/slgetkey.c, removed the DEC_8Bit_HACK, */
76 extern unsigned int SLang_Input_Buffer_Len;
77 extern unsigned char SLang_Input_Buffer [];
78 #if SLANG_VERSION >= 10000
79 extern unsigned int _SLsys_getkey (void);
80 extern int _SLsys_input_pending (int);
81 #else
82 extern unsigned int SLsys_getkey (void);
83 extern int SLsys_input_pending (int);
84 #endif
86 /* Forward declarations */
87 static void load_terminfo_keys (void);
89 static unsigned int SLang_getkey2 (void)
91 unsigned int imax;
92 unsigned int ch;
94 if (SLang_Input_Buffer_Len)
96 ch = (unsigned int) *SLang_Input_Buffer;
97 SLang_Input_Buffer_Len--;
98 imax = SLang_Input_Buffer_Len;
100 memcpy ((char *) SLang_Input_Buffer,
101 (char *) (SLang_Input_Buffer + 1), imax);
102 return(ch);
104 #if SLANG_VERSION >= 10000
105 else return(_SLsys_getkey ());
106 #else
107 else return(SLsys_getkey());
108 #endif
111 static int SLang_input_pending2 (int tsecs)
113 int n, i;
114 unsigned char c;
116 if (SLang_Input_Buffer_Len) return (int) SLang_Input_Buffer_Len;
117 #if SLANG_VERSION >= 10000
118 n = _SLsys_input_pending (tsecs);
119 #else
120 n = SLsys_input_pending (tsecs);
121 #endif
122 if (n <= 0) return 0;
124 i = SLang_getkey2 ();
125 if (i == SLANG_GETKEY_ERROR)
126 return 0; /* don't put crippled error codes into the input buffer */
127 c = (unsigned char)i;
128 SLang_ungetkey_string (&c, 1);
130 return n;
132 /* }}} */
134 static void
135 slang_intr (int signo)
137 slinterrupt = 1;
140 void
141 enable_interrupt_key(void)
143 struct sigaction act;
145 act.sa_handler = slang_intr;
146 sigemptyset (&act.sa_mask);
147 act.sa_flags = 0;
148 sigaction (SIGINT, &act, NULL);
149 slinterrupt = 0;
152 void
153 disable_interrupt_key(void)
155 struct sigaction act;
157 act.sa_handler = SIG_IGN;
158 act.sa_flags = 0;
159 sigemptyset (&act.sa_mask);
160 sigaction (SIGINT, &act, NULL);
164 got_interrupt (void)
166 int t;
168 t = slinterrupt;
169 slinterrupt = 0;
170 return t;
173 /* Only done the first time */
174 void
175 slang_init (void)
177 extern int SLtt_Blink_Mode;
178 extern int SLtt_Has_Alt_Charset;
179 extern int force_ugly_line_drawing;
180 struct sigaction act, oact;
182 SLtt_get_terminfo ();
185 * If the terminal in not in terminfo but begins with a well-known
186 * string such as "linux" or "xterm" S-Lang will go on, but the
187 * terminal size and several other variables won't be initialized
188 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
189 * small, large and negative screen dimensions.
191 if ((COLS < 10) || (LINES < 5) || (COLS > 1024) || (LINES > 1024)) {
192 fprintf (stderr,
193 _("Screen size %dx%d is not supported.\n"
194 "Check the TERM environment variable.\n"),
195 COLS, LINES);
196 exit (1);
199 tcgetattr (fileno (stdin), &boot_mode);
200 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
201 SLang_init_tty (XCTRL('c'), 1, 0);
203 /* If SLang uses fileno(stderr) for terminal input MC will hang
204 if we call SLang_getkey between calls to open_error_pipe and
205 close_error_pipe, e.g. when we do a growing view of an gzipped
206 file. */
207 if (SLang_TT_Read_FD == fileno (stderr))
208 SLang_TT_Read_FD = fileno (stdin);
210 if (force_ugly_line_drawing)
211 SLtt_Has_Alt_Charset = 0;
212 if (tcgetattr (SLang_TT_Read_FD, &new_mode) == 0) {
213 #ifdef VDSUSP
214 new_mode.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */
215 #endif
216 #ifdef VLNEXT
217 new_mode.c_cc[VLNEXT] = NULL_VALUE; /* to ignore ^V */
218 #endif
219 tcsetattr (SLang_TT_Read_FD, TCSADRAIN, &new_mode);
221 slang_prog_mode ();
222 load_terminfo_keys ();
223 act.sa_handler = slang_intr;
224 sigemptyset (&act.sa_mask);
225 act.sa_flags = SA_RESTART;
226 sigaction (SIGINT, &act, &oact);
227 SLtt_Blink_Mode = 0;
230 void
231 slang_set_raw_mode (void)
233 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
236 /* Done each time we come back from done mode */
237 void
238 slang_prog_mode (void)
240 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
241 SLsmg_init_smg ();
242 SLsmg_touch_lines (0, LINES);
245 /* Called each time we want to shutdown slang screen manager */
246 void
247 slang_shell_mode (void)
249 tcsetattr (SLang_TT_Read_FD, TCSANOW, &boot_mode);
252 void
253 slang_shutdown (void)
255 char *op_cap;
257 slang_shell_mode ();
258 do_exit_ca_mode ();
259 SLang_reset_tty ();
260 dealloc_color_pairs ();
262 /* Load the op capability to reset the colors to those that were
263 * active when the program was started up
265 op_cap = SLtt_tgetstr ("op");
266 if (op_cap){
267 fprintf (stdout, "%s", op_cap);
268 fflush (stdout);
272 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
273 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
274 consequence is that function keys don't work in MC sometimes.
275 Unfortunately I don't now the one and only escape sequence to turn off
276 softkeys (elm uses three different capabilities to turn on softkeys and two
277 capabilities to turn them off).
278 Among other things elm uses the pair we already use in slang_keypad. That's
279 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
280 something better the softkeys are programmed to their defaults from the
281 termcap/terminfo database.
282 The escape sequence to program the softkeys is taken from elm and it is
283 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this
284 sequence. -- Norbert
287 static void
288 slang_reset_softkeys (void)
290 int key;
291 char *send;
292 static const char display [] = " ";
293 char tmp[BUF_SMALL];
295 for ( key = 1; key < 9; key++ ) {
296 g_snprintf (tmp, sizeof (tmp), "k%d", key);
297 send = (char *) SLtt_tgetstr (tmp);
298 if (send) {
299 g_snprintf(tmp, sizeof (tmp), "\033&f%dk%dd%dL%s%s", key,
300 sizeof (display) - 1, strlen(send), display, send);
301 SLtt_write_string (tmp);
306 /* keypad routines */
307 void
308 slang_keypad (int set)
310 char *keypad_string;
311 extern int reset_hp_softkeys;
313 keypad_string = (char *) SLtt_tgetstr (set ? "ks" : "ke");
314 if (keypad_string)
315 SLtt_write_string (keypad_string);
316 if (set && reset_hp_softkeys)
317 slang_reset_softkeys ();
320 void
321 set_slang_delay (int v)
323 no_slang_delay = v;
326 void
327 hline (int ch, int len)
329 int last_x, last_y;
331 last_x = SLsmg_get_column ();
332 last_y = SLsmg_get_row ();
334 if (ch == 0)
335 ch = ACS_HLINE;
337 if (ch == ACS_HLINE){
338 SLsmg_draw_hline (len);
339 } else {
340 while (len--)
341 addch (ch);
343 move (last_y, last_x);
346 void
347 vline (int character, int len)
349 if (!slow_terminal){
350 SLsmg_draw_vline (len);
351 } else {
352 int last_x, last_y, pos = 0;
354 last_x = SLsmg_get_column ();
355 last_y = SLsmg_get_row ();
357 while (len--){
358 move (last_y + pos++, last_x);
359 addch (' ');
361 move (last_x, last_y);
365 int has_colors (void)
367 char *terminal = getenv ("TERM");
368 char *cts = color_terminal_string, *s;
369 int i;
371 if (force_colors)
372 SLtt_Use_Ansi_Colors = 1;
373 if (NULL != getenv ("COLORTERM"))
374 SLtt_Use_Ansi_Colors = 1;
376 /* We want to allow overwriding */
377 if (!disable_colors){
378 /* check color_terminal_string */
379 if (*cts)
381 while (*cts)
383 while (*cts == ' ' || *cts == '\t') cts++;
385 s = cts;
386 i = 0;
388 while (*cts && *cts != ',')
390 cts++;
391 i++;
393 if (i && i == strlen(terminal) && strncmp(s, terminal, i) == 0)
394 SLtt_Use_Ansi_Colors = 1;
396 if (*cts == ',') cts++;
401 /* Setup emulated colors */
402 if (SLtt_Use_Ansi_Colors){
403 if (use_colors){
404 mc_init_pair (A_REVERSE, "black", "white");
405 mc_init_pair (A_BOLD, "white", "black");
406 } else {
407 mc_init_pair (A_REVERSE, "black", "lightgray");
408 mc_init_pair (A_BOLD, "white", "black");
409 mc_init_pair (A_BOLD_REVERSE, "white", "lightgray");
411 } else {
412 SLtt_set_mono (A_BOLD, NULL, SLTT_BOLD_MASK);
413 SLtt_set_mono (A_REVERSE, NULL, SLTT_REV_MASK);
414 SLtt_set_mono (A_BOLD|A_REVERSE, NULL, SLTT_BOLD_MASK | SLTT_REV_MASK);
416 return SLtt_Use_Ansi_Colors;
419 void
420 attrset (int color)
422 if (!SLtt_Use_Ansi_Colors){
423 SLsmg_set_color (color);
424 return;
427 if (color & A_BOLD){
428 if (color == A_BOLD)
429 SLsmg_set_color (A_BOLD);
430 else
431 SLsmg_set_color ((color & (~A_BOLD)) + 8);
432 return;
435 if (color == A_REVERSE)
436 SLsmg_set_color (A_REVERSE);
437 else
438 SLsmg_set_color (color);
441 /* This table describes which capabilities we want and which values we
442 * assign to them.
444 static const struct {
445 int key_code;
446 char *key_name;
447 } key_table [] = {
448 { KEY_F(0), "k0" },
449 { KEY_F(1), "k1" },
450 { KEY_F(2), "k2" },
451 { KEY_F(3), "k3" },
452 { KEY_F(4), "k4" },
453 { KEY_F(5), "k5" },
454 { KEY_F(6), "k6" },
455 { KEY_F(7), "k7" },
456 { KEY_F(8), "k8" },
457 { KEY_F(9), "k9" },
458 { KEY_F(10), "k;" },
459 { KEY_F(11), "F1" },
460 { KEY_F(12), "F2" },
461 { KEY_F(13), "F3" },
462 { KEY_F(14), "F4" },
463 { KEY_F(15), "F5" },
464 { KEY_F(16), "F6" },
465 { KEY_F(17), "F7" },
466 { KEY_F(18), "F8" },
467 { KEY_F(19), "F9" },
468 { KEY_F(20), "FA" },
469 { KEY_IC, "kI" },
470 { KEY_NPAGE, "kN" },
471 { KEY_PPAGE, "kP" },
472 { KEY_LEFT, "kl" },
473 { KEY_RIGHT, "kr" },
474 { KEY_UP, "ku" },
475 { KEY_DOWN, "kd" },
476 { KEY_DC, "kD" },
477 { KEY_BACKSPACE, "kb" },
478 { KEY_HOME, "kh" },
479 { KEY_END, "@7" },
480 { 0, 0}
483 static void
484 do_define_key (int code, char *strcap)
486 char *seq;
488 seq = (char *) SLtt_tgetstr (strcap);
489 if (seq)
490 define_sequence (code, seq, MCKEY_NOACTION);
493 static void
494 load_terminfo_keys (void)
496 int i;
498 for (i = 0; key_table [i].key_code; i++)
499 do_define_key (key_table [i].key_code, key_table [i].key_name);
502 int getch (void)
504 int c;
505 if (no_slang_delay)
506 if (SLang_input_pending2 (0) == 0)
507 return -1;
509 c = SLang_getkey2 ();
510 if (c == SLANG_GETKEY_ERROR) {
511 fprintf (stderr, "SLang_getkey returned SLANG_GETKEY_ERROR\n"
512 "Assuming EOF on stdin and exiting\n");
513 quiet_quit_cmd ();
515 return (c);
518 #else
520 /* Non slang builds do not understand got_interrupt */
521 int got_interrupt (void)
523 return 0;
525 #endif /* HAVE_SLANG */
527 void
528 mc_refresh (void)
530 if (!we_are_background)
531 refresh ();