Defuzzied one entry
[midnight-commander.git] / slang / sldisply.c
blob20eedf3cc63398b22e6b7d80336da65f0c2610b4
1 /* Copyright (c) 1992, 1995 John E. Davis
2 * All rights reserved.
3 *
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Perl Artistic License.
6 */
8 /*
9 * SLTT_TRANSP_ACS_PATCH (#define/#undef):
11 * The problem: some terminals (e.g. QNX/qansi*) map the whole upper half of
12 * the ASCII table to the lower half, when alt-char-set is activated with
13 * the smacs/as string-sequence. This means, that if 0 <= ch < 128 written
14 * to the terminal, it will be translated to (ch+128) automatically by the
15 * terminal: so not only the line-drawing characters can be written, when
16 * the alt-char-set is activated. It implicitly means, that space, NL, CR,
17 * etc. characters (exactly: anything besides the "standard" line drawing
18 * characters) can not be written directly to the terminal, when the
19 * alt-char-set is activated, because writing these characters doesn't cause
20 * an implicit/temporary switching-back to the standard char-set!
22 * The original code in SLang assumes that space, NL, CR, etc. can be
23 * printed when alt-char-set is activated. If SLTT_TRANSP_ACS_PATCH is
24 * defined, the modified code will not use this assumption.
25 * [Remark: the patch-code is not the most exact solution, but works...]
27 /*#define SLTT_TRANSP_ACS_PATCH 1*/
30 * QNX_QANSI_SLANG_COMPAT_ACS (#define/#undef):
32 * A more OS/terminal-specific solution for the problem mentioned above
33 * (->SLTT_TRANSP_ACS_PATCH).
35 * If QNX_QANSI_SLANG_COMPAT_ACS is defined, the default smacs/sa, rmacs/ae,
36 * acsc/ac [and sgr/sa, if it would be used!] command sequences will be
37 * replaced internally with the "old style" (pre-QNX 4.23) sequences in case
38 * of QNX/qansi terminals. Using these optional command sequences the terminal
39 * remains compatible with the original SLang code (without using the
40 * workaround-code enabled by defining SLTT_TRANSP_ACS_PATCH).
42 /*#define QNX_QANSI_SLANG_COMPAT_ACS 1*/
44 /* auto-configuration */
45 #ifdef SLTT_TRANSP_ACS_PATCH
46 # if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
47 # undef SLTT_TRANSP_ACS_PATCH
48 # endif
49 #else
50 # if defined(__QNX__) && !defined(QNX_QANSI_SLANG_COMPAT_ACS)
51 # define QNX_QANSI_SLANG_COMPAT_ACS 1
52 # endif
53 #endif
55 #include "sl-feat.h"
56 #include "config.h"
58 #include <stdio.h>
59 #include <string.h>
60 #ifdef SCO_FLAVOR
61 # include <sys/types.h>
62 # include <sys/timeb.h> /* for struct timeb, used in time.h */
63 #endif
64 #include <time.h>
65 #include <ctype.h>
67 #ifndef VMS
68 # include <sys/time.h>
69 # ifdef __QNX__
70 # include <sys/select.h>
71 # endif
72 # include <sys/types.h>
73 #endif
75 #ifdef __BEOS__
76 /* Prototype for select */
77 # include <net/socket.h>
78 #endif
80 #ifdef HAVE_TERMIOS_H
81 # include <termios.h>
82 #endif
84 #ifdef VMS
85 # include <unixlib.h>
86 # include <unixio.h>
87 # include <dvidef.h>
88 # include <descrip.h>
89 # include <lib$routines.h>
90 # include <starlet.h>
91 #else
92 # if !defined(sun)
93 # include <sys/ioctl.h>
94 # endif
95 #endif
98 #ifdef SYSV
99 # include <sys/termio.h>
100 # include <sys/stream.h>
101 # include <sys/ptem.h>
102 # include <sys/tty.h>
103 #endif
105 #if defined (_AIX) && !defined (FD_SET)
106 # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
107 #endif
109 #include <errno.h>
110 #include "slang.h"
111 #include "_slang.h"
113 #ifdef HAVE_STDLIB_H
114 # include <stdlib.h>
115 #endif
117 #ifdef HAVE_UNISTD_H
118 # include <unistd.h>
119 #endif
121 #if defined(__DECC) && defined(VMS)
122 /* These get prototypes for write an sleep */
123 # include <unixio.h>
124 #endif
125 #include <signal.h>
128 /* Colors: These definitions are used for the display. However, the
129 * application only uses object handles which get mapped to this
130 * internal representation. The mapping is performed by the Color_Map
131 * structure below. */
133 #define CHAR_MASK 0x000000FF
134 #define FG_MASK 0x0000FF00
135 #define BG_MASK 0x00FF0000
136 #define ATTR_MASK 0x1F000000
137 #define BGALL_MASK 0x0FFF0000
139 /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
140 * not include this attribute.
145 #define GET_FG(color) ((color & FG_MASK) >> 8)
146 #define GET_BG(color) ((color & BG_MASK) >> 16)
147 #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
149 int SLtt_Screen_Cols;
150 int SLtt_Screen_Rows;
151 int SLtt_Term_Cannot_Insert;
152 int SLtt_Term_Cannot_Scroll;
153 int SLtt_Use_Ansi_Colors;
154 int SLtt_Blink_Mode = 1;
155 int SLtt_Use_Blink_For_ACS = 0;
156 int SLtt_Newline_Ok = 0;
157 int SLtt_Has_Alt_Charset = 0;
158 int SLtt_Force_Keypad_Init = 0;
160 /* -1 means unknown */
161 int SLtt_Has_Status_Line = -1; /* hs */
163 static int Automatic_Margins;
164 /* static int No_Move_In_Standout; */
165 static int Worthless_Highlight;
166 #define HP_GLITCH_CODE
167 #ifdef HP_GLITCH_CODE
168 /* This glitch is exclusive to HP term. Basically it means that to clear
169 * attributes, one has to erase to the end of the line.
171 static int Has_HP_Glitch;
172 #endif
174 static char *Reset_Color_String;
176 static int Linux_Console;
178 /* It is crucial that JMAX_COLORS must be less than 128 since the high bit
179 * is used to indicate a character from the ACS (alt char set). The exception
180 * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
181 * the highbit is set, we interpret that as a blink character. This is
182 * exploited by DOSemu.
184 #define JMAX_COLORS 256
185 #define JNORMAL_COLOR 0
187 typedef struct
189 SLtt_Char_Type fgbg;
190 SLtt_Char_Type mono;
191 char *custom_esc;
192 } Ansi_Color_Type;
194 #define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
195 #define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
197 static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] =
199 {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL}, /* white/black */
200 {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK, NULL}, /* green/black */
201 {RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* magenta/black */
202 {RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* cyan/black */
203 {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
204 {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
205 {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
206 {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK, NULL},
207 {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK, NULL},
208 {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK, NULL},
209 {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
210 {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
211 {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
212 {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK, NULL},
213 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
214 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
215 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
216 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL}
220 /* This is the string to use to use when outputting color information.
222 #ifdef M_UNIX
223 /* work around for sco console bug that can't handle combined sequences */
224 static char *Color_Escape_Sequence = "\033[3%dm\033[4%dm";
225 #else
226 /* Believe it or not, this is what is in the linux terminfo database. It
227 * produces the same escape sequence but it is much more CPU intensive.
228 * Why not just encode it as "\033[3%p1%dm\033[4%p2%dm" ???
230 /* static char *Color_Escape_Sequence = "\033[%p1%{30}%+%dm\033[%p2%{40}%+%dm"; */
231 static char *Color_Escape_Sequence = "\033[3%d;4%dm";
232 #endif
234 char *SLtt_Graphics_Char_Pairs; /* ac termcap string -- def is vt100 */
237 /* 1 if terminal lacks the ability to do into insert mode or into delete
238 mode. Currently controlled by S-Lang but later perhaps termcap. */
240 static char *UnderLine_Vid_Str;
241 static char *Blink_Vid_Str;
242 static char *Bold_Vid_Str;
243 static char *Ins_Mode_Str; /* = "\033[4h"; */ /* ins mode (im) */
244 static char *Eins_Mode_Str; /* = "\033[4l"; */ /* end ins mode (ei) */
245 static char *Scroll_R_Str; /* = "\033[%d;%dr"; */ /* scroll region */
246 static char *Cls_Str; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
247 static char *Rev_Vid_Str; /* = "\033[7m"; */ /* mr,so termcap string */
248 static char *Norm_Vid_Str; /* = "\033[m"; */ /* me,se termcap string */
249 static char *Del_Eol_Str; /* = "\033[K"; */ /* ce */
250 static char *Del_Char_Str; /* = "\033[P"; */ /* dc */
251 static char *Del_N_Lines_Str; /* = "\033[%dM"; */ /* DL */
252 static char *Add_N_Lines_Str; /* = "\033[%dL"; */ /* AL */
253 static char *Rev_Scroll_Str;
254 static char *Curs_Up_Str;
255 static char *Curs_F_Str; /* RI termcap string */
256 static char *Cursor_Visible_Str; /* ve termcap string */
257 static char *Cursor_Invisible_Str; /* vi termcap string */
259 static char *Start_Alt_Chars_Str; /* as */
260 static char *End_Alt_Chars_Str; /* ae */
261 static char *Enable_Alt_Char_Set; /* eA */
263 static char *Term_Init_Str;
264 static char *Keypad_Init_Str;
265 static char *Term_Reset_Str;
266 static char *Keypad_Reset_Str;
268 /* status line functions */
269 static char *Disable_Status_line_Str; /* ds */
270 static char *Return_From_Status_Line_Str; /* fs */
271 static char *Goto_Status_Line_Str; /* ts */
272 static int Num_Status_Line_Columns; /* ws */
273 static int Status_Line_Esc_Ok; /* es */
275 /* static int Len_Curs_F_Str = 5; */
277 /* cm string has %i%d since termcap numbers columns from 0 */
278 /* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
279 static char *Curs_Pos_Str; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
282 /* scrolling region */
283 static int Scroll_r1 = 0, Scroll_r2 = 23;
284 static int Cursor_r, Cursor_c; /* 0 based */
286 /* current attributes --- initialized to impossible value */
287 static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFFU;
289 static int Cursor_Set; /* 1 if cursor position known, 0
290 * if not. -1 if only row is known
294 #define MAX_OUTPUT_BUFFER_SIZE 4096
296 static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
297 static unsigned char *Output_Bufferp = Output_Buffer;
299 unsigned long SLtt_Num_Chars_Output;
301 #ifdef SLTT_TRANSP_ACS_PATCH
302 static int SLtt_ACS_Active = 0;
303 #endif
305 static int sl_usleep (unsigned long usecs)
307 #ifndef VMS
308 struct timeval tv;
309 tv.tv_sec = usecs / 1000000;
310 tv.tv_usec = usecs % 1000000;
311 return select(0, NULL, NULL, NULL, &tv);
312 #else
313 return 0;
314 #endif
317 int SLtt_flush_output (void)
319 int nwrite = 0;
320 unsigned int total;
321 int n = (int) (Output_Bufferp - Output_Buffer);
323 SLtt_Num_Chars_Output += n;
325 total = 0;
326 while (n > 0)
328 nwrite = write (fileno(stdout), (char *) Output_Buffer + total, n);
329 if (nwrite == -1)
331 nwrite = 0;
332 #ifdef EAGAIN
333 if (errno == EAGAIN)
335 sl_usleep (100000); /* 1/10 sec */
336 continue;
338 #endif
339 #ifdef EWOULDBLOCK
340 if (errno == EWOULDBLOCK)
342 sl_usleep (100000);
343 continue;
345 #endif
346 #ifdef EINTR
347 if (errno == EINTR) continue;
348 #endif
349 break;
351 n -= nwrite;
352 total += nwrite;
354 Output_Bufferp = Output_Buffer;
355 return n;
359 int SLtt_Baud_Rate;
360 static void tt_write(char *str, unsigned int n)
362 static unsigned long last_time;
363 static int total;
364 unsigned long now;
365 unsigned int ndiff;
367 if ((str == NULL) || (n == 0)) return;
368 total += n;
370 while (1)
372 ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
373 if (ndiff < n)
375 SLMEMCPY ((char *) Output_Bufferp, (char *) str, ndiff);
376 Output_Bufferp += ndiff;
377 SLtt_flush_output ();
378 n -= ndiff;
379 str += ndiff;
381 else
383 SLMEMCPY ((char *) Output_Bufferp, str, n);
384 Output_Bufferp += n;
385 break;
389 if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
390 && (10 * total > SLtt_Baud_Rate))
392 total = 0;
393 if ((now = (unsigned long) time(NULL)) - last_time <= 1)
395 SLtt_flush_output ();
396 sleep((unsigned) 1);
398 last_time = now;
403 void SLtt_write_string (char *str)
405 if (str != NULL) tt_write(str, strlen(str));
409 void SLtt_putchar (char ch)
411 #ifdef SLTT_TRANSP_ACS_PATCH
412 int restore_acs = 0;
413 #endif
415 SLtt_normal_video ();
416 if (Cursor_Set == 1)
418 if (ch >= ' ') Cursor_c++;
419 #ifndef SLTT_TRANSP_ACS_PATCH
420 else if (ch == '\b') Cursor_c--;
421 #else
422 if (ch <= ' ' && SLtt_ACS_Active)
424 SLtt_set_alt_char_set (0);
425 restore_acs = 1;
427 if (ch == '\b') Cursor_c--;
428 #endif
429 else if (ch == '\r') Cursor_c = 0;
430 else Cursor_Set = 0;
432 if ((Cursor_c + 1 == SLtt_Screen_Cols)
433 && Automatic_Margins) Cursor_Set = 0;
436 if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
438 *Output_Bufferp++ = (unsigned char) ch;
440 else tt_write (&ch, 1);
442 #ifdef SLTT_TRANSP_ACS_PATCH
443 if (restore_acs)
445 SLtt_set_alt_char_set (1);
447 #endif
450 /* this is supposed to be fast--- also handles
451 termcap: %d, &i, %., %+, %r strings as well as terminfo stuff */
452 static unsigned int tt_sprintf(char *buf, char *fmt, int x, int y)
454 register unsigned char *f = (unsigned char *) fmt, *b, ch;
455 int offset = 0, tinfo = 0;
456 int stack[10];
457 int i = 0, z;
458 stack[0] = y; stack[1] = x; i = 2;
460 b = (unsigned char *) buf;
461 if (fmt != NULL) while ((ch = *f++) != 0)
463 if (ch != '%') *b++ = ch;
464 else
466 ch = *f++;
467 if (tinfo)
469 if ((ch <= '3') && (ch >= '0'))
471 /* map it to termcap. Since this is terminfo,
472 * it must be one of:
473 * %2d, %3d, %02d, %03d
475 * I am assuming that a terminal that understands
476 * %2d form will also understand the %02d form. These
477 * only differ by a space padding the field.
480 /* skip the 'd'-- hope it is there */
481 if (ch == '0')
483 ch = *f;
484 f += 2;
486 else f++;
490 switch (ch)
492 case 'p':
493 tinfo = 1;
494 ch = *f++;
495 if (ch == '1') stack[i++] = x; else stack[i++] = y;
496 break;
498 case '\'': /* 'x' */
499 stack[i++] = *f++;
500 f++;
501 break;
503 case '{': /* literal constant, e.g. {30} */
504 z = 0;
505 while (((ch = *f) <= '9') && (ch >= '0'))
507 z = z * 10 + (ch - '0');
508 f++;
510 stack[i++] = z;
511 if (ch == '}') f++;
512 break;
514 case 'd':
515 case '2':
516 case '3':
517 z = stack[--i];
518 z += offset;
519 if (z >= 100)
521 *b++ = z / 100 + '0';
522 z = z % 100;
523 goto ten;
525 else if (ch == 3)
527 *b++ = '0';
528 ch = '2';
531 if (z >= 10)
533 ten:
534 *b++ = z / 10 + '0';
535 z = z % 10;
537 else if (ch == 2) *b++ = '0';
539 *b++ = z + '0';
540 break;
542 case 'i':
543 offset = 1;
544 break;
546 case '+':
547 if (tinfo)
549 z = stack[--i];
550 stack[i-1] += z;
552 else
554 ch = *f++;
555 if ((unsigned char) ch == 128) ch = 0;
556 ch = ch + (unsigned char) stack[--i];
557 if (ch == '\n') ch++;
558 *b++ = ch;
560 break;
562 case 'r':
563 stack[0] = x;
564 stack[1] = y;
565 break;
567 case '.':
568 case 'c':
569 ch = (unsigned char) stack[--i];
570 if (ch == '\n') ch++;
571 *b++ = ch;
572 break;
574 default:
575 *b++ = ch;
579 *b = 0;
580 return((unsigned int) (b - (unsigned char *) buf));
583 static void tt_printf(char *fmt, int x, int y)
585 char buf[256];
586 unsigned int n;
587 if (fmt == NULL) return;
588 n = tt_sprintf(buf, fmt, x, y);
589 tt_write(buf, n);
593 void SLtt_set_scroll_region (int r1, int r2)
595 Scroll_r1 = r1;
596 Scroll_r2 = r2;
597 tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
598 Cursor_Set = 0;
601 void SLtt_reset_scroll_region (void)
603 SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
606 int SLtt_set_cursor_visibility (int show)
608 if ((Cursor_Visible_Str == NULL) || (Cursor_Invisible_Str == NULL))
609 return -1;
611 SLtt_write_string (show ? Cursor_Visible_Str : Cursor_Invisible_Str);
612 return 0;
616 /* the goto_rc function moves to row relative to scrolling region */
617 void SLtt_goto_rc(int r, int c)
619 char *s = NULL;
620 int n;
621 char buf[6];
622 #ifdef SLTT_TRANSP_ACS_PATCH
623 int check_alt_acs = 0;
624 #endif
626 if (c < 0)
628 c = -c - 1;
629 Cursor_Set = 0;
632 /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
633 r += Scroll_r1;
635 if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
637 n = r - Cursor_r;
638 if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c)
639 && (Curs_Up_Str != NULL))
641 s = Curs_Up_Str;
643 else if ((n >= 0) && (n <= 4))
645 if ((n == 0) && (Cursor_Set == 1)
646 && ((c > 1) || (c == Cursor_c)))
648 if (Cursor_c == c) return;
649 if (Cursor_c == c + 1)
651 s = buf;
652 *s++ = '\b'; *s = 0;
653 s = buf;
654 #ifdef SLTT_TRANSP_ACS_PATCH
655 check_alt_acs = 1;
656 #endif
659 else if (c == 0)
661 s = buf;
662 if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
663 while (n--) *s++ = '\n';
664 #ifdef VMS
665 /* Need to add this after \n to start a new record. Sheesh. */
666 *s++ = '\r';
667 #endif
668 *s = 0;
669 s = buf;
670 #ifdef SLTT_TRANSP_ACS_PATCH
671 check_alt_acs = 1;
672 #endif
674 /* Will fail on VMS */
675 #ifndef VMS
676 else if (SLtt_Newline_Ok && (Cursor_Set == 1) &&
677 (Cursor_c >= c) && (c + 3 > Cursor_c))
679 s = buf;
680 while (n--) *s++ = '\n';
681 n = Cursor_c - c;
682 while (n--) *s++ = '\b';
683 *s = 0;
684 s = buf;
685 #ifdef SLTT_TRANSP_ACS_PATCH
686 check_alt_acs = 1;
687 #endif
689 #endif
692 #ifndef SLTT_TRANSP_ACS_PATCH
693 if (s != NULL) SLtt_write_string(s);
694 #else
695 if (s != NULL)
697 if (check_alt_acs && SLtt_ACS_Active)
699 SLtt_set_alt_char_set (0);
700 SLtt_write_string(s);
701 SLtt_set_alt_char_set (1);
703 else SLtt_write_string(s);
705 #endif
706 else tt_printf(Curs_Pos_Str, r, c);
707 Cursor_c = c; Cursor_r = r;
708 Cursor_Set = 1;
711 void SLtt_begin_insert (void)
713 SLtt_write_string(Ins_Mode_Str);
716 void SLtt_end_insert (void)
718 SLtt_write_string(Eins_Mode_Str);
721 void SLtt_delete_char (void)
723 SLtt_normal_video ();
724 SLtt_write_string(Del_Char_Str);
727 void SLtt_erase_line (void)
729 SLtt_write_string("\r");
730 Cursor_Set = 1; Cursor_c = 0;
731 SLtt_del_eol();
734 void SLtt_delete_nlines (int n)
736 int r1, curs;
737 char buf[132];
738 #ifdef SLTT_TRANSP_ACS_PATCH
739 int restore_acs = 0;
740 #endif
742 if (n <= 0) return;
743 SLtt_normal_video ();
744 if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str,n, 0);
745 else
746 /* get a new terminal */
748 r1 = Scroll_r1;
749 curs = Cursor_r;
750 SLtt_set_scroll_region(curs, Scroll_r2);
751 SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
752 #ifdef SLTT_TRANSP_ACS_PATCH
753 if (SLtt_ACS_Active)
755 SLtt_set_alt_char_set (0);
756 restore_acs = 1;
758 #endif
759 SLMEMSET(buf, '\n', (unsigned int) n);
760 tt_write(buf, (unsigned int) n);
761 #ifdef SLTT_TRANSP_ACS_PATCH
762 if (restore_acs) SLtt_set_alt_char_set (1);
763 #endif
764 /* while (n--) tt_putchar('\n'); */
765 SLtt_set_scroll_region(r1, Scroll_r2);
766 SLtt_goto_rc(curs, 0);
770 void SLtt_cls (void)
772 SLtt_normal_video();
773 SLtt_reset_scroll_region ();
774 SLtt_write_string(Cls_Str);
777 void SLtt_reverse_index (int n)
779 if (!n) return;
781 SLtt_normal_video();
782 if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
783 else
785 while(n--) SLtt_write_string(Rev_Scroll_Str);
790 int SLtt_Ignore_Beep = 1;
791 static char *Visible_Bell_Str;
793 void SLtt_beep (void)
795 if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
797 if (SLtt_Ignore_Beep & 0x2)
799 if (Visible_Bell_Str != NULL) SLtt_write_string (Visible_Bell_Str);
800 #ifdef __linux__
801 else if (Linux_Console)
803 SLtt_write_string ("\033[?5h");
804 SLtt_flush_output ();
805 sl_usleep (50000);
806 SLtt_write_string ("\033[?5l");
808 #endif
810 SLtt_flush_output ();
813 void SLtt_del_eol (void)
815 if (Current_Fgbg != 0xFFFFFFFFU) SLtt_normal_video ();
816 SLtt_write_string(Del_Eol_Str);
819 typedef struct
821 char *name;
822 SLtt_Char_Type color;
824 Color_Def_Type;
826 #define MAX_COLOR_NAMES 17
827 static Color_Def_Type Color_Defs [MAX_COLOR_NAMES] =
829 {"black", SLSMG_COLOR_BLACK},
830 {"red", SLSMG_COLOR_RED},
831 {"green", SLSMG_COLOR_GREEN},
832 {"brown", SLSMG_COLOR_BROWN},
833 {"blue", SLSMG_COLOR_BLUE},
834 {"magenta", SLSMG_COLOR_MAGENTA},
835 {"cyan", SLSMG_COLOR_CYAN},
836 {"lightgray", SLSMG_COLOR_LGRAY},
837 {"gray", SLSMG_COLOR_GRAY},
838 {"brightred", SLSMG_COLOR_BRIGHT_RED},
839 {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN},
840 {"yellow", SLSMG_COLOR_BRIGHT_BROWN},
841 {"brightblue", SLSMG_COLOR_BRIGHT_BLUE},
842 {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN},
843 {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA},
844 {"white", SLSMG_COLOR_BRIGHT_WHITE},
845 {"default", 25}
849 void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
851 (void) what;
852 if ((obj < 0) || (obj >= JMAX_COLORS))
854 return;
856 Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
859 static char *check_color_for_digit_form (char *color)
861 unsigned int i, ich;
862 char *s = color;
864 i = 0;
865 while ((ich = (int) *s) != 0)
867 if ((ich < '0') || (ich > '9'))
868 return color;
870 i = i * 10 + (ich - '0');
871 s++;
874 if (i < MAX_COLOR_NAMES)
875 color = Color_Defs[i].name;
877 return color;
880 static int get_default_colors (char **fgp, char **bgp)
882 static char fg_buf[16], bg_buf[16], *bg, *fg;
883 static int already_parsed;
884 char *p, *pmax;
886 if (already_parsed == -1)
887 return -1;
889 if (already_parsed)
891 *fgp = fg;
892 *bgp = bg;
893 return 0;
896 already_parsed = -1;
898 bg = getenv ("COLORFGBG");
900 if (bg == NULL)
902 bg = getenv ("DEFAULT_COLORS");
903 if (bg == NULL)
904 return -1;
907 p = fg_buf;
908 pmax = p + (sizeof (fg_buf) - 1);
910 while ((*bg != 0) && (*bg != ';'))
912 if (p < pmax) *p++ = *bg;
913 bg++;
915 *p = 0;
917 if (*bg) bg++;
919 p = bg_buf;
920 pmax = p + (sizeof (bg_buf) - 1);
922 /* Mark suggested allowing for extra spplication specific stuff following
923 * the background color. That is what the check for the semi-colon is for.
925 while ((*bg != 0) && (*bg != ';'))
927 if (p < pmax) *p++ = *bg;
928 bg++;
930 *p = 0;
932 if (!strcmp (fg_buf, "default") || !strcmp(bg_buf, "default"))
934 *fgp = *bgp = fg = bg = "default";
936 else
938 *fgp = fg = check_color_for_digit_form (fg_buf);
939 *bgp = bg = check_color_for_digit_form (bg_buf);
941 already_parsed = 1;
942 return 0;
946 static unsigned char FgBg_Stats[JMAX_COLORS];
948 static int Color_0_Modified = 0;
950 void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
952 char *cust_esc;
954 if ((obj < 0) || (obj >= JMAX_COLORS)) return;
956 cust_esc = Ansi_Color_Map[obj].custom_esc;
957 if (cust_esc != NULL)
959 SLFREE (cust_esc);
960 FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
961 Ansi_Color_Map[obj].custom_esc = NULL;
964 Ansi_Color_Map[obj].fgbg = attr;
965 if (obj == 0) Color_0_Modified = 1;
968 SLtt_Char_Type SLtt_get_color_object (int obj)
970 if ((obj < 0) || (obj >= JMAX_COLORS)) return 0;
971 return Ansi_Color_Map[obj].fgbg;
975 void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
977 if ((obj < 0) || (obj >= JMAX_COLORS)) return;
979 Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
980 if (obj == 0) Color_0_Modified = 1;
983 static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
985 SLtt_Char_Type attr = 0;
987 if ((f & 0xF0) == 0)
989 if (f & 0x8) attr = SLTT_BOLD_MASK;
990 f &= 0x7;
992 else f = 9;
994 if ((b & 0xF0) == 0)
996 if (b & 0x8) attr |= SLTT_BLINK_MASK;
997 b &= 0x7;
999 else b = 9;
1001 return ((f << 8) | (b << 16) | attr);
1004 static int make_color_fgbg (char *fg, char *bg, SLtt_Char_Type *fgbg)
1006 SLtt_Char_Type f = 0xFFFFFFFFU, b = 0xFFFFFFFFU;
1007 char *dfg, *dbg;
1008 unsigned int i;
1010 if ((fg != NULL) && (*fg == 0)) fg = NULL;
1011 if ((bg != NULL) && (*bg == 0)) bg = NULL;
1013 if ((fg == NULL) || (bg == NULL))
1015 if (-1 == get_default_colors (&dfg, &dbg))
1016 return -1;
1018 if (fg == NULL) fg = dfg;
1019 if (bg == NULL) bg = dbg;
1022 for (i = 0; i < MAX_COLOR_NAMES; i++)
1024 if (strcmp(fg, Color_Defs[i].name)) continue;
1025 f = Color_Defs[i].color;
1026 break;
1029 for (i = 0; i < MAX_COLOR_NAMES; i++)
1031 if (strcmp(bg, Color_Defs[i].name)) continue;
1032 b = Color_Defs[i].color;
1033 break;
1036 if ((f == 0xFFFFFFFFU) || (b == 0xFFFFFFFFU))
1037 return -1;
1039 *fgbg = fb_to_fgbg (f, b);
1040 return 0;
1043 void SLtt_set_color (int obj, char *what, char *fg, char *bg)
1045 SLtt_Char_Type fgbg;
1047 (void) what;
1048 if ((obj < 0) || (obj >= JMAX_COLORS))
1049 return;
1051 if (-1 != make_color_fgbg (fg, bg, &fgbg))
1052 SLtt_set_color_object (obj, fgbg);
1055 void SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
1057 SLtt_set_color_object (obj, fb_to_fgbg (f, b));
1060 void SLtt_set_color_esc (int obj, char *esc)
1062 char *cust_esc;
1063 SLtt_Char_Type fgbg = 0;
1064 int i;
1066 if ((obj < 0) || (obj >= JMAX_COLORS))
1068 return;
1071 cust_esc = Ansi_Color_Map[obj].custom_esc;
1072 if (cust_esc != NULL)
1074 SLFREE (cust_esc);
1075 FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
1078 cust_esc = (char *) SLMALLOC (strlen(esc) + 1);
1079 if (cust_esc != NULL) strcpy (cust_esc, esc);
1081 Ansi_Color_Map[obj].custom_esc = cust_esc;
1082 if (cust_esc == NULL) fgbg = 0;
1083 else
1085 /* The whole point of this is to generate a unique fgbg */
1086 for (i = 0; i < JMAX_COLORS; i++)
1088 if (FgBg_Stats[i] == 0) fgbg = i;
1090 if (obj == i) continue;
1091 if ((Ansi_Color_Map[i].custom_esc) == NULL) continue;
1092 if (!strcmp (Ansi_Color_Map[i].custom_esc, cust_esc))
1094 fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
1095 break;
1098 FgBg_Stats[fgbg] += 1;
1101 fgbg |= 0x80;
1102 Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
1103 if (obj == 0) Color_0_Modified = 1;
1106 void SLtt_set_alt_char_set (int i)
1108 #ifndef SLTT_TRANSP_ACS_PATCH
1109 static int last_i;
1110 #else
1111 #define last_i SLtt_ACS_Active
1112 #endif
1113 if (SLtt_Has_Alt_Charset == 0) return;
1114 if (i == last_i) return;
1115 SLtt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
1116 /* if (i) Current_Fgbg |= SLTT_ALTC_MASK;
1117 else Current_Fgbg &= ~SLTT_ALTC_MASK; */
1118 last_i = i;
1119 #ifdef SLTT_TRANSP_ACS_PATCH
1120 #undef last_i
1121 #endif
1124 static void write_attributes (SLtt_Char_Type fgbg)
1126 int bg0, fg0;
1128 if (Worthless_Highlight) return;
1129 if (fgbg == Current_Fgbg) return;
1131 /* Before spitting out colors, fix attributes */
1132 if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
1134 if (Current_Fgbg & ATTR_MASK)
1136 SLtt_write_string(Norm_Vid_Str);
1137 /* In case normal video turns off ALL attributes: */
1138 if (fgbg & SLTT_ALTC_MASK)
1139 Current_Fgbg &= ~SLTT_ALTC_MASK;
1140 SLtt_set_alt_char_set (0);
1143 if ((fgbg & SLTT_ALTC_MASK)
1144 != (Current_Fgbg & SLTT_ALTC_MASK))
1146 SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
1149 if (fgbg & SLTT_ULINE_MASK) SLtt_write_string (UnderLine_Vid_Str);
1150 if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
1151 if (fgbg & SLTT_REV_MASK) SLtt_write_string (Rev_Vid_Str);
1152 if (fgbg & SLTT_BLINK_MASK)
1154 /* Someday Linux will have a blink mode that set high intensity
1155 * background. Lets be prepared.
1157 if (SLtt_Blink_Mode) SLtt_write_string (Blink_Vid_Str);
1161 if (SLtt_Use_Ansi_Colors)
1163 fg0 = (int) GET_FG(fgbg);
1164 bg0 = (int) GET_BG(fgbg);
1165 tt_printf(Color_Escape_Sequence, fg0, bg0);
1167 Current_Fgbg = fgbg;
1170 static int Video_Initialized;
1172 void SLtt_reverse_video (int color)
1174 SLtt_Char_Type fgbg;
1175 char *esc;
1177 if (Worthless_Highlight) return;
1178 if ((color < 0) || (color >= JMAX_COLORS)) return;
1180 if (Video_Initialized == 0)
1182 if (color == JNORMAL_COLOR)
1184 SLtt_write_string (Norm_Vid_Str);
1186 else SLtt_write_string (Rev_Vid_Str);
1187 Current_Fgbg = 0xFFFFFFFFU;
1188 return;
1191 if (SLtt_Use_Ansi_Colors)
1193 fgbg = Ansi_Color_Map[color].fgbg;
1194 if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
1196 if (fgbg != Current_Fgbg)
1198 Current_Fgbg = fgbg;
1199 SLtt_write_string (esc);
1200 return;
1204 else fgbg = Ansi_Color_Map[color].mono;
1206 if (fgbg == Current_Fgbg) return;
1207 write_attributes (fgbg);
1213 void SLtt_normal_video (void)
1215 SLtt_reverse_video(JNORMAL_COLOR);
1218 void SLtt_narrow_width (void)
1220 SLtt_write_string("\033[?3l");
1223 void SLtt_wide_width (void)
1225 SLtt_write_string("\033[?3h");
1228 /* Highest bit represents the character set. */
1229 #define COLOR_MASK 0x7F00
1231 #define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
1233 #define COLOR_EQS(a, b) \
1234 (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
1237 #define COLOR_EQS(a, b) \
1238 (SLtt_Use_Ansi_Colors \
1239 ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
1240 : (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
1243 #define CHAR_EQS(a, b) (((a) == (b))\
1244 || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
1245 && COLOR_EQS((a), (b))))
1248 /* The whole point of this routine is to prevent writing to the last column
1249 * and last row on terminals with automatic margins.
1251 static void write_string_with_care (char *str)
1253 unsigned int len;
1255 if (str == NULL) return;
1257 len = strlen (str);
1258 if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
1260 if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
1262 /* For now, just do not write there. Later, something more
1263 * sophisticated will be implemented.
1265 if (SLtt_Screen_Cols > Cursor_c)
1266 len = SLtt_Screen_Cols - Cursor_c - 1;
1267 else len = 0;
1270 tt_write (str, len);
1273 static void send_attr_str (unsigned short *s)
1275 unsigned char out[256], ch, *p;
1276 register SLtt_Char_Type attr;
1277 register unsigned short sh;
1278 int color, last_color = -1;
1280 p = out;
1281 while (0 != (sh = *s++))
1283 ch = sh & 0xFF;
1284 color = ((int) sh & 0xFF00) >> 8;
1285 #ifdef SLTT_TRANSP_ACS_PATCH
1286 if (ch <= ' ' && (color & 0x80)) color &= ~0x80;
1287 #endif
1288 if (color != last_color)
1290 if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
1291 else attr = Ansi_Color_Map[color & 0x7F].mono;
1293 /* sh => color */
1294 if (color & 0x80) /* alternate char set */
1296 if (SLtt_Use_Blink_For_ACS)
1298 if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
1300 else attr |= SLTT_ALTC_MASK;
1304 if (attr != Current_Fgbg)
1306 #ifndef SLTT_TRANSP_ACS_PATCH
1307 if ((ch != ' ') ||
1308 /* it is a space so only consider it different if it
1309 * has different attributes.
1311 (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK))
1312 #endif
1314 if (p != out)
1316 *p = 0;
1317 write_string_with_care ((char *) out);
1318 Cursor_c += (int) (p - out);
1319 p = out;
1322 if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
1324 SLtt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
1325 /* Just in case the custom escape sequence screwed up
1326 * the alt character set state...
1328 if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
1329 SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
1330 Current_Fgbg = attr;
1332 else write_attributes (attr);
1334 last_color = color;
1338 *p++ = ch;
1340 *p = 0;
1341 if (p != out) write_string_with_care ((char *) out);
1342 Cursor_c += (int) (p - out);
1345 static void forward_cursor (unsigned int n, int row)
1347 char buf[30];
1350 if (n <= 4)
1352 SLtt_normal_video ();
1353 SLMEMSET (buf, ' ', n);
1354 buf[n] = 0;
1355 write_string_with_care (buf);
1356 Cursor_c += n;
1358 else if (Curs_F_Str != NULL)
1360 Cursor_c += n;
1361 n = tt_sprintf(buf, Curs_F_Str, (int) n, 0);
1362 tt_write(buf, n);
1364 else SLtt_goto_rc (row, (int) (Cursor_c + n));
1368 #define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))
1370 void SLtt_smart_puts(unsigned short *neww, unsigned short *oldd, int len, int row)
1372 register unsigned short *p, *q, *qmax, *pmax, *buf;
1373 unsigned short buffer[256];
1374 unsigned int n_spaces;
1375 unsigned short *space_match, *last_buffered_match;
1376 #ifdef HP_GLITCH_CODE
1377 int handle_hp_glitch = 0;
1378 #endif
1380 q = oldd; p = neww;
1381 qmax = oldd + len;
1382 pmax = p + len;
1384 /* Find out where to begin --- while they match, we are ok */
1385 while (1)
1387 if (q == qmax) return;
1388 #if SLANG_HAS_KANJI_SUPPORT
1389 if (*p & 0x80)
1390 { /* new is kanji */
1391 if ((*q & 0x80) && ((q + 1) < qmax))
1392 { /* old is also kanji */
1393 if (((0xFF & *q) != (0xFF & *p))
1394 || ((0xFF & q[1]) != (0xFF & p[1])))
1395 break; /* both kanji, but not match */
1397 else
1398 { /* kanji match ! */
1399 if (!COLOR_EQS(*q, *p)) break;
1400 q++; p++;
1401 if (!COLOR_EQS(*q, *p)) break;
1402 /* really match! */
1403 q++; p++;
1404 continue;
1407 else break; /* old is not kanji */
1409 else
1410 { /* new is not kanji */
1411 if (*q & 0x80) break; /* old is kanji */
1413 #endif
1414 if (!CHAR_EQS(*q, *p)) break;
1415 q++; p++;
1418 /*position the cursor */
1419 SLtt_goto_rc (row, (int) (p - neww));
1421 #ifdef HP_GLITCH_CODE
1422 if (Has_HP_Glitch)
1424 unsigned short *qq = q;
1425 while (qq < qmax)
1427 if (*qq & 0xFF00)
1429 SLtt_normal_video ();
1430 SLtt_del_eol ();
1431 qmax = q;
1432 handle_hp_glitch = 1;
1433 break;
1435 qq++;
1438 #endif
1439 /* Find where the last non-blank character on old/new screen is */
1441 while (qmax > q)
1443 qmax--;
1444 if (!CHAR_EQS(*qmax, SPACE_CHAR))
1446 qmax++;
1447 break;
1451 while (pmax > p)
1453 pmax--;
1454 if (!CHAR_EQS(*pmax, SPACE_CHAR))
1456 pmax++;
1457 break;
1461 last_buffered_match = buf = buffer; /* buffer is empty */
1463 #ifdef HP_GLITCH_CODE
1464 if (handle_hp_glitch)
1466 while (p < pmax)
1468 *buf++ = *p++;
1471 #endif
1473 /* loop using overwrite then skip algorithm until done */
1474 while (1)
1476 /* while they do not match and we do not hit a space, buffer them up */
1477 n_spaces = 0;
1478 while (p < pmax)
1480 if (CHAR_EQS(*q,SPACE_CHAR) && CHAR_EQS(*p, SPACE_CHAR))
1482 /* If *q is not a space, we would have to overwrite it.
1483 * However, if *q is a space, then while *p is also one,
1484 * we only need to skip over the blank field.
1486 space_match = p;
1487 p++; q++;
1488 while ((p < pmax)
1489 && CHAR_EQS(*q,SPACE_CHAR)
1490 && CHAR_EQS(*p, SPACE_CHAR))
1492 p++;
1493 q++;
1495 n_spaces = (unsigned int) (p - space_match);
1496 break;
1498 #if SLANG_HAS_KANJI_SUPPORT
1499 if ((*p & 0x80) && ((p + 1) < pmax))
1500 { /* new is kanji */
1501 if (*q & 0x80)
1502 { /* old is also kanji */
1503 if (((0xFF & *q) != (0xFF & *p))
1504 || ((0xFF & q[1]) != (0xFF & p[1])))
1506 /* both kanji, but not match */
1507 *buf++ = *p++;
1508 *buf++ = *p++;
1509 q += 2;
1510 continue;
1512 else
1513 { /* kanji match ? */
1514 if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
1516 /* code is match ,but color is diff */
1517 *buf++ = *p++;
1518 *buf++ = *p++;
1519 continue;
1521 /* really match ! */
1522 break;
1525 else
1526 { /* old is not kanji */
1527 *buf++ = *p++;
1528 *buf++ = *p++;
1529 q += 2;
1530 continue;
1533 else
1534 { /* new is not kanji */
1535 if (*q & 0x80)
1536 { /* old is kanji */
1537 *buf++ = *p++;
1538 q++;
1539 continue;
1542 #endif
1544 if (CHAR_EQS(*q, *p)) break;
1545 *buf++ = *p++;
1546 q++;
1548 *buf = 0;
1550 if (buf != buffer) send_attr_str (buffer);
1551 buf = buffer;
1553 if (n_spaces && (p < pmax))
1555 forward_cursor (n_spaces, row);
1558 /* Now we overwrote what we could and cursor is placed at position
1559 * of a possible match of new and old. If this is the case, skip
1560 * some more.
1562 #if !SLANG_HAS_KANJI_SUPPORT
1563 while ((p < pmax) && CHAR_EQS(*p, *q))
1565 *buf++ = *p++;
1566 q++;
1568 #else
1569 /* Kanji */
1570 while (p < pmax)
1572 if ((*p & 0x80) && ((p + 1) < pmax))
1573 { /* new is kanji */
1574 if (*q & 0x80)
1575 { /* old is also kanji */
1576 if (((0xFF & *q) == (0xFF & *p))
1577 && ((0xFF & q[1]) == (0xFF & p[1])))
1579 /* kanji match ? */
1580 if (!COLOR_EQS(*q, *p)
1581 || !COLOR_EQS(q[1], p[1]))
1582 break;
1584 *buf++ = *p++;
1585 q++;
1586 if (p >= pmax)
1588 *buf++ = SPACE_CHAR;
1589 p++;
1590 break;
1592 else
1594 *buf++ = *p++;
1595 q++;
1596 continue;
1599 else break; /* both kanji, but not match */
1601 else break; /* old is not kanji */
1603 else
1604 { /* new is not kanji */
1605 if (*q & 0x80) break; /* old is kanji */
1606 if (!CHAR_EQS(*q, *p)) break;
1607 *buf++ = *p++;
1608 q++;
1611 #endif
1612 last_buffered_match = buf;
1613 if (p >= pmax) break;
1615 /* jump to new position is it is greater than 5 otherwise
1616 * let it sit in the buffer and output it later.
1618 if ((int) (buf - buffer) >= 5)
1620 forward_cursor ((unsigned int) (buf - buffer), row);
1621 last_buffered_match = buf = buffer;
1625 if (buf != buffer)
1627 if (q < qmax)
1629 if ((buf == last_buffered_match)
1630 && ((int) (buf - buffer) >= 5))
1632 forward_cursor ((unsigned int) (buf - buffer), row);
1634 else
1636 *buf = 0;
1637 send_attr_str (buffer);
1641 if (q < qmax) SLtt_del_eol ();
1642 if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
1646 static void get_color_info (void)
1648 char *fg, *bg;
1650 SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
1652 if (-1 == get_default_colors (&fg, &bg))
1653 return;
1655 /* Check to see if application has already set them. */
1656 if (Color_0_Modified)
1657 return;
1659 SLtt_set_color (0, NULL, fg, bg);
1660 SLtt_set_color (1, NULL, bg, fg);
1664 /* termcap stuff */
1666 #ifdef __unix__
1668 #ifndef USE_TERMCAP
1669 static char *Tbuf;
1670 static char *Tstr_Buf;
1672 #define tgetstr SLtt_tigetstr
1673 #define tgetent SLtt_tigetent
1674 #define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
1675 #define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
1676 #else
1678 extern char *tgetstr(char *, char **);
1679 extern int tgetent(char *, char *);
1680 extern int tgetnum(char *);
1681 extern int tgetflag(char *);
1682 static char Tstr_Buf[1024];
1683 static char Tbuf[4096];
1684 #define TGETNUM tgetnum
1685 #define TGETFLAG tgetflag
1686 #endif
1688 static char *my_tgetstr(char *what, char **p)
1690 register char *w, *w1;
1691 char *wsave;
1692 what = tgetstr(what, p);
1693 if (what != NULL)
1695 /* Check for AIX brain-damage */
1696 if (*what == '@')
1697 return NULL;
1699 /* lose pad info --- with today's technology, term is a loser if
1700 it is really needed */
1701 while ((*what == '.') ||
1702 ((*what >= '0') && (*what <= '9'))) what++;
1703 if (*what == '*') what++;
1705 /* lose terminfo padding--- looks like $<...> */
1706 w = what;
1707 while (*w) if ((*w++ == '$') && (*w == '<'))
1709 w1 = w - 1;
1710 while (*w && (*w != '>')) w++;
1711 if (*w == 0) break;
1712 w++;
1713 wsave = w1;
1714 while ((*w1++ = *w++) != 0);
1715 w = wsave;
1717 if (*what == 0) what = NULL;
1719 return(what);
1722 char *SLtt_tgetstr (char *s)
1724 #ifdef USE_TERMCAP
1725 static
1726 #endif
1727 char *p = Tstr_Buf;
1728 return my_tgetstr (s, &p);
1731 int SLtt_tgetnum (char *s)
1733 return TGETNUM (s);
1735 int SLtt_tgetflag (char *s)
1737 return TGETFLAG (s);
1741 static int Vt100_Like = 0;
1743 void SLtt_get_terminfo (void)
1745 char *term, *t, ch;
1746 int is_xterm;
1747 int almost_vtxxx;
1749 get_color_info ();
1751 if (NULL == (term = (char *) getenv("TERM")))
1753 SLang_exit_error("TERM environment variable needs set.");
1756 Linux_Console = (!strncmp (term, "linux", 5)
1757 #ifdef linux
1758 || !strncmp(term, "con", 3)
1759 #endif
1762 t = term;
1764 if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
1765 && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1;
1767 is_xterm = !strncmp (term, "xterm", 5);
1768 almost_vtxxx = (Vt100_Like
1769 || Linux_Console
1770 || is_xterm
1771 || !strcmp (term, "screen"));
1773 #ifndef USE_TERMCAP
1774 if (NULL == (Tbuf = tgetent (term)))
1776 char err_buf[512];
1777 if (almost_vtxxx) /* Special cases. */
1779 int vt102 = 1;
1780 if (!strcmp (term, "vt100")) vt102 = 0;
1781 SLtt_set_term_vtxxx (&vt102);
1782 return;
1784 g_snprintf (err_buf, sizeof (err_buf), "Unknown terminal: %s\n\
1785 Check the TERM environment variable.\n\
1786 Also make sure that the terminal is defined in the terminfo database.\n\
1787 Alternatively, set the TERMCAP environment variable to the desired\n\
1788 termcap entry.", term);
1789 SLang_exit_error(err_buf);
1791 Tstr_Buf = Tbuf;
1792 #else /* USE_TERMCAP */
1793 if (1 != tgetent(Tbuf, term)) SLang_exit_error("Unknown terminal.");
1794 #endif /* NOT USE_TERMCAP */
1796 if ((NULL == (Cls_Str = SLtt_tgetstr("cl")))
1797 || (NULL == (Curs_Pos_Str = SLtt_tgetstr("cm"))))
1799 SLang_exit_error("Terminal not powerful enough for SLang.");
1802 if ((NULL == (Ins_Mode_Str = SLtt_tgetstr("im")))
1803 || ( NULL == (Eins_Mode_Str = SLtt_tgetstr("ei")))
1804 || ( NULL == (Del_Char_Str = SLtt_tgetstr("dc"))))
1805 SLtt_Term_Cannot_Insert = 1;
1807 Visible_Bell_Str = SLtt_tgetstr ("vb");
1808 Curs_Up_Str = SLtt_tgetstr ("up");
1809 Rev_Scroll_Str = SLtt_tgetstr("sr");
1810 Del_N_Lines_Str = SLtt_tgetstr("DL");
1811 Add_N_Lines_Str = SLtt_tgetstr("AL");
1813 /* Actually these are used to initialize terminals that use cursor
1814 * addressing. Hard to believe.
1816 Term_Init_Str = SLtt_tgetstr ("ti");
1817 Term_Reset_Str = SLtt_tgetstr ("te");
1819 /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
1820 * which I do not want. This is mainly for HP terminals.
1822 if ((almost_vtxxx == 0) || SLtt_Force_Keypad_Init)
1824 Keypad_Init_Str = SLtt_tgetstr ("ks");
1825 Keypad_Reset_Str = SLtt_tgetstr ("ke");
1828 /* Make up for defective termcap/terminfo databases */
1829 if ((Vt100_Like && (term[2] != '1'))
1830 || Linux_Console
1831 || is_xterm
1834 if (Del_N_Lines_Str == NULL) Del_N_Lines_Str = "\033[%dM";
1835 if (Add_N_Lines_Str == NULL) Add_N_Lines_Str = "\033[%dL";
1838 Scroll_R_Str = SLtt_tgetstr("cs");
1840 SLtt_get_screen_size ();
1842 if ((Scroll_R_Str == NULL)
1843 || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
1844 && (NULL == Rev_Scroll_Str)))
1846 if (is_xterm
1847 || Linux_Console
1850 /* Defective termcap mode!!!! */
1851 SLtt_set_term_vtxxx (NULL);
1853 else SLtt_Term_Cannot_Scroll = 1;
1856 Del_Eol_Str = SLtt_tgetstr("ce");
1858 Rev_Vid_Str = SLtt_tgetstr("mr");
1859 if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
1861 Bold_Vid_Str = SLtt_tgetstr("md");
1863 /* Although xterm cannot blink, it does display the blinking characters
1864 * as bold ones. Some Rxvt will display the background as high intensity.
1866 if ((NULL == (Blink_Vid_Str = SLtt_tgetstr("mb")))
1867 && is_xterm)
1868 Blink_Vid_Str = "\033[5m";
1870 UnderLine_Vid_Str = SLtt_tgetstr("us");
1872 Start_Alt_Chars_Str = SLtt_tgetstr ("as"); /* smacs */
1873 End_Alt_Chars_Str = SLtt_tgetstr ("ae"); /* rmacs */
1874 Enable_Alt_Char_Set = SLtt_tgetstr ("eA"); /* enacs */
1875 SLtt_Graphics_Char_Pairs = SLtt_tgetstr ("ac");
1877 #ifndef NCURSES_BRAIN_DAMAGE_CONTROL
1878 # define NCURSES_BRAIN_DAMAGE_CONTROL 0
1879 #endif
1881 #if NCURSES_BRAIN_DAMAGE_CONTROL
1882 if (Linux_Console)
1884 # if 0
1885 char *lgcp = "l\332m\300k\277j\331u\264t\303v\301w\302q\304x\263n\053o\176s\137`\004a\260f\370g\361~\011,\020+\021.\031-\030h\261i\0250\333";
1887 SLtt_Graphics_Char_Pairs = lgcp;
1888 Start_Alt_Chars_Str = "\033(B\033)U\016";
1889 End_Alt_Chars_Str = "\033(B\033)0\017";
1890 Enable_Alt_Char_Set = NULL;
1891 # else
1892 char *lgcp = "`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o\302q\304r\362s_t\303u\264v\301w\302x\263y\371z\372{\373|\374}\375~";
1894 SLtt_Graphics_Char_Pairs = lgcp;
1895 Start_Alt_Chars_Str = "\033[11m";
1896 End_Alt_Chars_Str = "\033[10m";
1897 Enable_Alt_Char_Set = NULL;
1898 # endif
1900 #endif
1902 if (NULL == SLtt_Graphics_Char_Pairs)
1904 /* make up for defective termcap/terminfo */
1905 if (Vt100_Like)
1907 Start_Alt_Chars_Str = "\016";
1908 End_Alt_Chars_Str = "\017";
1909 Enable_Alt_Char_Set = "\033)0";
1913 /* aixterm added by willi */
1914 if (is_xterm || !strncmp (term, "aixterm", 7))
1916 Start_Alt_Chars_Str = "\016";
1917 End_Alt_Chars_Str = "\017";
1918 Enable_Alt_Char_Set = "\033(B\033)0";
1921 if ((SLtt_Graphics_Char_Pairs == NULL) &&
1922 ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
1924 SLtt_Has_Alt_Charset = 0;
1925 Enable_Alt_Char_Set = NULL;
1927 else SLtt_Has_Alt_Charset = 1;
1930 /* status line capabilities */
1931 if ((SLtt_Has_Status_Line == -1)
1932 && (0 != (SLtt_Has_Status_Line = TGETFLAG ("hs"))))
1934 Disable_Status_line_Str = SLtt_tgetstr ("ds");
1935 Return_From_Status_Line_Str = SLtt_tgetstr ("fs");
1936 Goto_Status_Line_Str = SLtt_tgetstr ("ts");
1937 Status_Line_Esc_Ok = TGETFLAG("es");
1938 Num_Status_Line_Columns = TGETNUM("ws");
1939 if (Num_Status_Line_Columns < 0) Num_Status_Line_Columns = 0;
1942 if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me")))
1944 Norm_Vid_Str = SLtt_tgetstr("se");
1947 Cursor_Invisible_Str = SLtt_tgetstr("vi");
1948 Cursor_Visible_Str = SLtt_tgetstr("ve");
1950 Curs_F_Str = SLtt_tgetstr("RI");
1952 #if 0
1953 if (NULL != Curs_F_Str)
1955 Len_Curs_F_Str = strlen(Curs_F_Str);
1957 else Len_Curs_F_Str = strlen(Curs_Pos_Str);
1958 #endif
1960 Automatic_Margins = TGETFLAG ("am");
1961 /* No_Move_In_Standout = !TGETFLAG ("ms"); */
1962 #ifdef HP_GLITCH_CODE
1963 Has_HP_Glitch = TGETFLAG ("xs");
1964 #else
1965 Worthless_Highlight = TGETFLAG ("xs");
1966 #endif
1968 if (Worthless_Highlight == 0)
1969 { /* Magic cookie glitch */
1970 Worthless_Highlight = (TGETNUM ("sg") > 0);
1973 if (Worthless_Highlight)
1974 SLtt_Has_Alt_Charset = 0;
1976 /* Check for color information in the termcap. A program should not
1977 * rely on this information being accurate.
1979 if (SLtt_Use_Ansi_Colors == 0)
1981 Reset_Color_String = SLtt_tgetstr ("op");
1983 SLtt_Use_Ansi_Colors = ((NULL != Reset_Color_String)
1984 || (NULL != SLtt_tgetstr ("Sf"))
1985 || (NULL != SLtt_tgetstr ("Sb"))
1986 || (NULL != SLtt_tgetstr ("AF"))
1987 || (NULL != SLtt_tgetstr ("AB"))
1988 || (-1 != SLtt_tgetnum ("Co"))
1989 || (-1 != SLtt_tgetnum ("pa")));
1993 #if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
1995 * Override the alt-char-set handling string in case of a
1996 * QNX/qansi terminal: use the "old style" strings in order
1997 * to be compatible with S-Lang without the SLTT_TRANSP_ACS_PATCH
1998 * code...
2000 if (SLtt_Has_Alt_Charset &&
2001 strncmp(term, "qansi", 5) == 0 &&
2002 Start_Alt_Chars_Str[0] != '\016')
2004 Start_Alt_Chars_Str = "\016"; /* smacs/as (^N) */
2005 End_Alt_Chars_Str = "\017"; /* rmacs/ae (^O) */
2006 SLtt_Graphics_Char_Pairs = /* acsc/ac */
2007 "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~O\141";
2010 * it would be required to modify the sgr/sa entry also, if it
2011 * would be used (->embedded as/ae sequences)...
2014 #endif /* __QNX__ && QNX_QANSI_SLANG_COMPAT_ACS */
2018 #endif
2019 /* Unix */
2021 /* specific to vtxxx only */
2022 void SLtt_enable_cursor_keys (void)
2024 #ifdef __unix__
2025 if (Vt100_Like)
2026 #endif
2027 SLtt_write_string("\033=\033[?1l");
2030 #ifdef VMS
2031 void SLtt_get_terminfo ()
2033 int zero = 0;
2035 get_color_info ();
2037 SLtt_set_term_vtxxx(&zero);
2038 Start_Alt_Chars_Str = "\016";
2039 End_Alt_Chars_Str = "\017";
2040 SLtt_Has_Alt_Charset = 1;
2041 SLtt_Graphics_Char_Pairs = "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
2042 Enable_Alt_Char_Set = "\033(B\033)0";
2043 SLtt_get_screen_size ();
2045 #endif
2047 /* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
2048 * is non-zero, set terminal appropriate for a only vt100
2049 * (no add line capability). */
2051 void SLtt_set_term_vtxxx(int *vt100)
2053 Norm_Vid_Str = "\033[m";
2055 Scroll_R_Str = "\033[%i%d;%dr";
2056 Cls_Str = "\033[2J\033[H";
2057 Rev_Vid_Str = "\033[7m";
2058 Bold_Vid_Str = "\033[1m";
2059 Blink_Vid_Str = "\033[5m";
2060 UnderLine_Vid_Str = "\033[4m";
2061 Del_Eol_Str = "\033[K";
2062 Rev_Scroll_Str = "\033M";
2063 Curs_F_Str = "\033[%dC";
2064 /* Len_Curs_F_Str = 5; */
2065 Curs_Pos_Str = "\033[%i%d;%dH";
2066 if ((vt100 == NULL) || (*vt100 == 0))
2068 Ins_Mode_Str = "\033[4h";
2069 Eins_Mode_Str = "\033[4l";
2070 Del_Char_Str = "\033[P";
2071 Del_N_Lines_Str = "\033[%dM";
2072 Add_N_Lines_Str = "\033[%dL";
2073 SLtt_Term_Cannot_Insert = 0;
2075 else
2077 Del_N_Lines_Str = NULL;
2078 Add_N_Lines_Str = NULL;
2079 SLtt_Term_Cannot_Insert = 1;
2081 SLtt_Term_Cannot_Scroll = 0;
2082 /* No_Move_In_Standout = 0; */
2085 void SLtt_init_video (void)
2087 /* send_string_to_term("\033[?6h"); */
2088 /* relative origin mode */
2089 SLtt_write_string (Term_Init_Str);
2090 SLtt_write_string (Keypad_Init_Str);
2091 SLtt_reset_scroll_region();
2092 SLtt_end_insert();
2093 SLtt_write_string (Enable_Alt_Char_Set);
2094 Video_Initialized = 1;
2098 void SLtt_reset_video (void)
2100 SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
2101 Cursor_Set = 0;
2102 SLtt_normal_video (); /* MSKermit requires this */
2103 SLtt_write_string(Norm_Vid_Str);
2105 Current_Fgbg = 0xFFFFFFFFU;
2106 SLtt_set_alt_char_set (0);
2107 if (SLtt_Use_Ansi_Colors)
2109 if (Reset_Color_String == NULL)
2111 SLtt_Char_Type attr;
2112 if (-1 != make_color_fgbg (NULL, NULL, &attr))
2113 write_attributes (attr);
2114 else SLtt_write_string ("\033[0m\033[m");
2116 else SLtt_write_string (Reset_Color_String);
2117 Current_Fgbg = 0xFFFFFFFFU;
2119 SLtt_erase_line ();
2120 SLtt_write_string (Keypad_Reset_Str);
2121 SLtt_write_string (Term_Reset_Str);
2122 SLtt_flush_output ();
2123 Video_Initialized = 0;
2126 void SLtt_bold_video (void)
2128 SLtt_write_string (Bold_Vid_Str);
2131 int SLtt_set_mouse_mode (int mode, int force)
2133 char *term;
2135 if (force == 0)
2137 if (NULL == (term = (char *) getenv("TERM"))) return -1;
2138 if (strncmp ("xterm", term, 5))
2139 return -1;
2142 if (mode)
2143 SLtt_write_string ("\033[?9h");
2144 else
2145 SLtt_write_string ("\033[?9l");
2147 return 0;
2151 void SLtt_disable_status_line (void)
2153 if (SLtt_Has_Status_Line > 0)
2154 SLtt_write_string (Disable_Status_line_Str);
2157 int SLtt_write_to_status_line (char *s, int col)
2159 if ((SLtt_Has_Status_Line <= 0)
2160 || (Goto_Status_Line_Str == NULL)
2161 || (Return_From_Status_Line_Str == NULL))
2162 return -1;
2164 tt_printf (Goto_Status_Line_Str, col, 0);
2165 SLtt_write_string (s);
2166 SLtt_write_string (Return_From_Status_Line_Str);
2167 return 0;
2171 void SLtt_get_screen_size (void)
2173 #ifdef VMS
2174 int status, code;
2175 unsigned short chan;
2176 $DESCRIPTOR(dev_dsc, "SYS$INPUT:");
2177 #endif
2178 #ifdef __os2__
2179 VIOMODEINFO vioModeInfo;
2180 #endif
2181 int r = 0, c = 0;
2183 #if defined(TIOCGWINSZ) && !defined(SCO_FLAVOR)
2184 struct winsize wind_struct;
2188 if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
2189 || (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
2190 || (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
2192 c = (int) wind_struct.ws_col;
2193 r = (int) wind_struct.ws_row;
2194 break;
2197 while (errno == EINTR);
2199 #endif
2201 #ifdef VMS
2202 status = sys$assign(&dev_dsc,&chan,0,0,0);
2203 if (status & 1)
2205 code = DVI$_DEVBUFSIZ;
2206 status = lib$getdvi(&code, &chan,0, &c, 0,0);
2207 if (!(status & 1))
2208 c = 80;
2209 code = DVI$_TT_PAGE;
2210 status = lib$getdvi(&code, &chan,0, &r, 0,0);
2211 if (!(status & 1))
2212 r = 24;
2213 sys$dassgn(chan);
2215 #endif
2217 #ifdef __os2__
2218 vioModeInfo.cb = sizeof(vioModeInfo);
2219 VioGetMode (&vioModeInfo, 0);
2220 c = vioModeInfo.col;
2221 r = vioModeInfo.row;
2222 #endif
2224 if (r <= 0)
2226 char *s = getenv ("LINES");
2227 if (s != NULL) r = atoi (s);
2230 if (c <= 0)
2232 char *s = getenv ("COLUMNS");
2233 if (s != NULL) c = atoi (s);
2236 if ((r <= 0) || (r > 200)) r = 24;
2237 if ((c <= 0) || (c > 250)) c = 80;
2238 SLtt_Screen_Rows = r;
2239 SLtt_Screen_Cols = c;