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 */
121 #if defined(__DECC) && defined(VMS)
122 /* These get prototypes for write an sleep */
128 /* Colors: These definitions are used for the display. However, the
129 * application only uses object handles which get mapped to this
130 * internal representation. The mapping is performed by the Color_Map
131 * structure below. */
133 #define CHAR_MASK 0x000000FF
134 #define FG_MASK 0x0000FF00
135 #define BG_MASK 0x00FF0000
136 #define ATTR_MASK 0x1F000000
137 #define BGALL_MASK 0x0FFF0000
139 /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
140 * not include this attribute.
145 #define GET_FG(color) ((color & FG_MASK) >> 8)
146 #define GET_BG(color) ((color & BG_MASK) >> 16)
147 #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
149 int SLtt_Screen_Cols
;
150 int SLtt_Screen_Rows
;
151 int SLtt_Term_Cannot_Insert
;
152 int SLtt_Term_Cannot_Scroll
;
153 int SLtt_Use_Ansi_Colors
;
154 int SLtt_Blink_Mode
= 1;
155 int SLtt_Use_Blink_For_ACS
= 0;
156 int SLtt_Newline_Ok
= 0;
157 int SLtt_Has_Alt_Charset
= 0;
158 int SLtt_Force_Keypad_Init
= 0;
160 /* -1 means unknown */
161 int SLtt_Has_Status_Line
= -1; /* hs */
163 static int Automatic_Margins
;
164 /* static int No_Move_In_Standout; */
165 static int Worthless_Highlight
;
166 #define HP_GLITCH_CODE
167 #ifdef HP_GLITCH_CODE
168 /* This glitch is exclusive to HP term. Basically it means that to clear
169 * attributes, one has to erase to the end of the line.
171 static int Has_HP_Glitch
;
174 static char *Reset_Color_String
;
176 static int Linux_Console
;
178 /* It is crucial that JMAX_COLORS must be less than 128 since the high bit
179 * is used to indicate a character from the ACS (alt char set). The exception
180 * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
181 * the highbit is set, we interpret that as a blink character. This is
182 * exploited by DOSemu.
184 #define JMAX_COLORS 256
185 #define JNORMAL_COLOR 0
194 #define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
195 #define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
197 static Ansi_Color_Type Ansi_Color_Map
[JMAX_COLORS
] =
199 {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL
}, /* white/black */
200 {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK
, NULL
}, /* green/black */
201 {RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK
, NULL
}, /* magenta/black */
202 {RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK
, NULL
}, /* cyan/black */
203 {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK
, NULL
},
204 {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK
, NULL
},
205 {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK
, NULL
},
206 {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK
, NULL
},
207 {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK
, NULL
},
208 {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK
, NULL
},
209 {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK
, NULL
},
210 {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK
, NULL
},
211 {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK
, NULL
},
212 {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK
, NULL
},
213 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK
, NULL
},
214 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK
, NULL
},
215 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK
, NULL
},
216 {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK
, NULL
}
220 /* This is the string to use to use when outputting color information.
223 /* work around for sco console bug that can't handle combined sequences */
224 static char *Color_Escape_Sequence
= "\033[3%dm\033[4%dm";
226 /* Believe it or not, this is what is in the linux terminfo database. It
227 * produces the same escape sequence but it is much more CPU intensive.
228 * Why not just encode it as "\033[3%p1%dm\033[4%p2%dm" ???
230 /* static char *Color_Escape_Sequence = "\033[%p1%{30}%+%dm\033[%p2%{40}%+%dm"; */
231 static char *Color_Escape_Sequence
= "\033[3%d;4%dm";
234 char *SLtt_Graphics_Char_Pairs
; /* ac termcap string -- def is vt100 */
237 /* 1 if terminal lacks the ability to do into insert mode or into delete
238 mode. Currently controlled by S-Lang but later perhaps termcap. */
240 static char *UnderLine_Vid_Str
;
241 static char *Blink_Vid_Str
;
242 static char *Bold_Vid_Str
;
243 static char *Ins_Mode_Str
; /* = "\033[4h"; */ /* ins mode (im) */
244 static char *Eins_Mode_Str
; /* = "\033[4l"; */ /* end ins mode (ei) */
245 static char *Scroll_R_Str
; /* = "\033[%d;%dr"; */ /* scroll region */
246 static char *Cls_Str
; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
247 static char *Rev_Vid_Str
; /* = "\033[7m"; */ /* mr,so termcap string */
248 static char *Norm_Vid_Str
; /* = "\033[m"; */ /* me,se termcap string */
249 static char *Del_Eol_Str
; /* = "\033[K"; */ /* ce */
250 static char *Del_Char_Str
; /* = "\033[P"; */ /* dc */
251 static char *Del_N_Lines_Str
; /* = "\033[%dM"; */ /* DL */
252 static char *Add_N_Lines_Str
; /* = "\033[%dL"; */ /* AL */
253 static char *Rev_Scroll_Str
;
254 static char *Curs_Up_Str
;
255 static char *Curs_F_Str
; /* RI termcap string */
256 static char *Cursor_Visible_Str
; /* ve termcap string */
257 static char *Cursor_Invisible_Str
; /* vi termcap string */
259 static char *Start_Alt_Chars_Str
; /* as */
260 static char *End_Alt_Chars_Str
; /* ae */
261 static char *Enable_Alt_Char_Set
; /* eA */
263 static char *Term_Init_Str
;
264 static char *Keypad_Init_Str
;
265 static char *Term_Reset_Str
;
266 static char *Keypad_Reset_Str
;
268 /* status line functions */
269 static char *Disable_Status_line_Str
; /* ds */
270 static char *Return_From_Status_Line_Str
; /* fs */
271 static char *Goto_Status_Line_Str
; /* ts */
272 static int Num_Status_Line_Columns
; /* ws */
273 static int Status_Line_Esc_Ok
; /* es */
275 /* static int Len_Curs_F_Str = 5; */
277 /* cm string has %i%d since termcap numbers columns from 0 */
278 /* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
279 static char *Curs_Pos_Str
; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
282 /* scrolling region */
283 static int Scroll_r1
= 0, Scroll_r2
= 23;
284 static int Cursor_r
, Cursor_c
; /* 0 based */
286 /* current attributes --- initialized to impossible value */
287 static SLtt_Char_Type Current_Fgbg
= 0xFFFFFFFFU
;
289 static int Cursor_Set
; /* 1 if cursor position known, 0
290 * if not. -1 if only row is known
294 #define MAX_OUTPUT_BUFFER_SIZE 4096
296 static unsigned char Output_Buffer
[MAX_OUTPUT_BUFFER_SIZE
];
297 static unsigned char *Output_Bufferp
= Output_Buffer
;
299 unsigned long SLtt_Num_Chars_Output
;
301 #ifdef SLTT_TRANSP_ACS_PATCH
302 static int SLtt_ACS_Active
= 0;
305 static int sl_usleep (unsigned long usecs
)
309 tv
.tv_sec
= usecs
/ 1000000;
310 tv
.tv_usec
= usecs
% 1000000;
311 return select(0, NULL
, NULL
, NULL
, &tv
);
317 int SLtt_flush_output (void)
321 int n
= (int) (Output_Bufferp
- Output_Buffer
);
323 SLtt_Num_Chars_Output
+= n
;
328 nwrite
= write (fileno(stdout
), (char *) Output_Buffer
+ total
, n
);
335 sl_usleep (100000); /* 1/10 sec */
340 if (errno
== EWOULDBLOCK
)
347 if (errno
== EINTR
) continue;
354 Output_Bufferp
= Output_Buffer
;
360 static void tt_write(char *str
, unsigned int n
)
362 static unsigned long last_time
;
367 if ((str
== NULL
) || (n
== 0)) return;
372 ndiff
= MAX_OUTPUT_BUFFER_SIZE
- (int) (Output_Bufferp
- Output_Buffer
);
375 SLMEMCPY ((char *) Output_Bufferp
, (char *) str
, ndiff
);
376 Output_Bufferp
+= ndiff
;
377 SLtt_flush_output ();
383 SLMEMCPY ((char *) Output_Bufferp
, str
, n
);
389 if (((SLtt_Baud_Rate
> 150) && (SLtt_Baud_Rate
<= 9600))
390 && (10 * total
> SLtt_Baud_Rate
))
393 if ((now
= (unsigned long) time(NULL
)) - last_time
<= 1)
395 SLtt_flush_output ();
403 void SLtt_write_string (char *str
)
405 if (str
!= NULL
) tt_write(str
, strlen(str
));
409 void SLtt_putchar (char ch
)
411 #ifdef SLTT_TRANSP_ACS_PATCH
415 SLtt_normal_video ();
418 if (ch
>= ' ') Cursor_c
++;
419 #ifndef SLTT_TRANSP_ACS_PATCH
420 else if (ch
== '\b') Cursor_c
--;
422 if (ch
<= ' ' && SLtt_ACS_Active
)
424 SLtt_set_alt_char_set (0);
427 if (ch
== '\b') Cursor_c
--;
429 else if (ch
== '\r') Cursor_c
= 0;
432 if ((Cursor_c
+ 1 == SLtt_Screen_Cols
)
433 && Automatic_Margins
) Cursor_Set
= 0;
436 if (Output_Bufferp
< Output_Buffer
+ MAX_OUTPUT_BUFFER_SIZE
)
438 *Output_Bufferp
++ = (unsigned char) ch
;
440 else tt_write (&ch
, 1);
442 #ifdef SLTT_TRANSP_ACS_PATCH
445 SLtt_set_alt_char_set (1);
450 /* this is supposed to be fast--- also handles
451 termcap: %d, &i, %., %+, %r strings as well as terminfo stuff */
452 static unsigned int tt_sprintf(char *buf
, char *fmt
, int x
, int y
)
454 register unsigned char *f
= (unsigned char *) fmt
, *b
, ch
;
455 int offset
= 0, tinfo
= 0;
458 stack
[0] = y
; stack
[1] = x
; i
= 2;
460 b
= (unsigned char *) buf
;
461 if (fmt
!= NULL
) while ((ch
= *f
++) != 0)
463 if (ch
!= '%') *b
++ = ch
;
469 if ((ch
<= '3') && (ch
>= '0'))
471 /* map it to termcap. Since this is terminfo,
473 * %2d, %3d, %02d, %03d
475 * I am assuming that a terminal that understands
476 * %2d form will also understand the %02d form. These
477 * only differ by a space padding the field.
480 /* skip the 'd'-- hope it is there */
495 if (ch
== '1') stack
[i
++] = x
; else stack
[i
++] = y
;
503 case '{': /* literal constant, e.g. {30} */
505 while (((ch
= *f
) <= '9') && (ch
>= '0'))
507 z
= z
* 10 + (ch
- '0');
521 *b
++ = z
/ 100 + '0';
537 else if (ch
== 2) *b
++ = '0';
555 if ((unsigned char) ch
== 128) ch
= 0;
556 ch
= ch
+ (unsigned char) stack
[--i
];
557 if (ch
== '\n') ch
++;
569 ch
= (unsigned char) stack
[--i
];
570 if (ch
== '\n') ch
++;
580 return((unsigned int) (b
- (unsigned char *) buf
));
583 static void tt_printf(char *fmt
, int x
, int y
)
587 if (fmt
== NULL
) return;
588 n
= tt_sprintf(buf
, fmt
, x
, y
);
593 void SLtt_set_scroll_region (int r1
, int r2
)
597 tt_printf (Scroll_R_Str
, Scroll_r1
, Scroll_r2
);
601 void SLtt_reset_scroll_region (void)
603 SLtt_set_scroll_region(0, SLtt_Screen_Rows
- 1);
606 int SLtt_set_cursor_visibility (int show
)
608 if ((Cursor_Visible_Str
== NULL
) || (Cursor_Invisible_Str
== NULL
))
611 SLtt_write_string (show
? Cursor_Visible_Str
: Cursor_Invisible_Str
);
616 /* the goto_rc function moves to row relative to scrolling region */
617 void SLtt_goto_rc(int r
, int c
)
622 #ifdef SLTT_TRANSP_ACS_PATCH
623 int check_alt_acs
= 0;
632 /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
635 if ((Cursor_Set
> 0) || ((Cursor_Set
< 0) && !Automatic_Margins
))
638 if ((n
== -1) && (Cursor_Set
> 0) && (Cursor_c
== c
)
639 && (Curs_Up_Str
!= NULL
))
643 else if ((n
>= 0) && (n
<= 4))
645 if ((n
== 0) && (Cursor_Set
== 1)
646 && ((c
> 1) || (c
== Cursor_c
)))
648 if (Cursor_c
== c
) return;
649 if (Cursor_c
== c
+ 1)
654 #ifdef SLTT_TRANSP_ACS_PATCH
662 if ((Cursor_Set
!= 1) || (Cursor_c
!= 0)) *s
++ = '\r';
663 while (n
--) *s
++ = '\n';
665 /* Need to add this after \n to start a new record. Sheesh. */
670 #ifdef SLTT_TRANSP_ACS_PATCH
674 /* Will fail on VMS */
676 else if (SLtt_Newline_Ok
&& (Cursor_Set
== 1) &&
677 (Cursor_c
>= c
) && (c
+ 3 > Cursor_c
))
680 while (n
--) *s
++ = '\n';
682 while (n
--) *s
++ = '\b';
685 #ifdef SLTT_TRANSP_ACS_PATCH
692 #ifndef SLTT_TRANSP_ACS_PATCH
693 if (s
!= NULL
) SLtt_write_string(s
);
697 if (check_alt_acs
&& SLtt_ACS_Active
)
699 SLtt_set_alt_char_set (0);
700 SLtt_write_string(s
);
701 SLtt_set_alt_char_set (1);
703 else SLtt_write_string(s
);
706 else tt_printf(Curs_Pos_Str
, r
, c
);
707 Cursor_c
= c
; Cursor_r
= r
;
711 void SLtt_begin_insert (void)
713 SLtt_write_string(Ins_Mode_Str
);
716 void SLtt_end_insert (void)
718 SLtt_write_string(Eins_Mode_Str
);
721 void SLtt_delete_char (void)
723 SLtt_normal_video ();
724 SLtt_write_string(Del_Char_Str
);
727 void SLtt_erase_line (void)
729 SLtt_write_string("\r");
730 Cursor_Set
= 1; Cursor_c
= 0;
734 void SLtt_delete_nlines (int n
)
738 #ifdef SLTT_TRANSP_ACS_PATCH
743 SLtt_normal_video ();
744 if (Del_N_Lines_Str
!= NULL
) tt_printf(Del_N_Lines_Str
,n
, 0);
746 /* get a new terminal */
750 SLtt_set_scroll_region(curs
, Scroll_r2
);
751 SLtt_goto_rc(Scroll_r2
- Scroll_r1
, 0);
752 #ifdef SLTT_TRANSP_ACS_PATCH
755 SLtt_set_alt_char_set (0);
759 SLMEMSET(buf
, '\n', (unsigned int) n
);
760 tt_write(buf
, (unsigned int) n
);
761 #ifdef SLTT_TRANSP_ACS_PATCH
762 if (restore_acs
) SLtt_set_alt_char_set (1);
764 /* while (n--) tt_putchar('\n'); */
765 SLtt_set_scroll_region(r1
, Scroll_r2
);
766 SLtt_goto_rc(curs
, 0);
773 SLtt_reset_scroll_region ();
774 SLtt_write_string(Cls_Str
);
777 void SLtt_reverse_index (int n
)
782 if (Add_N_Lines_Str
!= NULL
) tt_printf(Add_N_Lines_Str
,n
, 0);
785 while(n
--) SLtt_write_string(Rev_Scroll_Str
);
790 int SLtt_Ignore_Beep
= 1;
791 static char *Visible_Bell_Str
;
793 void SLtt_beep (void)
795 if (SLtt_Ignore_Beep
& 0x1) SLtt_putchar('\007');
797 if (SLtt_Ignore_Beep
& 0x2)
799 if (Visible_Bell_Str
!= NULL
) SLtt_write_string (Visible_Bell_Str
);
801 else if (Linux_Console
)
803 SLtt_write_string ("\033[?5h");
804 SLtt_flush_output ();
806 SLtt_write_string ("\033[?5l");
810 SLtt_flush_output ();
813 void SLtt_del_eol (void)
815 if (Current_Fgbg
!= 0xFFFFFFFFU
) SLtt_normal_video ();
816 SLtt_write_string(Del_Eol_Str
);
822 SLtt_Char_Type color
;
826 #define MAX_COLOR_NAMES 17
827 static Color_Def_Type Color_Defs
[MAX_COLOR_NAMES
] =
829 {"black", SLSMG_COLOR_BLACK
},
830 {"red", SLSMG_COLOR_RED
},
831 {"green", SLSMG_COLOR_GREEN
},
832 {"brown", SLSMG_COLOR_BROWN
},
833 {"blue", SLSMG_COLOR_BLUE
},
834 {"magenta", SLSMG_COLOR_MAGENTA
},
835 {"cyan", SLSMG_COLOR_CYAN
},
836 {"lightgray", SLSMG_COLOR_LGRAY
},
837 {"gray", SLSMG_COLOR_GRAY
},
838 {"brightred", SLSMG_COLOR_BRIGHT_RED
},
839 {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN
},
840 {"yellow", SLSMG_COLOR_BRIGHT_BROWN
},
841 {"brightblue", SLSMG_COLOR_BRIGHT_BLUE
},
842 {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN
},
843 {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA
},
844 {"white", SLSMG_COLOR_BRIGHT_WHITE
},
849 void SLtt_set_mono (int obj
, char *what
, SLtt_Char_Type mask
)
852 if ((obj
< 0) || (obj
>= JMAX_COLORS
))
856 Ansi_Color_Map
[obj
].mono
= mask
& ATTR_MASK
;
859 static char *check_color_for_digit_form (char *color
)
865 while ((ich
= (int) *s
) != 0)
867 if ((ich
< '0') || (ich
> '9'))
870 i
= i
* 10 + (ich
- '0');
874 if (i
< MAX_COLOR_NAMES
)
875 color
= Color_Defs
[i
].name
;
880 static int get_default_colors (char **fgp
, char **bgp
)
882 static char fg_buf
[16], bg_buf
[16], *bg
, *fg
;
883 static int already_parsed
;
886 if (already_parsed
== -1)
898 bg
= getenv ("COLORFGBG");
902 bg
= getenv ("DEFAULT_COLORS");
908 pmax
= p
+ (sizeof (fg_buf
) - 1);
910 while ((*bg
!= 0) && (*bg
!= ';'))
912 if (p
< pmax
) *p
++ = *bg
;
920 pmax
= p
+ (sizeof (bg_buf
) - 1);
922 /* Mark suggested allowing for extra spplication specific stuff following
923 * the background color. That is what the check for the semi-colon is for.
925 while ((*bg
!= 0) && (*bg
!= ';'))
927 if (p
< pmax
) *p
++ = *bg
;
932 if (!strcmp (fg_buf
, "default") || !strcmp(bg_buf
, "default"))
934 *fgp
= *bgp
= fg
= bg
= "default";
938 *fgp
= fg
= check_color_for_digit_form (fg_buf
);
939 *bgp
= bg
= check_color_for_digit_form (bg_buf
);
946 static unsigned char FgBg_Stats
[JMAX_COLORS
];
948 static int Color_0_Modified
= 0;
950 void SLtt_set_color_object (int obj
, SLtt_Char_Type attr
)
954 if ((obj
< 0) || (obj
>= JMAX_COLORS
)) return;
956 cust_esc
= Ansi_Color_Map
[obj
].custom_esc
;
957 if (cust_esc
!= NULL
)
960 FgBg_Stats
[(Ansi_Color_Map
[obj
].fgbg
>> 8) & 0x7F] -= 1;
961 Ansi_Color_Map
[obj
].custom_esc
= NULL
;
964 Ansi_Color_Map
[obj
].fgbg
= attr
;
965 if (obj
== 0) Color_0_Modified
= 1;
968 SLtt_Char_Type
SLtt_get_color_object (int obj
)
970 if ((obj
< 0) || (obj
>= JMAX_COLORS
)) return 0;
971 return Ansi_Color_Map
[obj
].fgbg
;
975 void SLtt_add_color_attribute (int obj
, SLtt_Char_Type attr
)
977 if ((obj
< 0) || (obj
>= JMAX_COLORS
)) return;
979 Ansi_Color_Map
[obj
].fgbg
|= (attr
& ATTR_MASK
);
980 if (obj
== 0) Color_0_Modified
= 1;
983 static SLtt_Char_Type
fb_to_fgbg (SLtt_Char_Type f
, SLtt_Char_Type b
)
985 SLtt_Char_Type attr
= 0;
989 if (f
& 0x8) attr
= SLTT_BOLD_MASK
;
996 if (b
& 0x8) attr
|= SLTT_BLINK_MASK
;
1001 return ((f
<< 8) | (b
<< 16) | attr
);
1004 static int make_color_fgbg (char *fg
, char *bg
, SLtt_Char_Type
*fgbg
)
1006 SLtt_Char_Type f
= 0xFFFFFFFFU
, b
= 0xFFFFFFFFU
;
1010 if ((fg
!= NULL
) && (*fg
== 0)) fg
= NULL
;
1011 if ((bg
!= NULL
) && (*bg
== 0)) bg
= NULL
;
1013 if ((fg
== NULL
) || (bg
== NULL
))
1015 if (-1 == get_default_colors (&dfg
, &dbg
))
1018 if (fg
== NULL
) fg
= dfg
;
1019 if (bg
== NULL
) bg
= dbg
;
1022 for (i
= 0; i
< MAX_COLOR_NAMES
; i
++)
1024 if (strcmp(fg
, Color_Defs
[i
].name
)) continue;
1025 f
= Color_Defs
[i
].color
;
1029 for (i
= 0; i
< MAX_COLOR_NAMES
; i
++)
1031 if (strcmp(bg
, Color_Defs
[i
].name
)) continue;
1032 b
= Color_Defs
[i
].color
;
1036 if ((f
== 0xFFFFFFFFU
) || (b
== 0xFFFFFFFFU
))
1039 *fgbg
= fb_to_fgbg (f
, b
);
1043 void SLtt_set_color (int obj
, char *what
, char *fg
, char *bg
)
1045 SLtt_Char_Type fgbg
;
1048 if ((obj
< 0) || (obj
>= JMAX_COLORS
))
1051 if (-1 != make_color_fgbg (fg
, bg
, &fgbg
))
1052 SLtt_set_color_object (obj
, fgbg
);
1055 void SLtt_set_color_fgbg (int obj
, SLtt_Char_Type f
, SLtt_Char_Type b
)
1057 SLtt_set_color_object (obj
, fb_to_fgbg (f
, b
));
1060 void SLtt_set_color_esc (int obj
, char *esc
)
1063 SLtt_Char_Type fgbg
= 0;
1066 if ((obj
< 0) || (obj
>= JMAX_COLORS
))
1071 cust_esc
= Ansi_Color_Map
[obj
].custom_esc
;
1072 if (cust_esc
!= NULL
)
1075 FgBg_Stats
[(Ansi_Color_Map
[obj
].fgbg
>> 8) & 0x7F] -= 1;
1078 cust_esc
= (char *) SLMALLOC (strlen(esc
) + 1);
1079 if (cust_esc
!= NULL
) strcpy (cust_esc
, esc
);
1081 Ansi_Color_Map
[obj
].custom_esc
= cust_esc
;
1082 if (cust_esc
== NULL
) fgbg
= 0;
1085 /* The whole point of this is to generate a unique fgbg */
1086 for (i
= 0; i
< JMAX_COLORS
; i
++)
1088 if (FgBg_Stats
[i
] == 0) fgbg
= i
;
1090 if (obj
== i
) continue;
1091 if ((Ansi_Color_Map
[i
].custom_esc
) == NULL
) continue;
1092 if (!strcmp (Ansi_Color_Map
[i
].custom_esc
, cust_esc
))
1094 fgbg
= (Ansi_Color_Map
[i
].fgbg
>> 8) & 0x7F;
1098 FgBg_Stats
[fgbg
] += 1;
1102 Ansi_Color_Map
[obj
].fgbg
= (fgbg
| (fgbg
<< 8)) << 8;
1103 if (obj
== 0) Color_0_Modified
= 1;
1106 void SLtt_set_alt_char_set (int i
)
1108 #ifndef SLTT_TRANSP_ACS_PATCH
1111 #define last_i SLtt_ACS_Active
1113 if (SLtt_Has_Alt_Charset
== 0) return;
1114 if (i
== last_i
) return;
1115 SLtt_write_string (i
? Start_Alt_Chars_Str
: End_Alt_Chars_Str
);
1116 /* if (i) Current_Fgbg |= SLTT_ALTC_MASK;
1117 else Current_Fgbg &= ~SLTT_ALTC_MASK; */
1119 #ifdef SLTT_TRANSP_ACS_PATCH
1124 static void write_attributes (SLtt_Char_Type fgbg
)
1128 if (Worthless_Highlight
) return;
1129 if (fgbg
== Current_Fgbg
) return;
1131 /* Before spitting out colors, fix attributes */
1132 if ((fgbg
& ATTR_MASK
) != (Current_Fgbg
& ATTR_MASK
))
1134 if (Current_Fgbg
& ATTR_MASK
)
1136 SLtt_write_string(Norm_Vid_Str
);
1137 /* In case normal video turns off ALL attributes: */
1138 if (fgbg
& SLTT_ALTC_MASK
)
1139 Current_Fgbg
&= ~SLTT_ALTC_MASK
;
1140 SLtt_set_alt_char_set (0);
1143 if ((fgbg
& SLTT_ALTC_MASK
)
1144 != (Current_Fgbg
& SLTT_ALTC_MASK
))
1146 SLtt_set_alt_char_set ((int) (fgbg
& SLTT_ALTC_MASK
));
1149 if (fgbg
& SLTT_ULINE_MASK
) SLtt_write_string (UnderLine_Vid_Str
);
1150 if (fgbg
& SLTT_BOLD_MASK
) SLtt_bold_video ();
1151 if (fgbg
& SLTT_REV_MASK
) SLtt_write_string (Rev_Vid_Str
);
1152 if (fgbg
& SLTT_BLINK_MASK
)
1154 /* Someday Linux will have a blink mode that set high intensity
1155 * background. Lets be prepared.
1157 if (SLtt_Blink_Mode
) SLtt_write_string (Blink_Vid_Str
);
1161 if (SLtt_Use_Ansi_Colors
)
1163 fg0
= (int) GET_FG(fgbg
);
1164 bg0
= (int) GET_BG(fgbg
);
1165 tt_printf(Color_Escape_Sequence
, fg0
, bg0
);
1167 Current_Fgbg
= fgbg
;
1170 static int Video_Initialized
;
1172 void SLtt_reverse_video (int color
)
1174 SLtt_Char_Type fgbg
;
1177 if (Worthless_Highlight
) return;
1178 if ((color
< 0) || (color
>= JMAX_COLORS
)) return;
1180 if (Video_Initialized
== 0)
1182 if (color
== JNORMAL_COLOR
)
1184 SLtt_write_string (Norm_Vid_Str
);
1186 else SLtt_write_string (Rev_Vid_Str
);
1187 Current_Fgbg
= 0xFFFFFFFFU
;
1191 if (SLtt_Use_Ansi_Colors
)
1193 fgbg
= Ansi_Color_Map
[color
].fgbg
;
1194 if ((esc
= Ansi_Color_Map
[color
].custom_esc
) != NULL
)
1196 if (fgbg
!= Current_Fgbg
)
1198 Current_Fgbg
= fgbg
;
1199 SLtt_write_string (esc
);
1204 else fgbg
= Ansi_Color_Map
[color
].mono
;
1206 if (fgbg
== Current_Fgbg
) return;
1207 write_attributes (fgbg
);
1213 void SLtt_normal_video (void)
1215 SLtt_reverse_video(JNORMAL_COLOR
);
1218 void SLtt_narrow_width (void)
1220 SLtt_write_string("\033[?3l");
1223 void SLtt_wide_width (void)
1225 SLtt_write_string("\033[?3h");
1228 /* Highest bit represents the character set. */
1229 #define COLOR_MASK 0x7F00
1231 #define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
1233 #define COLOR_EQS(a, b) \
1234 (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
1237 #define COLOR_EQS(a, b) \
1238 (SLtt_Use_Ansi_Colors \
1239 ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
1240 : (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
1243 #define CHAR_EQS(a, b) (((a) == (b))\
1244 || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
1245 && COLOR_EQS((a), (b))))
1248 /* The whole point of this routine is to prevent writing to the last column
1249 * and last row on terminals with automatic margins.
1251 static void write_string_with_care (char *str
)
1255 if (str
== NULL
) return;
1258 if (Automatic_Margins
&& (Cursor_r
+ 1 == SLtt_Screen_Rows
))
1260 if (len
+ (unsigned int) Cursor_c
>= (unsigned int) SLtt_Screen_Cols
)
1262 /* For now, just do not write there. Later, something more
1263 * sophisticated will be implemented.
1265 if (SLtt_Screen_Cols
> Cursor_c
)
1266 len
= SLtt_Screen_Cols
- Cursor_c
- 1;
1270 tt_write (str
, len
);
1273 static void send_attr_str (unsigned short *s
)
1275 unsigned char out
[256], ch
, *p
;
1276 register SLtt_Char_Type attr
;
1277 register unsigned short sh
;
1278 int color
, last_color
= -1;
1281 while (0 != (sh
= *s
++))
1284 color
= ((int) sh
& 0xFF00) >> 8;
1285 #ifdef SLTT_TRANSP_ACS_PATCH
1286 if (ch
<= ' ' && (color
& 0x80)) color
&= ~0x80;
1288 if (color
!= last_color
)
1290 if (SLtt_Use_Ansi_Colors
) attr
= Ansi_Color_Map
[color
& 0x7F].fgbg
;
1291 else attr
= Ansi_Color_Map
[color
& 0x7F].mono
;
1294 if (color
& 0x80) /* alternate char set */
1296 if (SLtt_Use_Blink_For_ACS
)
1298 if (SLtt_Blink_Mode
) attr
|= SLTT_BLINK_MASK
;
1300 else attr
|= SLTT_ALTC_MASK
;
1304 if (attr
!= Current_Fgbg
)
1306 #ifndef SLTT_TRANSP_ACS_PATCH
1308 /* it is a space so only consider it different if it
1309 * has different attributes.
1311 (attr
& BGALL_MASK
) != (Current_Fgbg
& BGALL_MASK
))
1317 write_string_with_care ((char *) out
);
1318 Cursor_c
+= (int) (p
- out
);
1322 if (SLtt_Use_Ansi_Colors
&& (NULL
!= Ansi_Color_Map
[color
& 0x7F].custom_esc
))
1324 SLtt_write_string (Ansi_Color_Map
[color
& 0x7F].custom_esc
);
1325 /* Just in case the custom escape sequence screwed up
1326 * the alt character set state...
1328 if ((attr
& SLTT_ALTC_MASK
) != (Current_Fgbg
& SLTT_ALTC_MASK
))
1329 SLtt_set_alt_char_set ((int) (attr
& SLTT_ALTC_MASK
));
1330 Current_Fgbg
= attr
;
1332 else write_attributes (attr
);
1341 if (p
!= out
) write_string_with_care ((char *) out
);
1342 Cursor_c
+= (int) (p
- out
);
1345 static void forward_cursor (unsigned int n
, int row
)
1352 SLtt_normal_video ();
1353 SLMEMSET (buf
, ' ', n
);
1355 write_string_with_care (buf
);
1358 else if (Curs_F_Str
!= NULL
)
1361 n
= tt_sprintf(buf
, Curs_F_Str
, (int) n
, 0);
1364 else SLtt_goto_rc (row
, (int) (Cursor_c
+ n
));
1368 #define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))
1370 void SLtt_smart_puts(unsigned short *neww
, unsigned short *oldd
, int len
, int row
)
1372 register unsigned short *p
, *q
, *qmax
, *pmax
, *buf
;
1373 unsigned short buffer
[256];
1374 unsigned int n_spaces
;
1375 unsigned short *space_match
, *last_buffered_match
;
1376 #ifdef HP_GLITCH_CODE
1377 int handle_hp_glitch
= 0;
1384 /* Find out where to begin --- while they match, we are ok */
1387 if (q
== qmax
) return;
1388 #if SLANG_HAS_KANJI_SUPPORT
1390 { /* new is kanji */
1391 if ((*q
& 0x80) && ((q
+ 1) < qmax
))
1392 { /* old is also kanji */
1393 if (((0xFF & *q
) != (0xFF & *p
))
1394 || ((0xFF & q
[1]) != (0xFF & p
[1])))
1395 break; /* both kanji, but not match */
1398 { /* kanji match ! */
1399 if (!COLOR_EQS(*q
, *p
)) break;
1401 if (!COLOR_EQS(*q
, *p
)) break;
1407 else break; /* old is not kanji */
1410 { /* new is not kanji */
1411 if (*q
& 0x80) break; /* old is kanji */
1414 if (!CHAR_EQS(*q
, *p
)) break;
1418 /*position the cursor */
1419 SLtt_goto_rc (row
, (int) (p
- neww
));
1421 #ifdef HP_GLITCH_CODE
1424 unsigned short *qq
= q
;
1429 SLtt_normal_video ();
1432 handle_hp_glitch
= 1;
1439 /* Find where the last non-blank character on old/new screen is */
1444 if (!CHAR_EQS(*qmax
, SPACE_CHAR
))
1454 if (!CHAR_EQS(*pmax
, SPACE_CHAR
))
1461 last_buffered_match
= buf
= buffer
; /* buffer is empty */
1463 #ifdef HP_GLITCH_CODE
1464 if (handle_hp_glitch
)
1473 /* loop using overwrite then skip algorithm until done */
1476 /* while they do not match and we do not hit a space, buffer them up */
1480 if (CHAR_EQS(*q
,SPACE_CHAR
) && CHAR_EQS(*p
, SPACE_CHAR
))
1482 /* If *q is not a space, we would have to overwrite it.
1483 * However, if *q is a space, then while *p is also one,
1484 * we only need to skip over the blank field.
1489 && CHAR_EQS(*q
,SPACE_CHAR
)
1490 && CHAR_EQS(*p
, SPACE_CHAR
))
1495 n_spaces
= (unsigned int) (p
- space_match
);
1498 #if SLANG_HAS_KANJI_SUPPORT
1499 if ((*p
& 0x80) && ((p
+ 1) < pmax
))
1500 { /* new is kanji */
1502 { /* old is also kanji */
1503 if (((0xFF & *q
) != (0xFF & *p
))
1504 || ((0xFF & q
[1]) != (0xFF & p
[1])))
1506 /* both kanji, but not match */
1513 { /* kanji match ? */
1514 if (!COLOR_EQS(*q
, *p
) || !COLOR_EQS(*(q
+1), *(p
+1)))
1516 /* code is match ,but color is diff */
1521 /* really match ! */
1526 { /* old is not kanji */
1534 { /* new is not kanji */
1536 { /* old is kanji */
1544 if (CHAR_EQS(*q
, *p
)) break;
1550 if (buf
!= buffer
) send_attr_str (buffer
);
1553 if (n_spaces
&& (p
< pmax
))
1555 forward_cursor (n_spaces
, row
);
1558 /* Now we overwrote what we could and cursor is placed at position
1559 * of a possible match of new and old. If this is the case, skip
1562 #if !SLANG_HAS_KANJI_SUPPORT
1563 while ((p
< pmax
) && CHAR_EQS(*p
, *q
))
1572 if ((*p
& 0x80) && ((p
+ 1) < pmax
))
1573 { /* new is kanji */
1575 { /* old is also kanji */
1576 if (((0xFF & *q
) == (0xFF & *p
))
1577 && ((0xFF & q
[1]) == (0xFF & p
[1])))
1580 if (!COLOR_EQS(*q
, *p
)
1581 || !COLOR_EQS(q
[1], p
[1]))
1588 *buf
++ = SPACE_CHAR
;
1599 else break; /* both kanji, but not match */
1601 else break; /* old is not kanji */
1604 { /* new is not kanji */
1605 if (*q
& 0x80) break; /* old is kanji */
1606 if (!CHAR_EQS(*q
, *p
)) break;
1612 last_buffered_match
= buf
;
1613 if (p
>= pmax
) break;
1615 /* jump to new position is it is greater than 5 otherwise
1616 * let it sit in the buffer and output it later.
1618 if ((int) (buf
- buffer
) >= 5)
1620 forward_cursor ((unsigned int) (buf
- buffer
), row
);
1621 last_buffered_match
= buf
= buffer
;
1629 if ((buf
== last_buffered_match
)
1630 && ((int) (buf
- buffer
) >= 5))
1632 forward_cursor ((unsigned int) (buf
- buffer
), row
);
1637 send_attr_str (buffer
);
1641 if (q
< qmax
) SLtt_del_eol ();
1642 if (Automatic_Margins
&& (Cursor_c
+ 1 >= SLtt_Screen_Cols
)) Cursor_Set
= 0;
1646 static void get_color_info (void)
1650 SLtt_Use_Ansi_Colors
= (NULL
!= getenv ("COLORTERM"));
1652 if (-1 == get_default_colors (&fg
, &bg
))
1655 /* Check to see if application has already set them. */
1656 if (Color_0_Modified
)
1659 SLtt_set_color (0, NULL
, fg
, bg
);
1660 SLtt_set_color (1, NULL
, bg
, fg
);
1670 static char *Tstr_Buf
;
1672 #define tgetstr SLtt_tigetstr
1673 #define tgetent SLtt_tigetent
1674 #define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
1675 #define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
1678 extern char *tgetstr(char *, char **);
1679 extern int tgetent(char *, char *);
1680 extern int tgetnum(char *);
1681 extern int tgetflag(char *);
1682 static char Tstr_Buf
[1024];
1683 static char Tbuf
[4096];
1684 #define TGETNUM tgetnum
1685 #define TGETFLAG tgetflag
1688 static char *my_tgetstr(char *what
, char **p
)
1690 register char *w
, *w1
;
1692 what
= tgetstr(what
, p
);
1695 /* Check for AIX brain-damage */
1699 /* lose pad info --- with today's technology, term is a loser if
1700 it is really needed */
1701 while ((*what
== '.') ||
1702 ((*what
>= '0') && (*what
<= '9'))) what
++;
1703 if (*what
== '*') what
++;
1705 /* lose terminfo padding--- looks like $<...> */
1707 while (*w
) if ((*w
++ == '$') && (*w
== '<'))
1710 while (*w
&& (*w
!= '>')) w
++;
1714 while ((*w1
++ = *w
++) != 0);
1717 if (*what
== 0) what
= NULL
;
1722 char *SLtt_tgetstr (char *s
)
1728 return my_tgetstr (s
, &p
);
1731 int SLtt_tgetnum (char *s
)
1735 int SLtt_tgetflag (char *s
)
1737 return TGETFLAG (s
);
1741 static int Vt100_Like
= 0;
1743 void SLtt_get_terminfo (void)
1751 if (NULL
== (term
= (char *) getenv("TERM")))
1753 SLang_exit_error("TERM environment variable needs set.");
1756 Linux_Console
= (!strncmp (term
, "linux", 5)
1758 || !strncmp(term
, "con", 3)
1764 if (strcmp(t
, "vt52") && (*t
++ == 'v') && (*t
++ == 't')
1765 && (ch
= *t
, (ch
>= '1') && (ch
<= '9'))) Vt100_Like
= 1;
1767 is_xterm
= !strncmp (term
, "xterm", 5);
1768 almost_vtxxx
= (Vt100_Like
1771 || !strcmp (term
, "screen"));
1774 if (NULL
== (Tbuf
= tgetent (term
)))
1777 if (almost_vtxxx
) /* Special cases. */
1780 if (!strcmp (term
, "vt100")) vt102
= 0;
1781 SLtt_set_term_vtxxx (&vt102
);
1784 g_snprintf (err_buf
, sizeof (err_buf
), "Unknown terminal: %s\n\
1785 Check the TERM environment variable.\n\
1786 Also make sure that the terminal is defined in the terminfo database.\n\
1787 Alternatively, set the TERMCAP environment variable to the desired\n\
1788 termcap entry.", term
);
1789 SLang_exit_error(err_buf
);
1792 #else /* USE_TERMCAP */
1793 if (1 != tgetent(Tbuf
, term
)) SLang_exit_error("Unknown terminal.");
1794 #endif /* NOT USE_TERMCAP */
1796 if ((NULL
== (Cls_Str
= SLtt_tgetstr("cl")))
1797 || (NULL
== (Curs_Pos_Str
= SLtt_tgetstr("cm"))))
1799 SLang_exit_error("Terminal not powerful enough for SLang.");
1802 if ((NULL
== (Ins_Mode_Str
= SLtt_tgetstr("im")))
1803 || ( NULL
== (Eins_Mode_Str
= SLtt_tgetstr("ei")))
1804 || ( NULL
== (Del_Char_Str
= SLtt_tgetstr("dc"))))
1805 SLtt_Term_Cannot_Insert
= 1;
1807 Visible_Bell_Str
= SLtt_tgetstr ("vb");
1808 Curs_Up_Str
= SLtt_tgetstr ("up");
1809 Rev_Scroll_Str
= SLtt_tgetstr("sr");
1810 Del_N_Lines_Str
= SLtt_tgetstr("DL");
1811 Add_N_Lines_Str
= SLtt_tgetstr("AL");
1813 /* Actually these are used to initialize terminals that use cursor
1814 * addressing. Hard to believe.
1816 Term_Init_Str
= SLtt_tgetstr ("ti");
1817 Term_Reset_Str
= SLtt_tgetstr ("te");
1819 /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
1820 * which I do not want. This is mainly for HP terminals.
1822 if ((almost_vtxxx
== 0) || SLtt_Force_Keypad_Init
)
1824 Keypad_Init_Str
= SLtt_tgetstr ("ks");
1825 Keypad_Reset_Str
= SLtt_tgetstr ("ke");
1828 /* Make up for defective termcap/terminfo databases */
1829 if ((Vt100_Like
&& (term
[2] != '1'))
1834 if (Del_N_Lines_Str
== NULL
) Del_N_Lines_Str
= "\033[%dM";
1835 if (Add_N_Lines_Str
== NULL
) Add_N_Lines_Str
= "\033[%dL";
1838 Scroll_R_Str
= SLtt_tgetstr("cs");
1840 SLtt_get_screen_size ();
1842 if ((Scroll_R_Str
== NULL
)
1843 || (((NULL
== Del_N_Lines_Str
) || (NULL
== Add_N_Lines_Str
))
1844 && (NULL
== Rev_Scroll_Str
)))
1850 /* Defective termcap mode!!!! */
1851 SLtt_set_term_vtxxx (NULL
);
1853 else SLtt_Term_Cannot_Scroll
= 1;
1856 Del_Eol_Str
= SLtt_tgetstr("ce");
1858 Rev_Vid_Str
= SLtt_tgetstr("mr");
1859 if (Rev_Vid_Str
== NULL
) Rev_Vid_Str
= SLtt_tgetstr("so");
1861 Bold_Vid_Str
= SLtt_tgetstr("md");
1863 /* Although xterm cannot blink, it does display the blinking characters
1864 * as bold ones. Some Rxvt will display the background as high intensity.
1866 if ((NULL
== (Blink_Vid_Str
= SLtt_tgetstr("mb")))
1868 Blink_Vid_Str
= "\033[5m";
1870 UnderLine_Vid_Str
= SLtt_tgetstr("us");
1872 Start_Alt_Chars_Str
= SLtt_tgetstr ("as"); /* smacs */
1873 End_Alt_Chars_Str
= SLtt_tgetstr ("ae"); /* rmacs */
1874 Enable_Alt_Char_Set
= SLtt_tgetstr ("eA"); /* enacs */
1875 SLtt_Graphics_Char_Pairs
= SLtt_tgetstr ("ac");
1877 #ifndef NCURSES_BRAIN_DAMAGE_CONTROL
1878 # define NCURSES_BRAIN_DAMAGE_CONTROL 0
1881 #if NCURSES_BRAIN_DAMAGE_CONTROL
1885 char *lgcp
= "l\332m\300k\277j\331u\264t\303v\301w\302q\304x\263n\053o\176s\137`\004a\260f\370g\361~\011,\020+\021.\031-\030h\261i\0250\333";
1887 SLtt_Graphics_Char_Pairs
= lgcp
;
1888 Start_Alt_Chars_Str
= "\033(B\033)U\016";
1889 End_Alt_Chars_Str
= "\033(B\033)0\017";
1890 Enable_Alt_Char_Set
= NULL
;
1892 char *lgcp
= "`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o\302q\304r\362s_t\303u\264v\301w\302x\263y\371z\372{\373|\374}\375~";
1894 SLtt_Graphics_Char_Pairs
= lgcp
;
1895 Start_Alt_Chars_Str
= "\033[11m";
1896 End_Alt_Chars_Str
= "\033[10m";
1897 Enable_Alt_Char_Set
= NULL
;
1902 if (NULL
== SLtt_Graphics_Char_Pairs
)
1904 /* make up for defective termcap/terminfo */
1907 Start_Alt_Chars_Str
= "\016";
1908 End_Alt_Chars_Str
= "\017";
1909 Enable_Alt_Char_Set
= "\033)0";
1913 /* aixterm added by willi */
1914 if (is_xterm
|| !strncmp (term
, "aixterm", 7))
1916 Start_Alt_Chars_Str
= "\016";
1917 End_Alt_Chars_Str
= "\017";
1918 Enable_Alt_Char_Set
= "\033(B\033)0";
1921 if ((SLtt_Graphics_Char_Pairs
== NULL
) &&
1922 ((Start_Alt_Chars_Str
== NULL
) || (End_Alt_Chars_Str
== NULL
)))
1924 SLtt_Has_Alt_Charset
= 0;
1925 Enable_Alt_Char_Set
= NULL
;
1927 else SLtt_Has_Alt_Charset
= 1;
1930 /* status line capabilities */
1931 if ((SLtt_Has_Status_Line
== -1)
1932 && (0 != (SLtt_Has_Status_Line
= TGETFLAG ("hs"))))
1934 Disable_Status_line_Str
= SLtt_tgetstr ("ds");
1935 Return_From_Status_Line_Str
= SLtt_tgetstr ("fs");
1936 Goto_Status_Line_Str
= SLtt_tgetstr ("ts");
1937 Status_Line_Esc_Ok
= TGETFLAG("es");
1938 Num_Status_Line_Columns
= TGETNUM("ws");
1939 if (Num_Status_Line_Columns
< 0) Num_Status_Line_Columns
= 0;
1942 if (NULL
== (Norm_Vid_Str
= SLtt_tgetstr("me")))
1944 Norm_Vid_Str
= SLtt_tgetstr("se");
1947 Cursor_Invisible_Str
= SLtt_tgetstr("vi");
1948 Cursor_Visible_Str
= SLtt_tgetstr("ve");
1950 Curs_F_Str
= SLtt_tgetstr("RI");
1953 if (NULL
!= Curs_F_Str
)
1955 Len_Curs_F_Str
= strlen(Curs_F_Str
);
1957 else Len_Curs_F_Str
= strlen(Curs_Pos_Str
);
1960 Automatic_Margins
= TGETFLAG ("am");
1961 /* No_Move_In_Standout = !TGETFLAG ("ms"); */
1962 #ifdef HP_GLITCH_CODE
1963 Has_HP_Glitch
= TGETFLAG ("xs");
1965 Worthless_Highlight
= TGETFLAG ("xs");
1968 if (Worthless_Highlight
== 0)
1969 { /* Magic cookie glitch */
1970 Worthless_Highlight
= (TGETNUM ("sg") > 0);
1973 if (Worthless_Highlight
)
1974 SLtt_Has_Alt_Charset
= 0;
1976 /* Check for color information in the termcap. A program should not
1977 * rely on this information being accurate.
1979 if (SLtt_Use_Ansi_Colors
== 0)
1981 Reset_Color_String
= SLtt_tgetstr ("op");
1983 SLtt_Use_Ansi_Colors
= ((NULL
!= Reset_Color_String
)
1984 || (NULL
!= SLtt_tgetstr ("Sf"))
1985 || (NULL
!= SLtt_tgetstr ("Sb"))
1986 || (NULL
!= SLtt_tgetstr ("AF"))
1987 || (NULL
!= SLtt_tgetstr ("AB"))
1988 || (-1 != SLtt_tgetnum ("Co"))
1989 || (-1 != SLtt_tgetnum ("pa")));
1993 #if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
1995 * Override the alt-char-set handling string in case of a
1996 * QNX/qansi terminal: use the "old style" strings in order
1997 * to be compatible with S-Lang without the SLTT_TRANSP_ACS_PATCH
2000 if (SLtt_Has_Alt_Charset
&&
2001 strncmp(term
, "qansi", 5) == 0 &&
2002 Start_Alt_Chars_Str
[0] != '\016')
2004 Start_Alt_Chars_Str
= "\016"; /* smacs/as (^N) */
2005 End_Alt_Chars_Str
= "\017"; /* rmacs/ae (^O) */
2006 SLtt_Graphics_Char_Pairs
= /* acsc/ac */
2007 "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~O\141";
2010 * it would be required to modify the sgr/sa entry also, if it
2011 * would be used (->embedded as/ae sequences)...
2014 #endif /* __QNX__ && QNX_QANSI_SLANG_COMPAT_ACS */
2021 /* specific to vtxxx only */
2022 void SLtt_enable_cursor_keys (void)
2027 SLtt_write_string("\033=\033[?1l");
2031 void SLtt_get_terminfo ()
2037 SLtt_set_term_vtxxx(&zero
);
2038 Start_Alt_Chars_Str
= "\016";
2039 End_Alt_Chars_Str
= "\017";
2040 SLtt_Has_Alt_Charset
= 1;
2041 SLtt_Graphics_Char_Pairs
= "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
2042 Enable_Alt_Char_Set
= "\033(B\033)0";
2043 SLtt_get_screen_size ();
2047 /* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
2048 * is non-zero, set terminal appropriate for a only vt100
2049 * (no add line capability). */
2051 void SLtt_set_term_vtxxx(int *vt100
)
2053 Norm_Vid_Str
= "\033[m";
2055 Scroll_R_Str
= "\033[%i%d;%dr";
2056 Cls_Str
= "\033[2J\033[H";
2057 Rev_Vid_Str
= "\033[7m";
2058 Bold_Vid_Str
= "\033[1m";
2059 Blink_Vid_Str
= "\033[5m";
2060 UnderLine_Vid_Str
= "\033[4m";
2061 Del_Eol_Str
= "\033[K";
2062 Rev_Scroll_Str
= "\033M";
2063 Curs_F_Str
= "\033[%dC";
2064 /* Len_Curs_F_Str = 5; */
2065 Curs_Pos_Str
= "\033[%i%d;%dH";
2066 if ((vt100
== NULL
) || (*vt100
== 0))
2068 Ins_Mode_Str
= "\033[4h";
2069 Eins_Mode_Str
= "\033[4l";
2070 Del_Char_Str
= "\033[P";
2071 Del_N_Lines_Str
= "\033[%dM";
2072 Add_N_Lines_Str
= "\033[%dL";
2073 SLtt_Term_Cannot_Insert
= 0;
2077 Del_N_Lines_Str
= NULL
;
2078 Add_N_Lines_Str
= NULL
;
2079 SLtt_Term_Cannot_Insert
= 1;
2081 SLtt_Term_Cannot_Scroll
= 0;
2082 /* No_Move_In_Standout = 0; */
2085 void SLtt_init_video (void)
2087 /* send_string_to_term("\033[?6h"); */
2088 /* relative origin mode */
2089 SLtt_write_string (Term_Init_Str
);
2090 SLtt_write_string (Keypad_Init_Str
);
2091 SLtt_reset_scroll_region();
2093 SLtt_write_string (Enable_Alt_Char_Set
);
2094 Video_Initialized
= 1;
2098 void SLtt_reset_video (void)
2100 SLtt_goto_rc (SLtt_Screen_Rows
- 1, 0);
2102 SLtt_normal_video (); /* MSKermit requires this */
2103 SLtt_write_string(Norm_Vid_Str
);
2105 Current_Fgbg
= 0xFFFFFFFFU
;
2106 SLtt_set_alt_char_set (0);
2107 if (SLtt_Use_Ansi_Colors
)
2109 if (Reset_Color_String
== NULL
)
2111 SLtt_Char_Type attr
;
2112 if (-1 != make_color_fgbg (NULL
, NULL
, &attr
))
2113 write_attributes (attr
);
2114 else SLtt_write_string ("\033[0m\033[m");
2116 else SLtt_write_string (Reset_Color_String
);
2117 Current_Fgbg
= 0xFFFFFFFFU
;
2120 SLtt_write_string (Keypad_Reset_Str
);
2121 SLtt_write_string (Term_Reset_Str
);
2122 SLtt_flush_output ();
2123 Video_Initialized
= 0;
2126 void SLtt_bold_video (void)
2128 SLtt_write_string (Bold_Vid_Str
);
2131 int SLtt_set_mouse_mode (int mode
, int force
)
2137 if (NULL
== (term
= (char *) getenv("TERM"))) return -1;
2138 if (strncmp ("xterm", term
, 5))
2143 SLtt_write_string ("\033[?9h");
2145 SLtt_write_string ("\033[?9l");
2151 void SLtt_disable_status_line (void)
2153 if (SLtt_Has_Status_Line
> 0)
2154 SLtt_write_string (Disable_Status_line_Str
);
2157 int SLtt_write_to_status_line (char *s
, int col
)
2159 if ((SLtt_Has_Status_Line
<= 0)
2160 || (Goto_Status_Line_Str
== NULL
)
2161 || (Return_From_Status_Line_Str
== NULL
))
2164 tt_printf (Goto_Status_Line_Str
, col
, 0);
2165 SLtt_write_string (s
);
2166 SLtt_write_string (Return_From_Status_Line_Str
);
2171 void SLtt_get_screen_size (void)
2175 unsigned short chan
;
2176 $
DESCRIPTOR(dev_dsc
, "SYS$INPUT:");
2179 VIOMODEINFO vioModeInfo
;
2183 #if defined(TIOCGWINSZ) && !defined(SCO_FLAVOR)
2184 struct winsize wind_struct
;
2188 if ((ioctl(1,TIOCGWINSZ
,&wind_struct
) == 0)
2189 || (ioctl(0, TIOCGWINSZ
, &wind_struct
) == 0)
2190 || (ioctl(2, TIOCGWINSZ
, &wind_struct
) == 0))
2192 c
= (int) wind_struct
.ws_col
;
2193 r
= (int) wind_struct
.ws_row
;
2197 while (errno
== EINTR
);
2202 status
= sys$
assign(&dev_dsc
,&chan
,0,0,0);
2205 code
= DVI$_DEVBUFSIZ
;
2206 status
= lib$
getdvi(&code
, &chan
,0, &c
, 0,0);
2209 code
= DVI$_TT_PAGE
;
2210 status
= lib$
getdvi(&code
, &chan
,0, &r
, 0,0);
2218 vioModeInfo
.cb
= sizeof(vioModeInfo
);
2219 VioGetMode (&vioModeInfo
, 0);
2220 c
= vioModeInfo
.col
;
2221 r
= vioModeInfo
.row
;
2226 char *s
= getenv ("LINES");
2227 if (s
!= NULL
) r
= atoi (s
);
2232 char *s
= getenv ("COLUMNS");
2233 if (s
!= NULL
) c
= atoi (s
);
2236 if ((r
<= 0) || (r
> 200)) r
= 24;
2237 if ((c
<= 0) || (c
> 250)) c
= 80;
2238 SLtt_Screen_Rows
= r
;
2239 SLtt_Screen_Cols
= c
;