1 /* Copyright (c) 1992, 1995 John E. Davis
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Perl Artistic License.
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
50 # if defined(__QNX__) && !defined(QNX_QANSI_SLANG_COMPAT_ACS)
51 # define QNX_QANSI_SLANG_COMPAT_ACS 1
61 # include <sys/types.h>
62 # include <sys/timeb.h> /* for struct timeb, used in time.h */
68 # include <sys/time.h>
70 # include <sys/select.h>
72 # include <sys/types.h>
76 /* Prototype for select */
77 # include <net/socket.h>
89 # include <lib$routines.h>
93 # include <sys/ioctl.h>
99 # include <sys/termio.h>
100 # include <sys/stream.h>
101 # include <sys/ptem.h>
102 # include <sys/tty.h>
105 #if defined (_AIX) && !defined (FD_SET)
106 # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
120 #if defined(__DECC) && defined(VMS)
121 /* These get prototypes for write an sleep */
127 /* Colors: These definitions are used for the display. However, the
128 * application only uses object handles which get mapped to this
129 * internal representation. The mapping is performed by the Color_Map
130 * structure below. */
132 #define CHAR_MASK 0x000000FF
133 #define FG_MASK 0x0000FF00
134 #define BG_MASK 0x00FF0000
135 #define ATTR_MASK 0x1F000000
136 #define BGALL_MASK 0x0FFF0000
138 /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
139 * not include this attribute.
144 #define GET_FG(color) ((color & FG_MASK) >> 8)
145 #define GET_BG(color) ((color & BG_MASK) >> 16)
146 #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
148 int SLtt_Screen_Cols
;
149 int SLtt_Screen_Rows
;
150 int SLtt_Term_Cannot_Insert
;
151 int SLtt_Term_Cannot_Scroll
;
152 int SLtt_Use_Ansi_Colors
;
153 int SLtt_Blink_Mode
= 1;
154 int SLtt_Use_Blink_For_ACS
= 0;
155 int SLtt_Newline_Ok
= 0;
156 int SLtt_Has_Alt_Charset
= 0;
157 int SLtt_Force_Keypad_Init
= 0;
159 /* -1 means unknown */
160 int SLtt_Has_Status_Line
= -1; /* hs */
162 static int Automatic_Margins
;
163 /* static int No_Move_In_Standout; */
164 static int Worthless_Highlight
;
165 #define HP_GLITCH_CODE
166 #ifdef HP_GLITCH_CODE
167 /* This glitch is exclusive to HP term. Basically it means that to clear
168 * attributes, one has to erase to the end of the line.
170 static int Has_HP_Glitch
;
173 static char *Reset_Color_String
;
175 static int Linux_Console
;
177 /* It is crucial that JMAX_COLORS must be less than 128 since the high bit
178 * is used to indicate a character from the ACS (alt char set). The exception
179 * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
180 * the highbit is set, we interpret that as a blink character. This is
181 * exploited by DOSemu.
183 #define JMAX_COLORS 256
184 #define JNORMAL_COLOR 0
193 #define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
194 #define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
196 static Ansi_Color_Type Ansi_Color_Map
[JMAX_COLORS
] =
198 {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL
}, /* white/black */
199 {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK
, NULL
}, /* green/black */
200 {RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK
, NULL
}, /* magenta/black */
201 {RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK
, NULL
}, /* cyan/black */
202 {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK
, NULL
},
203 {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK
, NULL
},
204 {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK
, NULL
},
205 {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK
, NULL
},
206 {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK
, NULL
},
207 {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK
, NULL
},
208 {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK
, NULL
},
209 {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK
, NULL
},
210 {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK
, NULL
},
211 {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK
, NULL
},
212 {RGB(0, 1, 0, 1, 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
}
219 /* This is the string to use to use when outputting color information.
222 /* work around for sco console bug that can't handle combined sequences */
223 static char *Color_Escape_Sequence
= "\033[3%dm\033[4%dm";
225 /* Believe it or not, this is what is in the linux terminfo database. It
226 * produces the same escape sequence but it is much more CPU intensive.
227 * Why not just encode it as "\033[3%p1%dm\033[4%p2%dm" ???
229 /* static char *Color_Escape_Sequence = "\033[%p1%{30}%+%dm\033[%p2%{40}%+%dm"; */
230 static char *Color_Escape_Sequence
= "\033[3%d;4%dm";
233 char *SLtt_Graphics_Char_Pairs
; /* ac termcap string -- def is vt100 */
236 /* 1 if terminal lacks the ability to do into insert mode or into delete
237 mode. Currently controlled by S-Lang but later perhaps termcap. */
239 static char *UnderLine_Vid_Str
;
240 static char *Blink_Vid_Str
;
241 static char *Bold_Vid_Str
;
242 static char *Ins_Mode_Str
; /* = "\033[4h"; */ /* ins mode (im) */
243 static char *Eins_Mode_Str
; /* = "\033[4l"; */ /* end ins mode (ei) */
244 static char *Scroll_R_Str
; /* = "\033[%d;%dr"; */ /* scroll region */
245 static char *Cls_Str
; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
246 static char *Rev_Vid_Str
; /* = "\033[7m"; */ /* mr,so termcap string */
247 static char *Norm_Vid_Str
; /* = "\033[m"; */ /* me,se termcap string */
248 static char *Del_Eol_Str
; /* = "\033[K"; */ /* ce */
249 static char *Del_Char_Str
; /* = "\033[P"; */ /* dc */
250 static char *Del_N_Lines_Str
; /* = "\033[%dM"; */ /* DL */
251 static char *Add_N_Lines_Str
; /* = "\033[%dL"; */ /* AL */
252 static char *Rev_Scroll_Str
;
253 static char *Curs_Up_Str
;
254 static char *Curs_F_Str
; /* RI termcap string */
255 static char *Cursor_Visible_Str
; /* ve termcap string */
256 static char *Cursor_Invisible_Str
; /* vi termcap string */
258 static char *Start_Alt_Chars_Str
; /* as */
259 static char *End_Alt_Chars_Str
; /* ae */
260 static char *Enable_Alt_Char_Set
; /* eA */
262 static char *Term_Init_Str
;
263 static char *Keypad_Init_Str
;
264 static char *Term_Reset_Str
;
265 static char *Keypad_Reset_Str
;
267 /* status line functions */
268 static char *Disable_Status_line_Str
; /* ds */
269 static char *Return_From_Status_Line_Str
; /* fs */
270 static char *Goto_Status_Line_Str
; /* ts */
271 static int Num_Status_Line_Columns
; /* ws */
272 static int Status_Line_Esc_Ok
; /* es */
274 /* static int Len_Curs_F_Str = 5; */
276 /* cm string has %i%d since termcap numbers columns from 0 */
277 /* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
278 static char *Curs_Pos_Str
; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
281 /* scrolling region */
282 static int Scroll_r1
= 0, Scroll_r2
= 23;
283 static int Cursor_r
, Cursor_c
; /* 0 based */
285 /* current attributes --- initialized to impossible value */
286 static SLtt_Char_Type Current_Fgbg
= 0xFFFFFFFFU
;
288 static int Cursor_Set
; /* 1 if cursor position known, 0
289 * if not. -1 if only row is known
293 #define MAX_OUTPUT_BUFFER_SIZE 4096
295 static unsigned char Output_Buffer
[MAX_OUTPUT_BUFFER_SIZE
];
296 static unsigned char *Output_Bufferp
= Output_Buffer
;
298 unsigned long SLtt_Num_Chars_Output
;
300 #ifdef SLTT_TRANSP_ACS_PATCH
301 static int SLtt_ACS_Active
= 0;
304 static int sl_usleep (unsigned long usecs
)
308 tv
.tv_sec
= usecs
/ 1000000;
309 tv
.tv_usec
= usecs
% 1000000;
310 return select(0, NULL
, NULL
, NULL
, &tv
);
316 int SLtt_flush_output (void)
320 int n
= (int) (Output_Bufferp
- Output_Buffer
);
322 SLtt_Num_Chars_Output
+= n
;
327 nwrite
= write (fileno(stdout
), (char *) Output_Buffer
+ total
, n
);
334 sl_usleep (100000); /* 1/10 sec */
339 if (errno
== EWOULDBLOCK
)
346 if (errno
== EINTR
) continue;
353 Output_Bufferp
= Output_Buffer
;
359 static void tt_write(char *str
, unsigned int n
)
361 static unsigned long last_time
;
366 if ((str
== NULL
) || (n
== 0)) return;
371 ndiff
= MAX_OUTPUT_BUFFER_SIZE
- (int) (Output_Bufferp
- Output_Buffer
);
374 SLMEMCPY ((char *) Output_Bufferp
, (char *) str
, ndiff
);
375 Output_Bufferp
+= ndiff
;
376 SLtt_flush_output ();
382 SLMEMCPY ((char *) Output_Bufferp
, str
, n
);
388 if (((SLtt_Baud_Rate
> 150) && (SLtt_Baud_Rate
<= 9600))
389 && (10 * total
> SLtt_Baud_Rate
))
392 if ((now
= (unsigned long) time(NULL
)) - last_time
<= 1)
394 SLtt_flush_output ();
402 void SLtt_write_string (char *str
)
404 if (str
!= NULL
) tt_write(str
, strlen(str
));
408 void SLtt_putchar (char ch
)
410 #ifdef SLTT_TRANSP_ACS_PATCH
414 SLtt_normal_video ();
417 if (ch
>= ' ') Cursor_c
++;
418 #ifndef SLTT_TRANSP_ACS_PATCH
419 else if (ch
== '\b') Cursor_c
--;
421 if (ch
<= ' ' && SLtt_ACS_Active
)
423 SLtt_set_alt_char_set (0);
426 if (ch
== '\b') Cursor_c
--;
428 else if (ch
== '\r') Cursor_c
= 0;
431 if ((Cursor_c
+ 1 == SLtt_Screen_Cols
)
432 && Automatic_Margins
) Cursor_Set
= 0;
435 if (Output_Bufferp
< Output_Buffer
+ MAX_OUTPUT_BUFFER_SIZE
)
437 *Output_Bufferp
++ = (unsigned char) ch
;
439 else tt_write (&ch
, 1);
441 #ifdef SLTT_TRANSP_ACS_PATCH
444 SLtt_set_alt_char_set (1);
449 /* this is supposed to be fast--- also handles
450 termcap: %d, &i, %., %+, %r strings as well as terminfo stuff */
451 static unsigned int tt_sprintf(char *buf
, char *fmt
, int x
, int y
)
453 register unsigned char *f
= (unsigned char *) fmt
, *b
, ch
;
454 int offset
= 0, tinfo
= 0;
457 stack
[0] = y
; stack
[1] = x
; i
= 2;
459 b
= (unsigned char *) buf
;
460 if (fmt
!= NULL
) while ((ch
= *f
++) != 0)
462 if (ch
!= '%') *b
++ = ch
;
468 if ((ch
<= '3') && (ch
>= '0'))
470 /* map it to termcap. Since this is terminfo,
472 * %2d, %3d, %02d, %03d
474 * I am assuming that a terminal that understands
475 * %2d form will also understand the %02d form. These
476 * only differ by a space padding the field.
479 /* skip the 'd'-- hope it is there */
494 if (ch
== '1') stack
[i
++] = x
; else stack
[i
++] = y
;
502 case '{': /* literal constant, e.g. {30} */
504 while (((ch
= *f
) <= '9') && (ch
>= '0'))
506 z
= z
* 10 + (ch
- '0');
520 *b
++ = z
/ 100 + '0';
536 else if (ch
== 2) *b
++ = '0';
554 if ((unsigned char) ch
== 128) ch
= 0;
555 ch
= ch
+ (unsigned char) stack
[--i
];
556 if (ch
== '\n') ch
++;
568 ch
= (unsigned char) stack
[--i
];
569 if (ch
== '\n') ch
++;
579 return((unsigned int) (b
- (unsigned char *) buf
));
582 static void tt_printf(char *fmt
, int x
, int y
)
586 if (fmt
== NULL
) return;
587 n
= tt_sprintf(buf
, fmt
, x
, y
);
592 void SLtt_set_scroll_region (int r1
, int r2
)
596 tt_printf (Scroll_R_Str
, Scroll_r1
, Scroll_r2
);
600 void SLtt_reset_scroll_region (void)
602 SLtt_set_scroll_region(0, SLtt_Screen_Rows
- 1);
605 int SLtt_set_cursor_visibility (int show
)
607 if ((Cursor_Visible_Str
== NULL
) || (Cursor_Invisible_Str
== NULL
))
610 SLtt_write_string (show
? Cursor_Visible_Str
: Cursor_Invisible_Str
);
615 /* the goto_rc function moves to row relative to scrolling region */
616 void SLtt_goto_rc(int r
, int c
)
621 #ifdef SLTT_TRANSP_ACS_PATCH
622 int check_alt_acs
= 0;
631 /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
634 if ((Cursor_Set
> 0) || ((Cursor_Set
< 0) && !Automatic_Margins
))
637 if ((n
== -1) && (Cursor_Set
> 0) && (Cursor_c
== c
)
638 && (Curs_Up_Str
!= NULL
))
642 else if ((n
>= 0) && (n
<= 4))
644 if ((n
== 0) && (Cursor_Set
== 1)
645 && ((c
> 1) || (c
== Cursor_c
)))
647 if (Cursor_c
== c
) return;
648 if (Cursor_c
== c
+ 1)
653 #ifdef SLTT_TRANSP_ACS_PATCH
661 if ((Cursor_Set
!= 1) || (Cursor_c
!= 0)) *s
++ = '\r';
662 while (n
--) *s
++ = '\n';
664 /* Need to add this after \n to start a new record. Sheesh. */
669 #ifdef SLTT_TRANSP_ACS_PATCH
673 /* Will fail on VMS */
675 else if (SLtt_Newline_Ok
&& (Cursor_Set
== 1) &&
676 (Cursor_c
>= c
) && (c
+ 3 > Cursor_c
))
679 while (n
--) *s
++ = '\n';
681 while (n
--) *s
++ = '\b';
684 #ifdef SLTT_TRANSP_ACS_PATCH
691 #ifndef SLTT_TRANSP_ACS_PATCH
692 if (s
!= NULL
) SLtt_write_string(s
);
696 if (check_alt_acs
&& SLtt_ACS_Active
)
698 SLtt_set_alt_char_set (0);
699 SLtt_write_string(s
);
700 SLtt_set_alt_char_set (1);
702 else SLtt_write_string(s
);
705 else tt_printf(Curs_Pos_Str
, r
, c
);
706 Cursor_c
= c
; Cursor_r
= r
;
710 void SLtt_begin_insert (void)
712 SLtt_write_string(Ins_Mode_Str
);
715 void SLtt_end_insert (void)
717 SLtt_write_string(Eins_Mode_Str
);
720 void SLtt_delete_char (void)
722 SLtt_normal_video ();
723 SLtt_write_string(Del_Char_Str
);
726 void SLtt_erase_line (void)
728 SLtt_write_string("\r");
729 Cursor_Set
= 1; Cursor_c
= 0;
733 void SLtt_delete_nlines (int n
)
737 #ifdef SLTT_TRANSP_ACS_PATCH
742 SLtt_normal_video ();
743 if (Del_N_Lines_Str
!= NULL
) tt_printf(Del_N_Lines_Str
,n
, 0);
745 /* get a new terminal */
749 SLtt_set_scroll_region(curs
, Scroll_r2
);
750 SLtt_goto_rc(Scroll_r2
- Scroll_r1
, 0);
751 #ifdef SLTT_TRANSP_ACS_PATCH
754 SLtt_set_alt_char_set (0);
758 SLMEMSET(buf
, '\n', (unsigned int) n
);
759 tt_write(buf
, (unsigned int) n
);
760 #ifdef SLTT_TRANSP_ACS_PATCH
761 if (restore_acs
) SLtt_set_alt_char_set (1);
763 /* while (n--) tt_putchar('\n'); */
764 SLtt_set_scroll_region(r1
, Scroll_r2
);
765 SLtt_goto_rc(curs
, 0);
772 SLtt_reset_scroll_region ();
773 SLtt_write_string(Cls_Str
);
776 void SLtt_reverse_index (int n
)
781 if (Add_N_Lines_Str
!= NULL
) tt_printf(Add_N_Lines_Str
,n
, 0);
784 while(n
--) SLtt_write_string(Rev_Scroll_Str
);
789 int SLtt_Ignore_Beep
= 1;
790 static char *Visible_Bell_Str
;
792 void SLtt_beep (void)
794 if (SLtt_Ignore_Beep
& 0x1) SLtt_putchar('\007');
796 if (SLtt_Ignore_Beep
& 0x2)
798 if (Visible_Bell_Str
!= NULL
) SLtt_write_string (Visible_Bell_Str
);
800 else if (Linux_Console
)
802 SLtt_write_string ("\033[?5h");
803 SLtt_flush_output ();
805 SLtt_write_string ("\033[?5l");
809 SLtt_flush_output ();
812 void SLtt_del_eol (void)
814 if (Current_Fgbg
!= 0xFFFFFFFFU
) SLtt_normal_video ();
815 SLtt_write_string(Del_Eol_Str
);
821 SLtt_Char_Type color
;
825 #define MAX_COLOR_NAMES 17
826 static Color_Def_Type Color_Defs
[MAX_COLOR_NAMES
] =
828 {"black", SLSMG_COLOR_BLACK
},
829 {"red", SLSMG_COLOR_RED
},
830 {"green", SLSMG_COLOR_GREEN
},
831 {"brown", SLSMG_COLOR_BROWN
},
832 {"blue", SLSMG_COLOR_BLUE
},
833 {"magenta", SLSMG_COLOR_MAGENTA
},
834 {"cyan", SLSMG_COLOR_CYAN
},
835 {"lightgray", SLSMG_COLOR_LGRAY
},
836 {"gray", SLSMG_COLOR_GRAY
},
837 {"brightred", SLSMG_COLOR_BRIGHT_RED
},
838 {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN
},
839 {"yellow", SLSMG_COLOR_BRIGHT_BROWN
},
840 {"brightblue", SLSMG_COLOR_BRIGHT_BLUE
},
841 {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN
},
842 {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA
},
843 {"white", SLSMG_COLOR_BRIGHT_WHITE
},
848 void SLtt_set_mono (int obj
, char *what
, SLtt_Char_Type mask
)
851 if ((obj
< 0) || (obj
>= JMAX_COLORS
))
855 Ansi_Color_Map
[obj
].mono
= mask
& ATTR_MASK
;
858 static char *check_color_for_digit_form (char *color
)
864 while ((ich
= (int) *s
) != 0)
866 if ((ich
< '0') || (ich
> '9'))
869 i
= i
* 10 + (ich
- '0');
873 if (i
< MAX_COLOR_NAMES
)
874 color
= Color_Defs
[i
].name
;
879 static int get_default_colors (char **fgp
, char **bgp
)
881 static char fg_buf
[16], bg_buf
[16], *bg
, *fg
;
882 static int already_parsed
;
885 if (already_parsed
== -1)
897 bg
= getenv ("COLORFGBG");
901 bg
= getenv ("DEFAULT_COLORS");
907 pmax
= p
+ (sizeof (fg_buf
) - 1);
909 while ((*bg
!= 0) && (*bg
!= ';'))
911 if (p
< pmax
) *p
++ = *bg
;
919 pmax
= p
+ (sizeof (bg_buf
) - 1);
921 /* Mark suggested allowing for extra spplication specific stuff following
922 * the background color. That is what the check for the semi-colon is for.
924 while ((*bg
!= 0) && (*bg
!= ';'))
926 if (p
< pmax
) *p
++ = *bg
;
931 if (!strcmp (fg_buf
, "default") || !strcmp(bg_buf
, "default"))
933 *fgp
= *bgp
= fg
= bg
= "default";
937 *fgp
= fg
= check_color_for_digit_form (fg_buf
);
938 *bgp
= bg
= check_color_for_digit_form (bg_buf
);
945 static unsigned char FgBg_Stats
[JMAX_COLORS
];
947 static int Color_0_Modified
= 0;
949 void SLtt_set_color_object (int obj
, SLtt_Char_Type attr
)
953 if ((obj
< 0) || (obj
>= JMAX_COLORS
)) return;
955 cust_esc
= Ansi_Color_Map
[obj
].custom_esc
;
956 if (cust_esc
!= NULL
)
959 FgBg_Stats
[(Ansi_Color_Map
[obj
].fgbg
>> 8) & 0x7F] -= 1;
960 Ansi_Color_Map
[obj
].custom_esc
= NULL
;
963 Ansi_Color_Map
[obj
].fgbg
= attr
;
964 if (obj
== 0) Color_0_Modified
= 1;
967 SLtt_Char_Type
SLtt_get_color_object (int obj
)
969 if ((obj
< 0) || (obj
>= JMAX_COLORS
)) return 0;
970 return Ansi_Color_Map
[obj
].fgbg
;
974 void SLtt_add_color_attribute (int obj
, SLtt_Char_Type attr
)
976 if ((obj
< 0) || (obj
>= JMAX_COLORS
)) return;
978 Ansi_Color_Map
[obj
].fgbg
|= (attr
& ATTR_MASK
);
979 if (obj
== 0) Color_0_Modified
= 1;
982 static SLtt_Char_Type
fb_to_fgbg (SLtt_Char_Type f
, SLtt_Char_Type b
)
984 SLtt_Char_Type attr
= 0;
988 if (f
& 0x8) attr
= SLTT_BOLD_MASK
;
995 if (b
& 0x8) attr
|= SLTT_BLINK_MASK
;
1000 return ((f
<< 8) | (b
<< 16) | attr
);
1003 static int make_color_fgbg (char *fg
, char *bg
, SLtt_Char_Type
*fgbg
)
1005 SLtt_Char_Type f
= 0xFFFFFFFFU
, b
= 0xFFFFFFFFU
;
1009 if ((fg
!= NULL
) && (*fg
== 0)) fg
= NULL
;
1010 if ((bg
!= NULL
) && (*bg
== 0)) bg
= NULL
;
1012 if ((fg
== NULL
) || (bg
== NULL
))
1014 if (-1 == get_default_colors (&dfg
, &dbg
))
1017 if (fg
== NULL
) fg
= dfg
;
1018 if (bg
== NULL
) bg
= dbg
;
1021 for (i
= 0; i
< MAX_COLOR_NAMES
; i
++)
1023 if (strcmp(fg
, Color_Defs
[i
].name
)) continue;
1024 f
= Color_Defs
[i
].color
;
1028 for (i
= 0; i
< MAX_COLOR_NAMES
; i
++)
1030 if (strcmp(bg
, Color_Defs
[i
].name
)) continue;
1031 b
= Color_Defs
[i
].color
;
1035 if ((f
== 0xFFFFFFFFU
) || (b
== 0xFFFFFFFFU
))
1038 *fgbg
= fb_to_fgbg (f
, b
);
1042 void SLtt_set_color (int obj
, char *what
, char *fg
, char *bg
)
1044 SLtt_Char_Type fgbg
;
1047 if ((obj
< 0) || (obj
>= JMAX_COLORS
))
1050 if (-1 != make_color_fgbg (fg
, bg
, &fgbg
))
1051 SLtt_set_color_object (obj
, fgbg
);
1054 void SLtt_set_color_fgbg (int obj
, SLtt_Char_Type f
, SLtt_Char_Type b
)
1056 SLtt_set_color_object (obj
, fb_to_fgbg (f
, b
));
1059 void SLtt_set_color_esc (int obj
, char *esc
)
1062 SLtt_Char_Type fgbg
= 0;
1065 if ((obj
< 0) || (obj
>= JMAX_COLORS
))
1070 cust_esc
= Ansi_Color_Map
[obj
].custom_esc
;
1071 if (cust_esc
!= NULL
)
1074 FgBg_Stats
[(Ansi_Color_Map
[obj
].fgbg
>> 8) & 0x7F] -= 1;
1077 cust_esc
= (char *) SLMALLOC (strlen(esc
) + 1);
1078 if (cust_esc
!= NULL
) strcpy (cust_esc
, esc
);
1080 Ansi_Color_Map
[obj
].custom_esc
= cust_esc
;
1081 if (cust_esc
== NULL
) fgbg
= 0;
1084 /* The whole point of this is to generate a unique fgbg */
1085 for (i
= 0; i
< JMAX_COLORS
; i
++)
1087 if (FgBg_Stats
[i
] == 0) fgbg
= i
;
1089 if (obj
== i
) continue;
1090 if ((Ansi_Color_Map
[i
].custom_esc
) == NULL
) continue;
1091 if (!strcmp (Ansi_Color_Map
[i
].custom_esc
, cust_esc
))
1093 fgbg
= (Ansi_Color_Map
[i
].fgbg
>> 8) & 0x7F;
1097 FgBg_Stats
[fgbg
] += 1;
1101 Ansi_Color_Map
[obj
].fgbg
= (fgbg
| (fgbg
<< 8)) << 8;
1102 if (obj
== 0) Color_0_Modified
= 1;
1105 void SLtt_set_alt_char_set (int i
)
1107 #ifndef SLTT_TRANSP_ACS_PATCH
1110 #define last_i SLtt_ACS_Active
1112 if (SLtt_Has_Alt_Charset
== 0) return;
1113 if (i
== last_i
) return;
1114 SLtt_write_string (i
? Start_Alt_Chars_Str
: End_Alt_Chars_Str
);
1115 /* if (i) Current_Fgbg |= SLTT_ALTC_MASK;
1116 else Current_Fgbg &= ~SLTT_ALTC_MASK; */
1118 #ifdef SLTT_TRANSP_ACS_PATCH
1123 static void write_attributes (SLtt_Char_Type fgbg
)
1127 if (Worthless_Highlight
) return;
1128 if (fgbg
== Current_Fgbg
) return;
1130 /* Before spitting out colors, fix attributes */
1131 if ((fgbg
& ATTR_MASK
) != (Current_Fgbg
& ATTR_MASK
))
1133 if (Current_Fgbg
& ATTR_MASK
)
1135 SLtt_write_string(Norm_Vid_Str
);
1136 /* In case normal video turns off ALL attributes: */
1137 if (fgbg
& SLTT_ALTC_MASK
)
1138 Current_Fgbg
&= ~SLTT_ALTC_MASK
;
1139 SLtt_set_alt_char_set (0);
1142 if ((fgbg
& SLTT_ALTC_MASK
)
1143 != (Current_Fgbg
& SLTT_ALTC_MASK
))
1145 SLtt_set_alt_char_set ((int) (fgbg
& SLTT_ALTC_MASK
));
1148 if (fgbg
& SLTT_ULINE_MASK
) SLtt_write_string (UnderLine_Vid_Str
);
1149 if (fgbg
& SLTT_BOLD_MASK
) SLtt_bold_video ();
1150 if (fgbg
& SLTT_REV_MASK
) SLtt_write_string (Rev_Vid_Str
);
1151 if (fgbg
& SLTT_BLINK_MASK
)
1153 /* Someday Linux will have a blink mode that set high intensity
1154 * background. Lets be prepared.
1156 if (SLtt_Blink_Mode
) SLtt_write_string (Blink_Vid_Str
);
1160 if (SLtt_Use_Ansi_Colors
)
1162 fg0
= (int) GET_FG(fgbg
);
1163 bg0
= (int) GET_BG(fgbg
);
1164 tt_printf(Color_Escape_Sequence
, fg0
, bg0
);
1166 Current_Fgbg
= fgbg
;
1169 static int Video_Initialized
;
1171 void SLtt_reverse_video (int color
)
1173 SLtt_Char_Type fgbg
;
1176 if (Worthless_Highlight
) return;
1177 if ((color
< 0) || (color
>= JMAX_COLORS
)) return;
1179 if (Video_Initialized
== 0)
1181 if (color
== JNORMAL_COLOR
)
1183 SLtt_write_string (Norm_Vid_Str
);
1185 else SLtt_write_string (Rev_Vid_Str
);
1186 Current_Fgbg
= 0xFFFFFFFFU
;
1190 if (SLtt_Use_Ansi_Colors
)
1192 fgbg
= Ansi_Color_Map
[color
].fgbg
;
1193 if ((esc
= Ansi_Color_Map
[color
].custom_esc
) != NULL
)
1195 if (fgbg
!= Current_Fgbg
)
1197 Current_Fgbg
= fgbg
;
1198 SLtt_write_string (esc
);
1203 else fgbg
= Ansi_Color_Map
[color
].mono
;
1205 if (fgbg
== Current_Fgbg
) return;
1206 write_attributes (fgbg
);
1212 void SLtt_normal_video (void)
1214 SLtt_reverse_video(JNORMAL_COLOR
);
1217 void SLtt_narrow_width (void)
1219 SLtt_write_string("\033[?3l");
1222 void SLtt_wide_width (void)
1224 SLtt_write_string("\033[?3h");
1227 /* Highest bit represents the character set. */
1228 #define COLOR_MASK 0x7F00
1230 #define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
1232 #define COLOR_EQS(a, b) \
1233 (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
1236 #define COLOR_EQS(a, b) \
1237 (SLtt_Use_Ansi_Colors \
1238 ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
1239 : (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
1242 #define CHAR_EQS(a, b) (((a) == (b))\
1243 || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
1244 && COLOR_EQS((a), (b))))
1247 /* The whole point of this routine is to prevent writing to the last column
1248 * and last row on terminals with automatic margins.
1250 static void write_string_with_care (char *str
)
1254 if (str
== NULL
) return;
1257 if (Automatic_Margins
&& (Cursor_r
+ 1 == SLtt_Screen_Rows
))
1259 if (len
+ (unsigned int) Cursor_c
>= (unsigned int) SLtt_Screen_Cols
)
1261 /* For now, just do not write there. Later, something more
1262 * sophisticated will be implemented.
1264 if (SLtt_Screen_Cols
> Cursor_c
)
1265 len
= SLtt_Screen_Cols
- Cursor_c
- 1;
1269 tt_write (str
, len
);
1272 static void send_attr_str (unsigned short *s
)
1274 unsigned char out
[256], ch
, *p
;
1275 register SLtt_Char_Type attr
;
1276 register unsigned short sh
;
1277 int color
, last_color
= -1;
1280 while (0 != (sh
= *s
++))
1283 color
= ((int) sh
& 0xFF00) >> 8;
1284 #ifdef SLTT_TRANSP_ACS_PATCH
1285 if (ch
<= ' ' && (color
& 0x80)) color
&= ~0x80;
1287 if (color
!= last_color
)
1289 if (SLtt_Use_Ansi_Colors
) attr
= Ansi_Color_Map
[color
& 0x7F].fgbg
;
1290 else attr
= Ansi_Color_Map
[color
& 0x7F].mono
;
1293 if (color
& 0x80) /* alternate char set */
1295 if (SLtt_Use_Blink_For_ACS
)
1297 if (SLtt_Blink_Mode
) attr
|= SLTT_BLINK_MASK
;
1299 else attr
|= SLTT_ALTC_MASK
;
1303 if (attr
!= Current_Fgbg
)
1305 #ifndef SLTT_TRANSP_ACS_PATCH
1307 /* it is a space so only consider it different if it
1308 * has different attributes.
1310 (attr
& BGALL_MASK
) != (Current_Fgbg
& BGALL_MASK
))
1316 write_string_with_care ((char *) out
);
1317 Cursor_c
+= (int) (p
- out
);
1321 if (SLtt_Use_Ansi_Colors
&& (NULL
!= Ansi_Color_Map
[color
& 0x7F].custom_esc
))
1323 SLtt_write_string (Ansi_Color_Map
[color
& 0x7F].custom_esc
);
1324 /* Just in case the custom escape sequence screwed up
1325 * the alt character set state...
1327 if ((attr
& SLTT_ALTC_MASK
) != (Current_Fgbg
& SLTT_ALTC_MASK
))
1328 SLtt_set_alt_char_set ((int) (attr
& SLTT_ALTC_MASK
));
1329 Current_Fgbg
= attr
;
1331 else write_attributes (attr
);
1340 if (p
!= out
) write_string_with_care ((char *) out
);
1341 Cursor_c
+= (int) (p
- out
);
1344 static void forward_cursor (unsigned int n
, int row
)
1351 SLtt_normal_video ();
1352 SLMEMSET (buf
, ' ', n
);
1354 write_string_with_care (buf
);
1357 else if (Curs_F_Str
!= NULL
)
1360 n
= tt_sprintf(buf
, Curs_F_Str
, (int) n
, 0);
1363 else SLtt_goto_rc (row
, (int) (Cursor_c
+ n
));
1367 #define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))
1369 void SLtt_smart_puts(unsigned short *neww
, unsigned short *oldd
, int len
, int row
)
1371 register unsigned short *p
, *q
, *qmax
, *pmax
, *buf
;
1372 unsigned short buffer
[256];
1373 unsigned int n_spaces
;
1374 unsigned short *space_match
, *last_buffered_match
;
1375 #ifdef HP_GLITCH_CODE
1376 int handle_hp_glitch
= 0;
1383 /* Find out where to begin --- while they match, we are ok */
1386 if (q
== qmax
) return;
1387 #if SLANG_HAS_KANJI_SUPPORT
1389 { /* new is kanji */
1390 if ((*q
& 0x80) && ((q
+ 1) < qmax
))
1391 { /* old is also kanji */
1392 if (((0xFF & *q
) != (0xFF & *p
))
1393 || ((0xFF & q
[1]) != (0xFF & p
[1])))
1394 break; /* both kanji, but not match */
1397 { /* kanji match ! */
1398 if (!COLOR_EQS(*q
, *p
)) break;
1400 if (!COLOR_EQS(*q
, *p
)) break;
1406 else break; /* old is not kanji */
1409 { /* new is not kanji */
1410 if (*q
& 0x80) break; /* old is kanji */
1413 if (!CHAR_EQS(*q
, *p
)) break;
1417 /*position the cursor */
1418 SLtt_goto_rc (row
, (int) (p
- neww
));
1420 #ifdef HP_GLITCH_CODE
1423 unsigned short *qq
= q
;
1428 SLtt_normal_video ();
1431 handle_hp_glitch
= 1;
1438 /* Find where the last non-blank character on old/new screen is */
1443 if (!CHAR_EQS(*qmax
, SPACE_CHAR
))
1453 if (!CHAR_EQS(*pmax
, SPACE_CHAR
))
1460 last_buffered_match
= buf
= buffer
; /* buffer is empty */
1462 #ifdef HP_GLITCH_CODE
1463 if (handle_hp_glitch
)
1472 /* loop using overwrite then skip algorithm until done */
1475 /* while they do not match and we do not hit a space, buffer them up */
1479 if (CHAR_EQS(*q
,SPACE_CHAR
) && CHAR_EQS(*p
, SPACE_CHAR
))
1481 /* If *q is not a space, we would have to overwrite it.
1482 * However, if *q is a space, then while *p is also one,
1483 * we only need to skip over the blank field.
1488 && CHAR_EQS(*q
,SPACE_CHAR
)
1489 && CHAR_EQS(*p
, SPACE_CHAR
))
1494 n_spaces
= (unsigned int) (p
- space_match
);
1497 #if SLANG_HAS_KANJI_SUPPORT
1498 if ((*p
& 0x80) && ((p
+ 1) < pmax
))
1499 { /* new is kanji */
1501 { /* old is also kanji */
1502 if (((0xFF & *q
) != (0xFF & *p
))
1503 || ((0xFF & q
[1]) != (0xFF & p
[1])))
1505 /* both kanji, but not match */
1512 { /* kanji match ? */
1513 if (!COLOR_EQS(*q
, *p
) || !COLOR_EQS(*(q
+1), *(p
+1)))
1515 /* code is match ,but color is diff */
1520 /* really match ! */
1525 { /* old is not kanji */
1533 { /* new is not kanji */
1535 { /* old is kanji */
1543 if (CHAR_EQS(*q
, *p
)) break;
1549 if (buf
!= buffer
) send_attr_str (buffer
);
1552 if (n_spaces
&& (p
< pmax
))
1554 forward_cursor (n_spaces
, row
);
1557 /* Now we overwrote what we could and cursor is placed at position
1558 * of a possible match of new and old. If this is the case, skip
1561 #if !SLANG_HAS_KANJI_SUPPORT
1562 while ((p
< pmax
) && CHAR_EQS(*p
, *q
))
1571 if ((*p
& 0x80) && ((p
+ 1) < pmax
))
1572 { /* new is kanji */
1574 { /* old is also kanji */
1575 if (((0xFF & *q
) == (0xFF & *p
))
1576 && ((0xFF & q
[1]) == (0xFF & p
[1])))
1579 if (!COLOR_EQS(*q
, *p
)
1580 || !COLOR_EQS(q
[1], p
[1]))
1587 *buf
++ = SPACE_CHAR
;
1598 else break; /* both kanji, but not match */
1600 else break; /* old is not kanji */
1603 { /* new is not kanji */
1604 if (*q
& 0x80) break; /* old is kanji */
1605 if (!CHAR_EQS(*q
, *p
)) break;
1611 last_buffered_match
= buf
;
1612 if (p
>= pmax
) break;
1614 /* jump to new position is it is greater than 5 otherwise
1615 * let it sit in the buffer and output it later.
1617 if ((int) (buf
- buffer
) >= 5)
1619 forward_cursor ((unsigned int) (buf
- buffer
), row
);
1620 last_buffered_match
= buf
= buffer
;
1628 if ((buf
== last_buffered_match
)
1629 && ((int) (buf
- buffer
) >= 5))
1631 forward_cursor ((unsigned int) (buf
- buffer
), row
);
1636 send_attr_str (buffer
);
1640 if (q
< qmax
) SLtt_del_eol ();
1641 if (Automatic_Margins
&& (Cursor_c
+ 1 >= SLtt_Screen_Cols
)) Cursor_Set
= 0;
1645 static void get_color_info (void)
1649 SLtt_Use_Ansi_Colors
= (NULL
!= getenv ("COLORTERM"));
1651 if (-1 == get_default_colors (&fg
, &bg
))
1654 /* Check to see if application has already set them. */
1655 if (Color_0_Modified
)
1658 SLtt_set_color (0, NULL
, fg
, bg
);
1659 SLtt_set_color (1, NULL
, bg
, fg
);
1669 static char *Tstr_Buf
;
1671 #define tgetstr SLtt_tigetstr
1672 #define tgetent SLtt_tigetent
1673 #define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
1674 #define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
1677 extern char *tgetstr(char *, char **);
1678 extern int tgetent(char *, char *);
1679 extern int tgetnum(char *);
1680 extern int tgetflag(char *);
1681 static char Tstr_Buf
[1024];
1682 static char Tbuf
[4096];
1683 #define TGETNUM tgetnum
1684 #define TGETFLAG tgetflag
1687 static char *my_tgetstr(char *what
, char **p
)
1689 register char *w
, *w1
;
1691 what
= tgetstr(what
, p
);
1694 /* Check for AIX brain-damage */
1698 /* lose pad info --- with today's technology, term is a loser if
1699 it is really needed */
1700 while ((*what
== '.') ||
1701 ((*what
>= '0') && (*what
<= '9'))) what
++;
1702 if (*what
== '*') what
++;
1704 /* lose terminfo padding--- looks like $<...> */
1706 while (*w
) if ((*w
++ == '$') && (*w
== '<'))
1709 while (*w
&& (*w
!= '>')) w
++;
1713 while ((*w1
++ = *w
++) != 0);
1716 if (*what
== 0) what
= NULL
;
1721 char *SLtt_tgetstr (char *s
)
1727 return my_tgetstr (s
, &p
);
1730 int SLtt_tgetnum (char *s
)
1734 int SLtt_tgetflag (char *s
)
1736 return TGETFLAG (s
);
1740 static int Vt100_Like
= 0;
1742 void SLtt_get_terminfo (void)
1750 if (NULL
== (term
= (char *) getenv("TERM")))
1752 SLang_exit_error("TERM environment variable needs set.");
1755 Linux_Console
= (!strncmp (term
, "linux", 5)
1757 || !strncmp(term
, "con", 3)
1763 if (strcmp(t
, "vt52") && (*t
++ == 'v') && (*t
++ == 't')
1764 && (ch
= *t
, (ch
>= '1') && (ch
<= '9'))) Vt100_Like
= 1;
1766 is_xterm
= !strncmp (term
, "xterm", 5);
1767 almost_vtxxx
= (Vt100_Like
1770 || !strcmp (term
, "screen"));
1773 if (NULL
== (Tbuf
= tgetent (term
)))
1776 if (almost_vtxxx
) /* Special cases. */
1779 if (!strcmp (term
, "vt100")) vt102
= 0;
1780 SLtt_set_term_vtxxx (&vt102
);
1783 g_snprintf (err_buf
, sizeof (err_buf
), "Unknown terminal: %s\n\
1784 Check the TERM environment variable.\n\
1785 Also make sure that the terminal is defined in the terminfo database.\n\
1786 Alternatively, set the TERMCAP environment variable to the desired\n\
1787 termcap entry.", term
);
1788 SLang_exit_error(err_buf
);
1791 #else /* USE_TERMCAP */
1792 if (1 != tgetent(Tbuf
, term
)) SLang_exit_error("Unknown terminal.");
1793 #endif /* NOT USE_TERMCAP */
1795 if ((NULL
== (Cls_Str
= SLtt_tgetstr("cl")))
1796 || (NULL
== (Curs_Pos_Str
= SLtt_tgetstr("cm"))))
1798 SLang_exit_error("Terminal not powerful enough for SLang.");
1801 if ((NULL
== (Ins_Mode_Str
= SLtt_tgetstr("im")))
1802 || ( NULL
== (Eins_Mode_Str
= SLtt_tgetstr("ei")))
1803 || ( NULL
== (Del_Char_Str
= SLtt_tgetstr("dc"))))
1804 SLtt_Term_Cannot_Insert
= 1;
1806 Visible_Bell_Str
= SLtt_tgetstr ("vb");
1807 Curs_Up_Str
= SLtt_tgetstr ("up");
1808 Rev_Scroll_Str
= SLtt_tgetstr("sr");
1809 Del_N_Lines_Str
= SLtt_tgetstr("DL");
1810 Add_N_Lines_Str
= SLtt_tgetstr("AL");
1812 /* Actually these are used to initialize terminals that use cursor
1813 * addressing. Hard to believe.
1815 Term_Init_Str
= SLtt_tgetstr ("ti");
1816 Term_Reset_Str
= SLtt_tgetstr ("te");
1818 /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
1819 * which I do not want. This is mainly for HP terminals.
1821 if ((almost_vtxxx
== 0) || SLtt_Force_Keypad_Init
)
1823 Keypad_Init_Str
= SLtt_tgetstr ("ks");
1824 Keypad_Reset_Str
= SLtt_tgetstr ("ke");
1827 /* Make up for defective termcap/terminfo databases */
1828 if ((Vt100_Like
&& (term
[2] != '1'))
1833 if (Del_N_Lines_Str
== NULL
) Del_N_Lines_Str
= "\033[%dM";
1834 if (Add_N_Lines_Str
== NULL
) Add_N_Lines_Str
= "\033[%dL";
1837 Scroll_R_Str
= SLtt_tgetstr("cs");
1839 SLtt_get_screen_size ();
1841 if ((Scroll_R_Str
== NULL
)
1842 || (((NULL
== Del_N_Lines_Str
) || (NULL
== Add_N_Lines_Str
))
1843 && (NULL
== Rev_Scroll_Str
)))
1849 /* Defective termcap mode!!!! */
1850 SLtt_set_term_vtxxx (NULL
);
1852 else SLtt_Term_Cannot_Scroll
= 1;
1855 Del_Eol_Str
= SLtt_tgetstr("ce");
1857 Rev_Vid_Str
= SLtt_tgetstr("mr");
1858 if (Rev_Vid_Str
== NULL
) Rev_Vid_Str
= SLtt_tgetstr("so");
1860 Bold_Vid_Str
= SLtt_tgetstr("md");
1862 /* Although xterm cannot blink, it does display the blinking characters
1863 * as bold ones. Some Rxvt will display the background as high intensity.
1865 if ((NULL
== (Blink_Vid_Str
= SLtt_tgetstr("mb")))
1867 Blink_Vid_Str
= "\033[5m";
1869 UnderLine_Vid_Str
= SLtt_tgetstr("us");
1871 Start_Alt_Chars_Str
= SLtt_tgetstr ("as"); /* smacs */
1872 End_Alt_Chars_Str
= SLtt_tgetstr ("ae"); /* rmacs */
1873 Enable_Alt_Char_Set
= SLtt_tgetstr ("eA"); /* enacs */
1874 SLtt_Graphics_Char_Pairs
= SLtt_tgetstr ("ac");
1876 #ifndef NCURSES_BRAIN_DAMAGE_CONTROL
1877 # define NCURSES_BRAIN_DAMAGE_CONTROL 0
1880 #if NCURSES_BRAIN_DAMAGE_CONTROL
1884 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";
1886 SLtt_Graphics_Char_Pairs
= lgcp
;
1887 Start_Alt_Chars_Str
= "\033(B\033)U\016";
1888 End_Alt_Chars_Str
= "\033(B\033)0\017";
1889 Enable_Alt_Char_Set
= NULL
;
1891 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~";
1893 SLtt_Graphics_Char_Pairs
= lgcp
;
1894 Start_Alt_Chars_Str
= "\033[11m";
1895 End_Alt_Chars_Str
= "\033[10m";
1896 Enable_Alt_Char_Set
= NULL
;
1901 if (NULL
== SLtt_Graphics_Char_Pairs
)
1903 /* make up for defective termcap/terminfo */
1906 Start_Alt_Chars_Str
= "\016";
1907 End_Alt_Chars_Str
= "\017";
1908 Enable_Alt_Char_Set
= "\033)0";
1912 /* aixterm added by willi */
1913 if (is_xterm
|| !strncmp (term
, "aixterm", 7))
1915 Start_Alt_Chars_Str
= "\016";
1916 End_Alt_Chars_Str
= "\017";
1917 Enable_Alt_Char_Set
= "\033(B\033)0";
1920 if ((SLtt_Graphics_Char_Pairs
== NULL
) &&
1921 ((Start_Alt_Chars_Str
== NULL
) || (End_Alt_Chars_Str
== NULL
)))
1923 SLtt_Has_Alt_Charset
= 0;
1924 Enable_Alt_Char_Set
= NULL
;
1926 else SLtt_Has_Alt_Charset
= 1;
1929 /* status line capabilities */
1930 if ((SLtt_Has_Status_Line
== -1)
1931 && (0 != (SLtt_Has_Status_Line
= TGETFLAG ("hs"))))
1933 Disable_Status_line_Str
= SLtt_tgetstr ("ds");
1934 Return_From_Status_Line_Str
= SLtt_tgetstr ("fs");
1935 Goto_Status_Line_Str
= SLtt_tgetstr ("ts");
1936 Status_Line_Esc_Ok
= TGETFLAG("es");
1937 Num_Status_Line_Columns
= TGETNUM("ws");
1938 if (Num_Status_Line_Columns
< 0) Num_Status_Line_Columns
= 0;
1941 if (NULL
== (Norm_Vid_Str
= SLtt_tgetstr("me")))
1943 Norm_Vid_Str
= SLtt_tgetstr("se");
1946 Cursor_Invisible_Str
= SLtt_tgetstr("vi");
1947 Cursor_Visible_Str
= SLtt_tgetstr("ve");
1949 Curs_F_Str
= SLtt_tgetstr("RI");
1952 if (NULL
!= Curs_F_Str
)
1954 Len_Curs_F_Str
= strlen(Curs_F_Str
);
1956 else Len_Curs_F_Str
= strlen(Curs_Pos_Str
);
1959 Automatic_Margins
= TGETFLAG ("am");
1960 /* No_Move_In_Standout = !TGETFLAG ("ms"); */
1961 #ifdef HP_GLITCH_CODE
1962 Has_HP_Glitch
= TGETFLAG ("xs");
1964 Worthless_Highlight
= TGETFLAG ("xs");
1967 if (Worthless_Highlight
== 0)
1968 { /* Magic cookie glitch */
1969 Worthless_Highlight
= (TGETNUM ("sg") > 0);
1972 if (Worthless_Highlight
)
1973 SLtt_Has_Alt_Charset
= 0;
1975 /* Check for color information in the termcap. A program should not
1976 * rely on this information being accurate.
1978 if (SLtt_Use_Ansi_Colors
== 0)
1980 Reset_Color_String
= SLtt_tgetstr ("op");
1982 SLtt_Use_Ansi_Colors
= ((NULL
!= Reset_Color_String
)
1983 || (NULL
!= SLtt_tgetstr ("Sf"))
1984 || (NULL
!= SLtt_tgetstr ("Sb"))
1985 || (NULL
!= SLtt_tgetstr ("AF"))
1986 || (NULL
!= SLtt_tgetstr ("AB"))
1987 || (-1 != SLtt_tgetnum ("Co"))
1988 || (-1 != SLtt_tgetnum ("pa")));
1992 #if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
1994 * Override the alt-char-set handling string in case of a
1995 * QNX/qansi terminal: use the "old style" strings in order
1996 * to be compatible with S-Lang without the SLTT_TRANSP_ACS_PATCH
1999 if (SLtt_Has_Alt_Charset
&&
2000 strncmp(term
, "qansi", 5) == 0 &&
2001 Start_Alt_Chars_Str
[0] != '\016')
2003 Start_Alt_Chars_Str
= "\016"; /* smacs/as (^N) */
2004 End_Alt_Chars_Str
= "\017"; /* rmacs/ae (^O) */
2005 SLtt_Graphics_Char_Pairs
= /* acsc/ac */
2006 "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~O\141";
2009 * it would be required to modify the sgr/sa entry also, if it
2010 * would be used (->embedded as/ae sequences)...
2013 #endif /* __QNX__ && QNX_QANSI_SLANG_COMPAT_ACS */
2020 /* specific to vtxxx only */
2021 void SLtt_enable_cursor_keys (void)
2026 SLtt_write_string("\033=\033[?1l");
2030 void SLtt_get_terminfo ()
2036 SLtt_set_term_vtxxx(&zero
);
2037 Start_Alt_Chars_Str
= "\016";
2038 End_Alt_Chars_Str
= "\017";
2039 SLtt_Has_Alt_Charset
= 1;
2040 SLtt_Graphics_Char_Pairs
= "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
2041 Enable_Alt_Char_Set
= "\033(B\033)0";
2042 SLtt_get_screen_size ();
2046 /* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
2047 * is non-zero, set terminal appropriate for a only vt100
2048 * (no add line capability). */
2050 void SLtt_set_term_vtxxx(int *vt100
)
2052 Norm_Vid_Str
= "\033[m";
2054 Scroll_R_Str
= "\033[%i%d;%dr";
2055 Cls_Str
= "\033[2J\033[H";
2056 Rev_Vid_Str
= "\033[7m";
2057 Bold_Vid_Str
= "\033[1m";
2058 Blink_Vid_Str
= "\033[5m";
2059 UnderLine_Vid_Str
= "\033[4m";
2060 Del_Eol_Str
= "\033[K";
2061 Rev_Scroll_Str
= "\033M";
2062 Curs_F_Str
= "\033[%dC";
2063 /* Len_Curs_F_Str = 5; */
2064 Curs_Pos_Str
= "\033[%i%d;%dH";
2065 if ((vt100
== NULL
) || (*vt100
== 0))
2067 Ins_Mode_Str
= "\033[4h";
2068 Eins_Mode_Str
= "\033[4l";
2069 Del_Char_Str
= "\033[P";
2070 Del_N_Lines_Str
= "\033[%dM";
2071 Add_N_Lines_Str
= "\033[%dL";
2072 SLtt_Term_Cannot_Insert
= 0;
2076 Del_N_Lines_Str
= NULL
;
2077 Add_N_Lines_Str
= NULL
;
2078 SLtt_Term_Cannot_Insert
= 1;
2080 SLtt_Term_Cannot_Scroll
= 0;
2081 /* No_Move_In_Standout = 0; */
2084 void SLtt_init_video (void)
2086 /* send_string_to_term("\033[?6h"); */
2087 /* relative origin mode */
2088 SLtt_write_string (Term_Init_Str
);
2089 SLtt_write_string (Keypad_Init_Str
);
2090 SLtt_reset_scroll_region();
2092 SLtt_write_string (Enable_Alt_Char_Set
);
2093 Video_Initialized
= 1;
2097 void SLtt_reset_video (void)
2099 SLtt_goto_rc (SLtt_Screen_Rows
- 1, 0);
2101 SLtt_normal_video (); /* MSKermit requires this */
2102 SLtt_write_string(Norm_Vid_Str
);
2104 Current_Fgbg
= 0xFFFFFFFFU
;
2105 SLtt_set_alt_char_set (0);
2106 if (SLtt_Use_Ansi_Colors
)
2108 if (Reset_Color_String
== NULL
)
2110 SLtt_Char_Type attr
;
2111 if (-1 != make_color_fgbg (NULL
, NULL
, &attr
))
2112 write_attributes (attr
);
2113 else SLtt_write_string ("\033[0m\033[m");
2115 else SLtt_write_string (Reset_Color_String
);
2116 Current_Fgbg
= 0xFFFFFFFFU
;
2119 SLtt_write_string (Keypad_Reset_Str
);
2120 SLtt_write_string (Term_Reset_Str
);
2121 SLtt_flush_output ();
2122 Video_Initialized
= 0;
2125 void SLtt_bold_video (void)
2127 SLtt_write_string (Bold_Vid_Str
);
2130 int SLtt_set_mouse_mode (int mode
, int force
)
2136 if (NULL
== (term
= (char *) getenv("TERM"))) return -1;
2137 if (strncmp ("xterm", term
, 5))
2142 SLtt_write_string ("\033[?9h");
2144 SLtt_write_string ("\033[?9l");
2150 void SLtt_disable_status_line (void)
2152 if (SLtt_Has_Status_Line
> 0)
2153 SLtt_write_string (Disable_Status_line_Str
);
2156 int SLtt_write_to_status_line (char *s
, int col
)
2158 if ((SLtt_Has_Status_Line
<= 0)
2159 || (Goto_Status_Line_Str
== NULL
)
2160 || (Return_From_Status_Line_Str
== NULL
))
2163 tt_printf (Goto_Status_Line_Str
, col
, 0);
2164 SLtt_write_string (s
);
2165 SLtt_write_string (Return_From_Status_Line_Str
);
2170 void SLtt_get_screen_size (void)
2174 unsigned short chan
;
2175 $
DESCRIPTOR(dev_dsc
, "SYS$INPUT:");
2178 VIOMODEINFO vioModeInfo
;
2182 #if defined(TIOCGWINSZ) && !defined(SCO_FLAVOR)
2183 struct winsize wind_struct
;
2187 if ((ioctl(1,TIOCGWINSZ
,&wind_struct
) == 0)
2188 || (ioctl(0, TIOCGWINSZ
, &wind_struct
) == 0)
2189 || (ioctl(2, TIOCGWINSZ
, &wind_struct
) == 0))
2191 c
= (int) wind_struct
.ws_col
;
2192 r
= (int) wind_struct
.ws_row
;
2196 while (errno
== EINTR
);
2201 status
= sys$
assign(&dev_dsc
,&chan
,0,0,0);
2204 code
= DVI$_DEVBUFSIZ
;
2205 status
= lib$
getdvi(&code
, &chan
,0, &c
, 0,0);
2208 code
= DVI$_TT_PAGE
;
2209 status
= lib$
getdvi(&code
, &chan
,0, &r
, 0,0);
2217 vioModeInfo
.cb
= sizeof(vioModeInfo
);
2218 VioGetMode (&vioModeInfo
, 0);
2219 c
= vioModeInfo
.col
;
2220 r
= vioModeInfo
.row
;
2225 char *s
= getenv ("LINES");
2226 if (s
!= NULL
) r
= atoi (s
);
2231 char *s
= getenv ("COLUMNS");
2232 if (s
!= NULL
) c
= atoi (s
);
2235 if ((r
<= 0) || (r
> 200)) r
= 24;
2236 if ((c
<= 0) || (c
> 250)) c
= 80;
2237 SLtt_Screen_Rows
= r
;
2238 SLtt_Screen_Cols
= c
;