it.po converted in UTF-8, changed some upper/lower convention in a more 'italian...
[midnight-commander.git] / slang / sldisply.c
blob651c5da3867357205caa77cc9f6240f50f943815
1 /* Copyright (c) 1992, 1999, 2001, 2002 John E. Davis
2 * This file is part of the S-Lang library.
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Perl Artistic License.
6 */
7 #include "slinclud.h"
9 #include <time.h>
10 #include <ctype.h>
12 #if !defined(VMS) || (__VMS_VER >= 70000000)
13 # include <sys/time.h>
14 # ifdef __QNX__
15 # include <sys/select.h>
16 # endif
17 # include <sys/types.h>
18 #endif
20 #ifdef __BEOS__
21 /* Prototype for select */
22 # include <net/socket.h>
23 #endif
25 #ifdef HAVE_TERMIOS_H
26 # include <termios.h>
27 #endif
29 #ifdef VMS
30 # include <unixlib.h>
31 # include <unixio.h>
32 # include <dvidef.h>
33 # include <descrip.h>
34 # include <lib$routines.h>
35 # include <starlet.h>
36 #else
37 # if !defined(sun)
38 # include <sys/ioctl.h>
39 # endif
40 #endif
42 #ifdef SYSV
43 # include <sys/termio.h>
44 # include <sys/stream.h>
45 # include <sys/ptem.h>
46 # include <sys/tty.h>
47 #endif
49 #if defined (_AIX) && !defined (FD_SET)
50 # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
51 #endif
53 #include <errno.h>
55 #if defined(__DECC) && defined(VMS)
56 /* These get prototypes for write an sleep */
57 # include <unixio.h>
58 #endif
59 #include <signal.h>
61 #include "slang.h"
62 #include "_slang.h"
64 /* Colors: These definitions are used for the display. However, the
65 * application only uses object handles which get mapped to this
66 * internal representation. The mapping is performed by the Color_Map
67 * structure below. */
69 #define CHAR_MASK 0x000000FF
70 #define FG_MASK 0x0000FF00
71 #define BG_MASK 0x00FF0000
72 #define ATTR_MASK 0x1F000000
73 #define BGALL_MASK 0x0FFF0000
75 /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
76 * not include this attribute.
79 #define GET_FG(color) ((color & FG_MASK) >> 8)
80 #define GET_BG(color) ((color & BG_MASK) >> 16)
81 #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
83 int SLtt_Screen_Cols;
84 int SLtt_Screen_Rows;
85 int SLtt_Term_Cannot_Insert;
86 int SLtt_Term_Cannot_Scroll;
87 int SLtt_Use_Ansi_Colors;
88 int SLtt_Blink_Mode = 1;
89 int SLtt_Use_Blink_For_ACS = 0;
90 int SLtt_Newline_Ok = 0;
91 int SLtt_Has_Alt_Charset = 0;
92 int SLtt_Force_Keypad_Init = 0;
94 void (*_SLtt_color_changed_hook)(void);
96 #if SLTT_HAS_NON_BCE_SUPPORT
97 static int Bce_Color_Offset = 0;
98 #endif
99 static int Can_Background_Color_Erase = 1;
101 /* -1 means unknown */
102 int SLtt_Has_Status_Line = -1; /* hs */
103 int SLang_TT_Write_FD = -1;
105 static int Automatic_Margins;
106 /* static int No_Move_In_Standout; */
107 static int Worthless_Highlight;
108 #define HP_GLITCH_CODE
109 #ifdef HP_GLITCH_CODE
110 /* This glitch is exclusive to HP term. Basically it means that to clear
111 * attributes, one has to erase to the end of the line.
113 static int Has_HP_Glitch;
114 #endif
116 static char *Reset_Color_String;
117 static int Is_Color_Terminal = 0;
119 static int Linux_Console;
121 /* It is crucial that JMAX_COLORS must be less than 128 since the high bit
122 * is used to indicate a character from the ACS (alt char set). The exception
123 * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
124 * the highbit is set, we interpret that as a blink character. This is
125 * exploited by DOSemu.
127 #define JMAX_COLORS 256
128 #define JNORMAL_COLOR 0
130 typedef struct
132 SLtt_Char_Type fgbg;
133 SLtt_Char_Type mono;
134 char *custom_esc;
136 Ansi_Color_Type;
138 #define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
139 #define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
141 static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] =
143 {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL}, /* white/black */
144 {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK, NULL}, /* green/black */
145 {RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* magenta/black */
146 {RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* cyan/black */
147 {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
148 {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
149 {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
150 {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK, NULL},
151 {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK, NULL},
152 {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK, NULL},
153 {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
154 {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
155 {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
156 {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK, NULL},
157 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
158 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
159 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
160 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL}
163 /* 0 if least significant bit is blue, not red */
164 static int Is_Fg_BGR = 0;
165 static int Is_Bg_BGR = 0;
166 #define COLOR_ARG(color, is_bgr) (is_bgr ? RGB_to_BGR[color] : color)
167 static int RGB_to_BGR[] =
169 0, 4, 2, 6, 1, 5, 3, 7
172 static char *Color_Fg_Str = "\033[3%dm";
173 static char *Color_Bg_Str = "\033[4%dm";
174 static char *Default_Color_Fg_Str = "\033[39m";
175 static char *Default_Color_Bg_Str = "\033[49m";
177 static int Max_Terminfo_Colors = 8; /* termcap Co */
179 char *SLtt_Graphics_Char_Pairs; /* ac termcap string -- def is vt100 */
181 /* 1 if terminal lacks the ability to go into insert mode or into delete
182 mode. Currently controlled by S-Lang but later perhaps termcap. */
184 static char *UnderLine_Vid_Str;
185 static char *Blink_Vid_Str;
186 static char *Bold_Vid_Str;
187 static char *Ins_Mode_Str; /* = "\033[4h"; */ /* ins mode (im) */
188 static char *Eins_Mode_Str; /* = "\033[4l"; */ /* end ins mode (ei) */
189 static char *Scroll_R_Str; /* = "\033[%d;%dr"; */ /* scroll region */
190 static char *Cls_Str; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
191 static char *Rev_Vid_Str; /* = "\033[7m"; */ /* mr,so termcap string */
192 static char *Norm_Vid_Str; /* = "\033[m"; */ /* me,se termcap string */
193 static char *Del_Eol_Str; /* = "\033[K"; */ /* ce */
194 static char *Del_Bol_Str; /* = "\033[1K"; */ /* cb */
195 static char *Del_Char_Str; /* = "\033[P"; */ /* dc */
196 static char *Del_N_Lines_Str; /* = "\033[%dM"; */ /* DL */
197 static char *Add_N_Lines_Str; /* = "\033[%dL"; */ /* AL */
198 static char *Rev_Scroll_Str;
199 static char *Curs_Up_Str;
200 static char *Curs_F_Str; /* RI termcap string */
201 static char *Cursor_Visible_Str; /* ve termcap string */
202 static char *Cursor_Invisible_Str; /* vi termcap string */
203 #if 0
204 static char *Start_Mouse_Rpt_Str; /* Start mouse reporting mode */
205 static char *End_Mouse_Rpt_Str; /* End mouse reporting mode */
206 #endif
207 static char *Start_Alt_Chars_Str; /* as */
208 static char *End_Alt_Chars_Str; /* ae */
209 static char *Enable_Alt_Char_Set; /* eA */
211 static char *Term_Init_Str;
212 static char *Keypad_Init_Str;
213 static char *Term_Reset_Str;
214 static char *Keypad_Reset_Str;
216 /* status line functions */
217 static char *Disable_Status_line_Str; /* ds */
218 static char *Return_From_Status_Line_Str; /* fs */
219 static char *Goto_Status_Line_Str; /* ts */
220 static int Num_Status_Line_Columns; /* ws */
221 /* static int Status_Line_Esc_Ok; */ /* es */
223 /* static int Len_Curs_F_Str = 5; */
225 /* cm string has %i%d since termcap numbers columns from 0 */
226 /* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
227 static char *Curs_Pos_Str; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
229 /* scrolling region */
230 static int Scroll_r1 = 0, Scroll_r2 = 23;
231 static int Cursor_r, Cursor_c; /* 0 based */
233 /* current attributes --- initialized to impossible value */
234 static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFFU;
236 static int Cursor_Set; /* 1 if cursor position known, 0
237 * if not. -1 if only row is known
240 #define MAX_OUTPUT_BUFFER_SIZE 4096
242 static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
243 static unsigned char *Output_Bufferp = Output_Buffer;
245 unsigned long SLtt_Num_Chars_Output;
247 int _SLusleep (unsigned long usecs)
249 #if !defined(VMS) || (__VMS_VER >= 70000000)
250 struct timeval tv;
251 tv.tv_sec = usecs / 1000000;
252 tv.tv_usec = usecs % 1000000;
253 return select(0, NULL, NULL, NULL, &tv);
254 #else
255 return 0;
256 #endif
259 int SLtt_flush_output (void)
261 int nwrite = 0;
262 unsigned int total;
263 int n = (int) (Output_Bufferp - Output_Buffer);
265 SLtt_Num_Chars_Output += n;
267 total = 0;
268 while (n > 0)
270 nwrite = write (SLang_TT_Write_FD, (char *) Output_Buffer + total, n);
271 if (nwrite == -1)
273 nwrite = 0;
274 #ifdef EAGAIN
275 if (errno == EAGAIN)
277 _SLusleep (100000); /* 1/10 sec */
278 continue;
280 #endif
281 #ifdef EWOULDBLOCK
282 if (errno == EWOULDBLOCK)
284 _SLusleep (100000);
285 continue;
287 #endif
288 #ifdef EINTR
289 if (errno == EINTR) continue;
290 #endif
291 break;
293 n -= nwrite;
294 total += nwrite;
296 Output_Bufferp = Output_Buffer;
297 return n;
300 int SLtt_Baud_Rate;
301 static void tt_write(char *str, unsigned int n)
303 static unsigned long last_time;
304 static int total;
305 unsigned long now;
306 unsigned int ndiff;
308 if ((str == NULL) || (n == 0)) return;
309 total += n;
311 while (1)
313 ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
314 if (ndiff < n)
316 SLMEMCPY ((char *) Output_Bufferp, (char *) str, ndiff);
317 Output_Bufferp += ndiff;
318 SLtt_flush_output ();
319 n -= ndiff;
320 str += ndiff;
322 else
324 SLMEMCPY ((char *) Output_Bufferp, str, n);
325 Output_Bufferp += n;
326 break;
330 if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
331 && (10 * total > SLtt_Baud_Rate))
333 total = 0;
334 if ((now = (unsigned long) time(NULL)) - last_time <= 1)
336 SLtt_flush_output ();
337 sleep((unsigned) 1);
339 last_time = now;
343 static void tt_write_string (char *str)
345 if (str != NULL) tt_write(str, strlen(str));
348 void SLtt_write_string (char *str)
350 tt_write_string (str);
351 Cursor_Set = 0;
354 void SLtt_putchar (char ch)
356 SLtt_normal_video ();
357 if (Cursor_Set == 1)
359 if (ch >= ' ') Cursor_c++;
360 else if (ch == '\b') Cursor_c--;
361 else if (ch == '\r') Cursor_c = 0;
362 else Cursor_Set = 0;
364 if ((Cursor_c + 1 == SLtt_Screen_Cols)
365 && Automatic_Margins) Cursor_Set = 0;
368 if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
370 *Output_Bufferp++ = (unsigned char) ch;
372 else tt_write (&ch, 1);
375 static unsigned int tt_sprintf(char *buf, char *fmt, int x, int y)
377 char *fmt_max;
378 register unsigned char *b, ch;
379 int offset;
380 int z, z1, parse_level;
381 int zero_pad;
382 int field_width;
383 int variables [26];
384 int stack [64];
385 unsigned int stack_len;
386 int parms [10];
387 #define STACK_POP (stack_len ? stack[--stack_len] : 0)
389 if (fmt == NULL)
391 *buf = 0;
392 return 0;
395 stack [0] = y; /* pushed for termcap */
396 stack [1] = x;
397 stack_len = 2;
399 parms [1] = x; /* p1 */
400 parms [2] = y; /* p2 */
402 offset = 0;
403 zero_pad = 0;
404 field_width = 0;
406 b = (unsigned char *) buf;
407 fmt_max = fmt + strlen (fmt);
409 while (fmt < fmt_max)
411 ch = *fmt++;
413 if (ch != '%')
415 *b++ = ch;
416 continue;
419 if (fmt == fmt_max) break;
420 ch = *fmt++;
422 switch (ch)
424 default:
425 *b++ = ch;
426 break;
428 case 'p':
430 if (fmt == fmt_max) break;
431 ch = *fmt++;
432 if ((ch >= '0') && (ch <= '9'))
433 stack [stack_len++] = parms [ch - '0'];
434 break;
436 case '\'': /* 'x' */
437 if (fmt == fmt_max) break;
438 stack [stack_len++] = *fmt++;
439 if (fmt < fmt_max) fmt++; /* skip ' */
440 break;
442 case '{': /* literal constant, e.g. {30} */
443 z = 0;
444 while ((fmt < fmt_max) && ((ch = *fmt) <= '9') && (ch >= '0'))
446 z = z * 10 + (ch - '0');
447 fmt++;
449 stack [stack_len++] = z;
450 if ((ch == '}') && (fmt < fmt_max)) fmt++;
451 break;
453 case '0':
454 if (fmt == fmt_max) break;
455 ch = *fmt;
456 if ((ch != '2') && (ch != '3'))
457 break;
458 zero_pad = 1;
459 fmt++;
460 /* drop */
462 case '2':
463 case '3':
464 if (fmt == fmt_max)
465 if (*fmt == 'x')
467 char x_fmt_buf [4];
468 char *x_fmt_buf_ptr;
470 x_fmt_buf_ptr = x_fmt_buf;
471 if (zero_pad) *x_fmt_buf_ptr++ = '0';
472 *x_fmt_buf_ptr++ = ch;
473 *x_fmt_buf_ptr++ = 'X';
474 *x_fmt_buf_ptr = 0;
476 z = STACK_POP;
477 z += offset;
479 sprintf ((char *)b, x_fmt_buf, z);
480 b += strlen ((char *)b);
481 zero_pad = 0;
482 break;
485 field_width = (ch - '0');
486 /* drop */
488 case 'd':
489 z = STACK_POP;
490 z += offset;
491 if (z >= 100)
493 *b++ = z / 100 + '0';
494 z = z % 100;
495 zero_pad = 1;
496 field_width = 2;
498 else if (zero_pad && (field_width == 3))
499 *b++ = '0';
501 if (z >= 10)
503 *b++ = z / 10 + '0';
504 z = z % 10;
506 else if (zero_pad && (field_width >= 2))
507 *b++ = '0';
509 *b++ = z + '0';
510 field_width = zero_pad = 0;
511 break;
513 case 'x':
514 z = STACK_POP;
515 z += offset;
516 sprintf ((char *) b, "%X", z);
517 b += strlen ((char *)b);
518 break;
520 case 'i':
521 offset = 1;
522 break;
524 case '+':
525 /* Handling this depends upon whether or not we are parsing
526 * terminfo. Terminfo requires the stack so use it as an
527 * indicator.
529 if (stack_len > 2)
531 z = STACK_POP;
532 stack [stack_len - 1] += z;
534 else if (fmt < fmt_max)
536 ch = *fmt++;
537 if ((unsigned char) ch == 128) ch = 0;
538 ch = ch + (unsigned char) STACK_POP;
539 if (ch == '\n') ch++;
540 *b++ = ch;
542 break;
544 /* Binary operators */
545 case '-':
546 case '*':
547 case '/':
548 case 'm':
549 case '&':
550 case '|':
551 case '^':
552 case '=':
553 case '>':
554 case '<':
555 case 'A':
556 case 'O':
557 z1 = STACK_POP;
558 z = STACK_POP;
559 switch (ch)
561 case '-': z = (z - z1); break;
562 case '*': z = (z * z1); break;
563 case '/': z = (z / z1); break;
564 case 'm': z = (z % z1); break;
565 case '&': z = (z & z1); break;
566 case '|': z = (z | z1); break;
567 case '^': z = (z ^ z1); break;
568 case '=': z = (z == z1); break;
569 case '>': z = (z > z1); break;
570 case '<': z = (z < z1); break;
571 case 'A': z = (z && z1); break;
572 case 'O': z = (z || z1); break;
574 stack [stack_len++] = z;
575 break;
577 /* unary */
578 case '!':
579 z = STACK_POP;
580 stack [stack_len++] = !z;
581 break;
583 case '~':
584 z = STACK_POP;
585 stack [stack_len++] = ~z;
586 break;
588 case 'r': /* termcap -- swap parameters */
589 z = stack [0];
590 stack [0] = stack [1];
591 stack [1] = z;
592 break;
594 case '.': /* termcap */
595 case 'c':
596 ch = (unsigned char) STACK_POP;
597 if (ch == '\n') ch++;
598 *b++ = ch;
599 break;
601 case 'g':
602 if (fmt == fmt_max) break;
603 ch = *fmt++;
604 if ((ch >= 'a') && (ch <= 'z'))
605 stack [stack_len++] = variables [ch - 'a'];
606 break;
608 case 'P':
609 if (fmt == fmt_max) break;
610 ch = *fmt++;
611 if ((ch >= 'a') && (ch <= 'z'))
612 variables [ch - 'a'] = STACK_POP;
613 break;
615 /* If then else parsing. Actually, this is rather easy. The
616 * key is to notice that 'then' does all the work. 'if' simply
617 * there to indicate the start of a test and endif indicates
618 * the end of tests. If 'else' is seen, then skip to
619 * endif.
621 case '?': /* if */
622 case ';': /* endif */
623 break;
625 case 't': /* then */
626 z = STACK_POP;
627 if (z != 0)
628 break; /* good. Continue parsing. */
630 /* z == 0 and test has failed. So, skip past this entire if
631 * expression to the matching else or matching endif.
633 /* drop */
634 case 'e': /* else */
636 parse_level = 0;
637 while (fmt < fmt_max)
639 unsigned char ch1;
641 ch1 = *fmt++;
642 if ((ch1 != '%') || (fmt == fmt_max))
643 continue;
645 ch1 = *fmt++;
647 if (ch1 == '?') parse_level++; /* new if */
648 else if (ch1 == 'e')
650 if ((ch != 'e') && (parse_level == 0))
651 break;
653 else if (ch1 == ';')
655 if (parse_level == 0)
656 break;
657 parse_level--;
660 break;
663 *b = 0;
664 return (unsigned int) (b - (unsigned char *) buf);
667 static void tt_printf(char *fmt, int x, int y)
669 char buf[1024];
670 unsigned int n;
671 if (fmt == NULL) return;
672 n = tt_sprintf(buf, fmt, x, y);
673 tt_write(buf, n);
676 void SLtt_set_scroll_region (int r1, int r2)
678 Scroll_r1 = r1;
679 Scroll_r2 = r2;
680 tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
681 Cursor_Set = 0;
684 void SLtt_reset_scroll_region (void)
686 SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
689 int SLtt_set_cursor_visibility (int show)
691 if ((Cursor_Visible_Str == NULL) || (Cursor_Invisible_Str == NULL))
692 return -1;
694 tt_write_string (show ? Cursor_Visible_Str : Cursor_Invisible_Str);
695 return 0;
698 /* the goto_rc function moves to row relative to scrolling region */
699 void SLtt_goto_rc(int r, int c)
701 char *s = NULL;
702 int n;
703 char buf[6];
705 if ((c < 0) || (r < 0))
707 Cursor_Set = 0;
708 return;
711 /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
712 r += Scroll_r1;
714 if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
716 n = r - Cursor_r;
717 if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c)
718 && (Curs_Up_Str != NULL))
720 s = Curs_Up_Str;
722 else if ((n >= 0) && (n <= 4))
724 if ((n == 0) && (Cursor_Set == 1)
725 && ((c > 1) || (c == Cursor_c)))
727 if (Cursor_c == c) return;
728 if (Cursor_c == c + 1)
730 s = buf;
731 *s++ = '\b'; *s = 0;
732 s = buf;
735 else if (c == 0)
737 s = buf;
738 if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
739 while (n--) *s++ = '\n';
740 #ifdef VMS
741 /* Need to add this after \n to start a new record. Sheesh. */
742 *s++ = '\r';
743 #endif
744 *s = 0;
745 s = buf;
747 /* Will fail on VMS */
748 #ifndef VMS
749 else if (SLtt_Newline_Ok && (Cursor_Set == 1) &&
750 (Cursor_c >= c) && (c + 3 > Cursor_c))
752 s = buf;
753 while (n--) *s++ = '\n';
754 n = Cursor_c - c;
755 while (n--) *s++ = '\b';
756 *s = 0;
757 s = buf;
759 #endif
762 if (s != NULL) tt_write_string(s);
763 else tt_printf(Curs_Pos_Str, r, c);
764 Cursor_c = c; Cursor_r = r;
765 Cursor_Set = 1;
768 void SLtt_begin_insert (void)
770 tt_write_string(Ins_Mode_Str);
773 void SLtt_end_insert (void)
775 tt_write_string(Eins_Mode_Str);
778 void SLtt_delete_char (void)
780 SLtt_normal_video ();
781 tt_write_string(Del_Char_Str);
784 void SLtt_erase_line (void)
786 tt_write_string("\r");
787 Cursor_Set = 1; Cursor_c = 0;
788 SLtt_del_eol();
791 /* It appears that the Linux console, and most likely others do not
792 * like scrolling regions that consist of one line. So I have to
793 * resort to this stupidity to make up for that stupidity.
795 static void delete_line_in_scroll_region (void)
797 SLtt_goto_rc (Cursor_r - Scroll_r1, 0);
798 SLtt_del_eol ();
801 void SLtt_delete_nlines (int n)
803 int r1, curs;
804 char buf[132];
806 if (n <= 0) return;
807 SLtt_normal_video ();
809 if (Scroll_r1 == Scroll_r2)
811 delete_line_in_scroll_region ();
812 return;
815 if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str,n, 0);
816 else
817 /* get a new terminal */
819 r1 = Scroll_r1;
820 curs = Cursor_r;
821 SLtt_set_scroll_region(curs, Scroll_r2);
822 SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
823 SLMEMSET(buf, '\n', (unsigned int) n);
824 tt_write(buf, (unsigned int) n);
825 /* while (n--) tt_putchar('\n'); */
826 SLtt_set_scroll_region(r1, Scroll_r2);
827 SLtt_goto_rc(curs, 0);
831 void SLtt_cls (void)
833 /* If the terminal is a color terminal but the user wants black and
834 * white, then make sure that the colors are reset. This appears to be
835 * necessary.
837 if ((SLtt_Use_Ansi_Colors == 0) && Is_Color_Terminal)
839 if (Reset_Color_String != NULL)
840 tt_write_string (Reset_Color_String);
841 else
842 tt_write_string ("\033[0m\033[m");
845 SLtt_normal_video();
846 SLtt_reset_scroll_region ();
847 tt_write_string(Cls_Str);
850 void SLtt_reverse_index (int n)
852 if (!n) return;
854 SLtt_normal_video();
856 if (Scroll_r1 == Scroll_r2)
858 delete_line_in_scroll_region ();
859 return;
862 if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
863 else
865 while(n--) tt_write_string(Rev_Scroll_Str);
869 int SLtt_Ignore_Beep = 1;
870 static char *Visible_Bell_Str;
872 void SLtt_beep (void)
874 if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
876 if (SLtt_Ignore_Beep & 0x2)
878 if (Visible_Bell_Str != NULL) tt_write_string (Visible_Bell_Str);
879 #ifdef __linux__
880 else if (Linux_Console)
882 tt_write_string ("\033[?5h");
883 SLtt_flush_output ();
884 _SLusleep (50000);
885 tt_write_string ("\033[?5l");
887 #endif
889 SLtt_flush_output ();
892 static void del_eol (void)
894 int c;
896 if (Del_Eol_Str != NULL)
898 tt_write_string(Del_Eol_Str);
899 return;
902 c = Cursor_c;
903 /* Avoid writing to the lower right corner. If the terminal does not
904 * have Del_Eol_Str, then it probably does not have what it takes to play
905 * games with insert for for a space into that corner.
907 if (Cursor_r + 1 < SLtt_Screen_Rows)
908 c++;
910 while (c < SLtt_Screen_Cols)
912 tt_write (" ", 1);
913 c++;
917 void SLtt_del_eol (void)
919 if (Current_Fgbg != 0xFFFFFFFFU) SLtt_normal_video ();
920 del_eol ();
923 typedef const struct
925 char *name;
926 SLtt_Char_Type color;
928 Color_Def_Type;
930 #define MAX_COLOR_NAMES 17
931 static Color_Def_Type Color_Defs [MAX_COLOR_NAMES] =
933 {"black", SLSMG_COLOR_BLACK},
934 {"red", SLSMG_COLOR_RED},
935 {"green", SLSMG_COLOR_GREEN},
936 {"brown", SLSMG_COLOR_BROWN},
937 {"blue", SLSMG_COLOR_BLUE},
938 {"magenta", SLSMG_COLOR_MAGENTA},
939 {"cyan", SLSMG_COLOR_CYAN},
940 {"lightgray", SLSMG_COLOR_LGRAY},
941 {"gray", SLSMG_COLOR_GRAY},
942 {"brightred", SLSMG_COLOR_BRIGHT_RED},
943 {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN},
944 {"yellow", SLSMG_COLOR_BRIGHT_BROWN},
945 {"brightblue", SLSMG_COLOR_BRIGHT_BLUE},
946 {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN},
947 {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA},
948 {"white", SLSMG_COLOR_BRIGHT_WHITE},
949 #define SLSMG_COLOR_DEFAULT 0xFF
950 {"default", SLSMG_COLOR_DEFAULT}
953 void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
955 (void) what;
956 if ((obj < 0) || (obj >= JMAX_COLORS))
958 return;
960 Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
963 static char *check_color_for_digit_form (char *color)
965 unsigned int i, ich;
966 char *s = color;
968 i = 0;
969 while ((ich = (int) *s) != 0)
971 if ((ich < '0') || (ich > '9'))
972 return color;
974 i = i * 10 + (ich - '0');
975 s++;
978 if (i < MAX_COLOR_NAMES)
979 color = Color_Defs[i].name;
981 return color;
984 static int get_default_colors (char **fgp, char **bgp)
986 static char fg_buf[16], bg_buf[16], *bg, *fg;
987 static int already_parsed;
988 char *p, *pmax;
990 if (already_parsed == -1)
991 return -1;
993 if (already_parsed)
995 *fgp = fg;
996 *bgp = bg;
997 return 0;
1000 already_parsed = -1;
1002 bg = getenv ("COLORFGBG");
1004 if (bg == NULL)
1006 bg = getenv ("DEFAULT_COLORS");
1007 if (bg == NULL)
1008 return -1;
1011 p = fg_buf;
1012 pmax = p + (sizeof (fg_buf) - 1);
1014 while ((*bg != 0) && (*bg != ';'))
1016 if (p < pmax) *p++ = *bg;
1017 bg++;
1019 *p = 0;
1021 if (*bg) bg++;
1023 p = bg_buf;
1024 pmax = p + (sizeof (bg_buf) - 1);
1026 /* Mark suggested allowing for extra spplication specific stuff following
1027 * the background color. That is what the check for the semi-colon is for.
1029 while ((*bg != 0) && (*bg != ';'))
1031 if (p < pmax) *p++ = *bg;
1032 bg++;
1034 *p = 0;
1036 if (!strcmp (fg_buf, "default") || !strcmp(bg_buf, "default"))
1038 *fgp = *bgp = fg = bg = "default";
1040 else
1042 *fgp = fg = check_color_for_digit_form (fg_buf);
1043 *bgp = bg = check_color_for_digit_form (bg_buf);
1045 already_parsed = 1;
1046 return 0;
1049 static unsigned char FgBg_Stats[JMAX_COLORS];
1051 static int Color_0_Modified = 0;
1053 void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
1055 char *cust_esc;
1057 if ((obj < 0) || (obj >= JMAX_COLORS)) return;
1059 cust_esc = Ansi_Color_Map[obj].custom_esc;
1060 if (cust_esc != NULL)
1062 SLfree (cust_esc);
1063 FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
1064 Ansi_Color_Map[obj].custom_esc = NULL;
1067 Ansi_Color_Map[obj].fgbg = attr;
1068 if (obj == 0) Color_0_Modified = 1;
1070 if (_SLtt_color_changed_hook != NULL)
1071 (*_SLtt_color_changed_hook)();
1074 SLtt_Char_Type SLtt_get_color_object (int obj)
1076 if ((obj < 0) || (obj >= JMAX_COLORS)) return 0;
1077 return Ansi_Color_Map[obj].fgbg;
1080 void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
1082 if ((obj < 0) || (obj >= JMAX_COLORS)) return;
1084 Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
1085 if (obj == 0) Color_0_Modified = 1;
1086 if (_SLtt_color_changed_hook != NULL)
1087 (*_SLtt_color_changed_hook)();
1090 static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
1092 SLtt_Char_Type attr;
1094 if (Max_Terminfo_Colors != 8)
1096 if (f != SLSMG_COLOR_DEFAULT) f %= Max_Terminfo_Colors;
1097 if (b != SLSMG_COLOR_DEFAULT) b %= Max_Terminfo_Colors;
1098 return ((f << 8) | (b << 16));
1101 /* Otherwise we have 8 ansi colors. Try to get bright versions
1102 * by using the BOLD and BLINK attributes.
1105 attr = 0;
1107 /* Note: If f represents default, it will have the value 0xFF */
1108 if (f != SLSMG_COLOR_DEFAULT)
1110 if (f & 0x8) attr = SLTT_BOLD_MASK;
1111 f &= 0x7;
1114 if (b != SLSMG_COLOR_DEFAULT)
1116 if (b & 0x8) attr |= SLTT_BLINK_MASK;
1117 b &= 0x7;
1120 return ((f << 8) | (b << 16) | attr);
1123 /* This looks for colors with name form 'colorN'. If color is of this
1124 * form, N is passed back via paramter list.
1126 static int parse_color_digit_name (char *color, SLtt_Char_Type *f)
1128 unsigned int i;
1129 unsigned char ch;
1131 if (strncmp (color, "color", 5))
1132 return -1;
1134 color += 5;
1135 if (*color == 0)
1136 return -1;
1138 i = 0;
1139 while (1)
1141 ch = (unsigned char) *color++;
1142 if (ch == 0)
1143 break;
1144 if ((ch > '9') || (ch < '0'))
1145 return -1;
1146 i = 10 * i + (ch - '0');
1149 *f = (SLtt_Char_Type) i;
1150 return 0;
1153 static int make_color_fgbg (char *fg, char *bg, SLtt_Char_Type *fgbg)
1155 SLtt_Char_Type f = 0xFFFFFFFFU, b = 0xFFFFFFFFU;
1156 char *dfg, *dbg;
1157 unsigned int i;
1159 if ((fg != NULL) && (*fg == 0)) fg = NULL;
1160 if ((bg != NULL) && (*bg == 0)) bg = NULL;
1162 if ((fg == NULL) || (bg == NULL))
1164 if (-1 == get_default_colors (&dfg, &dbg))
1165 return -1;
1167 if (fg == NULL) fg = dfg;
1168 if (bg == NULL) bg = dbg;
1171 if (-1 == parse_color_digit_name (fg, &f))
1173 for (i = 0; i < MAX_COLOR_NAMES; i++)
1175 if (strcmp(fg, Color_Defs[i].name)) continue;
1176 f = Color_Defs[i].color;
1177 break;
1181 if (-1 == parse_color_digit_name (bg, &b))
1183 for (i = 0; i < MAX_COLOR_NAMES; i++)
1185 if (strcmp(bg, Color_Defs[i].name)) continue;
1186 b = Color_Defs[i].color;
1187 break;
1191 if ((f == 0xFFFFFFFFU) || (b == 0xFFFFFFFFU))
1192 return -1;
1194 *fgbg = fb_to_fgbg (f, b);
1195 return 0;
1198 void SLtt_set_color (int obj, char *what, char *fg, char *bg)
1200 SLtt_Char_Type fgbg;
1202 (void) what;
1203 if ((obj < 0) || (obj >= JMAX_COLORS))
1204 return;
1206 if (-1 != make_color_fgbg (fg, bg, &fgbg))
1207 SLtt_set_color_object (obj, fgbg);
1210 void SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
1212 SLtt_set_color_object (obj, fb_to_fgbg (f, b));
1215 void SLtt_set_color_esc (int obj, char *esc)
1217 char *cust_esc;
1218 SLtt_Char_Type fgbg = 0;
1219 int i;
1221 if ((obj < 0) || (obj >= JMAX_COLORS))
1223 return;
1226 cust_esc = Ansi_Color_Map[obj].custom_esc;
1227 if (cust_esc != NULL)
1229 SLfree (cust_esc);
1230 FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
1233 cust_esc = (char *) SLmalloc (strlen(esc) + 1);
1234 if (cust_esc != NULL) strcpy (cust_esc, esc);
1236 Ansi_Color_Map[obj].custom_esc = cust_esc;
1237 if (cust_esc == NULL) fgbg = 0;
1238 else
1240 /* The whole point of this is to generate a unique fgbg */
1241 for (i = 0; i < JMAX_COLORS; i++)
1243 if (FgBg_Stats[i] == 0) fgbg = i;
1245 if (obj == i) continue;
1246 if ((Ansi_Color_Map[i].custom_esc) == NULL) continue;
1247 if (!strcmp (Ansi_Color_Map[i].custom_esc, cust_esc))
1249 fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
1250 break;
1253 FgBg_Stats[fgbg] += 1;
1256 fgbg |= 0x80;
1257 Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
1258 if (obj == 0) Color_0_Modified = 1;
1259 if (_SLtt_color_changed_hook != NULL)
1260 (*_SLtt_color_changed_hook)();
1263 void SLtt_set_alt_char_set (int i)
1265 static int last_i;
1266 if (SLtt_Has_Alt_Charset == 0) return;
1268 i = (i != 0);
1270 if (i == last_i) return;
1271 tt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
1272 last_i = i;
1275 static void write_attributes (SLtt_Char_Type fgbg)
1277 int bg0, fg0;
1278 int unknown_attributes;
1280 if (Worthless_Highlight) return;
1281 if (fgbg == Current_Fgbg) return;
1283 unknown_attributes = 0;
1285 /* Before spitting out colors, fix attributes */
1286 if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
1288 if (Current_Fgbg & ATTR_MASK)
1290 tt_write_string(Norm_Vid_Str);
1291 /* In case normal video turns off ALL attributes: */
1292 if (fgbg & SLTT_ALTC_MASK)
1293 Current_Fgbg &= ~SLTT_ALTC_MASK;
1294 SLtt_set_alt_char_set (0);
1297 if ((fgbg & SLTT_ALTC_MASK)
1298 != (Current_Fgbg & SLTT_ALTC_MASK))
1300 SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
1303 if (fgbg & SLTT_ULINE_MASK) tt_write_string (UnderLine_Vid_Str);
1304 if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
1305 if (fgbg & SLTT_REV_MASK) tt_write_string (Rev_Vid_Str);
1306 if (fgbg & SLTT_BLINK_MASK)
1308 /* Someday Linux will have a blink mode that set high intensity
1309 * background. Lets be prepared.
1311 if (SLtt_Blink_Mode) tt_write_string (Blink_Vid_Str);
1313 unknown_attributes = 1;
1316 if (SLtt_Use_Ansi_Colors)
1318 fg0 = (int) GET_FG(fgbg);
1319 bg0 = (int) GET_BG(fgbg);
1321 if (unknown_attributes
1322 || (fg0 != (int)GET_FG(Current_Fgbg)))
1324 if (fg0 == SLSMG_COLOR_DEFAULT)
1325 tt_write_string (Default_Color_Fg_Str);
1326 else
1327 tt_printf (Color_Fg_Str, COLOR_ARG(fg0, Is_Fg_BGR), 0);
1330 if (unknown_attributes
1331 || (bg0 != (int)GET_BG(Current_Fgbg)))
1333 if (bg0 == SLSMG_COLOR_DEFAULT)
1334 tt_write_string (Default_Color_Bg_Str);
1335 else
1336 tt_printf (Color_Bg_Str, COLOR_ARG(bg0, Is_Bg_BGR), 0);
1340 Current_Fgbg = fgbg;
1343 static int Video_Initialized;
1345 void SLtt_reverse_video (int color)
1347 SLtt_Char_Type fgbg;
1348 char *esc;
1350 if (Worthless_Highlight) return;
1351 if ((color < 0) || (color >= JMAX_COLORS)) return;
1353 if (Video_Initialized == 0)
1355 if (color == JNORMAL_COLOR)
1357 tt_write_string (Norm_Vid_Str);
1359 else tt_write_string (Rev_Vid_Str);
1360 Current_Fgbg = 0xFFFFFFFFU;
1361 return;
1364 if (SLtt_Use_Ansi_Colors)
1366 fgbg = Ansi_Color_Map[color].fgbg;
1367 if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
1369 if (fgbg != Current_Fgbg)
1371 Current_Fgbg = fgbg;
1372 tt_write_string (esc);
1373 return;
1377 else fgbg = Ansi_Color_Map[color].mono;
1379 if (fgbg == Current_Fgbg) return;
1380 write_attributes (fgbg);
1383 void SLtt_normal_video (void)
1385 SLtt_reverse_video(JNORMAL_COLOR);
1388 void SLtt_narrow_width (void)
1390 tt_write_string("\033[?3l");
1393 void SLtt_wide_width (void)
1395 tt_write_string("\033[?3h");
1398 /* Highest bit represents the character set. */
1399 #define COLOR_MASK 0x7F00
1401 #if SLTT_HAS_NON_BCE_SUPPORT
1402 static int bce_color_eqs (unsigned int a, unsigned int b)
1404 a = (a & COLOR_MASK) >> 8;
1405 b = (b & COLOR_MASK) >> 8;
1407 if (a == b)
1408 return 1;
1410 if (SLtt_Use_Ansi_Colors == 0)
1411 return Ansi_Color_Map[a].mono == Ansi_Color_Map[b].mono;
1413 if (Bce_Color_Offset == 0)
1414 return Ansi_Color_Map[a].fgbg == Ansi_Color_Map[b].fgbg;
1416 /* If either are color 0, then we do not know what that means since the
1417 * terminal does not support BCE */
1418 if ((a == 0) || (b == 0))
1419 return 0;
1421 return Ansi_Color_Map[a-1].fgbg == Ansi_Color_Map[b-1].fgbg;
1423 #define COLOR_EQS(a,b) bce_color_eqs (a,b)
1424 #else
1425 # define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
1426 # define COLOR_EQS(a, b) \
1427 (SLtt_Use_Ansi_Colors \
1428 ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
1429 : (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
1430 #endif
1432 #define CHAR_EQS(a, b) (((a) == (b))\
1433 || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
1434 && COLOR_EQS((a), (b))))
1436 /* The whole point of this routine is to prevent writing to the last column
1437 * and last row on terminals with automatic margins.
1439 static void write_string_with_care (char *str)
1441 unsigned int len;
1443 if (str == NULL) return;
1445 len = strlen (str);
1446 if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
1448 if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
1450 /* For now, just do not write there. Later, something more
1451 * sophisticated will be implemented.
1453 if (SLtt_Screen_Cols > Cursor_c)
1454 len = SLtt_Screen_Cols - Cursor_c - 1;
1455 else
1456 len = 0;
1459 tt_write (str, len);
1462 static void send_attr_str (SLsmg_Char_Type *s)
1464 unsigned char out[256], ch, *p;
1465 register SLtt_Char_Type attr;
1466 register SLsmg_Char_Type sh;
1467 int color, last_color = -1;
1469 p = out;
1470 while (0 != (sh = *s++))
1472 ch = sh & 0xFF;
1473 color = ((int) sh & 0xFF00) >> 8;
1475 #if SLTT_HAS_NON_BCE_SUPPORT
1476 if (Bce_Color_Offset
1477 && (color >= Bce_Color_Offset))
1478 color -= Bce_Color_Offset;
1479 #endif
1481 if (color != last_color)
1483 if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
1484 else attr = Ansi_Color_Map[color & 0x7F].mono;
1486 if (sh & 0x8000) /* alternate char set */
1488 if (SLtt_Use_Blink_For_ACS)
1490 if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
1492 else attr |= SLTT_ALTC_MASK;
1495 if (attr != Current_Fgbg)
1497 if ((ch != ' ') ||
1498 /* it is a space so only consider it different if it
1499 * has different attributes.
1501 (attr != Current_Fgbg))
1502 /* The previous line was: */
1503 /* (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK)) */
1504 /* However, it does not account for ACS */
1506 if (p != out)
1508 *p = 0;
1509 write_string_with_care ((char *) out);
1510 Cursor_c += (int) (p - out);
1511 p = out;
1514 if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
1516 tt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
1517 /* Just in case the custom escape sequence screwed up
1518 * the alt character set state...
1520 if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
1521 SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
1522 Current_Fgbg = attr;
1524 else write_attributes (attr);
1526 last_color = color;
1530 *p++ = ch;
1532 *p = 0;
1533 if (p != out) write_string_with_care ((char *) out);
1534 Cursor_c += (int) (p - out);
1537 static void forward_cursor (unsigned int n, int row)
1539 char buf [1024];
1541 if (n <= 4)
1543 SLtt_normal_video ();
1544 SLMEMSET (buf, ' ', n);
1545 buf[n] = 0;
1546 write_string_with_care (buf);
1547 Cursor_c += n;
1549 else if (Curs_F_Str != NULL)
1551 Cursor_c += n;
1552 n = tt_sprintf(buf, Curs_F_Str, (int) n, 0);
1553 tt_write(buf, n);
1555 else SLtt_goto_rc (row, (int) (Cursor_c + n));
1559 void SLtt_smart_puts(SLsmg_Char_Type *neww, SLsmg_Char_Type *oldd, int len, int row)
1561 register SLsmg_Char_Type *p, *q, *qmax, *pmax, *buf;
1562 SLsmg_Char_Type buffer[256];
1563 unsigned int n_spaces;
1564 SLsmg_Char_Type *space_match, *last_buffered_match;
1565 #ifdef HP_GLITCH_CODE
1566 int handle_hp_glitch = 0;
1567 #endif
1568 SLsmg_Char_Type space_char;
1569 #define SLTT_USE_INSERT_HACK 1
1570 #if SLTT_USE_INSERT_HACK
1571 SLsmg_Char_Type insert_hack_prev = 0;
1572 SLsmg_Char_Type insert_hack_char = 0;
1574 if ((row + 1 == SLtt_Screen_Rows)
1575 && (len == SLtt_Screen_Cols)
1576 && (len > 1)
1577 && (SLtt_Term_Cannot_Insert == 0)
1578 && Automatic_Margins)
1580 insert_hack_char = neww[len-1];
1581 if (oldd[len-1] == insert_hack_char)
1582 insert_hack_char = 0;
1583 else
1584 insert_hack_prev = neww[len-2];
1586 #endif
1588 q = oldd; p = neww;
1589 qmax = oldd + len;
1590 pmax = p + len;
1592 /* Find out where to begin --- while they match, we are ok */
1593 while (1)
1595 if (q == qmax) return;
1596 #if SLANG_HAS_KANJI_SUPPORT
1597 if (*p & 0x80)
1598 { /* new is kanji */
1599 if ((*q & 0x80) && ((q + 1) < qmax))
1600 { /* old is also kanji */
1601 if (((0xFF & *q) != (0xFF & *p))
1602 || ((0xFF & q[1]) != (0xFF & p[1])))
1603 break; /* both kanji, but not match */
1605 else
1606 { /* kanji match ! */
1607 if (!COLOR_EQS(*q, *p)) break;
1608 q++; p++;
1609 if (!COLOR_EQS(*q, *p)) break;
1610 /* really match! */
1611 q++; p++;
1612 continue;
1615 else break; /* old is not kanji */
1617 else
1618 { /* new is not kanji */
1619 if (*q & 0x80) break; /* old is kanji */
1621 #endif
1622 if (!CHAR_EQS(*q, *p)) break;
1623 q++; p++;
1626 #ifdef HP_GLITCH_CODE
1627 if (Has_HP_Glitch)
1629 SLsmg_Char_Type *qq = q;
1631 SLtt_goto_rc (row, (int) (p - neww));
1633 while (qq < qmax)
1635 if (*qq & 0xFF00)
1637 SLtt_normal_video ();
1638 SLtt_del_eol ();
1639 qmax = q;
1640 handle_hp_glitch = 1;
1641 break;
1643 qq++;
1646 #endif
1647 /* Find where the last non-blank character on old/new screen is */
1649 space_char = ' ';
1650 if ((*(pmax-1) & 0xFF) == ' ')
1652 /* If we get here, then we can erase to the end of the line to create
1653 * the final space. However, this will only work _if_ erasing will
1654 * get us the correct color. If the terminal supports BCE, then this
1655 * is easy. If it does not, then we can only perform this operation
1656 * if the color is known via something like COLORFGBG. For now,
1657 * I just will not perform the optimization for such terminals.
1659 if ((Can_Background_Color_Erase)
1660 && SLtt_Use_Ansi_Colors)
1661 space_char = *(pmax - 1);
1663 while (pmax > p)
1665 pmax--;
1666 if (!CHAR_EQS(*pmax, space_char))
1668 pmax++;
1669 break;
1674 while (qmax > q)
1676 qmax--;
1677 if (!CHAR_EQS(*qmax, space_char))
1679 qmax++;
1680 break;
1684 last_buffered_match = buf = buffer; /* buffer is empty */
1686 #ifdef HP_GLITCH_CODE
1687 if (handle_hp_glitch)
1689 while (p < pmax)
1691 *buf++ = *p++;
1694 #endif
1696 #ifdef HP_GLITCH_CODE
1697 if (Has_HP_Glitch == 0)
1699 #endif
1700 /* Try use use erase to bol if possible */
1701 if ((Del_Bol_Str != NULL) && ((*neww & 0xFF) == 32))
1703 SLsmg_Char_Type *p1;
1704 SLsmg_Char_Type blank;
1706 p1 = neww;
1707 if ((Can_Background_Color_Erase)
1708 && SLtt_Use_Ansi_Colors)
1709 blank = *p1;
1710 /* black+white attributes do not support bce */
1711 else
1712 blank = 32;
1714 while ((p1 < pmax) && (CHAR_EQS (*p1, blank)))
1715 p1++;
1717 /* Is this optimization worth it? Assume Del_Bol_Str is ESC [ 1 K
1718 * It costs 4 chars + the space needed to properly position the
1719 * cursor, e.g., ESC [ 10;10H. So, it costs at least 13 characters.
1721 if ((p1 > neww + 13)
1722 && (p1 >= p)
1723 /* Avoid erasing from the end of the line */
1724 && ((p1 != pmax) || (pmax < neww + len)))
1726 int ofs = (int) (p1 - neww);
1727 q = oldd + ofs;
1728 p = p1;
1729 SLtt_goto_rc (row, ofs - 1);
1730 SLtt_reverse_video (blank >> 8);
1731 tt_write_string (Del_Bol_Str);
1732 tt_write (" ", 1);
1733 Cursor_c += 1;
1735 else
1736 SLtt_goto_rc (row, (int) (p - neww));
1738 else
1739 SLtt_goto_rc (row, (int) (p - neww));
1740 #ifdef HP_GLITCH_CODE
1742 #endif
1745 /* loop using overwrite then skip algorithm until done */
1746 while (1)
1748 /* while they do not match and we do not hit a space, buffer them up */
1749 n_spaces = 0;
1750 while (p < pmax)
1752 if (CHAR_EQS(*q, 32) && CHAR_EQS(*p, 32))
1754 /* If *q is not a space, we would have to overwrite it.
1755 * However, if *q is a space, then while *p is also one,
1756 * we only need to skip over the blank field.
1758 space_match = p;
1759 p++; q++;
1760 while ((p < pmax)
1761 && CHAR_EQS(*q, 32)
1762 && CHAR_EQS(*p, 32))
1764 p++;
1765 q++;
1767 n_spaces = (unsigned int) (p - space_match);
1768 break;
1770 #if SLANG_HAS_KANJI_SUPPORT
1771 if ((*p & 0x80) && ((p + 1) < pmax))
1772 { /* new is kanji */
1773 if (*q & 0x80)
1774 { /* old is also kanji */
1775 if (((0xFF & *q) != (0xFF & *p))
1776 || ((0xFF & q[1]) != (0xFF & p[1])))
1778 /* both kanji, but not match */
1779 *buf++ = *p++;
1780 *buf++ = *p++;
1781 q += 2;
1782 continue;
1784 else
1785 { /* kanji match ? */
1786 if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
1788 /* code is match, but color is diff */
1789 *buf++ = *p++;
1790 *buf++ = *p++;
1791 q += 2;
1792 continue;
1794 /* really match ! */
1795 break;
1798 else
1799 { /* old is not kanji */
1800 *buf++ = *p++;
1801 *buf++ = *p++;
1802 q += 2;
1803 continue;
1806 else
1807 { /* new is not kanji */
1808 if (*q & 0x80)
1809 { /* old is kanji */
1810 *buf++ = *p++;
1811 q++;
1812 continue;
1815 #endif
1817 if (CHAR_EQS(*q, *p)) break;
1818 *buf++ = *p++;
1819 q++;
1821 *buf = 0;
1823 if (buf != buffer) send_attr_str (buffer);
1824 buf = buffer;
1826 if (n_spaces
1827 && ((p < pmax) /* erase to eol will achieve this effect*/
1828 || (space_char != 32)))/* unless space_char is not a simple space */
1830 forward_cursor (n_spaces, row);
1833 /* Now we overwrote what we could and cursor is placed at position
1834 * of a possible match of new and old. If this is the case, skip
1835 * some more.
1837 #if !SLANG_HAS_KANJI_SUPPORT
1838 while ((p < pmax) && CHAR_EQS(*p, *q))
1840 *buf++ = *p++;
1841 q++;
1843 #else
1844 /* Kanji */
1845 while (p < pmax)
1847 if ((*p & 0x80) && ((p + 1) < pmax))
1848 { /* new is kanji */
1849 if (*q & 0x80)
1850 { /* old is also kanji */
1851 if (((0xFF & *q) == (0xFF & *p))
1852 && ((0xFF & q[1]) == (0xFF & p[1])))
1854 /* kanji match ? */
1855 if (!COLOR_EQS(*q, *p)
1856 || !COLOR_EQS(q[1], p[1]))
1857 break;
1859 *buf++ = *p++;
1860 q++;
1861 if (p >= pmax)
1863 *buf++ = 32;
1864 p++;
1865 break;
1867 else
1869 *buf++ = *p++;
1870 q++;
1871 continue;
1874 else break; /* both kanji, but not match */
1876 else break; /* old is not kanji */
1878 else
1879 { /* new is not kanji */
1880 if (*q & 0x80) break; /* old is kanji */
1881 if (!CHAR_EQS(*q, *p)) break;
1882 *buf++ = *p++;
1883 q++;
1886 #endif
1887 last_buffered_match = buf;
1888 if (p >= pmax) break;
1890 /* jump to new position is it is greater than 5 otherwise
1891 * let it sit in the buffer and output it later.
1893 if ((int) (buf - buffer) >= 5)
1895 forward_cursor ((unsigned int) (buf - buffer), row);
1896 last_buffered_match = buf = buffer;
1900 if (buf != buffer)
1902 if (q < qmax)
1904 if ((buf == last_buffered_match)
1905 && ((int) (buf - buffer) >= 5))
1907 forward_cursor ((unsigned int) (buf - buffer), row);
1909 else
1911 *buf = 0;
1912 send_attr_str (buffer);
1917 if (q < qmax)
1919 SLtt_reverse_video (space_char >> 8);
1920 del_eol ();
1923 #if SLTT_USE_INSERT_HACK
1924 else if (insert_hack_char)
1926 SLtt_goto_rc (SLtt_Screen_Rows-1, SLtt_Screen_Cols-2);
1927 buffer[0] = insert_hack_char;
1928 buffer[1] = 0;
1929 send_attr_str (buffer);
1930 SLtt_goto_rc (SLtt_Screen_Rows-1, SLtt_Screen_Cols-2);
1931 buffer[0] = insert_hack_prev;
1932 SLtt_begin_insert ();
1933 send_attr_str (buffer);
1934 SLtt_end_insert ();
1936 #endif
1938 if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
1941 static void get_color_info (void)
1943 char *fg, *bg;
1945 /* Allow easy mechanism to override inadequate termcap/terminfo files. */
1946 if (SLtt_Use_Ansi_Colors == 0)
1947 SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
1949 if (SLtt_Use_Ansi_Colors)
1950 Is_Color_Terminal = 1;
1952 #if SLTT_HAS_NON_BCE_SUPPORT
1953 if (Can_Background_Color_Erase == 0)
1954 Can_Background_Color_Erase = (NULL != getenv ("COLORTERM_BCE"));
1955 #endif
1957 if (-1 == get_default_colors (&fg, &bg))
1958 return;
1960 /* Check to see if application has already set them. */
1961 if (Color_0_Modified)
1962 return;
1964 SLtt_set_color (0, NULL, fg, bg);
1965 SLtt_set_color (1, NULL, bg, fg);
1968 /* termcap stuff */
1970 #ifdef __unix__
1972 static int Termcap_Initalized = 0;
1974 #ifdef USE_TERMCAP
1975 /* Termcap based system */
1976 static char Termcap_Buf[4096];
1977 static char Termcap_String_Buf[4096];
1978 static char *Termcap_String_Ptr;
1979 extern char *tgetstr(char *, char **);
1980 extern int tgetent(char *, char *);
1981 extern int tgetnum(char *);
1982 extern int tgetflag(char *);
1983 #else
1984 /* Terminfo */
1985 static SLterminfo_Type *Terminfo;
1986 #endif
1988 #define TGETFLAG(x) (SLtt_tgetflag(x) > 0)
1990 static char *fixup_tgetstr (char *what)
1992 register char *w, *w1;
1993 char *wsave;
1995 if (what == NULL)
1996 return NULL;
1998 /* Check for AIX brain-damage */
1999 if (*what == '@')
2000 return NULL;
2002 /* lose pad info --- with today's technology, term is a loser if
2003 it is really needed */
2004 while ((*what == '.') ||
2005 ((*what >= '0') && (*what <= '9'))) what++;
2006 if (*what == '*') what++;
2008 /* lose terminfo padding--- looks like $<...> */
2009 w = what;
2010 while (*w) if ((*w++ == '$') && (*w == '<'))
2012 w1 = w - 1;
2013 while (*w && (*w != '>')) w++;
2014 if (*w == 0) break;
2015 w++;
2016 wsave = w1;
2017 while ((*w1++ = *w++) != 0);
2018 w = wsave;
2021 if (*what == 0) what = NULL;
2022 return what;
2025 char *SLtt_tgetstr (char *cap)
2027 char *s;
2029 if (Termcap_Initalized == 0)
2030 return NULL;
2032 #ifdef USE_TERMCAP
2033 s = tgetstr (cap, &Termcap_String_Ptr);
2034 #else
2035 s = _SLtt_tigetstr (Terminfo, cap);
2036 #endif
2038 /* Do not strip pad info for alternate character set. I need to make
2039 * this more general.
2041 /* FIXME: Priority=low; */
2042 if (0 == strcmp (cap, "ac"))
2043 return s;
2045 return fixup_tgetstr (s);
2048 int SLtt_tgetnum (char *s)
2050 if (Termcap_Initalized == 0)
2051 return -1;
2052 #ifdef USE_TERMCAP
2053 return tgetnum (s);
2054 #else
2055 return _SLtt_tigetnum (Terminfo, s);
2056 #endif
2059 int SLtt_tgetflag (char *s)
2061 if (Termcap_Initalized == 0)
2062 return -1;
2063 #ifdef USE_TERMCAP
2064 return tgetflag (s);
2065 #else
2066 return _SLtt_tigetflag (Terminfo, s);
2067 #endif
2070 static int Vt100_Like = 0;
2072 void SLtt_get_terminfo (void)
2074 char *term;
2075 int status;
2077 term = getenv ("TERM");
2078 if (term == NULL)
2079 SLang_exit_error("TERM environment variable needs set.");
2081 if (0 == (status = SLtt_initialize (term)))
2082 return;
2084 if (status == -1)
2086 SLang_exit_error ("Unknown terminal: %s\n\
2087 Check the TERM environment variable.\n\
2088 Also make sure that the terminal is defined in the terminfo database.\n\
2089 Alternatively, set the TERMCAP environment variable to the desired\n\
2090 termcap entry.",
2091 term);
2094 if (status == -2)
2096 SLang_exit_error ("\
2097 Your terminal lacks the ability to clear the screen or position the cursor.\n");
2101 /* Returns 0 if all goes well, -1 if terminal capabilities cannot be deduced,
2102 * or -2 if terminal cannot position the cursor.
2104 int SLtt_initialize (char *term)
2106 char *t, ch;
2107 int is_xterm;
2108 int almost_vtxxx;
2110 if (SLang_TT_Write_FD == -1)
2112 /* Apparantly, this cannot fail according to the man pages. */
2113 SLang_TT_Write_FD = fileno (stdout);
2116 if (term == NULL)
2118 term = getenv ("TERM");
2119 if (term == NULL)
2120 return -1;
2123 Linux_Console = (!strncmp (term, "linux", 5)
2124 # ifdef linux
2125 || !strncmp(term, "con", 3)
2126 # endif
2129 t = term;
2131 if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
2132 && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1;
2134 is_xterm = ((0 == strncmp (term, "xterm", 5))
2135 || (0 == strncmp (term, "rxvt", 4))
2136 || (0 == strncmp (term, "Eterm", 5)));
2138 almost_vtxxx = (Vt100_Like
2139 || Linux_Console
2140 || is_xterm
2141 || !strcmp (term, "screen"));
2143 # ifndef USE_TERMCAP
2144 if (NULL == (Terminfo = _SLtt_tigetent (term)))
2146 if (almost_vtxxx) /* Special cases. */
2148 int vt102 = 1;
2149 if (!strcmp (term, "vt100")) vt102 = 0;
2150 get_color_info ();
2151 SLtt_set_term_vtxxx (&vt102);
2152 (void) SLtt_get_screen_size ();
2153 return 0;
2155 return -1;
2157 # else /* USE_TERMCAP */
2158 if (1 != tgetent(Termcap_Buf, term))
2159 return -1;
2160 Termcap_String_Ptr = Termcap_String_Buf;
2161 # endif /* NOT USE_TERMCAP */
2163 Termcap_Initalized = 1;
2165 Cls_Str = SLtt_tgetstr ("cl");
2166 Curs_Pos_Str = SLtt_tgetstr ("cm");
2168 if ((NULL == (Ins_Mode_Str = SLtt_tgetstr("im")))
2169 || ( NULL == (Eins_Mode_Str = SLtt_tgetstr("ei")))
2170 || ( NULL == (Del_Char_Str = SLtt_tgetstr("dc"))))
2171 SLtt_Term_Cannot_Insert = 1;
2173 Visible_Bell_Str = SLtt_tgetstr ("vb");
2174 Curs_Up_Str = SLtt_tgetstr ("up");
2175 Rev_Scroll_Str = SLtt_tgetstr("sr");
2176 Del_N_Lines_Str = SLtt_tgetstr("DL");
2177 Add_N_Lines_Str = SLtt_tgetstr("AL");
2179 /* Actually these are used to initialize terminals that use cursor
2180 * addressing. Hard to believe.
2182 Term_Init_Str = SLtt_tgetstr ("ti");
2183 Term_Reset_Str = SLtt_tgetstr ("te");
2185 /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
2186 * which I do not want. This is mainly for HP terminals.
2188 if ((almost_vtxxx == 0) || SLtt_Force_Keypad_Init)
2190 Keypad_Init_Str = SLtt_tgetstr ("ks");
2191 Keypad_Reset_Str = SLtt_tgetstr ("ke");
2194 /* Make up for defective termcap/terminfo databases */
2195 if ((Vt100_Like && (term[2] != '1'))
2196 || Linux_Console
2197 || is_xterm
2200 if (Del_N_Lines_Str == NULL) Del_N_Lines_Str = "\033[%dM";
2201 if (Add_N_Lines_Str == NULL) Add_N_Lines_Str = "\033[%dL";
2204 Scroll_R_Str = SLtt_tgetstr("cs");
2206 SLtt_get_screen_size ();
2208 if ((Scroll_R_Str == NULL)
2209 || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
2210 && (NULL == Rev_Scroll_Str)))
2212 if (is_xterm
2213 || Linux_Console
2216 /* Defective termcap mode!!!! */
2217 SLtt_set_term_vtxxx (NULL);
2219 else SLtt_Term_Cannot_Scroll = 1;
2222 Del_Eol_Str = SLtt_tgetstr("ce");
2223 Del_Bol_Str = SLtt_tgetstr("cb");
2224 if (is_xterm && (Del_Bol_Str == NULL))
2225 Del_Bol_Str = "\033[1K";
2226 if (is_xterm && (Del_Eol_Str == NULL))
2227 Del_Bol_Str = "\033[K";
2229 Rev_Vid_Str = SLtt_tgetstr("mr");
2230 if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
2232 Bold_Vid_Str = SLtt_tgetstr("md");
2234 /* Although xterm cannot blink, it does display the blinking characters
2235 * as bold ones. Some Rxvt will display the background as high intensity.
2237 if ((NULL == (Blink_Vid_Str = SLtt_tgetstr("mb")))
2238 && is_xterm)
2239 Blink_Vid_Str = "\033[5m";
2241 UnderLine_Vid_Str = SLtt_tgetstr("us");
2243 Start_Alt_Chars_Str = SLtt_tgetstr ("as"); /* smacs */
2244 End_Alt_Chars_Str = SLtt_tgetstr ("ae"); /* rmacs */
2245 Enable_Alt_Char_Set = SLtt_tgetstr ("eA"); /* enacs */
2246 SLtt_Graphics_Char_Pairs = SLtt_tgetstr ("ac");
2248 if (NULL == SLtt_Graphics_Char_Pairs)
2250 /* make up for defective termcap/terminfo */
2251 if (Vt100_Like)
2253 Start_Alt_Chars_Str = "\016";
2254 End_Alt_Chars_Str = "\017";
2255 Enable_Alt_Char_Set = "\033)0";
2259 /* aixterm added by willi */
2260 if (is_xterm || !strncmp (term, "aixterm", 7))
2262 Start_Alt_Chars_Str = "\016";
2263 End_Alt_Chars_Str = "\017";
2264 Enable_Alt_Char_Set = "\033(B\033)0";
2267 if ((SLtt_Graphics_Char_Pairs == NULL) &&
2268 ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
2270 SLtt_Has_Alt_Charset = 0;
2271 Enable_Alt_Char_Set = NULL;
2273 else SLtt_Has_Alt_Charset = 1;
2275 #ifdef AMIGA
2276 Enable_Alt_Char_Set = Start_Alt_Chars_Str = End_Alt_Chars_Str = NULL;
2277 #endif
2279 /* status line capabilities */
2280 if ((SLtt_Has_Status_Line == -1)
2281 && (0 != (SLtt_Has_Status_Line = TGETFLAG ("hs"))))
2283 Disable_Status_line_Str = SLtt_tgetstr ("ds");
2284 Return_From_Status_Line_Str = SLtt_tgetstr ("fs");
2285 Goto_Status_Line_Str = SLtt_tgetstr ("ts");
2286 /* Status_Line_Esc_Ok = TGETFLAG("es"); */
2287 Num_Status_Line_Columns = SLtt_tgetnum ("ws");
2288 if (Num_Status_Line_Columns < 0) Num_Status_Line_Columns = 0;
2291 if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me")))
2293 Norm_Vid_Str = SLtt_tgetstr("se");
2296 Cursor_Invisible_Str = SLtt_tgetstr("vi");
2297 Cursor_Visible_Str = SLtt_tgetstr("ve");
2299 Curs_F_Str = SLtt_tgetstr("RI");
2301 # if 0
2302 if (NULL != Curs_F_Str)
2304 Len_Curs_F_Str = strlen(Curs_F_Str);
2306 else Len_Curs_F_Str = strlen(Curs_Pos_Str);
2307 # endif
2309 Automatic_Margins = TGETFLAG ("am");
2310 /* No_Move_In_Standout = !TGETFLAG ("ms"); */
2311 # ifdef HP_GLITCH_CODE
2312 Has_HP_Glitch = TGETFLAG ("xs");
2313 # else
2314 Worthless_Highlight = TGETFLAG ("xs");
2315 # endif
2317 if (Worthless_Highlight == 0)
2318 { /* Magic cookie glitch */
2319 Worthless_Highlight = (SLtt_tgetnum ("sg") > 0);
2322 if (Worthless_Highlight)
2323 SLtt_Has_Alt_Charset = 0;
2325 Reset_Color_String = SLtt_tgetstr ("op");
2326 Color_Fg_Str = SLtt_tgetstr ("AF"); /* ANSI setaf */
2327 if (Color_Fg_Str == NULL)
2329 Color_Fg_Str = SLtt_tgetstr ("Sf"); /* setf */
2330 Is_Fg_BGR = (Color_Fg_Str != NULL);
2332 Color_Bg_Str = SLtt_tgetstr ("AB"); /* ANSI setab */
2333 if (Color_Bg_Str == NULL)
2335 Color_Bg_Str = SLtt_tgetstr ("Sb"); /* setb */
2336 Is_Bg_BGR = (Color_Bg_Str != NULL);
2339 if ((Max_Terminfo_Colors = SLtt_tgetnum ("Co")) < 0)
2340 Max_Terminfo_Colors = 8;
2342 if ((Color_Bg_Str != NULL) && (Color_Fg_Str != NULL))
2343 SLtt_Use_Ansi_Colors = 1;
2344 else
2346 #if 0
2347 Color_Fg_Str = "%?%p1%{7}%>%t\033[1;3%p1%{8}%m%dm%e\033[3%p1%dm%;";
2348 Color_Bg_Str = "%?%p1%{7}%>%t\033[5;4%p1%{8}%m%dm%e\033[4%p1%dm%;";
2349 Max_Terminfo_Colors = 16;
2350 #else
2351 Color_Fg_Str = "\033[3%dm";
2352 Color_Bg_Str = "\033[4%dm";
2353 Max_Terminfo_Colors = 8;
2354 #endif
2357 #if SLTT_HAS_NON_BCE_SUPPORT
2358 Can_Background_Color_Erase = TGETFLAG ("ut"); /* bce */
2359 /* Modern xterms have the BCE capability as well as the linux console */
2360 if (Can_Background_Color_Erase == 0)
2362 Can_Background_Color_Erase = (Linux_Console
2363 # if SLTT_XTERM_ALWAYS_BCE
2364 || is_xterm
2365 # endif
2368 #endif
2369 get_color_info ();
2372 if ((Cls_Str == NULL)
2373 || (Curs_Pos_Str == NULL))
2374 return -2;
2376 return 0;
2379 #endif
2380 /* Unix */
2382 /* specific to vtxxx only */
2383 void SLtt_enable_cursor_keys (void)
2385 #ifdef __unix__
2386 if (Vt100_Like)
2387 #endif
2388 tt_write_string("\033=\033[?1l");
2391 #ifdef VMS
2392 int SLtt_initialize (char *term)
2394 SLtt_get_terminfo ();
2395 return 0;
2398 void SLtt_get_terminfo ()
2400 int zero = 0;
2402 Color_Fg_Str = "\033[3%dm";
2403 Color_Bg_Str = "\033[4%dm";
2404 Max_Terminfo_Colors = 8;
2406 get_color_info ();
2408 SLtt_set_term_vtxxx(&zero);
2409 Start_Alt_Chars_Str = "\016";
2410 End_Alt_Chars_Str = "\017";
2411 SLtt_Has_Alt_Charset = 1;
2412 SLtt_Graphics_Char_Pairs = "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
2413 Enable_Alt_Char_Set = "\033(B\033)0";
2414 SLtt_get_screen_size ();
2416 #endif
2418 /* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
2419 * is non-zero, set terminal appropriate for a only vt100
2420 * (no add line capability). */
2422 void SLtt_set_term_vtxxx(int *vt100)
2424 Norm_Vid_Str = "\033[m";
2426 Scroll_R_Str = "\033[%i%d;%dr";
2427 Cls_Str = "\033[2J\033[H";
2428 Rev_Vid_Str = "\033[7m";
2429 Bold_Vid_Str = "\033[1m";
2430 Blink_Vid_Str = "\033[5m";
2431 UnderLine_Vid_Str = "\033[4m";
2432 Del_Eol_Str = "\033[K";
2433 Del_Bol_Str = "\033[1K";
2434 Rev_Scroll_Str = "\033M";
2435 Curs_F_Str = "\033[%dC";
2436 /* Len_Curs_F_Str = 5; */
2437 Curs_Pos_Str = "\033[%i%d;%dH";
2438 if ((vt100 == NULL) || (*vt100 == 0))
2440 Ins_Mode_Str = "\033[4h";
2441 Eins_Mode_Str = "\033[4l";
2442 Del_Char_Str = "\033[P";
2443 Del_N_Lines_Str = "\033[%dM";
2444 Add_N_Lines_Str = "\033[%dL";
2445 SLtt_Term_Cannot_Insert = 0;
2447 else
2449 Del_N_Lines_Str = NULL;
2450 Add_N_Lines_Str = NULL;
2451 SLtt_Term_Cannot_Insert = 1;
2453 SLtt_Term_Cannot_Scroll = 0;
2454 /* No_Move_In_Standout = 0; */
2457 int SLtt_init_video (void)
2459 /* send_string_to_term("\033[?6h"); */
2460 /* relative origin mode */
2461 tt_write_string (Term_Init_Str);
2462 tt_write_string (Keypad_Init_Str);
2463 SLtt_reset_scroll_region();
2464 SLtt_end_insert();
2465 tt_write_string (Enable_Alt_Char_Set);
2466 Video_Initialized = 1;
2467 return 0;
2470 int SLtt_reset_video (void)
2472 SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
2473 Cursor_Set = 0;
2474 SLtt_normal_video (); /* MSKermit requires this */
2475 tt_write_string(Norm_Vid_Str);
2477 Current_Fgbg = 0xFFFFFFFFU;
2478 SLtt_set_alt_char_set (0);
2479 if (SLtt_Use_Ansi_Colors)
2481 if (Reset_Color_String == NULL)
2483 SLtt_Char_Type attr;
2484 if (-1 != make_color_fgbg (NULL, NULL, &attr))
2485 write_attributes (attr);
2486 else tt_write_string ("\033[0m\033[m");
2488 else tt_write_string (Reset_Color_String);
2489 Current_Fgbg = 0xFFFFFFFFU;
2491 SLtt_erase_line ();
2492 tt_write_string (Keypad_Reset_Str);
2493 tt_write_string (Term_Reset_Str);
2494 SLtt_flush_output ();
2495 Video_Initialized = 0;
2496 return 0;
2499 void SLtt_bold_video (void)
2501 tt_write_string (Bold_Vid_Str);
2504 int SLtt_set_mouse_mode (int mode, int force)
2506 char *term;
2508 if (force == 0)
2510 if (NULL == (term = (char *) getenv("TERM"))) return -1;
2511 if (strncmp ("xterm", term, 5))
2512 return -1;
2515 if (mode)
2516 tt_write_string ("\033[?9h");
2517 else
2518 tt_write_string ("\033[?9l");
2520 return 0;
2523 void SLtt_disable_status_line (void)
2525 if (SLtt_Has_Status_Line > 0)
2527 tt_write_string (Disable_Status_line_Str);
2528 SLtt_flush_output ();
2532 int SLtt_write_to_status_line (char *s, int col)
2534 if ((SLtt_Has_Status_Line <= 0)
2535 || (Goto_Status_Line_Str == NULL)
2536 || (Return_From_Status_Line_Str == NULL))
2537 return -1;
2539 tt_printf (Goto_Status_Line_Str, col, 0);
2540 tt_write_string (s);
2541 tt_write_string (Return_From_Status_Line_Str);
2542 return 0;
2545 void SLtt_get_screen_size (void)
2547 #ifdef VMS
2548 int status, code;
2549 unsigned short chan;
2550 $DESCRIPTOR(dev_dsc, "SYS$INPUT:");
2551 #endif
2552 int r = 0, c = 0;
2554 #ifdef TIOCGWINSZ
2555 struct winsize wind_struct;
2559 if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
2560 || (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
2561 || (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
2563 c = (int) wind_struct.ws_col;
2564 r = (int) wind_struct.ws_row;
2565 break;
2568 while (errno == EINTR);
2570 #endif
2572 #ifdef VMS
2573 status = sys$assign(&dev_dsc,&chan,0,0,0);
2574 if (status & 1)
2576 code = DVI$_DEVBUFSIZ;
2577 status = lib$getdvi(&code, &chan,0, &c, 0,0);
2578 if (!(status & 1))
2579 c = 80;
2580 code = DVI$_TT_PAGE;
2581 status = lib$getdvi(&code, &chan,0, &r, 0,0);
2582 if (!(status & 1))
2583 r = 24;
2584 sys$dassgn(chan);
2586 #endif
2588 if (r <= 0)
2590 char *s = getenv ("LINES");
2591 if (s != NULL) r = atoi (s);
2594 if (c <= 0)
2596 char *s = getenv ("COLUMNS");
2597 if (s != NULL) c = atoi (s);
2600 if (r <= 0) r = 24;
2601 if (c <= 0) c = 80;
2602 #if 0
2603 if ((r <= 0) || (r > 200)) r = 24;
2604 if ((c <= 0) || (c > 250)) c = 80;
2605 #endif
2606 SLtt_Screen_Rows = r;
2607 SLtt_Screen_Cols = c;
2610 #if SLTT_HAS_NON_BCE_SUPPORT
2611 int _SLtt_get_bce_color_offset (void)
2613 if ((SLtt_Use_Ansi_Colors == 0)
2614 || Can_Background_Color_Erase
2615 || SLtt_Use_Blink_For_ACS) /* in this case, we cannot lose a color */
2616 Bce_Color_Offset = 0;
2617 else
2619 if (GET_BG(Ansi_Color_Map[0].fgbg) == SLSMG_COLOR_DEFAULT)
2620 Bce_Color_Offset = 0;
2621 else
2622 Bce_Color_Offset = 1;
2625 return Bce_Color_Offset;
2627 #endif