711af7186fd90c23d27056b6beef3019d0d88000
[reactos.git] / rosapps / mc / slang / sldisply.c
1 /* Copyright (c) 1992, 1995 John E. Davis
2 * All rights reserved.
3 *
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Perl Artistic License.
6 */
7
8 /*
9 * SLTT_TRANSP_ACS_PATCH (#define/#undef):
10 *
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!
21 *
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...]
26 */
27 /*#define SLTT_TRANSP_ACS_PATCH 1*/
28
29 /*
30 * QNX_QANSI_SLANG_COMPAT_ACS (#define/#undef):
31 *
32 * A more OS/terminal-specific solution for the problem mentioned above
33 * (->SLTT_TRANSP_ACS_PATCH).
34 *
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).
41 */
42 /*#define QNX_QANSI_SLANG_COMPAT_ACS 1*/
43
44 /* auto-configuration */
45 #ifdef SLTT_TRANSP_ACS_PATCH
46 # if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
47 # undef SLTT_TRANSP_ACS_PATCH
48 # endif
49 #else
50 # if defined(__QNX__) && !defined(QNX_QANSI_SLANG_COMPAT_ACS)
51 # define QNX_QANSI_SLANG_COMPAT_ACS 1
52 # endif
53 #endif
54
55 #include "sl-feat.h"
56 #include "config.h"
57
58 #include <stdio.h>
59 #include <string.h>
60 #ifdef SCO_FLAVOR
61 # include <sys/types.h>
62 # include <sys/timeb.h> /* for struct timeb, used in time.h */
63 #endif
64 #include <time.h>
65 #include <ctype.h>
66
67 #ifndef VMS
68 # include <sys/time.h>
69 # ifdef __QNX__
70 # include <sys/select.h>
71 # endif
72 # include <sys/types.h>
73 #endif
74
75 #ifdef __BEOS__
76 /* Prototype for select */
77 # include <net/socket.h>
78 #endif
79
80 #ifdef HAVE_TERMIOS_H
81 # include <termios.h>
82 #endif
83
84 #ifdef VMS
85 # include <unixlib.h>
86 # include <unixio.h>
87 # include <dvidef.h>
88 # include <descrip.h>
89 # include <lib$routines.h>
90 # include <starlet.h>
91 #else
92 # if !defined(sun)
93 # include <sys/ioctl.h>
94 # endif
95 #endif
96
97
98 #ifdef SYSV
99 # include <sys/termio.h>
100 # include <sys/stream.h>
101 # include <sys/ptem.h>
102 # include <sys/tty.h>
103 #endif
104
105 #if defined (_AIX) && !defined (FD_SET)
106 # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
107 #endif
108
109 #include <errno.h>
110 #include "slang.h"
111 #include "_slang.h"
112
113 #ifdef HAVE_STDLIB_H
114 # include <stdlib.h>
115 #endif
116
117 #ifdef HAVE_UNISTD_H
118 # include <unistd.h>
119 #endif
120
121 #if defined(__DECC) && defined(VMS)
122 /* These get prototypes for write an sleep */
123 # include <unixio.h>
124 #endif
125 #include <signal.h>
126
127
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. */
132
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
138
139 /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
140 * not include this attribute.
141 */
142
143
144
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)
148
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;
159
160 /* -1 means unknown */
161 int SLtt_Has_Status_Line = -1; /* hs */
162
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.
170 */
171 static int Has_HP_Glitch;
172 #endif
173
174 static char *Reset_Color_String;
175
176 static int Linux_Console;
177
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.
183 */
184 #define JMAX_COLORS 256
185 #define JNORMAL_COLOR 0
186
187 typedef struct
188 {
189 SLtt_Char_Type fgbg;
190 SLtt_Char_Type mono;
191 char *custom_esc;
192 } Ansi_Color_Type;
193
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))
196
197 static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] =
198 {
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}
217 };
218
219
220 /* This is the string to use to use when outputting color information.
221 */
222 #ifdef M_UNIX
223 /* work around for sco console bug that can't handle combined sequences */
224 static char *Color_Escape_Sequence = "\033[3%dm\033[4%dm";
225 #else
226 /* Believe it or not, this is what is in the linux terminfo database. It
227 * produces the same escape sequence but it is much more CPU intensive.
228 * Why not just encode it as "\033[3%p1%dm\033[4%p2%dm" ???
229 */
230 /* static char *Color_Escape_Sequence = "\033[%p1%{30}%+%dm\033[%p2%{40}%+%dm"; */
231 static char *Color_Escape_Sequence = "\033[3%d;4%dm";
232 #endif
233
234 char *SLtt_Graphics_Char_Pairs; /* ac termcap string -- def is vt100 */
235
236
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. */
239
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 */
258
259 static char *Start_Alt_Chars_Str; /* as */
260 static char *End_Alt_Chars_Str; /* ae */
261 static char *Enable_Alt_Char_Set; /* eA */
262
263 static char *Term_Init_Str;
264 static char *Keypad_Init_Str;
265 static char *Term_Reset_Str;
266 static char *Keypad_Reset_Str;
267
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 */
274
275 /* static int Len_Curs_F_Str = 5; */
276
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 */
280
281
282 /* scrolling region */
283 static int Scroll_r1 = 0, Scroll_r2 = 23;
284 static int Cursor_r, Cursor_c; /* 0 based */
285
286 /* current attributes --- initialized to impossible value */
287 static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFFU;
288
289 static int Cursor_Set; /* 1 if cursor position known, 0
290 * if not. -1 if only row is known
291 */
292
293
294 #define MAX_OUTPUT_BUFFER_SIZE 4096
295
296 static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
297 static unsigned char *Output_Bufferp = Output_Buffer;
298
299 unsigned long SLtt_Num_Chars_Output;
300
301 #ifdef SLTT_TRANSP_ACS_PATCH
302 static int SLtt_ACS_Active = 0;
303 #endif
304
305 static int sl_usleep (unsigned long usecs)
306 {
307 #ifndef VMS
308 struct timeval tv;
309 tv.tv_sec = usecs / 1000000;
310 tv.tv_usec = usecs % 1000000;
311 return select(0, NULL, NULL, NULL, &tv);
312 #else
313 return 0;
314 #endif
315 }
316
317 int SLtt_flush_output (void)
318 {
319 int nwrite = 0;
320 unsigned int total;
321 int n = (int) (Output_Bufferp - Output_Buffer);
322
323 SLtt_Num_Chars_Output += n;
324
325 total = 0;
326 while (n > 0)
327 {
328 nwrite = write (fileno(stdout), (char *) Output_Buffer + total, n);
329 if (nwrite == -1)
330 {
331 nwrite = 0;
332 #ifdef EAGAIN
333 if (errno == EAGAIN)
334 {
335 sl_usleep (100000); /* 1/10 sec */
336 continue;
337 }
338 #endif
339 #ifdef EWOULDBLOCK
340 if (errno == EWOULDBLOCK)
341 {
342 sl_usleep (100000);
343 continue;
344 }
345 #endif
346 #ifdef EINTR
347 if (errno == EINTR) continue;
348 #endif
349 break;
350 }
351 n -= nwrite;
352 total += nwrite;
353 }
354 Output_Bufferp = Output_Buffer;
355 return n;
356 }
357
358
359 int SLtt_Baud_Rate;
360 static void tt_write(char *str, unsigned int n)
361 {
362 static unsigned long last_time;
363 static int total;
364 unsigned long now;
365 unsigned int ndiff;
366
367 if ((str == NULL) || (n == 0)) return;
368 total += n;
369
370 while (1)
371 {
372 ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
373 if (ndiff < n)
374 {
375 SLMEMCPY ((char *) Output_Bufferp, (char *) str, ndiff);
376 Output_Bufferp += ndiff;
377 SLtt_flush_output ();
378 n -= ndiff;
379 str += ndiff;
380 }
381 else
382 {
383 SLMEMCPY ((char *) Output_Bufferp, str, n);
384 Output_Bufferp += n;
385 break;
386 }
387 }
388
389 if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
390 && (10 * total > SLtt_Baud_Rate))
391 {
392 total = 0;
393 if ((now = (unsigned long) time(NULL)) - last_time <= 1)
394 {
395 SLtt_flush_output ();
396 sleep((unsigned) 1);
397 }
398 last_time = now;
399 }
400 }
401
402
403 void SLtt_write_string (char *str)
404 {
405 if (str != NULL) tt_write(str, strlen(str));
406 }
407
408
409 void SLtt_putchar (char ch)
410 {
411 #ifdef SLTT_TRANSP_ACS_PATCH
412 int restore_acs = 0;
413 #endif
414
415 SLtt_normal_video ();
416 if (Cursor_Set == 1)
417 {
418 if (ch >= ' ') Cursor_c++;
419 #ifndef SLTT_TRANSP_ACS_PATCH
420 else if (ch == '\b') Cursor_c--;
421 #else
422 if (ch <= ' ' && SLtt_ACS_Active)
423 {
424 SLtt_set_alt_char_set (0);
425 restore_acs = 1;
426 }
427 if (ch == '\b') Cursor_c--;
428 #endif
429 else if (ch == '\r') Cursor_c = 0;
430 else Cursor_Set = 0;
431
432 if ((Cursor_c + 1 == SLtt_Screen_Cols)
433 && Automatic_Margins) Cursor_Set = 0;
434 }
435
436 if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
437 {
438 *Output_Bufferp++ = (unsigned char) ch;
439 }
440 else tt_write (&ch, 1);
441
442 #ifdef SLTT_TRANSP_ACS_PATCH
443 if (restore_acs)
444 {
445 SLtt_set_alt_char_set (1);
446 }
447 #endif
448 }
449
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)
453 {
454 register unsigned char *f = (unsigned char *) fmt, *b, ch;
455 int offset = 0, tinfo = 0;
456 int stack[10];
457 int i = 0, z;
458 stack[0] = y; stack[1] = x; i = 2;
459
460 b = (unsigned char *) buf;
461 if (fmt != NULL) while ((ch = *f++) != 0)
462 {
463 if (ch != '%') *b++ = ch;
464 else
465 {
466 ch = *f++;
467 if (tinfo)
468 {
469 if ((ch <= '3') && (ch >= '0'))
470 {
471 /* map it to termcap. Since this is terminfo,
472 * it must be one of:
473 * %2d, %3d, %02d, %03d
474 *
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.
478 */
479
480 /* skip the 'd'-- hope it is there */
481 if (ch == '0')
482 {
483 ch = *f;
484 f += 2;
485 }
486 else f++;
487 }
488 }
489
490 switch (ch)
491 {
492 case 'p':
493 tinfo = 1;
494 ch = *f++;
495 if (ch == '1') stack[i++] = x; else stack[i++] = y;
496 break;
497
498 case '\'': /* 'x' */
499 stack[i++] = *f++;
500 f++;
501 break;
502
503 case '{': /* literal constant, e.g. {30} */
504 z = 0;
505 while (((ch = *f) <= '9') && (ch >= '0'))
506 {
507 z = z * 10 + (ch - '0');
508 f++;
509 }
510 stack[i++] = z;
511 if (ch == '}') f++;
512 break;
513
514 case 'd':
515 case '2':
516 case '3':
517 z = stack[--i];
518 z += offset;
519 if (z >= 100)
520 {
521 *b++ = z / 100 + '0';
522 z = z % 100;
523 goto ten;
524 }
525 else if (ch == 3)
526 {
527 *b++ = '0';
528 ch = '2';
529 }
530
531 if (z >= 10)
532 {
533 ten:
534 *b++ = z / 10 + '0';
535 z = z % 10;
536 }
537 else if (ch == 2) *b++ = '0';
538
539 *b++ = z + '0';
540 break;
541
542 case 'i':
543 offset = 1;
544 break;
545
546 case '+':
547 if (tinfo)
548 {
549 z = stack[--i];
550 stack[i-1] += z;
551 }
552 else
553 {
554 ch = *f++;
555 if ((unsigned char) ch == 128) ch = 0;
556 ch = ch + (unsigned char) stack[--i];
557 if (ch == '\n') ch++;
558 *b++ = ch;
559 }
560 break;
561
562 case 'r':
563 stack[0] = x;
564 stack[1] = y;
565 break;
566
567 case '.':
568 case 'c':
569 ch = (unsigned char) stack[--i];
570 if (ch == '\n') ch++;
571 *b++ = ch;
572 break;
573
574 default:
575 *b++ = ch;
576 }
577 }
578 }
579 *b = 0;
580 return((unsigned int) (b - (unsigned char *) buf));
581 }
582
583 static void tt_printf(char *fmt, int x, int y)
584 {
585 char buf[256];
586 unsigned int n;
587 if (fmt == NULL) return;
588 n = tt_sprintf(buf, fmt, x, y);
589 tt_write(buf, n);
590 }
591
592
593 void SLtt_set_scroll_region (int r1, int r2)
594 {
595 Scroll_r1 = r1;
596 Scroll_r2 = r2;
597 tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
598 Cursor_Set = 0;
599 }
600
601 void SLtt_reset_scroll_region (void)
602 {
603 SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
604 }
605
606 int SLtt_set_cursor_visibility (int show)
607 {
608 if ((Cursor_Visible_Str == NULL) || (Cursor_Invisible_Str == NULL))
609 return -1;
610
611 SLtt_write_string (show ? Cursor_Visible_Str : Cursor_Invisible_Str);
612 return 0;
613 }
614
615
616 /* the goto_rc function moves to row relative to scrolling region */
617 void SLtt_goto_rc(int r, int c)
618 {
619 char *s = NULL;
620 int n;
621 char buf[6];
622 #ifdef SLTT_TRANSP_ACS_PATCH
623 int check_alt_acs = 0;
624 #endif
625
626 if (c < 0)
627 {
628 c = -c - 1;
629 Cursor_Set = 0;
630 }
631
632 /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
633 r += Scroll_r1;
634
635 if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
636 {
637 n = r - Cursor_r;
638 if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c)
639 && (Curs_Up_Str != NULL))
640 {
641 s = Curs_Up_Str;
642 }
643 else if ((n >= 0) && (n <= 4))
644 {
645 if ((n == 0) && (Cursor_Set == 1)
646 && ((c > 1) || (c == Cursor_c)))
647 {
648 if (Cursor_c == c) return;
649 if (Cursor_c == c + 1)
650 {
651 s = buf;
652 *s++ = '\b'; *s = 0;
653 s = buf;
654 #ifdef SLTT_TRANSP_ACS_PATCH
655 check_alt_acs = 1;
656 #endif
657 }
658 }
659 else if (c == 0)
660 {
661 s = buf;
662 if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
663 while (n--) *s++ = '\n';
664 #ifdef VMS
665 /* Need to add this after \n to start a new record. Sheesh. */
666 *s++ = '\r';
667 #endif
668 *s = 0;
669 s = buf;
670 #ifdef SLTT_TRANSP_ACS_PATCH
671 check_alt_acs = 1;
672 #endif
673 }
674 /* Will fail on VMS */
675 #ifndef VMS
676 else if (SLtt_Newline_Ok && (Cursor_Set == 1) &&
677 (Cursor_c >= c) && (c + 3 > Cursor_c))
678 {
679 s = buf;
680 while (n--) *s++ = '\n';
681 n = Cursor_c - c;
682 while (n--) *s++ = '\b';
683 *s = 0;
684 s = buf;
685 #ifdef SLTT_TRANSP_ACS_PATCH
686 check_alt_acs = 1;
687 #endif
688 }
689 #endif
690 }
691 }
692 #ifndef SLTT_TRANSP_ACS_PATCH
693 if (s != NULL) SLtt_write_string(s);
694 #else
695 if (s != NULL)
696 {
697 if (check_alt_acs && SLtt_ACS_Active)
698 {
699 SLtt_set_alt_char_set (0);
700 SLtt_write_string(s);
701 SLtt_set_alt_char_set (1);
702 }
703 else SLtt_write_string(s);
704 }
705 #endif
706 else tt_printf(Curs_Pos_Str, r, c);
707 Cursor_c = c; Cursor_r = r;
708 Cursor_Set = 1;
709 }
710
711 void SLtt_begin_insert (void)
712 {
713 SLtt_write_string(Ins_Mode_Str);
714 }
715
716 void SLtt_end_insert (void)
717 {
718 SLtt_write_string(Eins_Mode_Str);
719 }
720
721 void SLtt_delete_char (void)
722 {
723 SLtt_normal_video ();
724 SLtt_write_string(Del_Char_Str);
725 }
726
727 void SLtt_erase_line (void)
728 {
729 SLtt_write_string("\r");
730 Cursor_Set = 1; Cursor_c = 0;
731 SLtt_del_eol();
732 }
733
734 void SLtt_delete_nlines (int n)
735 {
736 int r1, curs;
737 char buf[132];
738 #ifdef SLTT_TRANSP_ACS_PATCH
739 int restore_acs = 0;
740 #endif
741
742 if (n <= 0) return;
743 SLtt_normal_video ();
744 if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str,n, 0);
745 else
746 /* get a new terminal */
747 {
748 r1 = Scroll_r1;
749 curs = Cursor_r;
750 SLtt_set_scroll_region(curs, Scroll_r2);
751 SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
752 #ifdef SLTT_TRANSP_ACS_PATCH
753 if (SLtt_ACS_Active)
754 {
755 SLtt_set_alt_char_set (0);
756 restore_acs = 1;
757 }
758 #endif
759 SLMEMSET(buf, '\n', (unsigned int) n);
760 tt_write(buf, (unsigned int) n);
761 #ifdef SLTT_TRANSP_ACS_PATCH
762 if (restore_acs) SLtt_set_alt_char_set (1);
763 #endif
764 /* while (n--) tt_putchar('\n'); */
765 SLtt_set_scroll_region(r1, Scroll_r2);
766 SLtt_goto_rc(curs, 0);
767 }
768 }
769
770 void SLtt_cls (void)
771 {
772 SLtt_normal_video();
773 SLtt_reset_scroll_region ();
774 SLtt_write_string(Cls_Str);
775 }
776
777 void SLtt_reverse_index (int n)
778 {
779 if (!n) return;
780
781 SLtt_normal_video();
782 if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
783 else
784 {
785 while(n--) SLtt_write_string(Rev_Scroll_Str);
786 }
787 }
788
789
790 int SLtt_Ignore_Beep = 1;
791 static char *Visible_Bell_Str;
792
793 void SLtt_beep (void)
794 {
795 if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
796
797 if (SLtt_Ignore_Beep & 0x2)
798 {
799 if (Visible_Bell_Str != NULL) SLtt_write_string (Visible_Bell_Str);
800 #ifdef __linux__
801 else if (Linux_Console)
802 {
803 SLtt_write_string ("\033[?5h");
804 SLtt_flush_output ();
805 sl_usleep (50000);
806 SLtt_write_string ("\033[?5l");
807 }
808 #endif
809 }
810 SLtt_flush_output ();
811 }
812
813 void SLtt_del_eol (void)
814 {
815 if (Current_Fgbg != 0xFFFFFFFFU) SLtt_normal_video ();
816 SLtt_write_string(Del_Eol_Str);
817 }
818
819 typedef struct
820 {
821 char *name;
822 SLtt_Char_Type color;
823 }
824 Color_Def_Type;
825
826 #define MAX_COLOR_NAMES 17
827 static Color_Def_Type Color_Defs [MAX_COLOR_NAMES] =
828 {
829 {"black", SLSMG_COLOR_BLACK},
830 {"red", SLSMG_COLOR_RED},
831 {"green", SLSMG_COLOR_GREEN},
832 {"brown", SLSMG_COLOR_BROWN},
833 {"blue", SLSMG_COLOR_BLUE},
834 {"magenta", SLSMG_COLOR_MAGENTA},
835 {"cyan", SLSMG_COLOR_CYAN},
836 {"lightgray", SLSMG_COLOR_LGRAY},
837 {"gray", SLSMG_COLOR_GRAY},
838 {"brightred", SLSMG_COLOR_BRIGHT_RED},
839 {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN},
840 {"yellow", SLSMG_COLOR_BRIGHT_BROWN},
841 {"brightblue", SLSMG_COLOR_BRIGHT_BLUE},
842 {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN},
843 {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA},
844 {"white", SLSMG_COLOR_BRIGHT_WHITE},
845 {"default", 25}
846 };
847
848
849 void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
850 {
851 (void) what;
852 if ((obj < 0) || (obj >= JMAX_COLORS))
853 {
854 return;
855 }
856 Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
857 }
858
859 static char *check_color_for_digit_form (char *color)
860 {
861 unsigned int i, ich;
862 char *s = color;
863
864 i = 0;
865 while ((ich = (int) *s) != 0)
866 {
867 if ((ich < '0') || (ich > '9'))
868 return color;
869
870 i = i * 10 + (ich - '0');
871 s++;
872 }
873
874 if (i < MAX_COLOR_NAMES)
875 color = Color_Defs[i].name;
876
877 return color;
878 }
879
880 static int get_default_colors (char **fgp, char **bgp)
881 {
882 static char fg_buf[16], bg_buf[16], *bg, *fg;
883 static int already_parsed;
884 char *p, *pmax;
885
886 if (already_parsed == -1)
887 return -1;
888
889 if (already_parsed)
890 {
891 *fgp = fg;
892 *bgp = bg;
893 return 0;
894 }
895
896 already_parsed = -1;
897
898 bg = getenv ("COLORFGBG");
899
900 if (bg == NULL)
901 {
902 bg = getenv ("DEFAULT_COLORS");
903 if (bg == NULL)
904 return -1;
905 }
906
907 p = fg_buf;
908 pmax = p + (sizeof (fg_buf) - 1);
909
910 while ((*bg != 0) && (*bg != ';'))
911 {
912 if (p < pmax) *p++ = *bg;
913 bg++;
914 }
915 *p = 0;
916
917 if (*bg) bg++;
918
919 p = bg_buf;
920 pmax = p + (sizeof (bg_buf) - 1);
921
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.
924 */
925 while ((*bg != 0) && (*bg != ';'))
926 {
927 if (p < pmax) *p++ = *bg;
928 bg++;
929 }
930 *p = 0;
931
932 if (!strcmp (fg_buf, "default") || !strcmp(bg_buf, "default"))
933 {
934 *fgp = *bgp = fg = bg = "default";
935 }
936 else
937 {
938 *fgp = fg = check_color_for_digit_form (fg_buf);
939 *bgp = bg = check_color_for_digit_form (bg_buf);
940 }
941 already_parsed = 1;
942 return 0;
943 }
944
945
946 static unsigned char FgBg_Stats[JMAX_COLORS];
947
948 static int Color_0_Modified = 0;
949
950 void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
951 {
952 char *cust_esc;
953
954 if ((obj < 0) || (obj >= JMAX_COLORS)) return;
955
956 cust_esc = Ansi_Color_Map[obj].custom_esc;
957 if (cust_esc != NULL)
958 {
959 SLFREE (cust_esc);
960 FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
961 Ansi_Color_Map[obj].custom_esc = NULL;
962 }
963
964 Ansi_Color_Map[obj].fgbg = attr;
965 if (obj == 0) Color_0_Modified = 1;
966 }
967
968 SLtt_Char_Type SLtt_get_color_object (int obj)
969 {
970 if ((obj < 0) || (obj >= JMAX_COLORS)) return 0;
971 return Ansi_Color_Map[obj].fgbg;
972 }
973
974
975 void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
976 {
977 if ((obj < 0) || (obj >= JMAX_COLORS)) return;
978
979 Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
980 if (obj == 0) Color_0_Modified = 1;
981 }
982
983 static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
984 {
985 SLtt_Char_Type attr = 0;
986
987 if ((f & 0xF0) == 0)
988 {
989 if (f & 0x8) attr = SLTT_BOLD_MASK;
990 f &= 0x7;
991 }
992 else f = 9;
993
994 if ((b & 0xF0) == 0)
995 {
996 if (b & 0x8) attr |= SLTT_BLINK_MASK;
997 b &= 0x7;
998 }
999 else b = 9;
1000
1001 return ((f << 8) | (b << 16) | attr);
1002 }
1003
1004 static int make_color_fgbg (char *fg, char *bg, SLtt_Char_Type *fgbg)
1005 {
1006 SLtt_Char_Type f = 0xFFFFFFFFU, b = 0xFFFFFFFFU;
1007 char *dfg, *dbg;
1008 unsigned int i;
1009
1010 if ((fg != NULL) && (*fg == 0)) fg = NULL;
1011 if ((bg != NULL) && (*bg == 0)) bg = NULL;
1012
1013 if ((fg == NULL) || (bg == NULL))
1014 {
1015 if (-1 == get_default_colors (&dfg, &dbg))
1016 return -1;
1017
1018 if (fg == NULL) fg = dfg;
1019 if (bg == NULL) bg = dbg;
1020 }
1021
1022 for (i = 0; i < MAX_COLOR_NAMES; i++)
1023 {
1024 if (strcmp(fg, Color_Defs[i].name)) continue;
1025 f = Color_Defs[i].color;
1026 break;
1027 }
1028
1029 for (i = 0; i < MAX_COLOR_NAMES; i++)
1030 {
1031 if (strcmp(bg, Color_Defs[i].name)) continue;
1032 b = Color_Defs[i].color;
1033 break;
1034 }
1035
1036 if ((f == 0xFFFFFFFFU) || (b == 0xFFFFFFFFU))
1037 return -1;
1038
1039 *fgbg = fb_to_fgbg (f, b);
1040 return 0;
1041 }
1042
1043 void SLtt_set_color (int obj, char *what, char *fg, char *bg)
1044 {
1045 SLtt_Char_Type fgbg;
1046
1047 (void) what;
1048 if ((obj < 0) || (obj >= JMAX_COLORS))
1049 return;
1050
1051 if (-1 != make_color_fgbg (fg, bg, &fgbg))
1052 SLtt_set_color_object (obj, fgbg);
1053 }
1054
1055 void SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
1056 {
1057 SLtt_set_color_object (obj, fb_to_fgbg (f, b));
1058 }
1059
1060 void SLtt_set_color_esc (int obj, char *esc)
1061 {
1062 char *cust_esc;
1063 SLtt_Char_Type fgbg = 0;
1064 int i;
1065
1066 if ((obj < 0) || (obj >= JMAX_COLORS))
1067 {
1068 return;
1069 }
1070
1071 cust_esc = Ansi_Color_Map[obj].custom_esc;
1072 if (cust_esc != NULL)
1073 {
1074 SLFREE (cust_esc);
1075 FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
1076 }
1077
1078 cust_esc = (char *) SLMALLOC (strlen(esc) + 1);
1079 if (cust_esc != NULL) strcpy (cust_esc, esc);
1080
1081 Ansi_Color_Map[obj].custom_esc = cust_esc;
1082 if (cust_esc == NULL) fgbg = 0;
1083 else
1084 {
1085 /* The whole point of this is to generate a unique fgbg */
1086 for (i = 0; i < JMAX_COLORS; i++)
1087 {
1088 if (FgBg_Stats[i] == 0) fgbg = i;
1089
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))
1093 {
1094 fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
1095 break;
1096 }
1097 }
1098 FgBg_Stats[fgbg] += 1;
1099 }
1100
1101 fgbg |= 0x80;
1102 Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
1103 if (obj == 0) Color_0_Modified = 1;
1104 }
1105
1106 void SLtt_set_alt_char_set (int i)
1107 {
1108 #ifndef SLTT_TRANSP_ACS_PATCH
1109 static int last_i;
1110 #else
1111 #define last_i SLtt_ACS_Active
1112 #endif
1113 if (SLtt_Has_Alt_Charset == 0) return;
1114 if (i == last_i) return;
1115 SLtt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
1116 /* if (i) Current_Fgbg |= SLTT_ALTC_MASK;
1117 else Current_Fgbg &= ~SLTT_ALTC_MASK; */
1118 last_i = i;
1119 #ifdef SLTT_TRANSP_ACS_PATCH
1120 #undef last_i
1121 #endif
1122 }
1123
1124 static void write_attributes (SLtt_Char_Type fgbg)
1125 {
1126 int bg0, fg0;
1127
1128 if (Worthless_Highlight) return;
1129 if (fgbg == Current_Fgbg) return;
1130
1131 /* Before spitting out colors, fix attributes */
1132 if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
1133 {
1134 if (Current_Fgbg & ATTR_MASK)
1135 {
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);
1141 }
1142
1143 if ((fgbg & SLTT_ALTC_MASK)
1144 != (Current_Fgbg & SLTT_ALTC_MASK))
1145 {
1146 SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
1147 }
1148
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)
1153 {
1154 /* Someday Linux will have a blink mode that set high intensity
1155 * background. Lets be prepared.
1156 */
1157 if (SLtt_Blink_Mode) SLtt_write_string (Blink_Vid_Str);
1158 }
1159 }
1160
1161 if (SLtt_Use_Ansi_Colors)
1162 {
1163 fg0 = (int) GET_FG(fgbg);
1164 bg0 = (int) GET_BG(fgbg);
1165 tt_printf(Color_Escape_Sequence, fg0, bg0);
1166 }
1167 Current_Fgbg = fgbg;
1168 }
1169
1170 static int Video_Initialized;
1171
1172 void SLtt_reverse_video (int color)
1173 {
1174 SLtt_Char_Type fgbg;
1175 char *esc;
1176
1177 if (Worthless_Highlight) return;
1178 if ((color < 0) || (color >= JMAX_COLORS)) return;
1179
1180 if (Video_Initialized == 0)
1181 {
1182 if (color == JNORMAL_COLOR)
1183 {
1184 SLtt_write_string (Norm_Vid_Str);
1185 }
1186 else SLtt_write_string (Rev_Vid_Str);
1187 Current_Fgbg = 0xFFFFFFFFU;
1188 return;
1189 }
1190
1191 if (SLtt_Use_Ansi_Colors)
1192 {
1193 fgbg = Ansi_Color_Map[color].fgbg;
1194 if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
1195 {
1196 if (fgbg != Current_Fgbg)
1197 {
1198 Current_Fgbg = fgbg;
1199 SLtt_write_string (esc);
1200 return;
1201 }
1202 }
1203 }
1204 else fgbg = Ansi_Color_Map[color].mono;
1205
1206 if (fgbg == Current_Fgbg) return;
1207 write_attributes (fgbg);
1208 }
1209
1210
1211
1212
1213 void SLtt_normal_video (void)
1214 {
1215 SLtt_reverse_video(JNORMAL_COLOR);
1216 }
1217
1218 void SLtt_narrow_width (void)
1219 {
1220 SLtt_write_string("\033[?3l");
1221 }
1222
1223 void SLtt_wide_width (void)
1224 {
1225 SLtt_write_string("\033[?3h");
1226 }
1227
1228 /* Highest bit represents the character set. */
1229 #define COLOR_MASK 0x7F00
1230
1231 #define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
1232 /*
1233 #define COLOR_EQS(a, b) \
1234 (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
1235 */
1236
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))
1241
1242
1243 #define CHAR_EQS(a, b) (((a) == (b))\
1244 || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
1245 && COLOR_EQS((a), (b))))
1246
1247
1248 /* The whole point of this routine is to prevent writing to the last column
1249 * and last row on terminals with automatic margins.
1250 */
1251 static void write_string_with_care (char *str)
1252 {
1253 unsigned int len;
1254
1255 if (str == NULL) return;
1256
1257 len = strlen (str);
1258 if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
1259 {
1260 if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
1261 {
1262 /* For now, just do not write there. Later, something more
1263 * sophisticated will be implemented.
1264 */
1265 if (SLtt_Screen_Cols > Cursor_c)
1266 len = SLtt_Screen_Cols - Cursor_c - 1;
1267 else len = 0;
1268 }
1269 }
1270 tt_write (str, len);
1271 }
1272
1273 static void send_attr_str (unsigned short *s)
1274 {
1275 unsigned char out[256], ch, *p;
1276 register SLtt_Char_Type attr;
1277 register unsigned short sh;
1278 int color, last_color = -1;
1279
1280 p = out;
1281 while (0 != (sh = *s++))
1282 {
1283 ch = sh & 0xFF;
1284 color = ((int) sh & 0xFF00) >> 8;
1285 #ifdef SLTT_TRANSP_ACS_PATCH
1286 if (ch <= ' ' && (color & 0x80)) color &= ~0x80;
1287 #endif
1288 if (color != last_color)
1289 {
1290 if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
1291 else attr = Ansi_Color_Map[color & 0x7F].mono;
1292
1293 /* sh => color */
1294 if (color & 0x80) /* alternate char set */
1295 {
1296 if (SLtt_Use_Blink_For_ACS)
1297 {
1298 if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
1299 }
1300 else attr |= SLTT_ALTC_MASK;
1301 }
1302
1303
1304 if (attr != Current_Fgbg)
1305 {
1306 #ifndef SLTT_TRANSP_ACS_PATCH
1307 if ((ch != ' ') ||
1308 /* it is a space so only consider it different if it
1309 * has different attributes.
1310 */
1311 (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK))
1312 #endif
1313 {
1314 if (p != out)
1315 {
1316 *p = 0;
1317 write_string_with_care ((char *) out);
1318 Cursor_c += (int) (p - out);
1319 p = out;
1320 }
1321
1322 if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
1323 {
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...
1327 */
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;
1331 }
1332 else write_attributes (attr);
1333
1334 last_color = color;
1335 }
1336 }
1337 }
1338 *p++ = ch;
1339 }
1340 *p = 0;
1341 if (p != out) write_string_with_care ((char *) out);
1342 Cursor_c += (int) (p - out);
1343 }
1344
1345 static void forward_cursor (unsigned int n, int row)
1346 {
1347 char buf[30];
1348
1349
1350 if (n <= 4)
1351 {
1352 SLtt_normal_video ();
1353 SLMEMSET (buf, ' ', n);
1354 buf[n] = 0;
1355 write_string_with_care (buf);
1356 Cursor_c += n;
1357 }
1358 else if (Curs_F_Str != NULL)
1359 {
1360 Cursor_c += n;
1361 n = tt_sprintf(buf, Curs_F_Str, (int) n, 0);
1362 tt_write(buf, n);
1363 }
1364 else SLtt_goto_rc (row, (int) (Cursor_c + n));
1365 }
1366
1367
1368 #define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))
1369
1370 void SLtt_smart_puts(unsigned short *neww, unsigned short *oldd, int len, int row)
1371 {
1372 register unsigned short *p, *q, *qmax, *pmax, *buf;
1373 unsigned short buffer[256];
1374 unsigned int n_spaces;
1375 unsigned short *space_match, *last_buffered_match;
1376 #ifdef HP_GLITCH_CODE
1377 int handle_hp_glitch = 0;
1378 #endif
1379
1380 q = oldd; p = neww;
1381 qmax = oldd + len;
1382 pmax = p + len;
1383
1384 /* Find out where to begin --- while they match, we are ok */
1385 while (1)
1386 {
1387 if (q == qmax) return;
1388 #if SLANG_HAS_KANJI_SUPPORT
1389 if (*p & 0x80)
1390 { /* new is kanji */
1391 if ((*q & 0x80) && ((q + 1) < qmax))
1392 { /* old is also kanji */
1393 if (((0xFF & *q) != (0xFF & *p))
1394 || ((0xFF & q[1]) != (0xFF & p[1])))
1395 break; /* both kanji, but not match */
1396
1397 else
1398 { /* kanji match ! */
1399 if (!COLOR_EQS(*q, *p)) break;
1400 q++; p++;
1401 if (!COLOR_EQS(*q, *p)) break;
1402 /* really match! */
1403 q++; p++;
1404 continue;
1405 }
1406 }
1407 else break; /* old is not kanji */
1408 }
1409 else
1410 { /* new is not kanji */
1411 if (*q & 0x80) break; /* old is kanji */
1412 }
1413 #endif
1414 if (!CHAR_EQS(*q, *p)) break;
1415 q++; p++;
1416 }
1417
1418 /*position the cursor */
1419 SLtt_goto_rc (row, (int) (p - neww));
1420
1421 #ifdef HP_GLITCH_CODE
1422 if (Has_HP_Glitch)
1423 {
1424 unsigned short *qq = q;
1425 while (qq < qmax)
1426 {
1427 if (*qq & 0xFF00)
1428 {
1429 SLtt_normal_video ();
1430 SLtt_del_eol ();
1431 qmax = q;
1432 handle_hp_glitch = 1;
1433 break;
1434 }
1435 qq++;
1436 }
1437 }
1438 #endif
1439 /* Find where the last non-blank character on old/new screen is */
1440
1441 while (qmax > q)
1442 {
1443 qmax--;
1444 if (!CHAR_EQS(*qmax, SPACE_CHAR))
1445 {
1446 qmax++;
1447 break;
1448 }
1449 }
1450
1451 while (pmax > p)
1452 {
1453 pmax--;
1454 if (!CHAR_EQS(*pmax, SPACE_CHAR))
1455 {
1456 pmax++;
1457 break;
1458 }
1459 }
1460
1461 last_buffered_match = buf = buffer; /* buffer is empty */
1462
1463 #ifdef HP_GLITCH_CODE
1464 if (handle_hp_glitch)
1465 {
1466 while (p < pmax)
1467 {
1468 *buf++ = *p++;
1469 }
1470 }
1471 #endif
1472
1473 /* loop using overwrite then skip algorithm until done */
1474 while (1)
1475 {
1476 /* while they do not match and we do not hit a space, buffer them up */
1477 n_spaces = 0;
1478 while (p < pmax)
1479 {
1480 if (CHAR_EQS(*q,SPACE_CHAR) && CHAR_EQS(*p, SPACE_CHAR))
1481 {
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.
1485 */
1486 space_match = p;
1487 p++; q++;
1488 while ((p < pmax)
1489 && CHAR_EQS(*q,SPACE_CHAR)
1490 && CHAR_EQS(*p, SPACE_CHAR))
1491 {
1492 p++;
1493 q++;
1494 }
1495 n_spaces = (unsigned int) (p - space_match);
1496 break;
1497 }
1498 #if SLANG_HAS_KANJI_SUPPORT
1499 if ((*p & 0x80) && ((p + 1) < pmax))
1500 { /* new is kanji */
1501 if (*q & 0x80)
1502 { /* old is also kanji */
1503 if (((0xFF & *q) != (0xFF & *p))
1504 || ((0xFF & q[1]) != (0xFF & p[1])))
1505 {
1506 /* both kanji, but not match */
1507 *buf++ = *p++;
1508 *buf++ = *p++;
1509 q += 2;
1510 continue;
1511 }
1512 else
1513 { /* kanji match ? */
1514 if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
1515 {
1516 /* code is match ,but color is diff */
1517 *buf++ = *p++;
1518 *buf++ = *p++;
1519 continue;
1520 }
1521 /* really match ! */
1522 break;
1523 }
1524 }
1525 else
1526 { /* old is not kanji */
1527 *buf++ = *p++;
1528 *buf++ = *p++;
1529 q += 2;
1530 continue;
1531 }
1532 }
1533 else
1534 { /* new is not kanji */
1535 if (*q & 0x80)
1536 { /* old is kanji */
1537 *buf++ = *p++;
1538 q++;
1539 continue;
1540 }
1541 }
1542 #endif
1543
1544 if (CHAR_EQS(*q, *p)) break;
1545 *buf++ = *p++;
1546 q++;
1547 }
1548 *buf = 0;
1549
1550 if (buf != buffer) send_attr_str (buffer);
1551 buf = buffer;
1552
1553 if (n_spaces && (p < pmax))
1554 {
1555 forward_cursor (n_spaces, row);
1556 }
1557
1558 /* Now we overwrote what we could and cursor is placed at position
1559 * of a possible match of new and old. If this is the case, skip
1560 * some more.
1561 */
1562 #if !SLANG_HAS_KANJI_SUPPORT
1563 while ((p < pmax) && CHAR_EQS(*p, *q))
1564 {
1565 *buf++ = *p++;
1566 q++;
1567 }
1568 #else
1569 /* Kanji */
1570 while (p < pmax)
1571 {
1572 if ((*p & 0x80) && ((p + 1) < pmax))
1573 { /* new is kanji */
1574 if (*q & 0x80)
1575 { /* old is also kanji */
1576 if (((0xFF & *q) == (0xFF & *p))
1577 && ((0xFF & q[1]) == (0xFF & p[1])))
1578 {
1579 /* kanji match ? */
1580 if (!COLOR_EQS(*q, *p)
1581 || !COLOR_EQS(q[1], p[1]))
1582 break;
1583
1584 *buf++ = *p++;
1585 q++;
1586 if (p >= pmax)
1587 {
1588 *buf++ = SPACE_CHAR;
1589 p++;
1590 break;
1591 }
1592 else
1593 {
1594 *buf++ = *p++;
1595 q++;
1596 continue;
1597 }
1598 }
1599 else break; /* both kanji, but not match */
1600 }
1601 else break; /* old is not kanji */
1602 }
1603 else
1604 { /* new is not kanji */
1605 if (*q & 0x80) break; /* old is kanji */
1606 if (!CHAR_EQS(*q, *p)) break;
1607 *buf++ = *p++;
1608 q++;
1609 }
1610 }
1611 #endif
1612 last_buffered_match = buf;
1613 if (p >= pmax) break;
1614
1615 /* jump to new position is it is greater than 5 otherwise
1616 * let it sit in the buffer and output it later.
1617 */
1618 if ((int) (buf - buffer) >= 5)
1619 {
1620 forward_cursor ((unsigned int) (buf - buffer), row);
1621 last_buffered_match = buf = buffer;
1622 }
1623 }
1624
1625 if (buf != buffer)
1626 {
1627 if (q < qmax)
1628 {
1629 if ((buf == last_buffered_match)
1630 && ((int) (buf - buffer) >= 5))
1631 {
1632 forward_cursor ((unsigned int) (buf - buffer), row);
1633 }
1634 else
1635 {
1636 *buf = 0;
1637 send_attr_str (buffer);
1638 }
1639 }
1640 }
1641 if (q < qmax) SLtt_del_eol ();
1642 if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
1643 }
1644
1645
1646 static void get_color_info (void)
1647 {
1648 char *fg, *bg;
1649
1650 SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
1651
1652 if (-1 == get_default_colors (&fg, &bg))
1653 return;
1654
1655 /* Check to see if application has already set them. */
1656 if (Color_0_Modified)
1657 return;
1658
1659 SLtt_set_color (0, NULL, fg, bg);
1660 SLtt_set_color (1, NULL, bg, fg);
1661 }
1662
1663
1664 /* termcap stuff */
1665
1666 #ifdef __unix__
1667
1668 #ifndef USE_TERMCAP
1669 static char *Tbuf;
1670 static char *Tstr_Buf;
1671
1672 #define tgetstr SLtt_tigetstr
1673 #define tgetent SLtt_tigetent
1674 #define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
1675 #define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
1676 #else
1677
1678 extern char *tgetstr(char *, char **);
1679 extern int tgetent(char *, char *);
1680 extern int tgetnum(char *);
1681 extern int tgetflag(char *);
1682 static char Tstr_Buf[1024];
1683 static char Tbuf[4096];
1684 #define TGETNUM tgetnum
1685 #define TGETFLAG tgetflag
1686 #endif
1687
1688 static char *my_tgetstr(char *what, char **p)
1689 {
1690 register char *w, *w1;
1691 char *wsave;
1692 what = tgetstr(what, p);
1693 if (what != NULL)
1694 {
1695 /* Check for AIX brain-damage */
1696 if (*what == '@')
1697 return NULL;
1698
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++;
1704
1705 /* lose terminfo padding--- looks like $<...> */
1706 w = what;
1707 while (*w) if ((*w++ == '$') && (*w == '<'))
1708 {
1709 w1 = w - 1;
1710 while (*w && (*w != '>')) w++;
1711 if (*w == 0) break;
1712 w++;
1713 wsave = w1;
1714 while ((*w1++ = *w++) != 0);
1715 w = wsave;
1716 }
1717 if (*what == 0) what = NULL;
1718 }
1719 return(what);
1720 }
1721
1722 char *SLtt_tgetstr (char *s)
1723 {
1724 #ifdef USE_TERMCAP
1725 static
1726 #endif
1727 char *p = Tstr_Buf;
1728 return my_tgetstr (s, &p);
1729 }
1730
1731 int SLtt_tgetnum (char *s)
1732 {
1733 return TGETNUM (s);
1734 }
1735 int SLtt_tgetflag (char *s)
1736 {
1737 return TGETFLAG (s);
1738 }
1739
1740
1741 static int Vt100_Like = 0;
1742
1743 void SLtt_get_terminfo (void)
1744 {
1745 char *term, *t, ch;
1746 int is_xterm;
1747 int almost_vtxxx;
1748
1749 get_color_info ();
1750
1751 if (NULL == (term = (char *) getenv("TERM")))
1752 {
1753 SLang_exit_error("TERM environment variable needs set.");
1754 }
1755
1756 Linux_Console = (!strncmp (term, "linux", 5)
1757 #ifdef linux
1758 || !strncmp(term, "con", 3)
1759 #endif
1760 );
1761
1762 t = term;
1763
1764 if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
1765 && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1;
1766
1767 is_xterm = !strncmp (term, "xterm", 5);
1768 almost_vtxxx = (Vt100_Like
1769 || Linux_Console
1770 || is_xterm
1771 || !strcmp (term, "screen"));
1772
1773 #ifndef USE_TERMCAP
1774 if (NULL == (Tbuf = tgetent (term)))
1775 {
1776 char err_buf[512];
1777 if (almost_vtxxx) /* Special cases. */
1778 {
1779 int vt102 = 1;
1780 if (!strcmp (term, "vt100")) vt102 = 0;
1781 SLtt_set_term_vtxxx (&vt102);
1782 return;
1783 }
1784 sprintf (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);
1790 }
1791 Tstr_Buf = Tbuf;
1792 #else /* USE_TERMCAP */
1793 if (1 != tgetent(Tbuf, term)) SLang_exit_error("Unknown terminal.");
1794 #endif /* NOT USE_TERMCAP */
1795
1796 if ((NULL == (Cls_Str = SLtt_tgetstr("cl")))
1797 || (NULL == (Curs_Pos_Str = SLtt_tgetstr("cm"))))
1798 {
1799 SLang_exit_error("Terminal not powerful enough for SLang.");
1800 }
1801
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;
1806
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");
1812
1813 /* Actually these are used to initialize terminals that use cursor
1814 * addressing. Hard to believe.
1815 */
1816 Term_Init_Str = SLtt_tgetstr ("ti");
1817 Term_Reset_Str = SLtt_tgetstr ("te");
1818
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.
1821 */
1822 if ((almost_vtxxx == 0) || SLtt_Force_Keypad_Init)
1823 {
1824 Keypad_Init_Str = SLtt_tgetstr ("ks");
1825 Keypad_Reset_Str = SLtt_tgetstr ("ke");
1826 }
1827
1828 /* Make up for defective termcap/terminfo databases */
1829 if ((Vt100_Like && (term[2] != '1'))
1830 || Linux_Console
1831 || is_xterm
1832 )
1833 {
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";
1836 }
1837
1838 Scroll_R_Str = SLtt_tgetstr("cs");
1839
1840 SLtt_get_screen_size ();
1841
1842 if ((Scroll_R_Str == NULL)
1843 || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
1844 && (NULL == Rev_Scroll_Str)))
1845 {
1846 if (is_xterm
1847 || Linux_Console
1848 )
1849 {
1850 /* Defective termcap mode!!!! */
1851 SLtt_set_term_vtxxx (NULL);
1852 }
1853 else SLtt_Term_Cannot_Scroll = 1;
1854 }
1855
1856 Del_Eol_Str = SLtt_tgetstr("ce");
1857
1858 Rev_Vid_Str = SLtt_tgetstr("mr");
1859 if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
1860
1861 Bold_Vid_Str = SLtt_tgetstr("md");
1862
1863 /* Although xterm cannot blink, it does display the blinking characters
1864 * as bold ones. Some Rxvt will display the background as high intensity.
1865 */
1866 if ((NULL == (Blink_Vid_Str = SLtt_tgetstr("mb")))
1867 && is_xterm)
1868 Blink_Vid_Str = "\033[5m";
1869
1870 UnderLine_Vid_Str = SLtt_tgetstr("us");
1871
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");
1876
1877 #ifndef NCURSES_BRAIN_DAMAGE_CONTROL
1878 # define NCURSES_BRAIN_DAMAGE_CONTROL 0
1879 #endif
1880
1881 #if NCURSES_BRAIN_DAMAGE_CONTROL
1882 if (Linux_Console)
1883 {
1884 # if 0
1885 char *lgcp = "l\332m\300k\277j\331u\264t\303v\301w\302q\304x\263n\053o\176s\137`\004a\260f\370g\361~\011,\020+\021.\031-\030h\261i\0250\333";
1886
1887 SLtt_Graphics_Char_Pairs = lgcp;
1888 Start_Alt_Chars_Str = "\033(B\033)U\016";
1889 End_Alt_Chars_Str = "\033(B\033)0\017";
1890 Enable_Alt_Char_Set = NULL;
1891 # else
1892 char *lgcp = "`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o\302q\304r\362s_t\303u\264v\301w\302x\263y\371z\372{\373|\374}\375~";
1893
1894 SLtt_Graphics_Char_Pairs = lgcp;
1895 Start_Alt_Chars_Str = "\033[11m";
1896 End_Alt_Chars_Str = "\033[10m";
1897 Enable_Alt_Char_Set = NULL;
1898 # endif
1899 }
1900 #endif
1901
1902 if (NULL == SLtt_Graphics_Char_Pairs)
1903 {
1904 /* make up for defective termcap/terminfo */
1905 if (Vt100_Like)
1906 {
1907 Start_Alt_Chars_Str = "\016";
1908 End_Alt_Chars_Str = "\017";
1909 Enable_Alt_Char_Set = "\033)0";
1910 }
1911 }
1912
1913 /* aixterm added by willi */
1914 if (is_xterm || !strncmp (term, "aixterm", 7))
1915 {
1916 Start_Alt_Chars_Str = "\016";
1917 End_Alt_Chars_Str = "\017";
1918 Enable_Alt_Char_Set = "\033(B\033)0";
1919 }
1920
1921 if ((SLtt_Graphics_Char_Pairs == NULL) &&
1922 ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
1923 {
1924 SLtt_Has_Alt_Charset = 0;
1925 Enable_Alt_Char_Set = NULL;
1926 }
1927 else SLtt_Has_Alt_Charset = 1;
1928
1929
1930 /* status line capabilities */
1931 if ((SLtt_Has_Status_Line == -1)
1932 && (0 != (SLtt_Has_Status_Line = TGETFLAG ("hs"))))
1933 {
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;
1940 }
1941
1942 if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me")))
1943 {
1944 Norm_Vid_Str = SLtt_tgetstr("se");
1945 }
1946
1947 Cursor_Invisible_Str = SLtt_tgetstr("vi");
1948 Cursor_Visible_Str = SLtt_tgetstr("ve");
1949
1950 Curs_F_Str = SLtt_tgetstr("RI");
1951
1952 #if 0
1953 if (NULL != Curs_F_Str)
1954 {
1955 Len_Curs_F_Str = strlen(Curs_F_Str);
1956 }
1957 else Len_Curs_F_Str = strlen(Curs_Pos_Str);
1958 #endif
1959
1960 Automatic_Margins = TGETFLAG ("am");
1961 /* No_Move_In_Standout = !TGETFLAG ("ms"); */
1962 #ifdef HP_GLITCH_CODE
1963 Has_HP_Glitch = TGETFLAG ("xs");
1964 #else
1965 Worthless_Highlight = TGETFLAG ("xs");
1966 #endif
1967
1968 if (Worthless_Highlight == 0)
1969 { /* Magic cookie glitch */
1970 Worthless_Highlight = (TGETNUM ("sg") > 0);
1971 }
1972
1973 if (Worthless_Highlight)
1974 SLtt_Has_Alt_Charset = 0;
1975
1976 /* Check for color information in the termcap. A program should not
1977 * rely on this information being accurate.
1978 */
1979 if (SLtt_Use_Ansi_Colors == 0)
1980 {
1981 Reset_Color_String = SLtt_tgetstr ("op");
1982
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")));
1990
1991 }
1992
1993 #if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
1994 /*
1995 * Override the alt-char-set handling string in case of a
1996 * QNX/qansi terminal: use the "old style" strings in order
1997 * to be compatible with S-Lang without the SLTT_TRANSP_ACS_PATCH
1998 * code...
1999 */
2000 if (SLtt_Has_Alt_Charset &&
2001 strncmp(term, "qansi", 5) == 0 &&
2002 Start_Alt_Chars_Str[0] != '\016')
2003 {
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";
2008
2009 /*
2010 * it would be required to modify the sgr/sa entry also, if it
2011 * would be used (->embedded as/ae sequences)...
2012 */
2013 }
2014 #endif /* __QNX__ && QNX_QANSI_SLANG_COMPAT_ACS */
2015
2016 }
2017
2018 #endif
2019 /* Unix */
2020
2021 /* specific to vtxxx only */
2022 void SLtt_enable_cursor_keys (void)
2023 {
2024 #ifdef __unix__
2025 if (Vt100_Like)
2026 #endif
2027 SLtt_write_string("\033=\033[?1l");
2028 }
2029
2030 #ifdef VMS
2031 void SLtt_get_terminfo ()
2032 {
2033 int zero = 0;
2034
2035 get_color_info ();
2036
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 ();
2044 }
2045 #endif
2046
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). */
2050
2051 void SLtt_set_term_vtxxx(int *vt100)
2052 {
2053 Norm_Vid_Str = "\033[m";
2054
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))
2067 {
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;
2074 }
2075 else
2076 {
2077 Del_N_Lines_Str = NULL;
2078 Add_N_Lines_Str = NULL;
2079 SLtt_Term_Cannot_Insert = 1;
2080 }
2081 SLtt_Term_Cannot_Scroll = 0;
2082 /* No_Move_In_Standout = 0; */
2083 }
2084
2085 void SLtt_init_video (void)
2086 {
2087 /* send_string_to_term("\033[?6h"); */
2088 /* relative origin mode */
2089 SLtt_write_string (Term_Init_Str);
2090 SLtt_write_string (Keypad_Init_Str);
2091 SLtt_reset_scroll_region();
2092 SLtt_end_insert();
2093 SLtt_write_string (Enable_Alt_Char_Set);
2094 Video_Initialized = 1;
2095 }
2096
2097
2098 void SLtt_reset_video (void)
2099 {
2100 SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
2101 Cursor_Set = 0;
2102 SLtt_normal_video (); /* MSKermit requires this */
2103 SLtt_write_string(Norm_Vid_Str);
2104
2105 Current_Fgbg = 0xFFFFFFFFU;
2106 SLtt_set_alt_char_set (0);
2107 if (SLtt_Use_Ansi_Colors)
2108 {
2109 if (Reset_Color_String == NULL)
2110 {
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");
2115 }
2116 else SLtt_write_string (Reset_Color_String);
2117 Current_Fgbg = 0xFFFFFFFFU;
2118 }
2119 SLtt_erase_line ();
2120 SLtt_write_string (Keypad_Reset_Str);
2121 SLtt_write_string (Term_Reset_Str);
2122 SLtt_flush_output ();
2123 Video_Initialized = 0;
2124 }
2125
2126 void SLtt_bold_video (void)
2127 {
2128 SLtt_write_string (Bold_Vid_Str);
2129 }
2130
2131 int SLtt_set_mouse_mode (int mode, int force)
2132 {
2133 char *term;
2134
2135 if (force == 0)
2136 {
2137 if (NULL == (term = (char *) getenv("TERM"))) return -1;
2138 if (strncmp ("xterm", term, 5))
2139 return -1;
2140 }
2141
2142 if (mode)
2143 SLtt_write_string ("\033[?9h");
2144 else
2145 SLtt_write_string ("\033[?9l");
2146
2147 return 0;
2148 }
2149
2150
2151 void SLtt_disable_status_line (void)
2152 {
2153 if (SLtt_Has_Status_Line > 0)
2154 SLtt_write_string (Disable_Status_line_Str);
2155 }
2156
2157 int SLtt_write_to_status_line (char *s, int col)
2158 {
2159 if ((SLtt_Has_Status_Line <= 0)
2160 || (Goto_Status_Line_Str == NULL)
2161 || (Return_From_Status_Line_Str == NULL))
2162 return -1;
2163
2164 tt_printf (Goto_Status_Line_Str, col, 0);
2165 SLtt_write_string (s);
2166 SLtt_write_string (Return_From_Status_Line_Str);
2167 return 0;
2168 }
2169
2170
2171 void SLtt_get_screen_size (void)
2172 {
2173 #ifdef VMS
2174 int status, code;
2175 unsigned short chan;
2176 $DESCRIPTOR(dev_dsc, "SYS$INPUT:");
2177 #endif
2178 #ifdef __os2__
2179 VIOMODEINFO vioModeInfo;
2180 #endif
2181 int r = 0, c = 0;
2182
2183 #if defined(TIOCGWINSZ) && !defined(SCO_FLAVOR)
2184 struct winsize wind_struct;
2185
2186 do
2187 {
2188 if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
2189 || (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
2190 || (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
2191 {
2192 c = (int) wind_struct.ws_col;
2193 r = (int) wind_struct.ws_row;
2194 break;
2195 }
2196 }
2197 while (errno == EINTR);
2198
2199 #endif
2200
2201 #ifdef VMS
2202 status = sys$assign(&dev_dsc,&chan,0,0,0);
2203 if (status & 1)
2204 {
2205 code = DVI$_DEVBUFSIZ;
2206 status = lib$getdvi(&code, &chan,0, &c, 0,0);
2207 if (!(status & 1))
2208 c = 80;
2209 code = DVI$_TT_PAGE;
2210 status = lib$getdvi(&code, &chan,0, &r, 0,0);
2211 if (!(status & 1))
2212 r = 24;
2213 sys$dassgn(chan);
2214 }
2215 #endif
2216
2217 #ifdef __os2__
2218 vioModeInfo.cb = sizeof(vioModeInfo);
2219 VioGetMode (&vioModeInfo, 0);
2220 c = vioModeInfo.col;
2221 r = vioModeInfo.row;
2222 #endif
2223
2224 if (r <= 0)
2225 {
2226 char *s = getenv ("LINES");
2227 if (s != NULL) r = atoi (s);
2228 }
2229
2230 if (c <= 0)
2231 {
2232 char *s = getenv ("COLUMNS");
2233 if (s != NULL) c = atoi (s);
2234 }
2235
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;
2240 }