De-fuzzyed some msgs...
[midnight-commander.git] / slang / slsmg.c
blob2c87ce8ac06e852df3c1db0befbdd04d5adbed17
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 */
9 #include "config.h"
11 #include <stdio.h>
12 #include <string.h>
14 #include "slang.h"
15 #include "_slang.h"
17 typedef struct Screen_Type
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
26 Screen_Type;
28 #define TOUCHED 0x1
29 #define TRASHED 0x2
31 #ifndef pc_system
32 #define MAX_SCREEN_SIZE 120
33 #else
34 #define MAX_SCREEN_SIZE 75
35 #endif
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.
48 #ifndef pc_system
49 #define ALT_CHAR_FLAG 0x80
50 #else
51 #define ALT_CHAR_FLAG 0x00
52 #endif
54 int SLsmg_Newline_Moves = 0;
55 int SLsmg_Backspace_Moves = 0;
57 static void blank_line (unsigned short *p, int n, unsigned char ch)
59 register unsigned short *pmax = p + n;
60 register unsigned short color_ch;
62 color_ch = (This_Color << 8) | (unsigned short) ch;
64 while (p < pmax)
66 *p++ = color_ch;
71 static void clear_region (int row, int n)
73 int i;
74 int imax = row + n;
76 if (imax > Screen_Rows) imax = Screen_Rows;
77 for (i = row; i < imax; i++)
79 if (i >= 0)
81 blank_line (SL_Screen[i].neew, Screen_Cols, ' ');
82 SL_Screen[i].flags |= TOUCHED;
87 void SLsmg_erase_eol (void)
89 int r, c;
91 c = This_Col - Start_Col;
92 r = This_Row - Start_Row;
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;
100 static void scroll_up (void)
102 unsigned int i, imax;
103 unsigned short *neew;
105 neew = SL_Screen[0].neew;
106 imax = Screen_Rows - 1;
107 for (i = 0; i < imax; i++)
109 SL_Screen[i].neew = SL_Screen[i + 1].neew;
110 SL_Screen[i].flags |= TOUCHED;
112 SL_Screen[i].neew = neew;
113 SL_Screen[i].flags |= TOUCHED;
114 blank_line (neew, Screen_Cols, ' ');
115 This_Row--;
121 void SLsmg_gotorc (int r, int c)
123 This_Row = r;
124 This_Col = c;
127 int SLsmg_get_row (void)
129 return This_Row;
132 int SLsmg_get_column (void)
134 return This_Col;
137 void SLsmg_erase_eos (void)
139 SLsmg_erase_eol ();
140 clear_region (This_Row + 1, Screen_Rows);
143 static int This_Alt_Char;
145 #ifndef pc_system
146 void SLsmg_set_char_set (int i)
148 if (SLtt_Use_Blink_For_ACS) return; /* alt chars not used and the alt bit
149 * is used to indicate a blink.
151 if (i) This_Alt_Char = ALT_CHAR_FLAG;
152 else This_Alt_Char = 0;
154 This_Color &= 0x7F;
155 This_Color |= This_Alt_Char;
157 #endif
159 void SLsmg_set_color (int color)
161 if (color < 0) return;
162 This_Color = color | This_Alt_Char;
166 void SLsmg_reverse_video (void)
168 SLsmg_set_color (1);
172 void SLsmg_normal_video (void)
174 This_Color = This_Alt_Char; /* reset video but NOT char set. */
178 static int point_visible (int col_too)
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))));
186 void SLsmg_printf (char *fmt, ...)
188 char p[1000];
189 va_list ap;
191 va_start(ap, fmt);
192 (void) g_vsnprintf(p, sizeof (p), fmt, ap);
193 va_end(ap);
195 SLsmg_write_string (p);
198 void SLsmg_write_string (char *str)
200 SLsmg_write_nchars (str, strlen (str));
203 void SLsmg_write_nstring (char *str, int n)
205 int width;
206 char blank = ' ';
207 if (str == NULL) width = 0;
208 else
210 width = strlen (str);
211 if (width > n) width = n;
212 SLsmg_write_nchars (str, width);
214 while (width++ < n) SLsmg_write_nchars (&blank, 1);
217 void SLsmg_write_wrapped_string (char *s, int r, int c, int dr, int dc, int fill)
219 register char ch, *p;
220 int maxc = dc;
222 if ((dr == 0) || (dc == 0)) return;
223 p = s;
224 dc = 0;
225 while (1)
227 ch = *p++;
228 if ((ch == 0) || (ch == '\n'))
230 int diff;
232 diff = maxc - dc;
234 SLsmg_gotorc (r, c);
235 SLsmg_write_nchars (s, dc);
236 if (fill && (diff > 0))
238 while (diff--) SLsmg_write_char (' ');
240 if ((ch == 0) || (dr == 1)) break;
242 r++;
243 dc = 0;
244 dr--;
245 s = p;
247 else if (dc == maxc)
249 SLsmg_gotorc (r, c);
250 SLsmg_write_nchars (s, dc + 1);
251 if (dr == 1) break;
253 r++;
254 dc = 0;
255 dr--;
256 s = p;
258 else dc++;
264 int SLsmg_Tab_Width = 8;
266 /* Minimum value for which eight bit char is displayed as is. */
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
275 void SLsmg_write_nchars (char *str, int n)
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;
286 alt_char_set_flag = ((SLtt_Use_Blink_For_ACS == 0)
287 && (This_Color & ALT_CHAR_FLAG));
288 #endif
290 str_max = str + n;
291 color = This_Color << 8;
293 top: /* get here only on newline */
295 newline_flag = 0;
296 start_len = Start_Col;
298 if (point_visible (0) == 0) return;
300 len = This_Col;
301 max_len = start_len + Screen_Cols;
303 p = SL_Screen[This_Row].neew;
304 if (len > start_len) p += (len - start_len);
306 flags = SL_Screen[This_Row].flags;
307 while ((len < max_len) && (str < str_max))
309 ch = (unsigned char) *str++;
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
322 len += 1;
323 if (len > start_len)
325 old = *p;
326 neew = color | (unsigned short) ch;
327 if (old != neew)
329 flags |= TOUCHED;
330 *p = neew;
332 p++;
336 else if ((ch == '\t') && (SLsmg_Tab_Width > 0))
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--)
345 len += 1;
346 if (len > start_len)
348 if (*p != neew)
350 flags |= TOUCHED;
351 *p = neew;
353 p++;
357 else if (ch == '\n')
359 newline_flag = 1;
360 break;
362 else if ((ch == 0x8) && SLsmg_Backspace_Moves)
364 if (len != 0) len--;
366 else
368 if (ch & 0x80)
370 neew = color | (unsigned short) '~';
371 len += 1;
372 if (len > start_len)
374 if (*p != neew)
376 *p = neew;
377 flags |= TOUCHED;
379 p++;
380 if (len == max_len) break;
381 ch &= 0x7F;
385 len += 1;
386 if (len > start_len)
388 neew = color | (unsigned short) '^';
389 if (*p != neew)
391 *p = neew;
392 flags |= TOUCHED;
394 p++;
395 if (len == max_len) break;
398 if (ch == 127) ch = '?'; else ch = ch + '@';
399 len++;
400 if (len > start_len)
402 neew = color | (unsigned short) ch;
403 if (*p != neew)
405 *p = neew;
406 flags |= TOUCHED;
408 p++;
413 SL_Screen[This_Row].flags = flags;
414 This_Col = len;
416 if (SLsmg_Newline_Moves == 0)
417 return;
419 if (newline_flag == 0)
421 while (str < str_max)
423 if (*str == '\n') break;
424 str++;
426 if (str == str_max) return;
427 str++;
430 This_Row++;
431 This_Col = 0;
432 if (This_Row == Start_Row + Screen_Rows)
434 if (SLsmg_Newline_Moves > 0) scroll_up ();
436 goto top;
440 void SLsmg_write_char (char ch)
442 SLsmg_write_nchars (&ch, 1);
445 static int Cls_Flag;
448 void SLsmg_cls (void)
450 This_Color = 0;
451 clear_region (0, Screen_Rows);
452 This_Color = This_Alt_Char;
453 Cls_Flag = 1;
455 #if 0
456 static void do_copy (unsigned short *a, unsigned short *b)
458 unsigned short *amax = a + Screen_Cols;
460 while (a < amax) *a++ = *b++;
462 #endif
464 #ifndef pc_system
465 int SLsmg_Scroll_Hash_Border = 0;
466 static unsigned long compute_hash (unsigned short *s, int n)
468 register unsigned long h = 0, g;
469 register unsigned long sum = 0;
470 register unsigned short *smax, ch;
471 int is_blank = 2;
473 s += SLsmg_Scroll_Hash_Border;
474 smax = s + (n - SLsmg_Scroll_Hash_Border);
475 while (s < smax)
477 ch = *s++;
478 if (is_blank && ((ch & 0xFF) != 32)) is_blank--;
480 sum += ch;
482 h = sum + (h << 3);
483 if ((g = h & 0xE0000000UL) != 0)
485 h = h ^ (g >> 24);
486 h = h ^ g;
489 if (is_blank) return 0;
490 return h;
493 static unsigned long Blank_Hash;
495 static void try_scroll (void)
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;
503 /* find region limits. */
505 for (rmax = Screen_Rows - 1; rmax > 0; rmax--)
507 if (SL_Screen[rmax].new_hash != SL_Screen[rmax].old_hash)
509 r1 = rmax - 1;
510 if ((r1 == 0)
511 || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
512 break;
514 rmax = r1;
518 for (rmin = 0; rmin < rmax; rmin++)
520 if (SL_Screen[rmin].new_hash != SL_Screen[rmin].old_hash)
522 r1 = rmin + 1;
523 if ((r1 == rmax)
524 || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
525 break;
527 rmin = r1;
532 for (i = rmax; i > rmin; i--)
534 hash = SL_Screen[i].new_hash;
535 if (hash == Blank_Hash) continue;
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;
542 for (j = i - 1; j >= rmin; j--)
544 if (hash == SL_Screen[j].old_hash) break;
546 if (j < rmin) continue;
548 r2 = i; /* end scroll region */
550 di = i - j;
551 j--;
552 ignore = 0;
553 while ((j >= rmin) && (SL_Screen[j].old_hash == SL_Screen[j + di].new_hash))
555 if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
556 j--;
558 r1 = j + 1;
560 /* If this scroll only scrolls this line into place, don't do it.
562 if ((di > 1) && (r1 + di + ignore == r2)) continue;
564 /* If there is anything in the scrolling region that is ok, abort the
565 * scroll.
568 for (j = r1; j <= r2; j++)
570 if ((SL_Screen[j].old_hash != Blank_Hash)
571 && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
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;
578 if (j <= r2) continue;
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.
590 for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
592 while (di--)
594 tmp = SL_Screen[r2].old;
595 for (j = r2; j > r1; j--)
597 SL_Screen[j].old = SL_Screen[j - 1].old;
598 SL_Screen[j].old_hash = SL_Screen[j - 1].old_hash;
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++;
605 This_Color = color;
607 if (did_scroll) return;
609 /* Try other direction */
611 for (i = rmin; i < rmax; i++)
613 hash = SL_Screen[i].new_hash;
614 if (hash == Blank_Hash) continue;
615 if (hash == SL_Screen[i].old_hash) continue;
617 /* find a match further down screen */
618 for (j = i + 1; j <= rmax; j++)
620 if (hash == SL_Screen[j].old_hash) break;
622 if (j > rmax) continue;
624 r1 = i; /* beg scroll region */
625 di = j - i; /* number of lines to scroll */
626 j++; /* since we know this is a match */
628 /* find end of scroll region */
629 ignore = 0;
630 while ((j <= rmax) && (SL_Screen[j].old_hash == SL_Screen[j - di].new_hash))
632 if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
633 j++;
635 r2 = j - 1; /* end of scroll region */
637 /* If this scroll only scrolls this line into place, don't do it.
639 if ((di > 1) && (r1 + di + ignore == r2)) continue;
641 /* If there is anything in the scrolling region that is ok, abort the
642 * scroll.
645 for (j = r1; j <= r2; j++)
647 if ((SL_Screen[j].old_hash != Blank_Hash)
648 && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
650 if ((j - di < r1) || (SL_Screen[j].old_hash != SL_Screen[j - di].new_hash))
651 break;
655 if (j <= r2) continue;
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.
666 for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
668 while (di--)
670 tmp = SL_Screen[r1].old;
671 for (j = r1; j < r2; j++)
673 SL_Screen[j].old = SL_Screen[j + 1].old;
674 SL_Screen[j].old_hash = SL_Screen[j + 1].old_hash;
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--;
681 This_Color = color;
685 #endif /* NOT pc_system */
689 static int Smg_Inited;
691 void SLsmg_refresh (void)
693 int i;
695 if (Smg_Inited == 0) return;
696 #ifndef pc_system
697 for (i = 0; i < Screen_Rows; i++)
699 if (SL_Screen[i].flags == 0) continue;
700 SL_Screen[i].new_hash = compute_hash (SL_Screen[i].neew, Screen_Cols);
702 #endif
704 if (Cls_Flag)
706 SLtt_normal_video (); SLtt_cls ();
708 #ifndef pc_system
709 else if (SLtt_Term_Cannot_Scroll == 0) try_scroll ();
710 #endif
712 for (i = 0; i < Screen_Rows; i++)
714 int trashed;
716 if (SL_Screen[i].flags == 0) continue;
718 if (SL_Screen[i].flags & TRASHED)
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;
725 else trashed = 0;
727 if (Cls_Flag || trashed)
729 int color = This_Color;
730 This_Color = 0;
731 blank_line (SL_Screen[i].old, Screen_Cols, ' ');
732 This_Color = color;
735 SL_Screen[i].old[Screen_Cols] = 0;
736 SL_Screen[i].neew[Screen_Cols] = 0;
738 SLtt_smart_puts (SL_Screen[i].neew, SL_Screen[i].old, Screen_Cols, i);
740 SLMEMCPY ((char *) SL_Screen[i].old, (char *) SL_Screen[i].neew,
741 Screen_Cols * sizeof (short));
743 SL_Screen[i].flags = 0;
744 #ifndef pc_system
745 SL_Screen[i].old_hash = SL_Screen[i].new_hash;
746 #endif
749 if (point_visible (1)) SLtt_goto_rc (This_Row - Start_Row, This_Col - Start_Col);
750 SLtt_flush_output ();
751 Cls_Flag = 0;
754 static int compute_clip (int row, int n, int box_start, int box_end,
755 int *rmin, int *rmax)
757 int row_max;
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;
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;
771 void SLsmg_touch_lines (int row, int n)
773 int i;
774 int r1, r2;
776 if (0 == compute_clip (row, n, Start_Row, Start_Row + Screen_Rows, &r1, &r2))
777 return;
779 r1 -= Start_Row;
780 r2 -= Start_Row;
781 for (i = r1; i < r2; i++)
783 SL_Screen[i].flags |= TRASHED;
787 #ifndef pc_system
788 static char Fake_Alt_Char_Pairs [] = "a:j+k+l+m+q-t+u+v+w+x|";
790 static void init_alt_char_set (void)
792 int i;
793 unsigned char *p, *pmax, ch;
795 if (Alt_Char_Set[128] == 128) return;
797 i = 32;
798 memset ((char *)Alt_Char_Set, ' ', i);
799 while (i <= 128)
801 Alt_Char_Set [i] = i;
802 i++;
805 /* Map to VT100 */
806 if (SLtt_Has_Alt_Charset)
808 p = (unsigned char *) SLtt_Graphics_Char_Pairs;
809 if (p == NULL) return;
811 else p = (unsigned char *) Fake_Alt_Char_Pairs;
812 pmax = p + strlen ((char *) p);
814 /* Some systems have messed up entries for this */
815 while (p < pmax)
817 ch = *p++;
818 ch &= 0x7F; /* should be unnecessary */
819 Alt_Char_Set [ch] = *p;
820 p++;
823 #endif
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
833 static int Smg_Suspended;
834 void SLsmg_suspend_smg (void)
836 BLOCK_SIGNALS
838 if (Smg_Suspended == 0)
840 SLtt_reset_video ();
841 Smg_Suspended = 1;
844 UNBLOCK_SIGNALS
847 void SLsmg_resume_smg (void)
849 int i;
850 BLOCK_SIGNALS
852 if (Smg_Suspended == 0)
854 UNBLOCK_SIGNALS
855 return;
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 ();
865 UNBLOCK_SIGNALS
868 int SLsmg_init_smg (void)
870 int i, len;
871 unsigned short *old, *neew;
872 BLOCK_SIGNALS
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;
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++)
889 if ((NULL == (old = (unsigned short *) SLMALLOC (sizeof(short) * len)))
890 || ((NULL == (neew = (unsigned short *) SLMALLOC (sizeof(short) * len)))))
892 SLang_Error = SL_MALLOC_ERROR;
893 UNBLOCK_SIGNALS
894 return 0;
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
906 Smg_Inited = 1;
907 UNBLOCK_SIGNALS
908 return 1;
912 void SLsmg_reset_smg (void)
914 int i;
915 BLOCK_SIGNALS
917 if (Smg_Inited == 0)
919 UNBLOCK_SIGNALS
920 return;
922 for (i = 0; i < Screen_Rows; i++)
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;
928 SLtt_reset_video ();
929 This_Alt_Char = This_Color = 0;
930 Smg_Inited = 0;
932 UNBLOCK_SIGNALS
936 unsigned short SLsmg_char_at (void)
938 if (point_visible (1))
940 return SL_Screen[This_Row - Start_Row].neew[This_Col - Start_Col];
942 return 0;
946 void SLsmg_vprintf (char *fmt, va_list ap)
948 char p[1000];
950 (void) g_vsnprintf(p, sizeof (p), fmt, ap);
952 SLsmg_write_string (p);
955 void SLsmg_set_screen_start (int *r, int *c)
957 int or = Start_Row, oc = Start_Col;
959 if (c == NULL) Start_Col = 0;
960 else
962 Start_Col = *c;
963 *c = oc;
965 if (r == NULL) Start_Row = 0;
966 else
968 Start_Row = *r;
969 *r = or;
973 void SLsmg_draw_object (int r, int c, unsigned char object)
975 This_Row = r; This_Col = c;
977 if (point_visible (1))
979 int color = This_Color;
980 This_Color |= ALT_CHAR_FLAG;
981 SLsmg_write_char (object);
982 This_Color = color;
985 This_Col = c + 1;
988 void SLsmg_draw_hline (int n)
990 static unsigned char hbuf[16];
991 int count;
992 int cmin, cmax;
993 int final_col = This_Col + n;
994 int save_color;
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)))
1000 This_Col = final_col;
1001 return;
1004 if (hbuf[0] == 0)
1006 SLMEMSET ((char *) hbuf, SLSMG_HLINE_CHAR, 16);
1009 n = cmax - cmin;
1010 count = n / 16;
1012 save_color = This_Color;
1013 This_Color |= ALT_CHAR_FLAG;
1014 This_Col = cmin;
1016 SLsmg_write_nchars ((char *) hbuf, n % 16);
1017 while (count-- > 0)
1019 SLsmg_write_nchars ((char *) hbuf, 16);
1022 This_Color = save_color;
1023 This_Col = final_col;
1026 void SLsmg_draw_vline (int n)
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;
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)))
1037 This_Row = final_row;
1038 return;
1041 save_color = This_Color;
1042 This_Color |= ALT_CHAR_FLAG;
1044 for (This_Row = rmin; This_Row < rmax; This_Row++)
1046 This_Col = c;
1047 SLsmg_write_nchars ((char *) &ch, 1);
1050 This_Col = c; This_Row = final_row;
1051 This_Color = save_color;
1054 void SLsmg_draw_box (int r, int c, int dr, int dc)
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;
1071 void SLsmg_fill_region (int r, int c, int dr, int dc, unsigned char ch)
1073 static unsigned char hbuf[16];
1074 int count;
1075 int dcmax, rmax;
1078 if ((dc < 0) || (dr < 0)) return;
1080 SLsmg_gotorc (r, c);
1081 r = This_Row; c = This_Col;
1083 dcmax = Screen_Cols - This_Col;
1084 if (dc > dcmax) dc = dcmax;
1086 rmax = This_Row + dr;
1087 if (rmax > Screen_Rows) rmax = Screen_Rows;
1089 #if 0
1090 ch = Alt_Char_Set[ch];
1091 #endif
1092 if (ch != hbuf[0]) SLMEMSET ((char *) hbuf, (char) ch, 16);
1094 for (This_Row = r; This_Row < rmax; This_Row++)
1096 This_Col = c;
1097 count = dc / 16;
1098 SLsmg_write_nchars ((char *) hbuf, dc % 16);
1099 while (count-- > 0)
1101 SLsmg_write_nchars ((char *) hbuf, 16);
1105 This_Row = r;
1108 void SLsmg_forward (int n)
1110 This_Col += n;
1113 void SLsmg_write_color_chars (unsigned short *s, unsigned int len)
1115 unsigned short *smax, sh;
1116 char buf[32], *b, *bmax;
1117 int color, save_color;
1119 smax = s + len;
1120 b = buf;
1121 bmax = b + sizeof (buf);
1123 save_color = This_Color;
1125 while (s < smax)
1127 sh = *s++;
1129 color = sh >> 8;
1130 if ((color != This_Color) || (b == bmax))
1132 if (b != buf)
1134 SLsmg_write_nchars (buf, (int) (b - buf));
1135 b = buf;
1137 This_Color = color;
1139 *b++ = (char) (sh & 0xFF);
1142 if (b != buf)
1143 SLsmg_write_nchars (buf, (int) (b - buf));
1145 This_Color = save_color;
1148 unsigned int SLsmg_read_raw (unsigned short *buf, unsigned int len)
1150 unsigned int r, c;
1152 if (0 == point_visible (1)) return 0;
1154 r = (unsigned int) (This_Row - Start_Row);
1155 c = (unsigned int) (This_Col - Start_Col);
1157 if (c + len > (unsigned int) Screen_Cols)
1158 len = (unsigned int) Screen_Cols - c;
1160 memcpy ((char *) buf, (char *) (SL_Screen[r].neew + c), len * sizeof (short));
1161 return len;
1164 unsigned int SLsmg_write_raw (unsigned short *buf, unsigned int len)
1166 unsigned int r, c;
1167 unsigned short *dest;
1169 if (0 == point_visible (1)) return 0;
1171 r = (unsigned int) (This_Row - Start_Row);
1172 c = (unsigned int) (This_Col - Start_Col);
1174 if (c + len > (unsigned int) Screen_Cols)
1175 len = (unsigned int) Screen_Cols - c;
1177 dest = SL_Screen[r].neew + c;
1179 if (0 != memcmp ((char *) dest, (char *) buf, len * sizeof (short)))
1181 memcpy ((char *) dest, (char *) buf, len * sizeof (short));
1182 SL_Screen[r].flags |= TOUCHED;
1184 return len;