1 /* SLang Screen management routines */
11 int n
; /* number of chars written last time */
12 int flags
; /* line untouched, etc... */
13 SLsmg_Char_Type
*old
, *neew
;
15 unsigned long old_hash
, new_hash
;
22 static int Screen_Trashed
;
24 static Screen_Type SL_Screen
[SLTT_MAX_SCREEN_ROWS
];
25 static int Start_Col
, Start_Row
;
26 static unsigned int Screen_Cols
, Screen_Rows
;
27 static int This_Row
, This_Col
;
28 static SLsmg_Color_Type This_Color
;
30 static int UTF8_Mode
= -1;
32 #if SLTT_HAS_NON_BCE_SUPPORT && !defined(IBMPC_SYSTEM)
33 #define REQUIRES_NON_BCE_SUPPORT 1
34 static int Bce_Color_Offset
;
37 int SLsmg_Newline_Behavior
= SLSMG_NEWLINE_IGNORED
;
38 int SLsmg_Backspace_Moves
= 0;
40 #if SLSMG_HAS_EMBEDDED_ESCAPE
41 /* If non-zero, interpret escape sequences ESC [ x m as an embedded set color
42 * sequence. The 'x' is a decimal integer that specifies the color. The sequence
43 * ends at m. Examples: \e[3m --> set color 3. \e[272m --> color=272.
44 * Note: These escape sequences are NOT ANSI, though similar. ANSI permits
45 * sequences such as \e[32;44m to set the foreground to green/blue. This interface
46 * will support such sequences, _but_ in will map such squences to the sum of
47 * the colors: \e[32;44m --> color (32+44)=76.
49 * In addition to 'm', ']' is also supported.
51 static int Embedded_Escape_Mode
= 0;
52 int SLsmg_embedded_escape_mode (int mode
)
54 int old_mode
= Embedded_Escape_Mode
;
55 Embedded_Escape_Mode
= mode
;
59 /* This function gets called with u pointing at what may be '['. If it sucessfully
60 * parses the escape sequence, *up and the color will be updated.
62 static int parse_embedded_escape (SLuchar_Type
*u
, SLuchar_Type
*umax
,
63 SLsmg_Color_Type default_color
,
64 SLuchar_Type
**up
, SLsmg_Color_Type
*colorp
)
69 if ((u
< umax
) && (*u
!= '['))
73 if ((u
< umax
) && ((*u
== 'm') || (*u
== ']')))
75 *colorp
= default_color
; /* ESC[m */
82 && (((ch
= *u
) >= '0') && (ch
<= '9')))
84 val
= 10*val
+ (ch
- '0');
87 if ((u
< umax
) && ((*u
== 'm') || (*u
== ']')) && (val
<= SLSMG_MAX_COLORS
))
89 # ifdef REQUIRES_NON_BCE_SUPPORT
90 val
+= Bce_Color_Offset
;
92 *colorp
= (SLsmg_Color_Type
) val
;
99 static void parse_embedded_set_color (SLuchar_Type
*u
, SLuchar_Type
*umax
,
100 SLsmg_Color_Type default_color
)
102 SLsmg_Color_Type color
= default_color
;
107 (void) parse_embedded_escape (u
, umax
, default_color
, &u
, &color
);
109 if (color
== default_color
)
112 #ifdef REQUIRES_NON_BCE_SUPPORT
113 color
-= Bce_Color_Offset
;
115 SLsmg_set_color (color
);
119 /* Backward compatibility. Not used. */
120 /* int SLsmg_Newline_Moves; */
121 static int *tt_Screen_Rows
= NULL
;
122 static int *tt_Screen_Cols
= NULL
;
123 static int *tt_unicode_ok
;
125 static void (*tt_normal_video
)(void);
126 static void (*tt_goto_rc
)(int, int);
127 static void (*tt_cls
) (void);
128 static void (*tt_del_eol
) (void);
129 static void (*tt_smart_puts
) (SLsmg_Char_Type
*, SLsmg_Char_Type
*, int, int);
130 static int (*tt_flush_output
) (void);
131 static int (*tt_reset_video
) (void);
132 static int (*tt_init_video
) (void);
135 static void (*tt_set_scroll_region
)(int, int);
136 static void (*tt_reverse_index
)(int);
137 static void (*tt_reset_scroll_region
)(void);
138 static void (*tt_delete_nlines
)(int);
142 static int *tt_Term_Cannot_Scroll
;
143 static int *tt_Has_Alt_Charset
;
144 static char **tt_Graphics_Char_Pairs
;
146 static int *tt_Has_Alt_Charset
= NULL
;
147 static char **tt_Graphics_Char_Pairs
= NULL
;
150 static int Smg_Inited
;
152 /* This is necessary because the windoze run-time linker cannot perform
153 * relocations on its own.
155 static void init_tt_symbols (void)
157 tt_Screen_Rows
= &SLtt_Screen_Rows
;
158 tt_Screen_Cols
= &SLtt_Screen_Cols
;
159 tt_unicode_ok
= &_pSLtt_UTF8_Mode
;
161 tt_normal_video
= SLtt_normal_video
;
162 tt_goto_rc
= SLtt_goto_rc
;
164 tt_del_eol
= SLtt_del_eol
;
165 tt_smart_puts
= SLtt_smart_puts
;
166 tt_flush_output
= SLtt_flush_output
;
167 tt_reset_video
= SLtt_reset_video
;
168 tt_init_video
= SLtt_init_video
;
171 tt_set_scroll_region
= SLtt_set_scroll_region
;
172 tt_reverse_index
= SLtt_reverse_index
;
173 tt_reset_scroll_region
= SLtt_reset_scroll_region
;
174 tt_delete_nlines
= SLtt_delete_nlines
;
178 tt_Term_Cannot_Scroll
= &SLtt_Term_Cannot_Scroll
;
179 tt_Has_Alt_Charset
= &SLtt_Has_Alt_Charset
;
180 tt_Graphics_Char_Pairs
= &SLtt_Graphics_Char_Pairs
;
182 tt_Has_Alt_Charset
= NULL
;
183 tt_Graphics_Char_Pairs
= NULL
;
187 /* Unicode box drawing characters */
189 /* This lookup table is indexed by the vt100 characters */
190 static SLwchar_Type ACS_Map
[128];
194 unsigned char vt100_char
;
196 SLwchar_Type unicode
;
200 static SLCONST ACS_Def_Type UTF8_ACS_Map
[] =
202 {'+', '>', 0x2192 }, /* RIGHTWARDS ARROW */
203 {',', '<', 0x2190 }, /* LEFTWARDS ARROW */
204 {'-', '^', 0x2191 }, /* UPWARDS ARROW */
205 {'.', 'v', 0x2193 }, /* DOWNWARDS ARROW */
206 {'0', '#', 0x25AE }, /* BLACK VERTICAL RECTANGLE */
207 {'`', '+', 0x25C6 }, /* BLACK DIAMOND */
208 {'a', ':', 0x2592 }, /* MEDIUM SHADE */
209 {'f', '\'', 0x00B0 },/* DEGREE SIGN */
210 {'g', '#', 0x00B1 }, /* PLUS-MINUS SIGN */
211 {'h', '#', 0x2592 }, /* MEDIUM SHADE */
212 {'i', '#', 0x2603 }, /* SNOWMAN */
213 {'j', '+', 0x2518 }, /* BOX DRAWINGS LIGHT UP AND LEFT */
214 {'k', '+', 0x2510 }, /* BOX DRAWINGS LIGHT DOWN AND LEFT */
215 {'l', '+', 0x250c }, /* BOX DRAWINGS LIGHT DOWN AND RIGHT */
216 {'m', '+', 0x2514 }, /* BOX DRAWINGS LIGHT UP AND RIGHT */
217 {'n', '+', 0x253C }, /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
218 {'o', '~', 0x23BA }, /* HORIZONTAL SCAN LINE-1 */
219 {'p', '-', 0x23BB }, /* HORIZONTAL SCAN LINE-3 (ncurses addition) */
220 {'q', '-', 0x2500 }, /* BOX DRAWINGS LIGHT HORIZONTAL */
221 {'r', '-', 0x23BC }, /* HORIZONTAL SCAN LINE-7 (ncurses addition) */
222 {'s', '_', 0x23BD }, /* HORIZONTAL SCAN LINE-9 */
223 {'t', '+', 0x251C }, /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
224 {'u', '+', 0x2524 }, /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */
225 {'v', '+', 0x2534 }, /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */
226 {'w', '+', 0x252C }, /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
227 {'x', '|', 0x2502 }, /* BOX DRAWINGS LIGHT VERTICAL */
228 {'y', '<', 0x2264 }, /* LESS-THAN OR EQUAL TO (ncurses addition) */
229 {'z', '>', 0x2265 }, /* GREATER-THAN OR EQUAL TO (ncurses addition) */
230 {'{', '*', 0x03C0 }, /* GREEK SMALL LETTER PI (ncurses addition) */
231 {'|', '!', 0x2260 }, /* NOT EQUAL TO (ncurses addition) */
232 {'}', 'f', 0x00A3 }, /* POUND SIGN (ncurses addition) */
233 {'~', 'o', 0x00B7 }, /* MIDDLE DOT */
237 #define ACS_MODE_NONE -1
238 #define ACS_MODE_AUTO 0
239 #define ACS_MODE_UNICODE 1
240 #define ACS_MODE_TERMINFO 2
241 #define ACS_MODE_ASCII 3
243 static int Current_ACS_Mode
= ACS_MODE_NONE
;
244 static void init_acs (int mode
)
247 SLCONST ACS_Def_Type
*acs
;
249 if (Current_ACS_Mode
== mode
)
252 for (i
= 0; i
< 0x80; i
++)
255 if (mode
== ACS_MODE_AUTO
)
258 (tt_unicode_ok
!= NULL
) && (*tt_unicode_ok
> 0))
259 mode
= ACS_MODE_UNICODE
;
261 mode
= ACS_MODE_TERMINFO
;
266 case ACS_MODE_UNICODE
:
267 SLsmg_Display_Eight_Bit
= 0xA0;
269 while (acs
->vt100_char
!= 0)
271 ACS_Map
[acs
->vt100_char
] = acs
->unicode
;
276 case ACS_MODE_TERMINFO
:
277 if ((tt_Has_Alt_Charset
!= NULL
)
278 && *tt_Has_Alt_Charset
279 && (tt_Graphics_Char_Pairs
!= NULL
)
280 && (*tt_Graphics_Char_Pairs
!= NULL
))
282 unsigned char *p
= (unsigned char *) *tt_Graphics_Char_Pairs
;
283 unsigned char *pmax
= p
+ strlen ((char *) p
);
287 unsigned char ch
= *p
++;
288 ACS_Map
[ch
& 0x7F] = *p
++;
292 mode
= ACS_MODE_ASCII
;
297 while (acs
->vt100_char
!= 0)
299 ACS_Map
[acs
->vt100_char
] = acs
->ascii
;
305 Current_ACS_Mode
= mode
;
308 static void blank_line (SLsmg_Char_Type
*c
, unsigned int n
, SLwchar_Type wch
)
310 SLsmg_Char_Type
*cmax
= c
+ n
;
311 SLsmg_Color_Type color
= This_Color
;
313 memset ((char *)c
, 0, n
*sizeof(SLsmg_Char_Type
));
323 static void clear_region (int row
, int n
, SLwchar_Type ch
)
328 if (imax
> (int) Screen_Rows
) imax
= (int) Screen_Rows
;
332 for (i
= row
; i
< imax
; i
++)
334 blank_line (SL_Screen
[i
].neew
, Screen_Cols
, ch
);
335 SL_Screen
[i
].flags
|= TOUCHED
;
339 void SLsmg_erase_eol (void)
343 if (Smg_Inited
== 0) return;
345 c
= This_Col
- Start_Col
;
346 r
= This_Row
- Start_Row
;
348 if ((r
< 0) || (r
>= (int)Screen_Rows
)) return;
349 if (c
< 0) c
= 0; else if (c
>= (int)Screen_Cols
) return;
350 blank_line (SL_Screen
[This_Row
].neew
+ c
, Screen_Cols
- c
, 0x20);
351 SL_Screen
[This_Row
].flags
|= TOUCHED
;
354 static void scroll_up (void)
356 unsigned int i
, imax
;
357 SLsmg_Char_Type
*neew
;
359 neew
= SL_Screen
[0].neew
;
360 imax
= Screen_Rows
- 1;
361 for (i
= 0; i
< imax
; i
++)
363 SL_Screen
[i
].neew
= SL_Screen
[i
+ 1].neew
;
364 SL_Screen
[i
].flags
|= TOUCHED
;
366 SL_Screen
[i
].neew
= neew
;
367 SL_Screen
[i
].flags
|= TOUCHED
;
368 blank_line (neew
, Screen_Cols
, 0x20);
372 void SLsmg_gotorc (int r
, int c
)
378 int SLsmg_get_row (void)
383 int SLsmg_get_column (void)
388 void SLsmg_erase_eos (void)
390 if (Smg_Inited
== 0) return;
393 clear_region (This_Row
+ 1, (int)Screen_Rows
, 0x20);
396 static int This_Alt_Char
;
398 void SLsmg_set_char_set (int i
)
404 This_Alt_Char
= SLSMG_ACS_MASK
;
405 else This_Alt_Char
= 0;
407 This_Color
&= SLSMG_COLOR_MASK
;
408 This_Color
|= This_Alt_Char
;
412 void SLsmg_set_color (SLsmg_Color_Type color
)
414 #ifdef REQUIRES_NON_BCE_SUPPORT
415 color
+= Bce_Color_Offset
;
417 This_Color
= color
| This_Alt_Char
;
420 void SLsmg_reverse_video (void)
425 void SLsmg_normal_video (void)
430 static int point_visible (int col_too
)
432 return ((This_Row
>= Start_Row
) && (This_Row
< Start_Row
+ (int)Screen_Rows
)
434 || ((This_Col
>= Start_Col
)
435 && (This_Col
< Start_Col
+ (int)Screen_Cols
))));
438 #define NEXT_CHAR_CELL \
442 if ((p->nchars != i) || (p->color != color)) flags |= TOUCHED; \
452 #define ADD_TO_CHAR_CELL(wc) \
454 if ((p < pmax) && (p->wchars[i] != wc)) \
462 #define ADD_CHAR_OR_BREAK(ch) \
463 if (col >= start_col) \
465 if (i != 0) NEXT_CHAR_CELL; \
466 if (last_was_double_width) \
468 last_was_double_width = 0; \
471 if (col >= max_col) break; \
472 ADD_TO_CHAR_CELL(ch); \
477 void SLsmg_write_chars (unsigned char *u
, unsigned char *umax
)
479 SLsmg_Char_Type
*p
, *pmax
;
480 SLsmg_Color_Type color
;
482 int col
, start_col
, max_col
;
484 int utf8_mode
= UTF8_Mode
;
485 unsigned char display_8bit
;
486 int last_was_double_width
= 0;
487 int alt_char_set_flag
;
489 #if SLSMG_HAS_EMBEDDED_ESCAPE
490 SLsmg_Color_Type default_color
;
492 if (Smg_Inited
== 0) return;
494 display_8bit
= (unsigned char) SLsmg_Display_Eight_Bit
;
499 /* If we are using unicode characters for the line drawing characters, then
500 * do not attempt to use the terminals alternate character set
502 alt_char_set_flag
= (color
& SLSMG_ACS_MASK
);
503 if (Current_ACS_Mode
== ACS_MODE_UNICODE
)
504 color
= color
& ~SLSMG_ACS_MASK
;
506 #if SLSMG_HAS_EMBEDDED_ESCAPE
507 default_color
= color
; /* used for ESC[m */
510 top
: /* get here only on newline */
513 start_col
= Start_Col
;
515 if (point_visible (0) == 0) return;
518 max_col
= start_col
+ Screen_Cols
;
520 p
= SL_Screen
[This_Row
- Start_Row
].neew
;
521 pmax
= p
+ Screen_Cols
;
523 if (col
>= start_col
)
525 p
+= (col
- start_col
);
526 if ((p
< pmax
) && (p
->nchars
== 0))
528 /* It looks like we are about to overwrite the right side of a
529 * double width character.
542 flags
= SL_Screen
[This_Row
- Start_Row
].flags
;
548 unsigned int width
, nconsumed
;
550 if (*u
< (SLuchar_Type
) 0x80) /* ASCII */
554 ch
= (unsigned char) *u
++;
556 if (alt_char_set_flag
)
559 ADD_CHAR_OR_BREAK(wc
);
563 if ((ch
>= (SLuchar_Type
)0x20) && (ch
< (SLuchar_Type
)0x7F))
565 ADD_CHAR_OR_BREAK(ch
);
569 if ((ch
== '\t') && (SLsmg_Tab_Width
> 0))
577 ADD_CHAR_OR_BREAK(' ');
581 while (col
% SLsmg_Tab_Width
);
586 && (SLsmg_Newline_Behavior
!= SLSMG_NEWLINE_PRINTABLE
))
592 if ((ch
== 0x8) && SLsmg_Backspace_Moves
)
607 #if SLSMG_HAS_EMBEDDED_ESCAPE
608 if ((ch
== 033) && Embedded_Escape_Mode
)
610 SLsmg_Color_Type next_color
;
612 if (0 == parse_embedded_escape (u
, umax
, default_color
, &u
, &next_color
))
621 ADD_CHAR_OR_BREAK('^');
622 if (ch
== 127) ch
= '?'; else ch
= ch
+ '@';
623 ADD_CHAR_OR_BREAK (ch
);
629 || (NULL
== SLutf8_decode (u
, umax
, &wc
, &nconsumed
)))
632 unsigned char hexbuf
[8];
635 && display_8bit
&& (*u
>= display_8bit
))
637 ADD_CHAR_OR_BREAK(*u
);
639 else for (ii
= 0; ii
< nconsumed
; ii
++)
641 sprintf ((char *)hexbuf
, "<%02X>", u
[ii
]);
642 for (jj
= 0; jj
< 4; jj
++)
644 ADD_CHAR_OR_BREAK (hexbuf
[jj
]);
652 if (wc
< (SLwchar_Type
)display_8bit
)
654 unsigned char hexbuf
[8];
657 sprintf ((char *)hexbuf
, "<%02X>", (unsigned char) wc
);
658 for (jj
= 0; jj
< 4; jj
++)
660 ADD_CHAR_OR_BREAK (hexbuf
[jj
]);
665 width
= SLwchar_wcwidth (wc
);
668 /* Combining character--- must follow non-zero width char */
671 if (i
< SLSMG_MAX_CHARS_PER_CELL
)
673 ADD_TO_CHAR_CELL (wc
);
680 if (col
+ 2 <= start_col
)
686 if (col
+ 2 > max_col
)
688 ADD_CHAR_OR_BREAK('>');
692 if (col
== start_col
- 1)
694 /* double width character is clipped at left part of screen.
695 * So, display right edge as a space */
697 ADD_CHAR_OR_BREAK('<');
701 ADD_CHAR_OR_BREAK(wc
);
702 last_was_double_width
= 1;
706 ADD_CHAR_OR_BREAK(wc
);
714 if (last_was_double_width
)
718 last_was_double_width
= 0;
720 else if ((col
< max_col
) && (p
->nchars
== 0))
722 /* The left side of a double with character was overwritten */
726 SL_Screen
[This_Row
- Start_Row
].flags
= flags
;
729 /* Why would u be NULL here?? */
731 if (SLsmg_Newline_Behavior
== SLSMG_NEWLINE_IGNORED
)
733 #if SLSMG_HAS_EMBEDDED_ESCAPE
734 if (Embedded_Escape_Mode
&& (u
!= NULL
))
735 parse_embedded_set_color (u
, umax
, default_color
);
740 if (newline_flag
== 0)
742 #if SLSMG_HAS_EMBEDDED_ESCAPE
743 SLuchar_Type
*usave
= u
;
750 if (*u
== '\n') break;
755 #if SLSMG_HAS_EMBEDDED_ESCAPE
756 if (Embedded_Escape_Mode
)
757 parse_embedded_set_color (usave
, umax
, default_color
);
766 if (This_Row
== Start_Row
+ (int)Screen_Rows
)
768 if (SLsmg_Newline_Behavior
== SLSMG_NEWLINE_SCROLLS
) scroll_up ();
774 void SLsmg_write_nchars (char *str
, unsigned int len
)
776 SLsmg_write_chars ((unsigned char *) str
, (unsigned char *)str
+ len
);
779 void SLsmg_write_string (char *str
)
781 SLsmg_write_chars ((unsigned char *)str
,
782 (unsigned char *)str
+ strlen (str
));
785 void SLsmg_write_nstring (char *str
, unsigned int n
)
788 unsigned char *blank
= (unsigned char *)" ";
789 unsigned char *u
= (unsigned char *)str
;
791 /* Avoid a problem if a user accidently passes a negative value */
795 if (u
== NULL
) width
= 0;
800 width
= strlen ((char *)u
);
802 umax
= SLutf8_skip_chars (u
, u
+width
, n
, &width
, 0);
805 if (width
> n
) width
= n
;
808 SLsmg_write_chars (u
, umax
);
811 while (width
++ < n
) SLsmg_write_chars (blank
, blank
+1);
814 void SLsmg_write_wrapped_string (SLuchar_Type
*u
, int r
, int c
,
815 unsigned int dr
, unsigned int dc
,
819 unsigned char *p
, *pmax
;
820 int utf8_mode
= UTF8_Mode
;
822 if ((dr
== 0) || (dc
== 0)) return;
824 pmax
= u
+ strlen ((char *)u
);
829 unsigned char ch
= *p
;
830 if ((ch
== 0) || (ch
== '\n'))
834 diff
= maxc
- (int) dc
;
837 SLsmg_write_chars (u
, p
);
838 if (fill
&& (diff
> 0))
840 unsigned char *blank
= (unsigned char *)" ";
841 while (diff
--) SLsmg_write_chars (blank
, blank
+1);
843 if ((ch
== 0) || (dr
== 1)) break;
853 if ((int) dc
== maxc
)
856 SLsmg_write_chars (u
, p
);
868 p
= SLutf8_skip_chars (p
, pmax
, 1, NULL
, 0);
874 int SLsmg_Tab_Width
= 8;
876 /* Minimum value for which eight bit char is displayed as is. */
879 int SLsmg_Display_Eight_Bit
= 160;
881 int SLsmg_Display_Eight_Bit
= 128;
884 void SLsmg_write_char (SLwchar_Type ch
)
886 unsigned char u
[SLUTF8_MAX_MBLEN
];
889 if ((ch
< 0x80) || (UTF8_Mode
== 0))
891 u
[0] = (unsigned char) ch
;
892 SLsmg_write_chars (u
, u
+1);
895 if (NULL
== (umax
= SLutf8_encode (ch
, u
, SLUTF8_MAX_MBLEN
)))
897 SLsmg_write_chars (u
, umax
);
902 void SLsmg_cls (void)
905 if (Smg_Inited
== 0) return;
907 tac
= This_Alt_Char
; This_Alt_Char
= 0;
909 clear_region (0, (int)Screen_Rows
, 0x20);
915 static void do_copy (SLsmg_Char_Type
*a
, SLsmg_Char_Type
*b
)
917 SLsmg_Char_Type
*amax
= a
+ Screen_Cols
;
919 while (a
< amax
) *a
++ = *b
++;
924 int SLsmg_Scroll_Hash_Border
= 0;
925 static unsigned long compute_hash (SLsmg_Char_Type
*c
, unsigned int n
)
927 SLsmg_Char_Type
*csave
, *cmax
;
930 c
+= SLsmg_Scroll_Hash_Border
;
932 cmax
= c
+ (n
- SLsmg_Scroll_Hash_Border
);
934 while ((c
< cmax
) && is_blank
)
936 if ((c
->wchars
[0] != 32) || (c
->nchars
!= 1))
940 if (is_blank
) return 0;
942 return _pSLstring_hash ((unsigned char *)csave
, (unsigned char *)cmax
);
945 static unsigned long Blank_Hash
;
947 static int try_scroll_down (int rmin
, int rmax
)
949 int i
, r1
, r2
, di
, j
;
952 SLsmg_Color_Type color
;
953 SLsmg_Char_Type
*tmp
;
957 for (i
= rmax
; i
> rmin
; i
--)
959 hash
= SL_Screen
[i
].new_hash
;
960 if (hash
== Blank_Hash
) continue;
962 if ((hash
== SL_Screen
[i
].old_hash
)
964 || ((i
+ 1 < Screen_Rows
) && (hash
== SL_Screen
[i
+ 1].old_hash
))
965 || ((i
- 1 > rmin
) && (SL_Screen
[i
].old_hash
== SL_Screen
[i
- 1].new_hash
))
970 for (j
= i
- 1; j
>= rmin
; j
--)
972 if (hash
== SL_Screen
[j
].old_hash
) break;
974 if (j
< rmin
) continue;
976 r2
= i
; /* end scroll region */
981 while ((j
>= rmin
) && (SL_Screen
[j
].old_hash
== SL_Screen
[j
+ di
].new_hash
))
983 if (SL_Screen
[j
].old_hash
== Blank_Hash
) ignore
++;
988 /* If this scroll only scrolls this line into place, don't do it.
990 if ((di
> 1) && (r1
+ di
+ ignore
== r2
)) continue;
992 /* If there is anything in the scrolling region that is ok, abort the
996 for (j
= r1
; j
<= r2
; j
++)
998 if ((SL_Screen
[j
].old_hash
!= Blank_Hash
)
999 && (SL_Screen
[j
].old_hash
== SL_Screen
[j
].new_hash
))
1001 /* See if the scroll is happens to scroll this one into place. */
1002 if ((j
+ di
> r2
) || (SL_Screen
[j
].old_hash
!= SL_Screen
[j
+ di
].new_hash
))
1006 if (j
<= r2
) continue;
1008 color
= This_Color
; This_Color
= 0;
1010 (*tt_normal_video
) ();
1011 (*tt_set_scroll_region
) (r1
, r2
);
1012 (*tt_goto_rc
) (0, 0);
1013 (*tt_reverse_index
) (di
);
1014 (*tt_reset_scroll_region
) ();
1015 /* Now we have a hole in the screen.
1016 * Make the virtual screen look like it.
1018 * Note that if the terminal does not support BCE, then we have
1019 * no idea what color the hole is. So, for this case, we do not
1020 * want to add Bce_Color_Offset to This_Color since if Bce_Color_Offset
1021 * is non-zero, then This_Color = 0 does not match any valid color
1022 * obtained by adding Bce_Color_Offset.
1024 for (j
= r1
; j
<= r2
; j
++) SL_Screen
[j
].flags
= TOUCHED
;
1028 tmp
= SL_Screen
[r2
].old
;
1029 for (j
= r2
; j
> r1
; j
--)
1031 SL_Screen
[j
].old
= SL_Screen
[j
- 1].old
;
1032 SL_Screen
[j
].old_hash
= SL_Screen
[j
- 1].old_hash
;
1034 SL_Screen
[r1
].old
= tmp
;
1035 blank_line (SL_Screen
[r1
].old
, Screen_Cols
, 0x20);
1036 SL_Screen
[r1
].old_hash
= Blank_Hash
;
1045 static int try_scroll_up (int rmin
, int rmax
)
1047 int i
, r1
, r2
, di
, j
;
1050 SLsmg_Color_Type color
;
1051 SLsmg_Char_Type
*tmp
;
1055 for (i
= rmin
; i
< rmax
; i
++)
1057 hash
= SL_Screen
[i
].new_hash
;
1058 if (hash
== Blank_Hash
) continue;
1059 if (hash
== SL_Screen
[i
].old_hash
)
1061 /* find a match further down screen */
1062 for (j
= i
+ 1; j
<= rmax
; j
++)
1064 if (hash
== SL_Screen
[j
].old_hash
) break;
1066 if (j
> rmax
) continue;
1068 r1
= i
; /* beg scroll region */
1069 di
= j
- i
; /* number of lines to scroll */
1070 j
++; /* since we know this is a match */
1072 /* find end of scroll region */
1074 while ((j
<= rmax
) && (SL_Screen
[j
].old_hash
== SL_Screen
[j
- di
].new_hash
))
1076 if (SL_Screen
[j
].old_hash
== Blank_Hash
) ignore
++;
1079 r2
= j
- 1; /* end of scroll region */
1081 /* If this scroll only scrolls this line into place, don't do it.
1083 if ((di
> 1) && (r1
+ di
+ ignore
== r2
)) continue;
1085 /* If there is anything in the scrolling region that is ok, abort the
1089 for (j
= r1
; j
<= r2
; j
++)
1091 if ((SL_Screen
[j
].old_hash
!= Blank_Hash
)
1092 && (SL_Screen
[j
].old_hash
== SL_Screen
[j
].new_hash
))
1094 if ((j
- di
< r1
) || (SL_Screen
[j
].old_hash
!= SL_Screen
[j
- di
].new_hash
))
1099 if (j
<= r2
) continue;
1103 /* See the above comments about BCE */
1104 color
= This_Color
; This_Color
= 0;
1105 (*tt_normal_video
) ();
1106 (*tt_set_scroll_region
) (r1
, r2
);
1107 (*tt_goto_rc
) (0, 0); /* relative to scroll region */
1108 (*tt_delete_nlines
) (di
);
1109 (*tt_reset_scroll_region
) ();
1110 /* Now we have a hole in the screen. Make the virtual screen look
1113 for (j
= r1
; j
<= r2
; j
++) SL_Screen
[j
].flags
= TOUCHED
;
1117 tmp
= SL_Screen
[r1
].old
;
1118 for (j
= r1
; j
< r2
; j
++)
1120 SL_Screen
[j
].old
= SL_Screen
[j
+ 1].old
;
1121 SL_Screen
[j
].old_hash
= SL_Screen
[j
+ 1].old_hash
;
1123 SL_Screen
[r2
].old
= tmp
;
1124 blank_line (SL_Screen
[r2
].old
, Screen_Cols
, ' ');
1125 SL_Screen
[r2
].old_hash
= Blank_Hash
;
1133 static void try_scroll (void)
1136 int num_up
, num_down
;
1137 /* find region limits. */
1139 for (rmax
= Screen_Rows
- 1; rmax
> 0; rmax
--)
1141 if (SL_Screen
[rmax
].new_hash
!= SL_Screen
[rmax
].old_hash
)
1145 || (SL_Screen
[r1
].new_hash
!= SL_Screen
[r1
].old_hash
))
1152 for (rmin
= 0; rmin
< rmax
; rmin
++)
1154 if (SL_Screen
[rmin
].new_hash
!= SL_Screen
[rmin
].old_hash
)
1158 || (SL_Screen
[r1
].new_hash
!= SL_Screen
[r1
].old_hash
))
1165 /* Below, we have two scrolling algorithms. The first has the effect of
1166 * scrolling lines down. This is usually appropriate when one moves
1167 * up the display, e.g., with the UP arrow. The second algorithm is
1168 * appropriate for going the other way. It is important to choose the
1173 for (r1
= rmin
; r1
< rmax
; r1
++)
1175 if (SL_Screen
[r1
].new_hash
== SL_Screen
[r1
+ 1].old_hash
)
1180 for (r1
= rmax
; r1
> rmin
; r1
--)
1182 if (SL_Screen
[r1
- 1].old_hash
== SL_Screen
[r1
].new_hash
)
1186 if (num_up
> num_down
)
1188 if (try_scroll_up (rmin
, rmax
))
1191 (void) try_scroll_down (rmin
, rmax
);
1195 if (try_scroll_down (rmin
, rmax
))
1198 (void) try_scroll_up (rmin
, rmax
);
1201 #endif /* NOT IBMPC_SYSTEM */
1203 #ifdef REQUIRES_NON_BCE_SUPPORT
1204 static void adjust_colors (void)
1209 bce
= Bce_Color_Offset
;
1210 Bce_Color_Offset
= _pSLtt_get_bce_color_offset ();
1211 if (bce
== Bce_Color_Offset
)
1214 for (i
= 0; i
< Screen_Rows
; i
++)
1216 SLsmg_Char_Type
*s
, *smax
;
1218 SL_Screen
[i
].flags
|= TRASHED
;
1219 s
= SL_Screen
[i
].neew
;
1220 smax
= s
+ Screen_Cols
;
1224 SLsmg_Color_Type color
= s
->color
;
1225 int acs
= color
& SLSMG_ACS_MASK
;
1226 color
= (color
& SLSMG_COLOR_MASK
) + (Bce_Color_Offset
- bce
);
1227 if (color
< SLSMG_MAX_COLORS
)
1228 s
->color
= color
| acs
;
1236 void SLsmg_refresh (void)
1239 #ifndef IBMPC_SYSTEM
1244 if (Smg_Inited
== 0) return;
1249 for (i
= 0; i
< Screen_Rows
; i
++)
1250 SL_Screen
[i
].flags
|= TRASHED
;
1251 #ifdef REQUIRES_NON_BCE_SUPPORT
1256 #ifndef IBMPC_SYSTEM
1257 for (i
= 0; i
< Screen_Rows
; i
++)
1259 if (SL_Screen
[i
].flags
== 0) continue;
1260 SL_Screen
[i
].new_hash
= compute_hash (SL_Screen
[i
].neew
, Screen_Cols
);
1267 (*tt_normal_video
) (); (*tt_cls
) ();
1269 #ifndef IBMPC_SYSTEM
1270 else if (trashed
&& (*tt_Term_Cannot_Scroll
== 0)) try_scroll ();
1273 for (i
= 0; i
< Screen_Rows
; i
++)
1275 if (SL_Screen
[i
].flags
== 0) continue;
1277 if (Cls_Flag
|| SL_Screen
[i
].flags
& TRASHED
)
1279 SLsmg_Color_Type color
= This_Color
;
1283 (*tt_goto_rc
) (i
, 0);
1287 blank_line (SL_Screen
[i
].old
, Screen_Cols
, 0x20);
1291 (*tt_smart_puts
) (SL_Screen
[i
].neew
, SL_Screen
[i
].old
, Screen_Cols
, i
);
1293 memcpy ((char *) SL_Screen
[i
].old
, (char *) SL_Screen
[i
].neew
,
1294 Screen_Cols
* sizeof (SLsmg_Char_Type
));
1296 SL_Screen
[i
].flags
= 0;
1297 #ifndef IBMPC_SYSTEM
1298 SL_Screen
[i
].old_hash
= SL_Screen
[i
].new_hash
;
1303 r
= This_Row
- Start_Row
;
1304 c
= This_Col
- Start_Col
;
1310 else if (r
>= (int)Screen_Rows
)
1312 r
= (int)Screen_Rows
;
1313 c
= (int)Screen_Cols
-1;
1317 else if (c
>= (int)Screen_Cols
)
1318 c
= (int)Screen_Cols
-1;
1320 (*tt_goto_rc
) (r
,c
);
1321 (void) (*tt_flush_output
) ();
1326 static int compute_clip (int row
, int n
, int box_start
, int box_end
,
1327 int *rmin
, int *rmax
)
1331 if (n
< 0) return 0;
1332 if (row
>= box_end
) return 0;
1334 if (row_max
<= box_start
) return 0;
1336 if (row
< box_start
) row
= box_start
;
1337 if (row_max
>= box_end
) row_max
= box_end
;
1343 void SLsmg_touch_lines (int row
, unsigned int n
)
1348 /* Allow this function to be called even when we are not initialied.
1349 * Calling this function is useful after calling SLtt_set_color
1350 * to force the display to be redrawn
1353 if (Smg_Inited
== 0)
1356 if (0 == compute_clip (row
, (int) n
, Start_Row
, Start_Row
+ Screen_Rows
, &r1
, &r2
))
1361 for (i
= r1
; i
< r2
; i
++)
1363 SL_Screen
[i
].flags
|= TRASHED
;
1367 void SLsmg_touch_screen (void)
1372 #ifndef IBMPC_SYSTEM
1373 # define BLOCK_SIGNALS SLsig_block_signals ()
1374 # define UNBLOCK_SIGNALS SLsig_unblock_signals ()
1376 # define BLOCK_SIGNALS (void)0
1377 # define UNBLOCK_SIGNALS (void)0
1380 static int Smg_Suspended
;
1381 int SLsmg_suspend_smg (void)
1385 if (Smg_Suspended
== 0)
1387 (*tt_reset_video
) ();
1395 int SLsmg_resume_smg (void)
1399 if (Smg_Suspended
== 0)
1407 if (-1 == (*tt_init_video
) ())
1414 SLsmg_touch_screen ();
1422 static void reset_smg (void)
1425 if (Smg_Inited
== 0)
1428 for (i
= 0; i
< Screen_Rows
; i
++)
1430 SLfree ((char *)SL_Screen
[i
].old
);
1431 SLfree ((char *)SL_Screen
[i
].neew
);
1432 SL_Screen
[i
].old
= SL_Screen
[i
].neew
= NULL
;
1434 This_Alt_Char
= This_Color
= 0;
1439 static int init_smg (void)
1441 unsigned int i
, len
;
1442 SLsmg_Char_Type
*old
, *neew
;
1446 #ifdef REQUIRES_NON_BCE_SUPPORT
1447 Bce_Color_Offset
= _pSLtt_get_bce_color_offset ();
1450 Screen_Rows
= *tt_Screen_Rows
;
1451 if (Screen_Rows
> SLTT_MAX_SCREEN_ROWS
)
1452 Screen_Rows
= SLTT_MAX_SCREEN_ROWS
;
1454 Screen_Cols
= *tt_Screen_Cols
;
1456 This_Col
= This_Row
= Start_Col
= Start_Row
= 0;
1459 SLsmg_set_color (0);
1462 init_acs (ACS_MODE_AUTO
);
1464 len
= Screen_Cols
+ 3;
1465 for (i
= 0; i
< Screen_Rows
; i
++)
1467 if ((NULL
== (old
= (SLsmg_Char_Type
*) SLmalloc (sizeof(SLsmg_Char_Type
) * len
)))
1468 || ((NULL
== (neew
= (SLsmg_Char_Type
*) SLmalloc (sizeof(SLsmg_Char_Type
) * len
)))))
1470 SLfree ((char *) old
);
1473 blank_line (old
, len
, ' ');
1474 blank_line (neew
, len
, ' ');
1475 SL_Screen
[i
].old
= old
;
1476 SL_Screen
[i
].neew
= neew
;
1477 SL_Screen
[i
].flags
= 0;
1478 #ifndef IBMPC_SYSTEM
1479 Blank_Hash
= compute_hash (old
, Screen_Cols
);
1480 SL_Screen
[i
].new_hash
= SL_Screen
[i
].old_hash
= Blank_Hash
;
1484 _pSLtt_color_changed_hook
= SLsmg_touch_screen
;
1491 int SLsmg_init_smg (void)
1497 if (tt_Screen_Rows
== NULL
)
1503 if (UTF8_Mode
== -1)
1504 UTF8_Mode
= _pSLutf8_mode
;
1506 if (-1 == (*tt_init_video
) ())
1512 if (-1 == (ret
= init_smg ()))
1513 (void) (*tt_reset_video
)();
1519 int SLsmg_reinit_smg (void)
1523 if (Smg_Inited
== 0)
1524 return SLsmg_init_smg ();
1533 void SLsmg_reset_smg (void)
1535 if (Smg_Inited
== 0)
1541 (*tt_reset_video
)();
1546 void SLsmg_vprintf (char *fmt
, va_list ap
)
1550 if (Smg_Inited
== 0) return;
1552 (void) SLvsnprintf (buf
, sizeof (buf
), fmt
, ap
);
1553 SLsmg_write_string (buf
);
1556 void SLsmg_printf (char *fmt
, ...)
1561 if (Smg_Inited
== 0) return;
1566 while (*f
&& (*f
!= '%'))
1569 SLsmg_write_chars ((SLuchar_Type
*)fmt
, (SLuchar_Type
*)f
);
1572 SLsmg_vprintf (f
, ap
);
1577 void SLsmg_set_screen_start (int *r
, int *c
)
1579 int orow
= Start_Row
, oc
= Start_Col
;
1581 if (Smg_Inited
== 0) return;
1583 if (c
== NULL
) Start_Col
= 0;
1589 if (r
== NULL
) Start_Row
= 0;
1597 void SLsmg_draw_object (int r
, int c
, SLwchar_Type object
)
1599 This_Row
= r
; This_Col
= c
;
1601 if (Smg_Inited
== 0) return;
1603 if (point_visible (1))
1605 int color
= This_Color
;
1606 This_Color
|= SLSMG_ACS_MASK
;
1607 SLsmg_write_char (object
);
1614 void SLsmg_draw_hline (unsigned int n
)
1616 static unsigned char hbuf
[16];
1618 int final_col
= This_Col
+ (int) n
;
1621 if (Smg_Inited
== 0) return;
1623 if ((This_Row
< Start_Row
) || (This_Row
>= Start_Row
+ (int)Screen_Rows
)
1624 || (0 == compute_clip (This_Col
, n
, Start_Col
, Start_Col
+ (int)Screen_Cols
,
1627 This_Col
= final_col
;
1631 n
= (unsigned int)(cmax
- cmin
);
1633 save_color
= This_Color
;
1634 This_Color
|= SLSMG_ACS_MASK
;
1640 SLMEMSET ((char *) hbuf
, SLSMG_HLINE_CHAR
, 16);
1646 SLsmg_write_char (SLSMG_HLINE_CHAR
);
1649 This_Color
= save_color
;
1650 This_Col
= final_col
;
1653 void SLsmg_draw_vline (int n
)
1655 int c
= This_Col
, rmin
, rmax
;
1656 int final_row
= This_Row
+ n
;
1659 if (Smg_Inited
== 0) return;
1661 if (((c
< Start_Col
) || (c
>= Start_Col
+ (int)Screen_Cols
))
1662 || (0 == compute_clip (This_Row
, n
, Start_Row
,
1663 Start_Row
+ (int)Screen_Rows
,
1666 This_Row
= final_row
;
1670 save_color
= This_Color
;
1671 This_Color
|= SLSMG_ACS_MASK
;
1673 for (This_Row
= rmin
; This_Row
< rmax
; This_Row
++)
1676 SLsmg_write_char (SLSMG_VLINE_CHAR
);
1679 This_Col
= c
; This_Row
= final_row
;
1680 This_Color
= save_color
;
1683 void SLsmg_draw_box (int r
, int c
, unsigned int dr
, unsigned int dc
)
1685 if (Smg_Inited
== 0) return;
1687 if (!dr
|| !dc
) return;
1688 This_Row
= r
; This_Col
= c
;
1690 SLsmg_draw_hline (dc
);
1691 SLsmg_draw_vline (dr
);
1692 This_Row
= r
; This_Col
= c
;
1693 SLsmg_draw_vline (dr
);
1694 SLsmg_draw_hline (dc
);
1695 SLsmg_draw_object (r
, c
, SLSMG_ULCORN_CHAR
);
1696 SLsmg_draw_object (r
, c
+ (int) dc
, SLSMG_URCORN_CHAR
);
1697 SLsmg_draw_object (r
+ (int) dr
, c
, SLSMG_LLCORN_CHAR
);
1698 SLsmg_draw_object (r
+ (int) dr
, c
+ (int) dc
, SLSMG_LRCORN_CHAR
);
1699 This_Row
= r
; This_Col
= c
;
1702 void SLsmg_fill_region (int r
, int c
, unsigned int dr
, unsigned int dc
, SLwchar_Type wch
)
1704 static unsigned char buf
[16];
1705 unsigned char ubuf
[16*SLUTF8_MAX_MBLEN
];
1706 unsigned char *b
, *bmax
;
1709 unsigned int wchlen
;
1711 if (Smg_Inited
== 0) return;
1713 SLsmg_gotorc (r
, c
);
1714 r
= This_Row
; c
= This_Col
;
1716 dcmax
= Screen_Cols
- This_Col
;
1720 if (dc
> (unsigned int) dcmax
) dc
= (unsigned int) dcmax
;
1722 rmax
= This_Row
+ (int)dr
;
1723 if (rmax
> (int)Screen_Rows
) rmax
= (int)Screen_Rows
;
1726 || (UTF8_Mode
== 0))
1728 if (buf
[0] != (unsigned char) wch
)
1729 memset ((char *) buf
, (unsigned char) wch
, sizeof(buf
));
1731 bmax
= buf
+ sizeof (buf
);
1739 bmax
= SLutf8_encode (wch
, b
, SLUTF8_MAX_MBLEN
);
1745 wchlen
= (unsigned int) (bmax
- b
);
1746 for (i
= 1; i
< 16; i
++)
1748 memcpy (bmax
, b
, wchlen
);
1753 for (This_Row
= r
; This_Row
< rmax
; This_Row
++)
1757 SLsmg_write_chars (b
, b
+ wchlen
* (dc
% 16));
1760 SLsmg_write_chars (b
, bmax
);
1767 void SLsmg_forward (int n
)
1773 SLsmg_set_color_in_region (int color
, int r
, int c
, unsigned int dr
, unsigned int dc
)
1777 if (Smg_Inited
== 0) return;
1782 cmax
= c
+ (int) dc
;
1783 rmax
= r
+ (int) dr
;
1785 if (cmax
> (int)Screen_Cols
) cmax
= (int)Screen_Cols
;
1786 if (rmax
> (int)Screen_Rows
) rmax
= (int)Screen_Rows
;
1791 #ifdef REQUIRES_NON_BCE_SUPPORT
1792 if (Bce_Color_Offset
)
1793 color
+= Bce_Color_Offset
;
1798 SLsmg_Char_Type
*cell
, *cell_max
;
1800 SL_Screen
[r
].flags
|= TOUCHED
;
1801 cell
= SL_Screen
[r
].neew
;
1802 cell_max
= cell
+ cmax
;
1805 while (cell
< cell_max
)
1807 int acs
= cell
->color
& SLSMG_ACS_MASK
;
1808 cell
->color
= color
| acs
;
1815 void SLsmg_set_terminal_info (SLsmg_Term_Type
*tt
)
1817 if (tt
== NULL
) /* use default */
1820 if ((tt
->tt_normal_video
== NULL
)
1821 || (tt
->tt_goto_rc
== NULL
)
1822 || (tt
->tt_cls
== NULL
)
1823 || (tt
->tt_del_eol
== NULL
)
1824 || (tt
->tt_smart_puts
== NULL
)
1825 || (tt
->tt_flush_output
== NULL
)
1826 || (tt
->tt_reset_video
== NULL
)
1827 || (tt
->tt_init_video
== NULL
)
1828 #ifndef IBMPC_SYSTEM
1829 || (tt
->tt_set_scroll_region
== NULL
)
1830 || (tt
->tt_reverse_index
== NULL
)
1831 || (tt
->tt_reset_scroll_region
== NULL
)
1832 || (tt
->tt_delete_nlines
== NULL
)
1834 || (tt
->tt_term_cannot_scroll
== NULL
)
1835 || (tt
->tt_has_alt_charset
== NULL
)
1836 #if 0 /* These can be NULL */
1837 || (tt
->tt_use_blink_for_acs
== NULL
)
1838 || (tt
->tt_graphic_char_pairs
== NULL
)
1840 || (tt
->tt_screen_cols
== NULL
)
1841 || (tt
->tt_screen_rows
== NULL
)
1844 SLang_exit_error ("The Terminal not powerful enough for S-Lang's SLsmg interface");
1846 tt_normal_video
= tt
->tt_normal_video
;
1847 tt_goto_rc
= tt
->tt_goto_rc
;
1848 tt_cls
= tt
->tt_cls
;
1849 tt_del_eol
= tt
->tt_del_eol
;
1850 tt_smart_puts
= tt
->tt_smart_puts
;
1851 tt_flush_output
= tt
->tt_flush_output
;
1852 tt_reset_video
= tt
->tt_reset_video
;
1853 tt_init_video
= tt
->tt_init_video
;
1855 #ifndef IBMPC_SYSTEM
1856 tt_set_scroll_region
= tt
->tt_set_scroll_region
;
1857 tt_reverse_index
= tt
->tt_reverse_index
;
1858 tt_reset_scroll_region
= tt
->tt_reset_scroll_region
;
1859 tt_delete_nlines
= tt
->tt_delete_nlines
;
1861 tt_Term_Cannot_Scroll
= tt
->tt_term_cannot_scroll
;
1864 tt_Has_Alt_Charset
= tt
->tt_has_alt_charset
;
1865 tt_Screen_Cols
= tt
->tt_screen_cols
;
1866 tt_Screen_Rows
= tt
->tt_screen_rows
;
1867 tt_unicode_ok
= tt
->unicode_ok
;
1870 /* The following routines are partially supported. */
1871 void SLsmg_write_color_chars (SLsmg_Char_Type
*s
, unsigned int len
)
1874 SLsmg_write_raw (s
, len
);
1876 SLsmg_Char_Type
*smax
, sh
;
1877 char buf
[32], *b
, *bmax
;
1878 int color
, save_color
;
1880 if (Smg_Inited
== 0) return;
1884 bmax
= b
+ sizeof (buf
);
1886 save_color
= This_Color
;
1892 color
= SLSMG_EXTRACT_COLOR(sh
);
1894 #ifdef REQUIRES_NON_BCE_SUPPORT
1895 if (Bce_Color_Offset
)
1898 color
= ((color
& 0x7F) + Bce_Color_Offset
) | 0x80;
1900 color
= ((color
& 0x7F) + Bce_Color_Offset
) & 0x7F;
1904 if ((color
!= This_Color
) || (b
== bmax
))
1908 SLsmg_write_nchars (buf
, (int) (b
- buf
));
1913 *b
++ = (char) SLSMG_EXTRACT_CHAR(sh
);
1917 SLsmg_write_nchars (buf
, (unsigned int) (b
- buf
));
1919 This_Color
= save_color
;
1923 unsigned int SLsmg_strwidth (SLuchar_Type
*u
, SLuchar_Type
*umax
)
1925 unsigned char display_8bit
;
1926 int utf8_mode
= UTF8_Mode
;
1932 display_8bit
= (unsigned char) SLsmg_Display_Eight_Bit
;
1934 display_8bit
= 0xA0;
1941 unsigned int nconsumed
;
1949 if ((ch
>= 0x20) && (ch
!= 0x7F))
1955 if ((ch
== '\t') && (SLsmg_Tab_Width
> 0))
1958 col
= (1 + col
/SLsmg_Tab_Width
) * SLsmg_Tab_Width
;
1960 col
= ((col
+ 1)/SLsmg_Tab_Width
) * SLsmg_Tab_Width
;
1966 && (SLsmg_Newline_Behavior
!= SLSMG_NEWLINE_PRINTABLE
))
1969 if ((ch
== 0x8) && SLsmg_Backspace_Moves
)
1974 #if SLSMG_HAS_EMBEDDED_ESCAPE
1975 if ((ch
== 033) && Embedded_Escape_Mode
)
1977 SLsmg_Color_Type color
;
1978 if (0 == parse_embedded_escape (u
, umax
, 0, &u
, &color
))
1987 if ((utf8_mode
== 0)
1988 || (NULL
== SLutf8_decode (u
, umax
, &wc
, &nconsumed
)))
1990 if ((utf8_mode
== 0)
1991 && (display_8bit
&& (*u
>= display_8bit
)))
2000 if (wc
< (SLwchar_Type
)display_8bit
)
2005 col
+= SLwchar_wcwidth (wc
);
2011 return (unsigned int) (col
- This_Col
);
2014 /* If the string u were written at the current positition, this function
2015 * returns the number of bytes necessary to reach the specified width.
2017 unsigned int SLsmg_strbytes (SLuchar_Type
*u
, SLuchar_Type
*umax
, unsigned int width
)
2019 SLuchar_Type
*ustart
;
2020 unsigned char display_8bit
;
2021 int utf8_mode
= UTF8_Mode
;
2027 display_8bit
= (unsigned char) SLsmg_Display_Eight_Bit
;
2029 display_8bit
= 0xA0;
2032 col_max
= col
+ width
;
2039 unsigned int nconsumed
= 1;
2044 if ((ch
>= 0x20) && (ch
!= 0x7F))
2046 else if ((ch
== '\t') && (SLsmg_Tab_Width
> 0))
2049 col
= (1 + col
/SLsmg_Tab_Width
) * SLsmg_Tab_Width
;
2051 col
= ((col
+ 1)/SLsmg_Tab_Width
) * SLsmg_Tab_Width
;
2053 else if ((ch
== '\n')
2054 && (SLsmg_Newline_Behavior
!= SLSMG_NEWLINE_PRINTABLE
))
2056 else if ((ch
== 0x8) && SLsmg_Backspace_Moves
)
2058 #if SLSMG_HAS_EMBEDDED_ESCAPE
2059 else if ((ch
== 033) && Embedded_Escape_Mode
)
2061 SLsmg_Color_Type color
;
2062 SLuchar_Type
*u1
= u
+1;
2063 if (-1 == parse_embedded_escape (u1
, umax
, 0, &u1
, &color
))
2065 nconsumed
= (u1
- u
);
2070 else if ((utf8_mode
== 0)
2071 || (NULL
== SLutf8_decode (u
, umax
, &wc
, &nconsumed
)))
2073 if ((utf8_mode
== 0)
2074 && (display_8bit
&& (*u
>= display_8bit
)))
2077 col
+= 4*nconsumed
; /* <XX> */
2079 else if (wc
< (SLwchar_Type
)display_8bit
)
2081 else col
+= SLwchar_wcwidth (wc
);
2089 return (unsigned int) (u
- ustart
);
2092 unsigned int SLsmg_read_raw (SLsmg_Char_Type
*buf
, unsigned int len
)
2096 if (Smg_Inited
== 0) return 0;
2098 if (0 == point_visible (1)) return 0;
2100 r
= (unsigned int) (This_Row
- Start_Row
);
2101 c
= (unsigned int) (This_Col
- Start_Col
);
2103 if (c
+ len
> (unsigned int) Screen_Cols
)
2104 len
= (unsigned int) Screen_Cols
- c
;
2106 memcpy ((char *) buf
, (char *) (SL_Screen
[r
].neew
+ c
), len
* sizeof (SLsmg_Char_Type
));
2110 unsigned int SLsmg_write_raw (SLsmg_Char_Type
*buf
, unsigned int len
)
2113 SLsmg_Char_Type
*dest
;
2115 if (Smg_Inited
== 0) return 0;
2117 if (0 == point_visible (1)) return 0;
2119 r
= (unsigned int) (This_Row
- Start_Row
);
2120 c
= (unsigned int) (This_Col
- Start_Col
);
2122 if (c
+ len
> (unsigned int) Screen_Cols
)
2123 len
= (unsigned int) Screen_Cols
- c
;
2125 dest
= SL_Screen
[r
].neew
+ c
;
2127 if (0 != memcmp ((char *) dest
, (char *) buf
, len
* sizeof (SLsmg_Char_Type
)))
2129 memcpy ((char *) dest
, (char *) buf
, len
* sizeof (SLsmg_Char_Type
));
2130 SL_Screen
[r
].flags
|= TOUCHED
;
2135 int SLsmg_char_at (SLsmg_Char_Type
*cp
)
2137 if (Smg_Inited
== 0) return -1;
2139 if (point_visible (1))
2141 SLsmg_Char_Type
*c
= &SL_Screen
[This_Row
- Start_Row
].neew
[This_Col
- Start_Col
];
2150 int SLsmg_utf8_enable (int mode
)
2153 mode
= _pSLutf8_mode
;
2155 return UTF8_Mode
= mode
;
2158 int SLsmg_is_utf8_mode (void)
2160 int mode
= UTF8_Mode
;
2162 mode
= _pSLutf8_mode
;