1 /* SLang Screen management routines */
2 /* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis
3 * This file is part of the S-Lang library.
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Perl Artistic License.
14 typedef struct Screen_Type
16 int n
; /* number of chars written last time */
17 int flags
; /* line untouched, etc... */
18 SLsmg_Char_Type
*old
, *neew
;
20 unsigned long old_hash
, new_hash
;
27 static int Screen_Trashed
;
29 Screen_Type SL_Screen
[SLTT_MAX_SCREEN_ROWS
];
30 static int Start_Col
, Start_Row
;
31 static int Screen_Cols
, Screen_Rows
;
32 static int This_Row
, This_Col
;
33 static int This_Color
; /* only the first 8 bits of this
34 * are used. The highest bit is used
35 * to indicate an alternate character
36 * set. This leaves 127 userdefineable
41 #define ALT_CHAR_FLAG 0x80
43 #define ALT_CHAR_FLAG 0x00
46 #if SLTT_HAS_NON_BCE_SUPPORT && !defined(IBMPC_SYSTEM)
47 #define REQUIRES_NON_BCE_SUPPORT 1
48 static int Bce_Color_Offset
;
51 int SLsmg_Newline_Behavior
= 0;
52 int SLsmg_Backspace_Moves
= 0;
53 /* Backward compatibility. Not used. */
54 /* int SLsmg_Newline_Moves; */
56 static void (*tt_normal_video
)(void) = SLtt_normal_video
;
57 static void (*tt_goto_rc
)(int, int) = SLtt_goto_rc
;
58 static void (*tt_cls
) (void) = SLtt_cls
;
59 static void (*tt_del_eol
) (void) = SLtt_del_eol
;
60 static void (*tt_smart_puts
) (SLsmg_Char_Type
*, SLsmg_Char_Type
*, int, int) = SLtt_smart_puts
;
61 static int (*tt_flush_output
) (void) = SLtt_flush_output
;
62 static int (*tt_reset_video
) (void) = SLtt_reset_video
;
63 static int (*tt_init_video
) (void) = SLtt_init_video
;
64 static int *tt_Screen_Rows
= &SLtt_Screen_Rows
;
65 static int *tt_Screen_Cols
= &SLtt_Screen_Cols
;
68 static void (*tt_set_scroll_region
)(int, int) = SLtt_set_scroll_region
;
69 static void (*tt_reverse_index
)(int) = SLtt_reverse_index
;
70 static void (*tt_reset_scroll_region
)(void) = SLtt_reset_scroll_region
;
71 static void (*tt_delete_nlines
)(int) = SLtt_delete_nlines
;
75 static int *tt_Term_Cannot_Scroll
= &SLtt_Term_Cannot_Scroll
;
76 static int *tt_Has_Alt_Charset
= &SLtt_Has_Alt_Charset
;
77 static char **tt_Graphics_Char_Pairs
= &SLtt_Graphics_Char_Pairs
;
78 static int *tt_Use_Blink_For_ACS
= &SLtt_Use_Blink_For_ACS
;
81 static int Smg_Inited
;
83 static void blank_line (SLsmg_Char_Type
*p
, int n
, unsigned char ch
)
85 register SLsmg_Char_Type
*pmax
= p
+ n
;
86 register SLsmg_Char_Type color_ch
;
88 color_ch
= SLSMG_BUILD_CHAR(ch
,This_Color
);
96 static void clear_region (int row
, int n
, unsigned char ch
)
101 if (imax
> Screen_Rows
) imax
= Screen_Rows
;
102 for (i
= row
; i
< imax
; i
++)
106 blank_line (SL_Screen
[i
].neew
, Screen_Cols
, ch
);
107 SL_Screen
[i
].flags
|= TOUCHED
;
112 void SLsmg_erase_eol (void)
116 if (Smg_Inited
== 0) return;
118 c
= This_Col
- Start_Col
;
119 r
= This_Row
- Start_Row
;
121 if ((r
< 0) || (r
>= Screen_Rows
)) return;
122 if (c
< 0) c
= 0; else if (c
>= Screen_Cols
) return;
123 blank_line (SL_Screen
[This_Row
].neew
+ c
, Screen_Cols
- c
, ' ');
124 SL_Screen
[This_Row
].flags
|= TOUCHED
;
127 static void scroll_up (void)
129 unsigned int i
, imax
;
130 SLsmg_Char_Type
*neew
;
132 neew
= SL_Screen
[0].neew
;
133 imax
= Screen_Rows
- 1;
134 for (i
= 0; i
< imax
; i
++)
136 SL_Screen
[i
].neew
= SL_Screen
[i
+ 1].neew
;
137 SL_Screen
[i
].flags
|= TOUCHED
;
139 SL_Screen
[i
].neew
= neew
;
140 SL_Screen
[i
].flags
|= TOUCHED
;
141 blank_line (neew
, Screen_Cols
, ' ');
145 void SLsmg_gotorc (int r
, int c
)
151 int SLsmg_get_row (void)
156 int SLsmg_get_column (void)
161 void SLsmg_erase_eos (void)
163 if (Smg_Inited
== 0) return;
166 clear_region (This_Row
+ 1, Screen_Rows
, ' ');
169 static int This_Alt_Char
;
171 void SLsmg_set_char_set (int i
)
176 if ((tt_Use_Blink_For_ACS
!= NULL
)
177 && (*tt_Use_Blink_For_ACS
!= 0))
178 return;/* alt chars not used and the alt bit
179 * is used to indicate a blink.
182 if (i
) This_Alt_Char
= ALT_CHAR_FLAG
;
183 else This_Alt_Char
= 0;
186 This_Color
|= This_Alt_Char
;
190 void SLsmg_set_color (int color
)
192 if (color
< 0) return;
193 #ifdef REQUIRES_NON_BCE_SUPPORT
194 color
+= Bce_Color_Offset
;
196 This_Color
= color
| This_Alt_Char
;
199 void SLsmg_reverse_video (void)
204 void SLsmg_normal_video (void)
209 static int point_visible (int col_too
)
211 return ((This_Row
>= Start_Row
) && (This_Row
< Start_Row
+ Screen_Rows
)
213 || ((This_Col
>= Start_Col
)
214 && (This_Col
< Start_Col
+ Screen_Cols
))));
217 void SLsmg_write_string (char *str
)
219 SLsmg_write_nchars (str
, strlen (str
));
222 void SLsmg_write_nstring (char *str
, unsigned int n
)
227 /* Avoid a problem if a user accidently passes a negative value */
231 if (str
== NULL
) width
= 0;
234 width
= strlen (str
);
235 if (width
> n
) width
= n
;
236 SLsmg_write_nchars (str
, width
);
238 while (width
++ < n
) SLsmg_write_nchars (&blank
, 1);
241 void SLsmg_write_wrapped_string (char *s
, int r
, int c
,
242 unsigned int dr
, unsigned int dc
,
245 register char ch
, *p
;
248 if ((dr
== 0) || (dc
== 0)) return;
254 if ((ch
== 0) || (ch
== '\n'))
258 diff
= maxc
- (int) dc
;
261 SLsmg_write_nchars (s
, dc
);
262 if (fill
&& (diff
> 0))
264 while (diff
--) SLsmg_write_char (' ');
266 if ((ch
== 0) || (dr
== 1)) break;
273 else if ((int) dc
== maxc
)
276 SLsmg_write_nchars (s
, dc
+ 1);
288 int SLsmg_Tab_Width
= 8;
290 /* Minimum value for which eight bit char is displayed as is. */
293 int SLsmg_Display_Eight_Bit
= 160;
294 static unsigned char Alt_Char_Set
[129];/* 129th is used as a flag */
296 int SLsmg_Display_Eight_Bit
= 128;
299 void SLsmg_write_nchars (char *str
, unsigned int n
)
301 register SLsmg_Char_Type
*p
, old
, neew
, color
;
304 int len
, start_len
, max_len
;
308 int alt_char_set_flag
;
310 alt_char_set_flag
= ((This_Color
& ALT_CHAR_FLAG
)
311 && ((tt_Use_Blink_For_ACS
== NULL
)
312 || (*tt_Use_Blink_For_ACS
== 0)));
315 if (Smg_Inited
== 0) return;
320 top
: /* get here only on newline */
323 start_len
= Start_Col
;
325 if (point_visible (0) == 0) return;
328 max_len
= start_len
+ Screen_Cols
;
330 p
= SL_Screen
[This_Row
- Start_Row
].neew
;
331 if (len
> start_len
) p
+= (len
- start_len
);
333 flags
= SL_Screen
[This_Row
- Start_Row
].flags
;
334 while ((len
< max_len
) && (str
< str_max
))
336 ch
= (unsigned char) *str
++;
339 if (alt_char_set_flag
)
340 ch
= Alt_Char_Set
[ch
& 0x7F];
342 if (((ch
>= ' ') && (ch
< 127))
343 || (ch
>= (unsigned char) SLsmg_Display_Eight_Bit
)
353 neew
= SLSMG_BUILD_CHAR(ch
,color
);
363 else if ((ch
== '\t') && (SLsmg_Tab_Width
> 0))
366 n
+= SLsmg_Tab_Width
;
367 n
= SLsmg_Tab_Width
- (n
% SLsmg_Tab_Width
);
368 if ((unsigned int) len
+ n
> (unsigned int) max_len
)
369 n
= (unsigned int) (max_len
- len
);
370 neew
= SLSMG_BUILD_CHAR(' ',color
);
385 else if ((ch
== '\n')
386 && (SLsmg_Newline_Behavior
!= SLSMG_NEWLINE_PRINTABLE
))
391 else if ((ch
== 0x8) && SLsmg_Backspace_Moves
)
399 neew
= SLSMG_BUILD_CHAR('~',color
);
409 if (len
== max_len
) break;
417 neew
= SLSMG_BUILD_CHAR('^',color
);
424 if (len
== max_len
) break;
427 if (ch
== 127) ch
= '?'; else ch
= ch
+ '@';
431 neew
= SLSMG_BUILD_CHAR(ch
,color
);
442 SL_Screen
[This_Row
- Start_Row
].flags
= flags
;
445 if (SLsmg_Newline_Behavior
== 0)
448 if (newline_flag
== 0)
450 while (str
< str_max
)
452 if (*str
== '\n') break;
455 if (str
== str_max
) return;
461 if (This_Row
== Start_Row
+ Screen_Rows
)
463 if (SLsmg_Newline_Behavior
== SLSMG_NEWLINE_SCROLLS
) scroll_up ();
468 void SLsmg_write_char (char ch
)
470 SLsmg_write_nchars (&ch
, 1);
475 void SLsmg_cls (void)
478 if (Smg_Inited
== 0) return;
480 tac
= This_Alt_Char
; This_Alt_Char
= 0;
482 clear_region (0, Screen_Rows
, ' ');
488 static void do_copy (SLsmg_Char_Type
*a
, SLsmg_Char_Type
*b
)
490 SLsmg_Char_Type
*amax
= a
+ Screen_Cols
;
492 while (a
< amax
) *a
++ = *b
++;
497 int SLsmg_Scroll_Hash_Border
= 0;
498 static unsigned long compute_hash (SLsmg_Char_Type
*s
, int n
)
500 register unsigned long h
= 0, g
;
501 register unsigned long sum
= 0;
502 register SLsmg_Char_Type
*smax
, ch
;
505 s
+= SLsmg_Scroll_Hash_Border
;
506 smax
= s
+ (n
- SLsmg_Scroll_Hash_Border
);
510 if (is_blank
&& (SLSMG_EXTRACT_CHAR(ch
) != 32)) is_blank
--;
515 if ((g
= h
& 0xE0000000UL
) != 0)
521 if (is_blank
) return 0;
525 static unsigned long Blank_Hash
;
527 static int try_scroll_down (int rmin
, int rmax
)
529 int i
, r1
, r2
, di
, j
;
533 SLsmg_Char_Type
*tmp
;
537 for (i
= rmax
; i
> rmin
; i
--)
539 hash
= SL_Screen
[i
].new_hash
;
540 if (hash
== Blank_Hash
) continue;
542 if ((hash
== SL_Screen
[i
].old_hash
)
544 || ((i
+ 1 < Screen_Rows
) && (hash
== SL_Screen
[i
+ 1].old_hash
))
545 || ((i
- 1 > rmin
) && (SL_Screen
[i
].old_hash
== SL_Screen
[i
- 1].new_hash
))
550 for (j
= i
- 1; j
>= rmin
; j
--)
552 if (hash
== SL_Screen
[j
].old_hash
) break;
554 if (j
< rmin
) continue;
556 r2
= i
; /* end scroll region */
561 while ((j
>= rmin
) && (SL_Screen
[j
].old_hash
== SL_Screen
[j
+ di
].new_hash
))
563 if (SL_Screen
[j
].old_hash
== Blank_Hash
) ignore
++;
568 /* If this scroll only scrolls this line into place, don't do it.
570 if ((di
> 1) && (r1
+ di
+ ignore
== r2
)) continue;
572 /* If there is anything in the scrolling region that is ok, abort the
576 for (j
= r1
; j
<= r2
; j
++)
578 if ((SL_Screen
[j
].old_hash
!= Blank_Hash
)
579 && (SL_Screen
[j
].old_hash
== SL_Screen
[j
].new_hash
))
581 /* See if the scroll is happens to scroll this one into place. */
582 if ((j
+ di
> r2
) || (SL_Screen
[j
].old_hash
!= SL_Screen
[j
+ di
].new_hash
))
586 if (j
<= r2
) continue;
588 color
= This_Color
; This_Color
= 0;
590 (*tt_normal_video
) ();
591 (*tt_set_scroll_region
) (r1
, r2
);
592 (*tt_goto_rc
) (0, 0);
593 (*tt_reverse_index
) (di
);
594 (*tt_reset_scroll_region
) ();
595 /* Now we have a hole in the screen.
596 * Make the virtual screen look like it.
598 * Note that if the terminal does not support BCE, then we have
599 * no idea what color the hole is. So, for this case, we do not
600 * want to add Bce_Color_Offset to This_Color since if Bce_Color_Offset
601 * is non-zero, then This_Color = 0 does not match any valid color
602 * obtained by adding Bce_Color_Offset.
604 for (j
= r1
; j
<= r2
; j
++) SL_Screen
[j
].flags
= TOUCHED
;
608 tmp
= SL_Screen
[r2
].old
;
609 for (j
= r2
; j
> r1
; j
--)
611 SL_Screen
[j
].old
= SL_Screen
[j
- 1].old
;
612 SL_Screen
[j
].old_hash
= SL_Screen
[j
- 1].old_hash
;
614 SL_Screen
[r1
].old
= tmp
;
615 blank_line (SL_Screen
[r1
].old
, Screen_Cols
, ' ');
616 SL_Screen
[r1
].old_hash
= Blank_Hash
;
625 static int try_scroll_up (int rmin
, int rmax
)
627 int i
, r1
, r2
, di
, j
;
631 SLsmg_Char_Type
*tmp
;
635 for (i
= rmin
; i
< rmax
; i
++)
637 hash
= SL_Screen
[i
].new_hash
;
638 if (hash
== Blank_Hash
) continue;
639 if (hash
== SL_Screen
[i
].old_hash
)
641 /* find a match further down screen */
642 for (j
= i
+ 1; j
<= rmax
; j
++)
644 if (hash
== SL_Screen
[j
].old_hash
) break;
646 if (j
> rmax
) continue;
648 r1
= i
; /* beg scroll region */
649 di
= j
- i
; /* number of lines to scroll */
650 j
++; /* since we know this is a match */
652 /* find end of scroll region */
654 while ((j
<= rmax
) && (SL_Screen
[j
].old_hash
== SL_Screen
[j
- di
].new_hash
))
656 if (SL_Screen
[j
].old_hash
== Blank_Hash
) ignore
++;
659 r2
= j
- 1; /* end of scroll region */
661 /* If this scroll only scrolls this line into place, don't do it.
663 if ((di
> 1) && (r1
+ di
+ ignore
== r2
)) continue;
665 /* If there is anything in the scrolling region that is ok, abort the
669 for (j
= r1
; j
<= r2
; j
++)
671 if ((SL_Screen
[j
].old_hash
!= Blank_Hash
)
672 && (SL_Screen
[j
].old_hash
== SL_Screen
[j
].new_hash
))
674 if ((j
- di
< r1
) || (SL_Screen
[j
].old_hash
!= SL_Screen
[j
- di
].new_hash
))
679 if (j
<= r2
) continue;
683 /* See the above comments about BCE */
684 color
= This_Color
; This_Color
= 0;
685 (*tt_normal_video
) ();
686 (*tt_set_scroll_region
) (r1
, r2
);
687 (*tt_goto_rc
) (0, 0); /* relative to scroll region */
688 (*tt_delete_nlines
) (di
);
689 (*tt_reset_scroll_region
) ();
690 /* Now we have a hole in the screen. Make the virtual screen look
693 for (j
= r1
; j
<= r2
; j
++) SL_Screen
[j
].flags
= TOUCHED
;
697 tmp
= SL_Screen
[r1
].old
;
698 for (j
= r1
; j
< r2
; j
++)
700 SL_Screen
[j
].old
= SL_Screen
[j
+ 1].old
;
701 SL_Screen
[j
].old_hash
= SL_Screen
[j
+ 1].old_hash
;
703 SL_Screen
[r2
].old
= tmp
;
704 blank_line (SL_Screen
[r2
].old
, Screen_Cols
, ' ');
705 SL_Screen
[r2
].old_hash
= Blank_Hash
;
713 static void try_scroll (void)
716 int num_up
, num_down
;
717 /* find region limits. */
719 for (rmax
= Screen_Rows
- 1; rmax
> 0; rmax
--)
721 if (SL_Screen
[rmax
].new_hash
!= SL_Screen
[rmax
].old_hash
)
725 || (SL_Screen
[r1
].new_hash
!= SL_Screen
[r1
].old_hash
))
732 for (rmin
= 0; rmin
< rmax
; rmin
++)
734 if (SL_Screen
[rmin
].new_hash
!= SL_Screen
[rmin
].old_hash
)
738 || (SL_Screen
[r1
].new_hash
!= SL_Screen
[r1
].old_hash
))
745 /* Below, we have two scrolling algorithms. The first has the effect of
746 * scrolling lines down. This is usually appropriate when one moves
747 * up the display, e.g., with the UP arrow. The second algorithm is
748 * appropriate for going the other way. It is important to choose the
753 for (r1
= rmin
; r1
< rmax
; r1
++)
755 if (SL_Screen
[r1
].new_hash
== SL_Screen
[r1
+ 1].old_hash
)
760 for (r1
= rmax
; r1
> rmin
; r1
--)
762 if (SL_Screen
[r1
- 1].old_hash
== SL_Screen
[r1
].new_hash
)
766 if (num_up
> num_down
)
768 if (try_scroll_up (rmin
, rmax
))
771 (void) try_scroll_down (rmin
, rmax
);
775 if (try_scroll_down (rmin
, rmax
))
778 (void) try_scroll_up (rmin
, rmax
);
781 #endif /* NOT IBMPC_SYSTEM */
784 #ifdef REQUIRES_NON_BCE_SUPPORT
785 static void adjust_colors (void)
790 bce
= Bce_Color_Offset
;
791 Bce_Color_Offset
= _SLtt_get_bce_color_offset ();
792 if (bce
== Bce_Color_Offset
)
795 if ((tt_Use_Blink_For_ACS
!= NULL
)
796 && (*tt_Use_Blink_For_ACS
!= 0))
797 return; /* this mode does not support non-BCE
801 for (i
= 0; i
< Screen_Rows
; i
++)
803 SLsmg_Char_Type
*s
, *smax
;
805 SL_Screen
[i
].flags
|= TRASHED
;
806 s
= SL_Screen
[i
].neew
;
807 smax
= s
+ Screen_Cols
;
811 int color
= (int) SLSMG_EXTRACT_COLOR(*s
);
821 color
= (color
& 0x7F) - bce
;
822 color
+= Bce_Color_Offset
;
825 unsigned char ch
= SLSMG_EXTRACT_CHAR(*s
);
826 *s
= SLSMG_BUILD_CHAR(ch
, ((color
&0x7F)|acs
));
834 void SLsmg_refresh (void)
841 if (Smg_Inited
== 0) return;
846 for (i
= 0; i
< Screen_Rows
; i
++)
847 SL_Screen
[i
].flags
|= TRASHED
;
848 #ifdef REQUIRES_NON_BCE_SUPPORT
854 for (i
= 0; i
< Screen_Rows
; i
++)
856 if (SL_Screen
[i
].flags
== 0) continue;
857 SL_Screen
[i
].new_hash
= compute_hash (SL_Screen
[i
].neew
, Screen_Cols
);
864 (*tt_normal_video
) (); (*tt_cls
) ();
867 else if (trashed
&& (*tt_Term_Cannot_Scroll
== 0)) try_scroll ();
870 for (i
= 0; i
< Screen_Rows
; i
++)
872 if (SL_Screen
[i
].flags
== 0) continue;
874 if (Cls_Flag
|| SL_Screen
[i
].flags
& TRASHED
)
876 int color
= This_Color
;
880 (*tt_goto_rc
) (i
, 0);
884 blank_line (SL_Screen
[i
].old
, Screen_Cols
, ' ');
888 SL_Screen
[i
].old
[Screen_Cols
] = 0;
889 SL_Screen
[i
].neew
[Screen_Cols
] = 0;
891 (*tt_smart_puts
) (SL_Screen
[i
].neew
, SL_Screen
[i
].old
, Screen_Cols
, i
);
893 SLMEMCPY ((char *) SL_Screen
[i
].old
, (char *) SL_Screen
[i
].neew
,
894 Screen_Cols
* sizeof (SLsmg_Char_Type
));
896 SL_Screen
[i
].flags
= 0;
898 SL_Screen
[i
].old_hash
= SL_Screen
[i
].new_hash
;
902 if (point_visible (1)) (*tt_goto_rc
) (This_Row
- Start_Row
, This_Col
- Start_Col
);
903 (*tt_flush_output
) ();
908 static int compute_clip (int row
, int n
, int box_start
, int box_end
,
909 int *rmin
, int *rmax
)
914 if (row
>= box_end
) return 0;
916 if (row_max
<= box_start
) return 0;
918 if (row
< box_start
) row
= box_start
;
919 if (row_max
>= box_end
) row_max
= box_end
;
925 void SLsmg_touch_lines (int row
, unsigned int n
)
930 /* Allow this function to be called even when we are not initialied.
931 * Calling this function is useful after calling SLtt_set_color
932 * to force the display to be redrawn
938 if (0 == compute_clip (row
, (int) n
, Start_Row
, Start_Row
+ Screen_Rows
, &r1
, &r2
))
943 for (i
= r1
; i
< r2
; i
++)
945 SL_Screen
[i
].flags
|= TRASHED
;
949 void SLsmg_touch_screen (void)
956 static const char Fake_Alt_Char_Pairs
[] = "a:j+k+l+m+q-t+u+v+w+x|n+`+f\\g#~o,<+>.v-^h#0#";
958 static void init_alt_char_set (void)
961 unsigned const char *p
, *pmax
;
964 if (Alt_Char_Set
[128] == 128) return;
967 memset ((char *)Alt_Char_Set
, ' ', i
);
970 Alt_Char_Set
[i
] = i
;
975 if (*tt_Has_Alt_Charset
)
977 if (tt_Graphics_Char_Pairs
== NULL
) p
= NULL
;
978 else p
= (unsigned char *) *tt_Graphics_Char_Pairs
;
979 if (p
== NULL
) return;
981 else p
= (unsigned const char *) Fake_Alt_Char_Pairs
;
982 pmax
= p
+ strlen ((const char *) p
);
984 /* Some systems have messed up entries for this */
988 ch
&= 0x7F; /* should be unnecessary */
989 Alt_Char_Set
[ch
] = *p
;
996 # define BLOCK_SIGNALS SLsig_block_signals ()
997 # define UNBLOCK_SIGNALS SLsig_unblock_signals ()
999 # define BLOCK_SIGNALS (void)0
1000 # define UNBLOCK_SIGNALS (void)0
1003 static int Smg_Suspended
;
1004 int SLsmg_suspend_smg (void)
1008 if (Smg_Suspended
== 0)
1010 (*tt_reset_video
) ();
1018 int SLsmg_resume_smg (void)
1022 if (Smg_Suspended
== 0)
1030 if (-1 == (*tt_init_video
) ())
1037 SLsmg_touch_screen ();
1045 static void reset_smg (void)
1048 if (Smg_Inited
== 0)
1051 for (i
= 0; i
< Screen_Rows
; i
++)
1053 SLfree ((char *)SL_Screen
[i
].old
);
1054 SLfree ((char *)SL_Screen
[i
].neew
);
1055 SL_Screen
[i
].old
= SL_Screen
[i
].neew
= NULL
;
1057 This_Alt_Char
= This_Color
= 0;
1062 static int init_smg (void)
1065 SLsmg_Char_Type
*old
, *neew
;
1069 #ifdef REQUIRES_NON_BCE_SUPPORT
1070 Bce_Color_Offset
= _SLtt_get_bce_color_offset ();
1073 Screen_Rows
= *tt_Screen_Rows
;
1074 if (Screen_Rows
> SLTT_MAX_SCREEN_ROWS
)
1075 Screen_Rows
= SLTT_MAX_SCREEN_ROWS
;
1077 Screen_Cols
= *tt_Screen_Cols
;
1079 This_Col
= This_Row
= Start_Col
= Start_Row
= 0;
1082 SLsmg_set_color (0);
1084 #ifndef IBMPC_SYSTEM
1085 init_alt_char_set ();
1087 len
= Screen_Cols
+ 3;
1088 for (i
= 0; i
< Screen_Rows
; i
++)
1090 if ((NULL
== (old
= (SLsmg_Char_Type
*) SLmalloc (sizeof(SLsmg_Char_Type
) * len
)))
1091 || ((NULL
== (neew
= (SLsmg_Char_Type
*) SLmalloc (sizeof(SLsmg_Char_Type
) * len
)))))
1093 SLfree ((char *) old
);
1096 blank_line (old
, len
, ' ');
1097 blank_line (neew
, len
, ' ');
1098 SL_Screen
[i
].old
= old
;
1099 SL_Screen
[i
].neew
= neew
;
1100 SL_Screen
[i
].flags
= 0;
1101 #ifndef IBMPC_SYSTEM
1102 Blank_Hash
= compute_hash (old
, Screen_Cols
);
1103 SL_Screen
[i
].new_hash
= SL_Screen
[i
].old_hash
= Blank_Hash
;
1107 _SLtt_color_changed_hook
= SLsmg_touch_screen
;
1114 int SLsmg_init_smg (void)
1123 if (-1 == (*tt_init_video
) ())
1129 if (-1 == (ret
= init_smg ()))
1130 (void) (*tt_reset_video
)();
1136 int SLsmg_reinit_smg (void)
1140 if (Smg_Inited
== 0)
1141 return SLsmg_init_smg ();
1150 void SLsmg_reset_smg (void)
1152 if (Smg_Inited
== 0)
1158 (*tt_reset_video
)();
1163 SLsmg_Char_Type
SLsmg_char_at (void)
1165 if (Smg_Inited
== 0) return 0;
1167 if (point_visible (1))
1169 return SL_Screen
[This_Row
- Start_Row
].neew
[This_Col
- Start_Col
];
1174 void SLsmg_vprintf (char *fmt
, va_list ap
)
1178 if (Smg_Inited
== 0) return;
1180 (void) _SLvsnprintf (buf
, sizeof (buf
), fmt
, ap
);
1181 SLsmg_write_string (buf
);
1184 void SLsmg_printf (char *fmt
, ...)
1190 if (Smg_Inited
== 0) return;
1195 while (*f
&& (*f
!= '%'))
1197 len
= (unsigned int) (f
- fmt
);
1198 if (len
) SLsmg_write_nchars (fmt
, len
);
1201 SLsmg_vprintf (f
, ap
);
1206 void SLsmg_set_screen_start (int *r
, int *c
)
1208 int orow
= Start_Row
, oc
= Start_Col
;
1210 if (Smg_Inited
== 0) return;
1212 if (c
== NULL
) Start_Col
= 0;
1218 if (r
== NULL
) Start_Row
= 0;
1226 void SLsmg_draw_object (int r
, int c
, unsigned char object
)
1228 This_Row
= r
; This_Col
= c
;
1230 if (Smg_Inited
== 0) return;
1232 if (point_visible (1))
1234 int color
= This_Color
;
1235 This_Color
|= ALT_CHAR_FLAG
;
1236 SLsmg_write_char (object
);
1243 void SLsmg_draw_hline (unsigned int n
)
1245 static unsigned char hbuf
[16];
1248 int final_col
= This_Col
+ (int) n
;
1251 if (Smg_Inited
== 0) return;
1253 if ((This_Row
< Start_Row
) || (This_Row
>= Start_Row
+ Screen_Rows
)
1254 || (0 == compute_clip (This_Col
, n
, Start_Col
, Start_Col
+ Screen_Cols
,
1257 This_Col
= final_col
;
1263 SLMEMSET ((char *) hbuf
, SLSMG_HLINE_CHAR
, 16);
1266 n
= (unsigned int)(cmax
- cmin
);
1269 save_color
= This_Color
;
1270 This_Color
|= ALT_CHAR_FLAG
;
1273 SLsmg_write_nchars ((char *) hbuf
, n
% 16);
1276 SLsmg_write_nchars ((char *) hbuf
, 16);
1279 This_Color
= save_color
;
1280 This_Col
= final_col
;
1283 void SLsmg_draw_vline (int n
)
1285 unsigned char ch
= SLSMG_VLINE_CHAR
;
1286 int c
= This_Col
, rmin
, rmax
;
1287 int final_row
= This_Row
+ n
;
1290 if (Smg_Inited
== 0) return;
1292 if (((c
< Start_Col
) || (c
>= Start_Col
+ Screen_Cols
)) ||
1293 (0 == compute_clip (This_Row
, n
, Start_Row
, Start_Row
+ Screen_Rows
,
1296 This_Row
= final_row
;
1300 save_color
= This_Color
;
1301 This_Color
|= ALT_CHAR_FLAG
;
1303 for (This_Row
= rmin
; This_Row
< rmax
; This_Row
++)
1306 SLsmg_write_nchars ((char *) &ch
, 1);
1309 This_Col
= c
; This_Row
= final_row
;
1310 This_Color
= save_color
;
1313 void SLsmg_draw_box (int r
, int c
, unsigned int dr
, unsigned int dc
)
1315 if (Smg_Inited
== 0) return;
1317 if (!dr
|| !dc
) return;
1318 This_Row
= r
; This_Col
= c
;
1320 SLsmg_draw_hline (dc
);
1321 SLsmg_draw_vline (dr
);
1322 This_Row
= r
; This_Col
= c
;
1323 SLsmg_draw_vline (dr
);
1324 SLsmg_draw_hline (dc
);
1325 SLsmg_draw_object (r
, c
, SLSMG_ULCORN_CHAR
);
1326 SLsmg_draw_object (r
, c
+ (int) dc
, SLSMG_URCORN_CHAR
);
1327 SLsmg_draw_object (r
+ (int) dr
, c
, SLSMG_LLCORN_CHAR
);
1328 SLsmg_draw_object (r
+ (int) dr
, c
+ (int) dc
, SLSMG_LRCORN_CHAR
);
1329 This_Row
= r
; This_Col
= c
;
1332 void SLsmg_fill_region (int r
, int c
, unsigned int dr
, unsigned int dc
, unsigned char ch
)
1334 static unsigned char hbuf
[16];
1338 if (Smg_Inited
== 0) return;
1340 SLsmg_gotorc (r
, c
);
1341 r
= This_Row
; c
= This_Col
;
1343 dcmax
= Screen_Cols
- This_Col
;
1347 if (dc
> (unsigned int) dcmax
) dc
= (unsigned int) dcmax
;
1349 rmax
= This_Row
+ dr
;
1350 if (rmax
> Screen_Rows
) rmax
= Screen_Rows
;
1353 ch
= Alt_Char_Set
[ch
];
1355 if (ch
!= hbuf
[0]) SLMEMSET ((char *) hbuf
, (char) ch
, 16);
1357 for (This_Row
= r
; This_Row
< rmax
; This_Row
++)
1361 SLsmg_write_nchars ((char *) hbuf
, dc
% 16);
1364 SLsmg_write_nchars ((char *) hbuf
, 16);
1371 void SLsmg_forward (int n
)
1376 void SLsmg_write_color_chars (SLsmg_Char_Type
*s
, unsigned int len
)
1378 SLsmg_Char_Type
*smax
, sh
;
1379 char buf
[32], *b
, *bmax
;
1380 int color
, save_color
;
1382 if (Smg_Inited
== 0) return;
1386 bmax
= b
+ sizeof (buf
);
1388 save_color
= This_Color
;
1394 color
= SLSMG_EXTRACT_COLOR(sh
);
1396 #if REQUIRES_NON_BCE_SUPPORT
1397 if (Bce_Color_Offset
)
1400 color
= ((color
& 0x7F) + Bce_Color_Offset
) | 0x80;
1402 color
= ((color
& 0x7F) + Bce_Color_Offset
) & 0x7F;
1406 if ((color
!= This_Color
) || (b
== bmax
))
1410 SLsmg_write_nchars (buf
, (int) (b
- buf
));
1415 *b
++ = (char) SLSMG_EXTRACT_CHAR(sh
);
1419 SLsmg_write_nchars (buf
, (unsigned int) (b
- buf
));
1421 This_Color
= save_color
;
1424 unsigned int SLsmg_read_raw (SLsmg_Char_Type
*buf
, unsigned int len
)
1428 if (Smg_Inited
== 0) return 0;
1430 if (0 == point_visible (1)) return 0;
1432 r
= (unsigned int) (This_Row
- Start_Row
);
1433 c
= (unsigned int) (This_Col
- Start_Col
);
1435 if (c
+ len
> (unsigned int) Screen_Cols
)
1436 len
= (unsigned int) Screen_Cols
- c
;
1438 memcpy ((char *) buf
, (char *) (SL_Screen
[r
].neew
+ c
), len
* sizeof (SLsmg_Char_Type
));
1442 unsigned int SLsmg_write_raw (SLsmg_Char_Type
*buf
, unsigned int len
)
1445 SLsmg_Char_Type
*dest
;
1447 if (Smg_Inited
== 0) return 0;
1449 if (0 == point_visible (1)) return 0;
1451 r
= (unsigned int) (This_Row
- Start_Row
);
1452 c
= (unsigned int) (This_Col
- Start_Col
);
1454 if (c
+ len
> (unsigned int) Screen_Cols
)
1455 len
= (unsigned int) Screen_Cols
- c
;
1457 dest
= SL_Screen
[r
].neew
+ c
;
1459 if (0 != memcmp ((char *) dest
, (char *) buf
, len
* sizeof (SLsmg_Char_Type
)))
1461 memcpy ((char *) dest
, (char *) buf
, len
* sizeof (SLsmg_Char_Type
));
1462 SL_Screen
[r
].flags
|= TOUCHED
;
1468 SLsmg_set_color_in_region (int color
, int r
, int c
, unsigned int dr
, unsigned int dc
)
1471 SLsmg_Char_Type char_mask
;
1473 if (Smg_Inited
== 0) return;
1478 cmax
= c
+ (int) dc
;
1479 rmax
= r
+ (int) dr
;
1481 if (cmax
> Screen_Cols
) cmax
= Screen_Cols
;
1482 if (rmax
> Screen_Rows
) rmax
= Screen_Rows
;
1487 #if REQUIRES_NON_BCE_SUPPORT
1488 if (Bce_Color_Offset
)
1491 color
= ((color
& 0x7F) + Bce_Color_Offset
) | 0x80;
1493 color
= ((color
& 0x7F) + Bce_Color_Offset
) & 0x7F;
1500 #ifndef IBMPC_SYSTEM
1501 if ((tt_Use_Blink_For_ACS
== NULL
)
1502 || (0 == *tt_Use_Blink_For_ACS
))
1508 SLsmg_Char_Type
*s
, *smax
;
1510 SL_Screen
[r
].flags
|= TOUCHED
;
1511 s
= SL_Screen
[r
].neew
;
1517 *s
= (*s
& char_mask
) | color
;
1524 void SLsmg_set_terminal_info (SLsmg_Term_Type
*tt
)
1526 if (tt
== NULL
) /* use default */
1529 if ((tt
->tt_normal_video
== NULL
)
1530 || (tt
->tt_goto_rc
== NULL
)
1531 || (tt
->tt_cls
== NULL
)
1532 || (tt
->tt_del_eol
== NULL
)
1533 || (tt
->tt_smart_puts
== NULL
)
1534 || (tt
->tt_flush_output
== NULL
)
1535 || (tt
->tt_reset_video
== NULL
)
1536 || (tt
->tt_init_video
== NULL
)
1537 #ifndef IBMPC_SYSTEM
1538 || (tt
->tt_set_scroll_region
== NULL
)
1539 || (tt
->tt_reverse_index
== NULL
)
1540 || (tt
->tt_reset_scroll_region
== NULL
)
1541 || (tt
->tt_delete_nlines
== NULL
)
1543 || (tt
->tt_term_cannot_scroll
== NULL
)
1544 || (tt
->tt_has_alt_charset
== NULL
)
1545 #if 0 /* These can be NULL */
1546 || (tt
->tt_use_blink_for_acs
== NULL
)
1547 || (tt
->tt_graphic_char_pairs
== NULL
)
1549 || (tt
->tt_screen_cols
== NULL
)
1550 || (tt
->tt_screen_rows
== NULL
)
1553 SLang_exit_error ("Terminal not powerful enough for SLsmg");
1555 tt_normal_video
= tt
->tt_normal_video
;
1556 tt_goto_rc
= tt
->tt_goto_rc
;
1557 tt_cls
= tt
->tt_cls
;
1558 tt_del_eol
= tt
->tt_del_eol
;
1559 tt_smart_puts
= tt
->tt_smart_puts
;
1560 tt_flush_output
= tt
->tt_flush_output
;
1561 tt_reset_video
= tt
->tt_reset_video
;
1562 tt_init_video
= tt
->tt_init_video
;
1564 #ifndef IBMPC_SYSTEM
1565 tt_set_scroll_region
= tt
->tt_set_scroll_region
;
1566 tt_reverse_index
= tt
->tt_reverse_index
;
1567 tt_reset_scroll_region
= tt
->tt_reset_scroll_region
;
1568 tt_delete_nlines
= tt
->tt_delete_nlines
;
1570 tt_Term_Cannot_Scroll
= tt
->tt_term_cannot_scroll
;
1571 tt_Has_Alt_Charset
= tt
->tt_has_alt_charset
;
1572 tt_Use_Blink_For_ACS
= tt
->tt_use_blink_for_acs
;
1573 tt_Graphics_Char_Pairs
= tt
->tt_graphic_char_pairs
;
1576 tt_Screen_Cols
= tt
->tt_screen_cols
;
1577 tt_Screen_Rows
= tt
->tt_screen_rows
;