- Rearrange reactos.dff according to rosapps rearrange.
[reactos.git] / rosapps / mc / slang / slsmg.c
1 /* SLang Screen management routines */
2 /* Copyright (c) 1992, 1995 John E. Davis
3 * All rights reserved.
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Perl Artistic License.
7 */
8
9 #include "config.h"
10
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "slang.h"
15 #include "_slang.h"
16
17 typedef struct Screen_Type
18 {
19 int n; /* number of chars written last time */
20 int flags; /* line untouched, etc... */
21 unsigned short *old, *neew;
22 #ifndef pc_system
23 unsigned long old_hash, new_hash;
24 #endif
25 }
26 Screen_Type;
27
28 #define TOUCHED 0x1
29 #define TRASHED 0x2
30
31 #ifndef pc_system
32 #define MAX_SCREEN_SIZE 120
33 #else
34 #define MAX_SCREEN_SIZE 75
35 #endif
36
37 Screen_Type SL_Screen[MAX_SCREEN_SIZE];
38 static int Start_Col, Start_Row;
39 static int Screen_Cols, Screen_Rows;
40 static int This_Row, This_Col;
41 static int This_Color; /* only the first 8 bits of this
42 * are used. The highest bit is used
43 * to indicate an alternate character
44 * set. This leaves 127 userdefineable
45 * color combination.
46 */
47
48 #ifndef pc_system
49 #define ALT_CHAR_FLAG 0x80
50 #else
51 #define ALT_CHAR_FLAG 0x00
52 #endif
53
54 int SLsmg_Newline_Moves = 0;
55 int SLsmg_Backspace_Moves = 0;
56
57 static void blank_line (unsigned short *p, int n, unsigned char ch)
58 {
59 register unsigned short *pmax = p + n;
60 register unsigned short color_ch;
61
62 color_ch = (This_Color << 8) | (unsigned short) ch;
63
64 while (p < pmax)
65 {
66 *p++ = color_ch;
67 }
68 }
69
70
71 static void clear_region (int row, int n)
72 {
73 int i;
74 int imax = row + n;
75
76 if (imax > Screen_Rows) imax = Screen_Rows;
77 for (i = row; i < imax; i++)
78 {
79 if (i >= 0)
80 {
81 blank_line (SL_Screen[i].neew, Screen_Cols, ' ');
82 SL_Screen[i].flags |= TOUCHED;
83 }
84 }
85 }
86
87 void SLsmg_erase_eol (void)
88 {
89 int r, c;
90
91 c = This_Col - Start_Col;
92 r = This_Row - Start_Row;
93
94 if ((r < 0) || (r >= Screen_Rows)) return;
95 if (c < 0) c = 0; else if (c >= Screen_Cols) return;
96 blank_line (SL_Screen[This_Row].neew + c , Screen_Cols - c, ' ');
97 SL_Screen[This_Row].flags |= TOUCHED;
98 }
99
100 static void scroll_up (void)
101 {
102 unsigned int i, imax;
103 unsigned short *neew;
104
105 neew = SL_Screen[0].neew;
106 imax = Screen_Rows - 1;
107 for (i = 0; i < imax; i++)
108 {
109 SL_Screen[i].neew = SL_Screen[i + 1].neew;
110 SL_Screen[i].flags |= TOUCHED;
111 }
112 SL_Screen[i].neew = neew;
113 SL_Screen[i].flags |= TOUCHED;
114 blank_line (neew, Screen_Cols, ' ');
115 This_Row--;
116 }
117
118
119
120
121 void SLsmg_gotorc (int r, int c)
122 {
123 This_Row = r;
124 This_Col = c;
125 }
126
127 int SLsmg_get_row (void)
128 {
129 return This_Row;
130 }
131
132 int SLsmg_get_column (void)
133 {
134 return This_Col;
135 }
136
137 void SLsmg_erase_eos (void)
138 {
139 SLsmg_erase_eol ();
140 clear_region (This_Row + 1, Screen_Rows);
141 }
142
143 static int This_Alt_Char;
144
145 #ifndef pc_system
146 void SLsmg_set_char_set (int i)
147 {
148 if (SLtt_Use_Blink_For_ACS) return; /* alt chars not used and the alt bit
149 * is used to indicate a blink.
150 */
151 if (i) This_Alt_Char = ALT_CHAR_FLAG;
152 else This_Alt_Char = 0;
153
154 This_Color &= 0x7F;
155 This_Color |= This_Alt_Char;
156 }
157 #endif
158
159 void SLsmg_set_color (int color)
160 {
161 if (color < 0) return;
162 This_Color = color | This_Alt_Char;
163 }
164
165
166 void SLsmg_reverse_video (void)
167 {
168 SLsmg_set_color (1);
169 }
170
171
172 void SLsmg_normal_video (void)
173 {
174 This_Color = This_Alt_Char; /* reset video but NOT char set. */
175 }
176
177
178 static int point_visible (int col_too)
179 {
180 return ((This_Row >= Start_Row) && (This_Row < Start_Row + Screen_Rows)
181 && ((col_too == 0)
182 || ((This_Col >= Start_Col)
183 && (This_Col < Start_Col + Screen_Cols))));
184 }
185
186 void SLsmg_printf (char *fmt, ...)
187 {
188 char p[1000];
189 va_list ap;
190
191 va_start(ap, fmt);
192 (void) vsprintf(p, fmt, ap);
193 va_end(ap);
194
195 SLsmg_write_string (p);
196 }
197
198 void SLsmg_write_string (char *str)
199 {
200 SLsmg_write_nchars (str, strlen (str));
201 }
202
203 void SLsmg_write_nstring (char *str, int n)
204 {
205 int width;
206 char blank = ' ';
207 if (str == NULL) width = 0;
208 else
209 {
210 width = strlen (str);
211 if (width > n) width = n;
212 SLsmg_write_nchars (str, width);
213 }
214 while (width++ < n) SLsmg_write_nchars (&blank, 1);
215 }
216
217 void SLsmg_write_wrapped_string (char *s, int r, int c, int dr, int dc, int fill)
218 {
219 register char ch, *p;
220 int maxc = dc;
221
222 if ((dr == 0) || (dc == 0)) return;
223 p = s;
224 dc = 0;
225 while (1)
226 {
227 ch = *p++;
228 if ((ch == 0) || (ch == '\n'))
229 {
230 int diff;
231
232 diff = maxc - dc;
233
234 SLsmg_gotorc (r, c);
235 SLsmg_write_nchars (s, dc);
236 if (fill && (diff > 0))
237 {
238 while (diff--) SLsmg_write_char (' ');
239 }
240 if ((ch == 0) || (dr == 1)) break;
241
242 r++;
243 dc = 0;
244 dr--;
245 s = p;
246 }
247 else if (dc == maxc)
248 {
249 SLsmg_gotorc (r, c);
250 SLsmg_write_nchars (s, dc + 1);
251 if (dr == 1) break;
252
253 r++;
254 dc = 0;
255 dr--;
256 s = p;
257 }
258 else dc++;
259 }
260 }
261
262
263
264 int SLsmg_Tab_Width = 8;
265
266 /* Minimum value for which eight bit char is displayed as is. */
267
268 #ifndef pc_system
269 int SLsmg_Display_Eight_Bit = 160;
270 static unsigned char Alt_Char_Set[129];/* 129th is used as a flag */
271 #else
272 int SLsmg_Display_Eight_Bit = 128;
273 #endif
274
275 void SLsmg_write_nchars (char *str, int n)
276 {
277 register unsigned short *p, old, neew, color;
278 unsigned char ch;
279 unsigned int flags;
280 int len, start_len, max_len;
281 char *str_max;
282 int newline_flag;
283 #ifndef pc_system
284 int alt_char_set_flag;
285
286 alt_char_set_flag = ((SLtt_Use_Blink_For_ACS == 0)
287 && (This_Color & ALT_CHAR_FLAG));
288 #endif
289
290 str_max = str + n;
291 color = This_Color << 8;
292
293 top: /* get here only on newline */
294
295 newline_flag = 0;
296 start_len = Start_Col;
297
298 if (point_visible (0) == 0) return;
299
300 len = This_Col;
301 max_len = start_len + Screen_Cols;
302
303 p = SL_Screen[This_Row].neew;
304 if (len > start_len) p += (len - start_len);
305
306 flags = SL_Screen[This_Row].flags;
307 while ((len < max_len) && (str < str_max))
308 {
309 ch = (unsigned char) *str++;
310
311 #ifndef pc_system
312 if (alt_char_set_flag)
313 ch = Alt_Char_Set [ch & 0x7F];
314 #endif
315 if (((ch >= ' ') && (ch < 127))
316 || (ch >= (unsigned char) SLsmg_Display_Eight_Bit)
317 #ifndef pc_system
318 || alt_char_set_flag
319 #endif
320 )
321 {
322 len += 1;
323 if (len > start_len)
324 {
325 old = *p;
326 neew = color | (unsigned short) ch;
327 if (old != neew)
328 {
329 flags |= TOUCHED;
330 *p = neew;
331 }
332 p++;
333 }
334 }
335
336 else if ((ch == '\t') && (SLsmg_Tab_Width > 0))
337 {
338 n = len;
339 n += SLsmg_Tab_Width;
340 n = SLsmg_Tab_Width - (n % SLsmg_Tab_Width);
341 if (len + n > max_len) n = max_len - len;
342 neew = color | (unsigned short) ' ';
343 while (n--)
344 {
345 len += 1;
346 if (len > start_len)
347 {
348 if (*p != neew)
349 {
350 flags |= TOUCHED;
351 *p = neew;
352 }
353 p++;
354 }
355 }
356 }
357 else if (ch == '\n')
358 {
359 newline_flag = 1;
360 break;
361 }
362 else if ((ch == 0x8) && SLsmg_Backspace_Moves)
363 {
364 if (len != 0) len--;
365 }
366 else
367 {
368 if (ch & 0x80)
369 {
370 neew = color | (unsigned short) '~';
371 len += 1;
372 if (len > start_len)
373 {
374 if (*p != neew)
375 {
376 *p = neew;
377 flags |= TOUCHED;
378 }
379 p++;
380 if (len == max_len) break;
381 ch &= 0x7F;
382 }
383 }
384
385 len += 1;
386 if (len > start_len)
387 {
388 neew = color | (unsigned short) '^';
389 if (*p != neew)
390 {
391 *p = neew;
392 flags |= TOUCHED;
393 }
394 p++;
395 if (len == max_len) break;
396 }
397
398 if (ch == 127) ch = '?'; else ch = ch + '@';
399 len++;
400 if (len > start_len)
401 {
402 neew = color | (unsigned short) ch;
403 if (*p != neew)
404 {
405 *p = neew;
406 flags |= TOUCHED;
407 }
408 p++;
409 }
410 }
411 }
412
413 SL_Screen[This_Row].flags = flags;
414 This_Col = len;
415
416 if (SLsmg_Newline_Moves == 0)
417 return;
418
419 if (newline_flag == 0)
420 {
421 while (str < str_max)
422 {
423 if (*str == '\n') break;
424 str++;
425 }
426 if (str == str_max) return;
427 str++;
428 }
429
430 This_Row++;
431 This_Col = 0;
432 if (This_Row == Start_Row + Screen_Rows)
433 {
434 if (SLsmg_Newline_Moves > 0) scroll_up ();
435 }
436 goto top;
437 }
438
439
440 void SLsmg_write_char (char ch)
441 {
442 SLsmg_write_nchars (&ch, 1);
443 }
444
445 static int Cls_Flag;
446
447
448 void SLsmg_cls (void)
449 {
450 This_Color = 0;
451 clear_region (0, Screen_Rows);
452 This_Color = This_Alt_Char;
453 Cls_Flag = 1;
454 }
455 #if 0
456 static void do_copy (unsigned short *a, unsigned short *b)
457 {
458 unsigned short *amax = a + Screen_Cols;
459
460 while (a < amax) *a++ = *b++;
461 }
462 #endif
463
464 #ifndef pc_system
465 int SLsmg_Scroll_Hash_Border = 0;
466 static unsigned long compute_hash (unsigned short *s, int n)
467 {
468 register unsigned long h = 0, g;
469 register unsigned long sum = 0;
470 register unsigned short *smax, ch;
471 int is_blank = 2;
472
473 s += SLsmg_Scroll_Hash_Border;
474 smax = s + (n - SLsmg_Scroll_Hash_Border);
475 while (s < smax)
476 {
477 ch = *s++;
478 if (is_blank && ((ch & 0xFF) != 32)) is_blank--;
479
480 sum += ch;
481
482 h = sum + (h << 3);
483 if ((g = h & 0xE0000000UL) != 0)
484 {
485 h = h ^ (g >> 24);
486 h = h ^ g;
487 }
488 }
489 if (is_blank) return 0;
490 return h;
491 }
492
493 static unsigned long Blank_Hash;
494
495 static void try_scroll (void)
496 {
497 int i, j, di, r1, r2, rmin, rmax;
498 unsigned long hash;
499 int color, did_scroll = 0;
500 unsigned short *tmp;
501 int ignore;
502
503 /* find region limits. */
504
505 for (rmax = Screen_Rows - 1; rmax > 0; rmax--)
506 {
507 if (SL_Screen[rmax].new_hash != SL_Screen[rmax].old_hash)
508 {
509 r1 = rmax - 1;
510 if ((r1 == 0)
511 || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
512 break;
513
514 rmax = r1;
515 }
516 }
517
518 for (rmin = 0; rmin < rmax; rmin++)
519 {
520 if (SL_Screen[rmin].new_hash != SL_Screen[rmin].old_hash)
521 {
522 r1 = rmin + 1;
523 if ((r1 == rmax)
524 || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
525 break;
526
527 rmin = r1;
528 }
529 }
530
531
532 for (i = rmax; i > rmin; i--)
533 {
534 hash = SL_Screen[i].new_hash;
535 if (hash == Blank_Hash) continue;
536
537 if ((hash == SL_Screen[i].old_hash)
538 || ((i + 1 < Screen_Rows) && (hash == SL_Screen[i + 1].old_hash))
539 || ((i - 1 > rmin) && (SL_Screen[i].old_hash == SL_Screen[i - 1].new_hash)))
540 continue;
541
542 for (j = i - 1; j >= rmin; j--)
543 {
544 if (hash == SL_Screen[j].old_hash) break;
545 }
546 if (j < rmin) continue;
547
548 r2 = i; /* end scroll region */
549
550 di = i - j;
551 j--;
552 ignore = 0;
553 while ((j >= rmin) && (SL_Screen[j].old_hash == SL_Screen[j + di].new_hash))
554 {
555 if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
556 j--;
557 }
558 r1 = j + 1;
559
560 /* If this scroll only scrolls this line into place, don't do it.
561 */
562 if ((di > 1) && (r1 + di + ignore == r2)) continue;
563
564 /* If there is anything in the scrolling region that is ok, abort the
565 * scroll.
566 */
567
568 for (j = r1; j <= r2; j++)
569 {
570 if ((SL_Screen[j].old_hash != Blank_Hash)
571 && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
572 {
573 /* See if the scroll is happens to scroll this one into place. */
574 if ((j + di > r2) || (SL_Screen[j].old_hash != SL_Screen[j + di].new_hash))
575 break;
576 }
577 }
578 if (j <= r2) continue;
579
580 color = This_Color; This_Color = 0;
581 did_scroll = 1;
582 SLtt_normal_video ();
583 SLtt_set_scroll_region (r1, r2);
584 SLtt_goto_rc (0, 0);
585 SLtt_reverse_index (di);
586 SLtt_reset_scroll_region ();
587 /* Now we have a hole in the screen. Make the virtual screen look
588 * like it.
589 */
590 for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
591
592 while (di--)
593 {
594 tmp = SL_Screen[r2].old;
595 for (j = r2; j > r1; j--)
596 {
597 SL_Screen[j].old = SL_Screen[j - 1].old;
598 SL_Screen[j].old_hash = SL_Screen[j - 1].old_hash;
599 }
600 SL_Screen[r1].old = tmp;
601 blank_line (SL_Screen[r1].old, Screen_Cols, ' ');
602 SL_Screen[r1].old_hash = Blank_Hash;
603 r1++;
604 }
605 This_Color = color;
606 }
607 if (did_scroll) return;
608
609 /* Try other direction */
610
611 for (i = rmin; i < rmax; i++)
612 {
613 hash = SL_Screen[i].new_hash;
614 if (hash == Blank_Hash) continue;
615 if (hash == SL_Screen[i].old_hash) continue;
616
617 /* find a match further down screen */
618 for (j = i + 1; j <= rmax; j++)
619 {
620 if (hash == SL_Screen[j].old_hash) break;
621 }
622 if (j > rmax) continue;
623
624 r1 = i; /* beg scroll region */
625 di = j - i; /* number of lines to scroll */
626 j++; /* since we know this is a match */
627
628 /* find end of scroll region */
629 ignore = 0;
630 while ((j <= rmax) && (SL_Screen[j].old_hash == SL_Screen[j - di].new_hash))
631 {
632 if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
633 j++;
634 }
635 r2 = j - 1; /* end of scroll region */
636
637 /* If this scroll only scrolls this line into place, don't do it.
638 */
639 if ((di > 1) && (r1 + di + ignore == r2)) continue;
640
641 /* If there is anything in the scrolling region that is ok, abort the
642 * scroll.
643 */
644
645 for (j = r1; j <= r2; j++)
646 {
647 if ((SL_Screen[j].old_hash != Blank_Hash)
648 && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
649 {
650 if ((j - di < r1) || (SL_Screen[j].old_hash != SL_Screen[j - di].new_hash))
651 break;
652 }
653
654 }
655 if (j <= r2) continue;
656
657 color = This_Color; This_Color = 0;
658 SLtt_normal_video ();
659 SLtt_set_scroll_region (r1, r2);
660 SLtt_goto_rc (0, 0); /* relative to scroll region */
661 SLtt_delete_nlines (di);
662 SLtt_reset_scroll_region ();
663 /* Now we have a hole in the screen. Make the virtual screen look
664 * like it.
665 */
666 for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
667
668 while (di--)
669 {
670 tmp = SL_Screen[r1].old;
671 for (j = r1; j < r2; j++)
672 {
673 SL_Screen[j].old = SL_Screen[j + 1].old;
674 SL_Screen[j].old_hash = SL_Screen[j + 1].old_hash;
675 }
676 SL_Screen[r2].old = tmp;
677 blank_line (SL_Screen[r2].old, Screen_Cols, ' ');
678 SL_Screen[r2].old_hash = Blank_Hash;
679 r2--;
680 }
681 This_Color = color;
682 }
683 }
684
685 #endif /* NOT pc_system */
686
687
688
689 static int Smg_Inited;
690
691 void SLsmg_refresh (void)
692 {
693 int i;
694
695 if (Smg_Inited == 0) return;
696 #ifndef pc_system
697 for (i = 0; i < Screen_Rows; i++)
698 {
699 if (SL_Screen[i].flags == 0) continue;
700 SL_Screen[i].new_hash = compute_hash (SL_Screen[i].neew, Screen_Cols);
701 }
702 #endif
703
704 if (Cls_Flag)
705 {
706 SLtt_normal_video (); SLtt_cls ();
707 }
708 #ifndef pc_system
709 else if (SLtt_Term_Cannot_Scroll == 0) try_scroll ();
710 #endif
711
712 for (i = 0; i < Screen_Rows; i++)
713 {
714 int trashed;
715
716 if (SL_Screen[i].flags == 0) continue;
717
718 if (SL_Screen[i].flags & TRASHED)
719 {
720 SLtt_goto_rc (i, -1); /* Force cursor to move */
721 SLtt_goto_rc (i, 0);
722 if (Cls_Flag == 0) SLtt_del_eol ();
723 trashed = 1;
724 }
725 else trashed = 0;
726
727 if (Cls_Flag || trashed)
728 {
729 int color = This_Color;
730 This_Color = 0;
731 blank_line (SL_Screen[i].old, Screen_Cols, ' ');
732 This_Color = color;
733 }
734
735 SL_Screen[i].old[Screen_Cols] = 0;
736 SL_Screen[i].neew[Screen_Cols] = 0;
737
738 SLtt_smart_puts (SL_Screen[i].neew, SL_Screen[i].old, Screen_Cols, i);
739
740 SLMEMCPY ((char *) SL_Screen[i].old, (char *) SL_Screen[i].neew,
741 Screen_Cols * sizeof (short));
742
743 SL_Screen[i].flags = 0;
744 #ifndef pc_system
745 SL_Screen[i].old_hash = SL_Screen[i].new_hash;
746 #endif
747 }
748
749 if (point_visible (1)) SLtt_goto_rc (This_Row - Start_Row, This_Col - Start_Col);
750 SLtt_flush_output ();
751 Cls_Flag = 0;
752 }
753
754 static int compute_clip (int row, int n, int box_start, int box_end,
755 int *rmin, int *rmax)
756 {
757 int row_max;
758
759 if (n < 0) return 0;
760 if (row >= box_end) return 0;
761 row_max = row + n;
762 if (row_max <= box_start) return 0;
763
764 if (row < box_start) row = box_start;
765 if (row_max >= box_end) row_max = box_end;
766 *rmin = row;
767 *rmax = row_max;
768 return 1;
769 }
770
771 void SLsmg_touch_lines (int row, int n)
772 {
773 int i;
774 int r1, r2;
775
776 if (0 == compute_clip (row, n, Start_Row, Start_Row + Screen_Rows, &r1, &r2))
777 return;
778
779 r1 -= Start_Row;
780 r2 -= Start_Row;
781 for (i = r1; i < r2; i++)
782 {
783 SL_Screen[i].flags |= TRASHED;
784 }
785 }
786
787 #ifndef pc_system
788 static char Fake_Alt_Char_Pairs [] = "a:j+k+l+m+q-t+u+v+w+x|";
789
790 static void init_alt_char_set (void)
791 {
792 int i;
793 unsigned char *p, *pmax, ch;
794
795 if (Alt_Char_Set[128] == 128) return;
796
797 i = 32;
798 memset ((char *)Alt_Char_Set, ' ', i);
799 while (i <= 128)
800 {
801 Alt_Char_Set [i] = i;
802 i++;
803 }
804
805 /* Map to VT100 */
806 if (SLtt_Has_Alt_Charset)
807 {
808 p = (unsigned char *) SLtt_Graphics_Char_Pairs;
809 if (p == NULL) return;
810 }
811 else p = (unsigned char *) Fake_Alt_Char_Pairs;
812 pmax = p + strlen ((char *) p);
813
814 /* Some systems have messed up entries for this */
815 while (p < pmax)
816 {
817 ch = *p++;
818 ch &= 0x7F; /* should be unnecessary */
819 Alt_Char_Set [ch] = *p;
820 p++;
821 }
822 }
823 #endif
824
825 #ifndef pc_system
826 # define BLOCK_SIGNALS SLsig_block_signals ();
827 # define UNBLOCK_SIGNALS SLsig_unblock_signals ();
828 #else
829 # define BLOCK_SIGNALS
830 # define UNBLOCK_SIGNALS
831 #endif
832
833 static int Smg_Suspended;
834 void SLsmg_suspend_smg (void)
835 {
836 BLOCK_SIGNALS
837
838 if (Smg_Suspended == 0)
839 {
840 SLtt_reset_video ();
841 Smg_Suspended = 1;
842 }
843
844 UNBLOCK_SIGNALS
845 }
846
847 void SLsmg_resume_smg (void)
848 {
849 int i;
850 BLOCK_SIGNALS
851
852 if (Smg_Suspended == 0)
853 {
854 UNBLOCK_SIGNALS
855 return;
856 }
857
858 Smg_Suspended = 0;
859 SLtt_init_video ();
860 Cls_Flag = 1;
861 for (i = 0; i < Screen_Rows; i++)
862 SL_Screen[i].flags |= TRASHED;
863 SLsmg_refresh ();
864
865 UNBLOCK_SIGNALS
866 }
867
868 int SLsmg_init_smg (void)
869 {
870 int i, len;
871 unsigned short *old, *neew;
872 BLOCK_SIGNALS
873
874 if (Smg_Inited) SLsmg_reset_smg ();
875 SLtt_init_video ();
876 Screen_Cols = SLtt_Screen_Cols;
877 Screen_Rows = SLtt_Screen_Rows;
878 This_Col = This_Row = Start_Col = Start_Row = 0;
879
880 This_Color = 0;
881 This_Alt_Char = 0;
882 Cls_Flag = 1;
883 #ifndef pc_system
884 init_alt_char_set ();
885 #endif
886 len = Screen_Cols + 3;
887 for (i = 0; i < Screen_Rows; i++)
888 {
889 if ((NULL == (old = (unsigned short *) SLMALLOC (sizeof(short) * len)))
890 || ((NULL == (neew = (unsigned short *) SLMALLOC (sizeof(short) * len)))))
891 {
892 SLang_Error = SL_MALLOC_ERROR;
893 UNBLOCK_SIGNALS
894 return 0;
895 }
896 blank_line (old, len, ' ');
897 blank_line (neew, len, ' ');
898 SL_Screen[i].old = old;
899 SL_Screen[i].neew = neew;
900 SL_Screen[i].flags = 0;
901 #ifndef pc_system
902 Blank_Hash = compute_hash (old, Screen_Cols);
903 SL_Screen[i].new_hash = SL_Screen[i].old_hash = Blank_Hash;
904 #endif
905 }
906 Smg_Inited = 1;
907 UNBLOCK_SIGNALS
908 return 1;
909 }
910
911
912 void SLsmg_reset_smg (void)
913 {
914 int i;
915 BLOCK_SIGNALS
916
917 if (Smg_Inited == 0)
918 {
919 UNBLOCK_SIGNALS
920 return;
921 }
922 for (i = 0; i < Screen_Rows; i++)
923 {
924 if (SL_Screen[i].old != NULL) SLFREE (SL_Screen[i].old);
925 if (SL_Screen[i].neew != NULL) SLFREE (SL_Screen[i].neew);
926 SL_Screen[i].old = SL_Screen[i].neew = NULL;
927 }
928 SLtt_reset_video ();
929 This_Alt_Char = This_Color = 0;
930 Smg_Inited = 0;
931
932 UNBLOCK_SIGNALS
933 }
934
935
936 unsigned short SLsmg_char_at (void)
937 {
938 if (point_visible (1))
939 {
940 return SL_Screen[This_Row - Start_Row].neew[This_Col - Start_Col];
941 }
942 return 0;
943 }
944
945
946 void SLsmg_vprintf (char *fmt, va_list ap)
947 {
948 char p[1000];
949
950 (void) vsprintf(p, fmt, ap);
951
952 SLsmg_write_string (p);
953 }
954
955 void SLsmg_set_screen_start (int *r, int *c)
956 {
957 int or = Start_Row, oc = Start_Col;
958
959 if (c == NULL) Start_Col = 0;
960 else
961 {
962 Start_Col = *c;
963 *c = oc;
964 }
965 if (r == NULL) Start_Row = 0;
966 else
967 {
968 Start_Row = *r;
969 *r = or;
970 }
971 }
972
973 void SLsmg_draw_object (int r, int c, unsigned char object)
974 {
975 This_Row = r; This_Col = c;
976
977 if (point_visible (1))
978 {
979 int color = This_Color;
980 This_Color |= ALT_CHAR_FLAG;
981 SLsmg_write_char (object);
982 This_Color = color;
983 }
984
985 This_Col = c + 1;
986 }
987
988 void SLsmg_draw_hline (int n)
989 {
990 static unsigned char hbuf[16];
991 int count;
992 int cmin, cmax;
993 int final_col = This_Col + n;
994 int save_color;
995
996 if ((This_Row < Start_Row) || (This_Row >= Start_Row + Screen_Rows)
997 || (0 == compute_clip (This_Col, n, Start_Col, Start_Col + Screen_Cols,
998 &cmin, &cmax)))
999 {
1000 This_Col = final_col;
1001 return;
1002 }
1003
1004 if (hbuf[0] == 0)
1005 {
1006 SLMEMSET ((char *) hbuf, SLSMG_HLINE_CHAR, 16);
1007 }
1008
1009 n = cmax - cmin;
1010 count = n / 16;
1011
1012 save_color = This_Color;
1013 This_Color |= ALT_CHAR_FLAG;
1014 This_Col = cmin;
1015
1016 SLsmg_write_nchars ((char *) hbuf, n % 16);
1017 while (count-- > 0)
1018 {
1019 SLsmg_write_nchars ((char *) hbuf, 16);
1020 }
1021
1022 This_Color = save_color;
1023 This_Col = final_col;
1024 }
1025
1026 void SLsmg_draw_vline (int n)
1027 {
1028 unsigned char ch = SLSMG_VLINE_CHAR;
1029 int c = This_Col, rmin, rmax;
1030 int final_row = This_Row + n;
1031 int save_color;
1032
1033 if (((c < Start_Col) || (c >= Start_Col + Screen_Cols)) ||
1034 (0 == compute_clip (This_Row, n, Start_Row, Start_Row + Screen_Rows,
1035 &rmin, &rmax)))
1036 {
1037 This_Row = final_row;
1038 return;
1039 }
1040
1041 save_color = This_Color;
1042 This_Color |= ALT_CHAR_FLAG;
1043
1044 for (This_Row = rmin; This_Row < rmax; This_Row++)
1045 {
1046 This_Col = c;
1047 SLsmg_write_nchars ((char *) &ch, 1);
1048 }
1049
1050 This_Col = c; This_Row = final_row;
1051 This_Color = save_color;
1052 }
1053
1054 void SLsmg_draw_box (int r, int c, int dr, int dc)
1055 {
1056 if (!dr || !dc) return;
1057 This_Row = r; This_Col = c;
1058 dr--; dc--;
1059 SLsmg_draw_hline (dc);
1060 SLsmg_draw_vline (dr);
1061 This_Row = r; This_Col = c;
1062 SLsmg_draw_vline (dr);
1063 SLsmg_draw_hline (dc);
1064 SLsmg_draw_object (r, c, SLSMG_ULCORN_CHAR);
1065 SLsmg_draw_object (r, c + dc, SLSMG_URCORN_CHAR);
1066 SLsmg_draw_object (r + dr, c, SLSMG_LLCORN_CHAR);
1067 SLsmg_draw_object (r + dr, c + dc, SLSMG_LRCORN_CHAR);
1068 This_Row = r; This_Col = c;
1069 }
1070
1071 void SLsmg_fill_region (int r, int c, int dr, int dc, unsigned char ch)
1072 {
1073 static unsigned char hbuf[16];
1074 int count;
1075 int dcmax, rmax;
1076
1077
1078 if ((dc < 0) || (dr < 0)) return;
1079
1080 SLsmg_gotorc (r, c);
1081 r = This_Row; c = This_Col;
1082
1083 dcmax = Screen_Cols - This_Col;
1084 if (dc > dcmax) dc = dcmax;
1085
1086 rmax = This_Row + dr;
1087 if (rmax > Screen_Rows) rmax = Screen_Rows;
1088
1089 #if 0
1090 ch = Alt_Char_Set[ch];
1091 #endif
1092 if (ch != hbuf[0]) SLMEMSET ((char *) hbuf, (char) ch, 16);
1093
1094 for (This_Row = r; This_Row < rmax; This_Row++)
1095 {
1096 This_Col = c;
1097 count = dc / 16;
1098 SLsmg_write_nchars ((char *) hbuf, dc % 16);
1099 while (count-- > 0)
1100 {
1101 SLsmg_write_nchars ((char *) hbuf, 16);
1102 }
1103 }
1104
1105 This_Row = r;
1106 }
1107
1108 void SLsmg_forward (int n)
1109 {
1110 This_Col += n;
1111 }
1112
1113 void SLsmg_write_color_chars (unsigned short *s, unsigned int len)
1114 {
1115 unsigned short *smax, sh;
1116 char buf[32], *b, *bmax;
1117 int color, save_color;
1118
1119 smax = s + len;
1120 b = buf;
1121 bmax = b + sizeof (buf);
1122
1123 save_color = This_Color;
1124
1125 while (s < smax)
1126 {
1127 sh = *s++;
1128
1129 color = sh >> 8;
1130 if ((color != This_Color) || (b == bmax))
1131 {
1132 if (b != buf)
1133 {
1134 SLsmg_write_nchars (buf, (int) (b - buf));
1135 b = buf;
1136 }
1137 This_Color = color;
1138 }
1139 *b++ = (char) (sh & 0xFF);
1140 }
1141
1142 if (b != buf)
1143 SLsmg_write_nchars (buf, (int) (b - buf));
1144
1145 This_Color = save_color;
1146 }
1147
1148 unsigned int SLsmg_read_raw (unsigned short *buf, unsigned int len)
1149 {
1150 unsigned int r, c;
1151
1152 if (0 == point_visible (1)) return 0;
1153
1154 r = (unsigned int) (This_Row - Start_Row);
1155 c = (unsigned int) (This_Col - Start_Col);
1156
1157 if (c + len > (unsigned int) Screen_Cols)
1158 len = (unsigned int) Screen_Cols - c;
1159
1160 memcpy ((char *) buf, (char *) (SL_Screen[r].neew + c), len * sizeof (short));
1161 return len;
1162 }
1163
1164 unsigned int SLsmg_write_raw (unsigned short *buf, unsigned int len)
1165 {
1166 unsigned int r, c;
1167 unsigned short *dest;
1168
1169 if (0 == point_visible (1)) return 0;
1170
1171 r = (unsigned int) (This_Row - Start_Row);
1172 c = (unsigned int) (This_Col - Start_Col);
1173
1174 if (c + len > (unsigned int) Screen_Cols)
1175 len = (unsigned int) Screen_Cols - c;
1176
1177 dest = SL_Screen[r].neew + c;
1178
1179 if (0 != memcmp ((char *) dest, (char *) buf, len * sizeof (short)))
1180 {
1181 memcpy ((char *) dest, (char *) buf, len * sizeof (short));
1182 SL_Screen[r].flags |= TOUCHED;
1183 }
1184 return len;
1185 }