updated the .TP cleanup for coherency in the key description pages.
[midnight-commander.git] / src / slint.c
blobb077f00bb71a5d6ab7b9b9656bb1c630c3f5ac0a
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 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <termios.h>
27 #include <signal.h>
28 #include <string.h>
30 #include "global.h"
31 #include "tty.h"
32 #include "color.h"
33 #include "mouse.h" /* Gpm_Event is required in key.h */
34 #include "key.h" /* define_sequence */
35 #include "main.h" /* extern: force_colors */
36 #include "win.h" /* do_exit_ca_mode */
37 #include "setup.h"
39 #ifdef HAVE_SLANG
41 /* Taken from S-Lang's slutty.c */
42 #ifdef ultrix /* Ultrix gets _POSIX_VDISABLE wrong! */
43 # define NULL_VALUE -1
44 #else
45 # ifdef _POSIX_VDISABLE
46 # define NULL_VALUE _POSIX_VDISABLE
47 # else
48 # define NULL_VALUE 255
49 # endif
50 #endif
52 /* Taken from S-Lang's sldisply.c file */
53 #ifndef USE_TERMCAP
54 # define tgetstr(a,b) SLtt_tgetstr (a)
55 #else
56 extern char *tgetstr(char *, char **);
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 /* Set if we get an interrupt */
68 static int slinterrupt;
70 /* Controls whether we should wait for input in getch */
71 static int no_slang_delay;
73 /* {{{ Copied from ../slang/slgetkey.c, removed the DEC_8Bit_HACK, */
74 extern unsigned int SLang_Input_Buffer_Len;
75 extern unsigned char SLang_Input_Buffer [];
76 #if SLANG_VERSION >= 10000
77 extern unsigned int _SLsys_getkey (void);
78 extern int _SLsys_input_pending (int);
79 #else
80 extern unsigned int SLsys_getkey (void);
81 extern int SLsys_input_pending (int);
82 #endif
84 /* Forward declarations */
85 static void load_terminfo_keys (void);
87 static unsigned int SLang_getkey2 (void)
89 unsigned int imax;
90 unsigned int ch;
92 if (SLang_Input_Buffer_Len)
94 ch = (unsigned int) *SLang_Input_Buffer;
95 SLang_Input_Buffer_Len--;
96 imax = SLang_Input_Buffer_Len;
98 memcpy ((char *) SLang_Input_Buffer,
99 (char *) (SLang_Input_Buffer + 1), imax);
100 return(ch);
102 #if SLANG_VERSION >= 10000
103 else return(_SLsys_getkey ());
104 #else
105 else return(SLsys_getkey());
106 #endif
109 static int SLang_input_pending2 (int tsecs)
111 int n, i;
112 unsigned char c;
114 if (SLang_Input_Buffer_Len) return (int) SLang_Input_Buffer_Len;
115 #if SLANG_VERSION >= 10000
116 n = _SLsys_input_pending (tsecs);
117 #else
118 n = SLsys_input_pending (tsecs);
119 #endif
120 if (n <= 0) return 0;
122 i = SLang_getkey2 ();
123 if (i == SLANG_GETKEY_ERROR)
124 return 0; /* don't put crippled error codes into the input buffer */
125 c = (unsigned char)i;
126 SLang_ungetkey_string (&c, 1);
128 return n;
130 /* }}} */
132 static void
133 slang_intr (int signo)
135 slinterrupt = 1;
138 void
139 enable_interrupt_key(void)
141 struct sigaction act;
143 act.sa_handler = slang_intr;
144 sigemptyset (&act.sa_mask);
145 act.sa_flags = 0;
146 sigaction (SIGINT, &act, NULL);
147 slinterrupt = 0;
150 void
151 disable_interrupt_key(void)
153 struct sigaction act;
155 act.sa_handler = SIG_IGN;
156 act.sa_flags = 0;
157 sigemptyset (&act.sa_mask);
158 sigaction (SIGINT, &act, NULL);
162 got_interrupt (void)
164 int t;
166 t = slinterrupt;
167 slinterrupt = 0;
168 return t;
171 /* Only done the first time */
172 void
173 slang_init (void)
175 extern int SLtt_Blink_Mode;
176 extern int SLtt_Has_Alt_Charset;
177 extern int force_ugly_line_drawing;
178 struct sigaction act, oact;
180 SLtt_get_terminfo ();
183 * If the terminal in not in terminfo but begins with a well-known
184 * string such as "linux" or "xterm" S-Lang will go on, but the
185 * terminal size and several other variables won't be initialized
186 * (as of S-Lang 1.4.4). Detect it and abort. Also detect extremely
187 * small, large and negative screen dimensions.
189 if ((COLS < 10) || (LINES < 5) || (COLS > 1024) || (LINES > 1024)) {
190 fprintf (stderr,
191 _("Screen size %dx%d is not supported.\n"
192 "Check the TERM environment variable.\n"),
193 COLS, LINES);
194 exit (1);
197 tcgetattr (fileno (stdin), &boot_mode);
198 /* 255 = ignore abort char; XCTRL('g') for abort char = ^g */
199 SLang_init_tty (XCTRL('c'), 1, 0);
201 /* If SLang uses fileno(stderr) for terminal input MC will hang
202 if we call SLang_getkey between calls to open_error_pipe and
203 close_error_pipe, e.g. when we do a growing view of an gzipped
204 file. */
205 if (SLang_TT_Read_FD == fileno (stderr))
206 SLang_TT_Read_FD = fileno (stdin);
208 if (force_ugly_line_drawing)
209 SLtt_Has_Alt_Charset = 0;
210 if (tcgetattr (SLang_TT_Read_FD, &new_mode) == 0) {
211 #ifdef VDSUSP
212 new_mode.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */
213 #endif
214 #ifdef VLNEXT
215 new_mode.c_cc[VLNEXT] = NULL_VALUE; /* to ignore ^V */
216 #endif
217 tcsetattr (SLang_TT_Read_FD, TCSADRAIN, &new_mode);
219 slang_prog_mode ();
220 load_terminfo_keys ();
221 act.sa_handler = slang_intr;
222 sigemptyset (&act.sa_mask);
223 act.sa_flags = SA_RESTART;
224 sigaction (SIGINT, &act, &oact);
225 SLtt_Blink_Mode = 0;
228 void
229 slang_set_raw_mode (void)
231 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
234 /* Done each time we come back from done mode */
235 void
236 slang_prog_mode (void)
238 tcsetattr (SLang_TT_Read_FD, TCSANOW, &new_mode);
239 SLsmg_init_smg ();
240 SLsmg_touch_lines (0, LINES);
243 /* Called each time we want to shutdown slang screen manager */
244 void
245 slang_shell_mode (void)
247 tcsetattr (SLang_TT_Read_FD, TCSANOW, &boot_mode);
250 void
251 slang_shutdown (void)
253 char *op_cap;
255 slang_shell_mode ();
256 do_exit_ca_mode ();
257 SLang_reset_tty ();
258 dealloc_color_pairs ();
260 /* Load the op capability to reset the colors to those that were
261 * active when the program was started up
263 op_cap = SLtt_tgetstr ("op");
264 if (op_cap){
265 fprintf (stdout, "%s", op_cap);
266 fflush (stdout);
270 /* HP Terminals have capabilities (pfkey, pfloc, pfx) to program function keys.
271 elm 2.4pl15 invoked with the -K option utilizes these softkeys and the
272 consequence is that function keys don't work in MC sometimes.
273 Unfortunately I don't now the one and only escape sequence to turn off
274 softkeys (elm uses three different capabilities to turn on softkeys and two
275 capabilities to turn them off).
276 Among other things elm uses the pair we already use in slang_keypad. That's
277 the reason why I call slang_reset_softkeys from slang_keypad. In lack of
278 something better the softkeys are programmed to their defaults from the
279 termcap/terminfo database.
280 The escape sequence to program the softkeys is taken from elm and it is
281 hardcoded because neither slang nor ncurses 4.1 know how to 'printf' this
282 sequence. -- Norbert
285 static void
286 slang_reset_softkeys (void)
288 int key;
289 char *send;
290 static const char display [] = " ";
291 char tmp[BUF_SMALL];
293 for ( key = 1; key < 9; key++ ) {
294 g_snprintf (tmp, sizeof (tmp), "k%d", key);
295 send = (char *) SLtt_tgetstr (tmp);
296 if (send) {
297 g_snprintf(tmp, sizeof (tmp), "\033&f%dk%dd%dL%s%s", key,
298 sizeof (display) - 1, strlen(send), display, send);
299 SLtt_write_string (tmp);
304 /* keypad routines */
305 void
306 slang_keypad (int set)
308 char *keypad_string;
309 extern int reset_hp_softkeys;
311 keypad_string = (char *) SLtt_tgetstr (set ? "ks" : "ke");
312 if (keypad_string)
313 SLtt_write_string (keypad_string);
314 if (set && reset_hp_softkeys)
315 slang_reset_softkeys ();
318 void
319 set_slang_delay (int v)
321 no_slang_delay = v;
324 void
325 hline (int ch, int len)
327 int last_x, last_y;
329 last_x = SLsmg_get_column ();
330 last_y = SLsmg_get_row ();
332 if (ch == 0)
333 ch = ACS_HLINE;
335 if (ch == ACS_HLINE){
336 SLsmg_draw_hline (len);
337 } else {
338 while (len--)
339 addch (ch);
341 move (last_y, last_x);
344 void
345 vline (int character, int len)
347 if (!slow_terminal){
348 SLsmg_draw_vline (len);
349 } else {
350 int last_x, last_y, pos = 0;
352 last_x = SLsmg_get_column ();
353 last_y = SLsmg_get_row ();
355 while (len--){
356 move (last_y + pos++, last_x);
357 addch (' ');
359 move (last_x, last_y);
363 int has_colors (void)
365 char *terminal = getenv ("TERM");
366 char *cts = color_terminal_string, *s;
367 int i;
369 if (force_colors)
370 SLtt_Use_Ansi_Colors = 1;
371 if (NULL != getenv ("COLORTERM"))
372 SLtt_Use_Ansi_Colors = 1;
374 /* We want to allow overwriding */
375 if (!disable_colors){
376 /* check color_terminal_string */
377 if (*cts)
379 while (*cts)
381 while (*cts == ' ' || *cts == '\t') cts++;
383 s = cts;
384 i = 0;
386 while (*cts && *cts != ',')
388 cts++;
389 i++;
391 if (i && i == strlen(terminal) && strncmp(s, terminal, i) == 0)
392 SLtt_Use_Ansi_Colors = 1;
394 if (*cts == ',') cts++;
399 /* Setup emulated colors */
400 if (SLtt_Use_Ansi_Colors){
401 if (use_colors){
402 mc_init_pair (A_REVERSE, "black", "white");
403 mc_init_pair (A_BOLD, "white", "black");
404 } else {
405 mc_init_pair (A_REVERSE, "black", "lightgray");
406 mc_init_pair (A_BOLD, "white", "black");
407 mc_init_pair (A_BOLD_REVERSE, "white", "lightgray");
409 } else {
410 SLtt_set_mono (A_BOLD, NULL, SLTT_BOLD_MASK);
411 SLtt_set_mono (A_REVERSE, NULL, SLTT_REV_MASK);
412 SLtt_set_mono (A_BOLD|A_REVERSE, NULL, SLTT_BOLD_MASK | SLTT_REV_MASK);
414 return SLtt_Use_Ansi_Colors;
417 void
418 attrset (int color)
420 if (!SLtt_Use_Ansi_Colors){
421 SLsmg_set_color (color);
422 return;
425 if (color & A_BOLD){
426 if (color == A_BOLD)
427 SLsmg_set_color (A_BOLD);
428 else
429 SLsmg_set_color ((color & (~A_BOLD)) + 8);
430 return;
433 if (color == A_REVERSE)
434 SLsmg_set_color (A_REVERSE);
435 else
436 SLsmg_set_color (color);
439 /* This table describes which capabilities we want and which values we
440 * assign to them.
442 static const struct {
443 int key_code;
444 char *key_name;
445 } key_table [] = {
446 { KEY_F(0), "k0" },
447 { KEY_F(1), "k1" },
448 { KEY_F(2), "k2" },
449 { KEY_F(3), "k3" },
450 { KEY_F(4), "k4" },
451 { KEY_F(5), "k5" },
452 { KEY_F(6), "k6" },
453 { KEY_F(7), "k7" },
454 { KEY_F(8), "k8" },
455 { KEY_F(9), "k9" },
456 { KEY_F(10), "k;" },
457 { KEY_F(11), "F1" },
458 { KEY_F(12), "F2" },
459 { KEY_F(13), "F3" },
460 { KEY_F(14), "F4" },
461 { KEY_F(15), "F5" },
462 { KEY_F(16), "F6" },
463 { KEY_F(17), "F7" },
464 { KEY_F(18), "F8" },
465 { KEY_F(19), "F9" },
466 { KEY_F(20), "FA" },
467 { KEY_IC, "kI" },
468 { KEY_NPAGE, "kN" },
469 { KEY_PPAGE, "kP" },
470 { KEY_LEFT, "kl" },
471 { KEY_RIGHT, "kr" },
472 { KEY_UP, "ku" },
473 { KEY_DOWN, "kd" },
474 { KEY_DC, "kD" },
475 { KEY_BACKSPACE, "kb" },
476 { KEY_HOME, "kh" },
477 { KEY_END, "@7" },
478 { 0, 0}
481 static void
482 do_define_key (int code, char *strcap)
484 char *seq;
486 seq = (char *) SLtt_tgetstr (strcap);
487 if (seq)
488 define_sequence (code, seq, MCKEY_NOACTION);
491 static void
492 load_terminfo_keys (void)
494 int i;
496 for (i = 0; key_table [i].key_code; i++)
497 do_define_key (key_table [i].key_code, key_table [i].key_name);
500 int getch (void)
502 int c;
503 if (no_slang_delay)
504 if (SLang_input_pending2 (0) == 0)
505 return -1;
507 c = SLang_getkey2 ();
508 if (c == SLANG_GETKEY_ERROR) {
509 fprintf (stderr, "SLang_getkey returned SLANG_GETKEY_ERROR\n"
510 "Assuming EOF on stdin and exiting\n");
511 quiet_quit_cmd ();
513 return (c);
516 #else
518 /* Non slang builds do not understand got_interrupt */
519 int got_interrupt (void)
521 return 0;
523 #endif /* HAVE_SLANG */
525 void
526 mc_refresh (void)
528 if (!we_are_background)
529 refresh ();