* subshell.c (pty_open_master) [IS_AIX]: Open /dev/ptc, not
[midnight-commander.git] / slang / slsmg.c
blobd548c0bc925d7c9a5c8345a435377226b2967283
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"
16 typedef struct Screen_Type
18 int n; /* number of chars written last time */
19 int flags; /* line untouched, etc... */
20 unsigned short *old, *neew;
21 #ifndef pc_system
22 unsigned long old_hash, new_hash;
23 #endif
25 Screen_Type;
27 #define TOUCHED 0x1
28 #define TRASHED 0x2
30 #ifndef pc_system
31 #define MAX_SCREEN_SIZE 120
32 #else
33 #define MAX_SCREEN_SIZE 75
34 #endif
36 Screen_Type SL_Screen[MAX_SCREEN_SIZE];
37 static int Start_Col, Start_Row;
38 static int Screen_Cols, Screen_Rows;
39 static int This_Row, This_Col;
40 static int This_Color; /* only the first 8 bits of this
41 * are used. The highest bit is used
42 * to indicate an alternate character
43 * set. This leaves 127 userdefineable
44 * color combination.
47 #ifndef pc_system
48 #define ALT_CHAR_FLAG 0x80
49 #else
50 #define ALT_CHAR_FLAG 0x00
51 #endif
53 int SLsmg_Newline_Moves = 0;
54 int SLsmg_Backspace_Moves = 0;
56 static void blank_line (unsigned short *p, int n, unsigned char ch)
58 register unsigned short *pmax = p + n;
59 register unsigned short color_ch;
61 color_ch = (This_Color << 8) | (unsigned short) ch;
63 while (p < pmax)
65 *p++ = color_ch;
70 static void clear_region (int row, int n)
72 int i;
73 int imax = row + n;
75 if (imax > Screen_Rows) imax = Screen_Rows;
76 for (i = row; i < imax; i++)
78 if (i >= 0)
80 blank_line (SL_Screen[i].neew, Screen_Cols, ' ');
81 SL_Screen[i].flags |= TOUCHED;
86 void SLsmg_erase_eol (void)
88 int r, c;
90 c = This_Col - Start_Col;
91 r = This_Row - Start_Row;
93 if ((r < 0) || (r >= Screen_Rows)) return;
94 if (c < 0) c = 0; else if (c >= Screen_Cols) return;
95 blank_line (SL_Screen[This_Row].neew + c , Screen_Cols - c, ' ');
96 SL_Screen[This_Row].flags |= TOUCHED;
99 static void scroll_up (void)
101 unsigned int i, imax;
102 unsigned short *neew;
104 neew = SL_Screen[0].neew;
105 imax = Screen_Rows - 1;
106 for (i = 0; i < imax; i++)
108 SL_Screen[i].neew = SL_Screen[i + 1].neew;
109 SL_Screen[i].flags |= TOUCHED;
111 SL_Screen[i].neew = neew;
112 SL_Screen[i].flags |= TOUCHED;
113 blank_line (neew, Screen_Cols, ' ');
114 This_Row--;
120 void SLsmg_gotorc (int r, int c)
122 This_Row = r;
123 This_Col = c;
126 int SLsmg_get_row (void)
128 return This_Row;
131 int SLsmg_get_column (void)
133 return This_Col;
136 void SLsmg_erase_eos (void)
138 SLsmg_erase_eol ();
139 clear_region (This_Row + 1, Screen_Rows);
142 static int This_Alt_Char;
144 #ifndef pc_system
145 void SLsmg_set_char_set (int i)
147 if (SLtt_Use_Blink_For_ACS) return; /* alt chars not used and the alt bit
148 * is used to indicate a blink.
150 if (i) This_Alt_Char = ALT_CHAR_FLAG;
151 else This_Alt_Char = 0;
153 This_Color &= 0x7F;
154 This_Color |= This_Alt_Char;
156 #endif
158 void SLsmg_set_color (int color)
160 if (color < 0) return;
161 This_Color = color | This_Alt_Char;
165 void SLsmg_reverse_video (void)
167 SLsmg_set_color (1);
171 void SLsmg_normal_video (void)
173 This_Color = This_Alt_Char; /* reset video but NOT char set. */
177 static int point_visible (int col_too)
179 return ((This_Row >= Start_Row) && (This_Row < Start_Row + Screen_Rows)
180 && ((col_too == 0)
181 || ((This_Col >= Start_Col)
182 && (This_Col < Start_Col + Screen_Cols))));
185 void SLsmg_printf (char *fmt, ...)
187 char p[1000];
188 va_list ap;
190 va_start(ap, fmt);
191 (void) g_vsnprintf(p, sizeof (p), fmt, ap);
192 va_end(ap);
194 SLsmg_write_string (p);
197 void SLsmg_write_string (char *str)
199 SLsmg_write_nchars (str, strlen (str));
202 void SLsmg_write_nstring (char *str, int n)
204 int width;
205 char blank = ' ';
206 if (str == NULL) width = 0;
207 else
209 width = strlen (str);
210 if (width > n) width = n;
211 SLsmg_write_nchars (str, width);
213 while (width++ < n) SLsmg_write_nchars (&blank, 1);
216 void SLsmg_write_wrapped_string (char *s, int r, int c, int dr, int dc, int fill)
218 register char ch, *p;
219 int maxc = dc;
221 if ((dr == 0) || (dc == 0)) return;
222 p = s;
223 dc = 0;
224 while (1)
226 ch = *p++;
227 if ((ch == 0) || (ch == '\n'))
229 int diff;
231 diff = maxc - dc;
233 SLsmg_gotorc (r, c);
234 SLsmg_write_nchars (s, dc);
235 if (fill && (diff > 0))
237 while (diff--) SLsmg_write_char (' ');
239 if ((ch == 0) || (dr == 1)) break;
241 r++;
242 dc = 0;
243 dr--;
244 s = p;
246 else if (dc == maxc)
248 SLsmg_gotorc (r, c);
249 SLsmg_write_nchars (s, dc + 1);
250 if (dr == 1) break;
252 r++;
253 dc = 0;
254 dr--;
255 s = p;
257 else dc++;
263 int SLsmg_Tab_Width = 8;
265 /* Minimum value for which eight bit char is displayed as is. */
267 #ifndef pc_system
268 int SLsmg_Display_Eight_Bit = 160;
269 static unsigned char Alt_Char_Set[129];/* 129th is used as a flag */
270 #else
271 int SLsmg_Display_Eight_Bit = 128;
272 #endif
274 void SLsmg_write_nchars (char *str, int n)
276 register unsigned short *p, old, neew, color;
277 unsigned char ch;
278 unsigned int flags;
279 int len, start_len, max_len;
280 char *str_max;
281 int newline_flag;
282 #ifndef pc_system
283 int alt_char_set_flag;
285 alt_char_set_flag = ((SLtt_Use_Blink_For_ACS == 0)
286 && (This_Color & ALT_CHAR_FLAG));
287 #endif
289 str_max = str + n;
290 color = This_Color << 8;
292 top: /* get here only on newline */
294 newline_flag = 0;
295 start_len = Start_Col;
297 if (point_visible (0) == 0) return;
299 len = This_Col;
300 max_len = start_len + Screen_Cols;
302 p = SL_Screen[This_Row].neew;
303 if (len > start_len) p += (len - start_len);
305 flags = SL_Screen[This_Row].flags;
306 while ((len < max_len) && (str < str_max))
308 ch = (unsigned char) *str++;
310 #ifndef pc_system
311 if (alt_char_set_flag)
312 ch = Alt_Char_Set [ch & 0x7F];
313 #endif
314 if (((ch >= ' ') && (ch < 127))
315 || (ch >= (unsigned char) SLsmg_Display_Eight_Bit)
316 #ifndef pc_system
317 || alt_char_set_flag
318 #endif
321 len += 1;
322 if (len > start_len)
324 old = *p;
325 neew = color | (unsigned short) ch;
326 if (old != neew)
328 flags |= TOUCHED;
329 *p = neew;
331 p++;
335 else if ((ch == '\t') && (SLsmg_Tab_Width > 0))
337 n = len;
338 n += SLsmg_Tab_Width;
339 n = SLsmg_Tab_Width - (n % SLsmg_Tab_Width);
340 if (len + n > max_len) n = max_len - len;
341 neew = color | (unsigned short) ' ';
342 while (n--)
344 len += 1;
345 if (len > start_len)
347 if (*p != neew)
349 flags |= TOUCHED;
350 *p = neew;
352 p++;
356 else if (ch == '\n')
358 newline_flag = 1;
359 break;
361 else if ((ch == 0x8) && SLsmg_Backspace_Moves)
363 if (len != 0) len--;
365 else
367 if (ch & 0x80)
369 neew = color | (unsigned short) '~';
370 len += 1;
371 if (len > start_len)
373 if (*p != neew)
375 *p = neew;
376 flags |= TOUCHED;
378 p++;
379 if (len == max_len) break;
380 ch &= 0x7F;
384 len += 1;
385 if (len > start_len)
387 neew = color | (unsigned short) '^';
388 if (*p != neew)
390 *p = neew;
391 flags |= TOUCHED;
393 p++;
394 if (len == max_len) break;
397 if (ch == 127) ch = '?'; else ch = ch + '@';
398 len++;
399 if (len > start_len)
401 neew = color | (unsigned short) ch;
402 if (*p != neew)
404 *p = neew;
405 flags |= TOUCHED;
407 p++;
412 SL_Screen[This_Row].flags = flags;
413 This_Col = len;
415 if (SLsmg_Newline_Moves == 0)
416 return;
418 if (newline_flag == 0)
420 while (str < str_max)
422 if (*str == '\n') break;
423 str++;
425 if (str == str_max) return;
426 str++;
429 This_Row++;
430 This_Col = 0;
431 if (This_Row == Start_Row + Screen_Rows)
433 if (SLsmg_Newline_Moves > 0) scroll_up ();
435 goto top;
439 void SLsmg_write_char (char ch)
441 SLsmg_write_nchars (&ch, 1);
444 static int Cls_Flag;
447 void SLsmg_cls (void)
449 This_Color = 0;
450 clear_region (0, Screen_Rows);
451 This_Color = This_Alt_Char;
452 Cls_Flag = 1;
454 #if 0
455 static void do_copy (unsigned short *a, unsigned short *b)
457 unsigned short *amax = a + Screen_Cols;
459 while (a < amax) *a++ = *b++;
461 #endif
463 #ifndef pc_system
464 int SLsmg_Scroll_Hash_Border = 0;
465 static unsigned long compute_hash (unsigned short *s, int n)
467 register unsigned long h = 0, g;
468 register unsigned long sum = 0;
469 register unsigned short *smax, ch;
470 int is_blank = 2;
472 s += SLsmg_Scroll_Hash_Border;
473 smax = s + (n - SLsmg_Scroll_Hash_Border);
474 while (s < smax)
476 ch = *s++;
477 if (is_blank && ((ch & 0xFF) != 32)) is_blank--;
479 sum += ch;
481 h = sum + (h << 3);
482 if ((g = h & 0xE0000000UL) != 0)
484 h = h ^ (g >> 24);
485 h = h ^ g;
488 if (is_blank) return 0;
489 return h;
492 static unsigned long Blank_Hash;
494 static void try_scroll (void)
496 int i, j, di, r1, r2, rmin, rmax;
497 unsigned long hash;
498 int color, did_scroll = 0;
499 unsigned short *tmp;
500 int ignore;
502 /* find region limits. */
504 for (rmax = Screen_Rows - 1; rmax > 0; rmax--)
506 if (SL_Screen[rmax].new_hash != SL_Screen[rmax].old_hash)
508 r1 = rmax - 1;
509 if ((r1 == 0)
510 || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
511 break;
513 rmax = r1;
517 for (rmin = 0; rmin < rmax; rmin++)
519 if (SL_Screen[rmin].new_hash != SL_Screen[rmin].old_hash)
521 r1 = rmin + 1;
522 if ((r1 == rmax)
523 || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
524 break;
526 rmin = r1;
531 for (i = rmax; i > rmin; i--)
533 hash = SL_Screen[i].new_hash;
534 if (hash == Blank_Hash) continue;
536 if ((hash == SL_Screen[i].old_hash)
537 || ((i + 1 < Screen_Rows) && (hash == SL_Screen[i + 1].old_hash))
538 || ((i - 1 > rmin) && (SL_Screen[i].old_hash == SL_Screen[i - 1].new_hash)))
539 continue;
541 for (j = i - 1; j >= rmin; j--)
543 if (hash == SL_Screen[j].old_hash) break;
545 if (j < rmin) continue;
547 r2 = i; /* end scroll region */
549 di = i - j;
550 j--;
551 ignore = 0;
552 while ((j >= rmin) && (SL_Screen[j].old_hash == SL_Screen[j + di].new_hash))
554 if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
555 j--;
557 r1 = j + 1;
559 /* If this scroll only scrolls this line into place, don't do it.
561 if ((di > 1) && (r1 + di + ignore == r2)) continue;
563 /* If there is anything in the scrolling region that is ok, abort the
564 * scroll.
567 for (j = r1; j <= r2; j++)
569 if ((SL_Screen[j].old_hash != Blank_Hash)
570 && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
572 /* See if the scroll is happens to scroll this one into place. */
573 if ((j + di > r2) || (SL_Screen[j].old_hash != SL_Screen[j + di].new_hash))
574 break;
577 if (j <= r2) continue;
579 color = This_Color; This_Color = 0;
580 did_scroll = 1;
581 SLtt_normal_video ();
582 SLtt_set_scroll_region (r1, r2);
583 SLtt_goto_rc (0, 0);
584 SLtt_reverse_index (di);
585 SLtt_reset_scroll_region ();
586 /* Now we have a hole in the screen. Make the virtual screen look
587 * like it.
589 for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
591 while (di--)
593 tmp = SL_Screen[r2].old;
594 for (j = r2; j > r1; j--)
596 SL_Screen[j].old = SL_Screen[j - 1].old;
597 SL_Screen[j].old_hash = SL_Screen[j - 1].old_hash;
599 SL_Screen[r1].old = tmp;
600 blank_line (SL_Screen[r1].old, Screen_Cols, ' ');
601 SL_Screen[r1].old_hash = Blank_Hash;
602 r1++;
604 This_Color = color;
606 if (did_scroll) return;
608 /* Try other direction */
610 for (i = rmin; i < rmax; i++)
612 hash = SL_Screen[i].new_hash;
613 if (hash == Blank_Hash) continue;
614 if (hash == SL_Screen[i].old_hash) continue;
616 /* find a match further down screen */
617 for (j = i + 1; j <= rmax; j++)
619 if (hash == SL_Screen[j].old_hash) break;
621 if (j > rmax) continue;
623 r1 = i; /* beg scroll region */
624 di = j - i; /* number of lines to scroll */
625 j++; /* since we know this is a match */
627 /* find end of scroll region */
628 ignore = 0;
629 while ((j <= rmax) && (SL_Screen[j].old_hash == SL_Screen[j - di].new_hash))
631 if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
632 j++;
634 r2 = j - 1; /* end of scroll region */
636 /* If this scroll only scrolls this line into place, don't do it.
638 if ((di > 1) && (r1 + di + ignore == r2)) continue;
640 /* If there is anything in the scrolling region that is ok, abort the
641 * scroll.
644 for (j = r1; j <= r2; j++)
646 if ((SL_Screen[j].old_hash != Blank_Hash)
647 && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
649 if ((j - di < r1) || (SL_Screen[j].old_hash != SL_Screen[j - di].new_hash))
650 break;
654 if (j <= r2) continue;
656 color = This_Color; This_Color = 0;
657 SLtt_normal_video ();
658 SLtt_set_scroll_region (r1, r2);
659 SLtt_goto_rc (0, 0); /* relative to scroll region */
660 SLtt_delete_nlines (di);
661 SLtt_reset_scroll_region ();
662 /* Now we have a hole in the screen. Make the virtual screen look
663 * like it.
665 for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
667 while (di--)
669 tmp = SL_Screen[r1].old;
670 for (j = r1; j < r2; j++)
672 SL_Screen[j].old = SL_Screen[j + 1].old;
673 SL_Screen[j].old_hash = SL_Screen[j + 1].old_hash;
675 SL_Screen[r2].old = tmp;
676 blank_line (SL_Screen[r2].old, Screen_Cols, ' ');
677 SL_Screen[r2].old_hash = Blank_Hash;
678 r2--;
680 This_Color = color;
684 #endif /* NOT pc_system */
688 static int Smg_Inited;
690 void SLsmg_refresh (void)
692 int i;
694 if (Smg_Inited == 0) return;
695 #ifndef pc_system
696 for (i = 0; i < Screen_Rows; i++)
698 if (SL_Screen[i].flags == 0) continue;
699 SL_Screen[i].new_hash = compute_hash (SL_Screen[i].neew, Screen_Cols);
701 #endif
703 if (Cls_Flag)
705 SLtt_normal_video (); SLtt_cls ();
707 #ifndef pc_system
708 else if (SLtt_Term_Cannot_Scroll == 0) try_scroll ();
709 #endif
711 for (i = 0; i < Screen_Rows; i++)
713 int trashed;
715 if (SL_Screen[i].flags == 0) continue;
717 if (SL_Screen[i].flags & TRASHED)
719 SLtt_goto_rc (i, -1); /* Force cursor to move */
720 SLtt_goto_rc (i, 0);
721 if (Cls_Flag == 0) SLtt_del_eol ();
722 trashed = 1;
724 else trashed = 0;
726 if (Cls_Flag || trashed)
728 int color = This_Color;
729 This_Color = 0;
730 blank_line (SL_Screen[i].old, Screen_Cols, ' ');
731 This_Color = color;
734 SL_Screen[i].old[Screen_Cols] = 0;
735 SL_Screen[i].neew[Screen_Cols] = 0;
737 SLtt_smart_puts (SL_Screen[i].neew, SL_Screen[i].old, Screen_Cols, i);
739 SLMEMCPY ((char *) SL_Screen[i].old, (char *) SL_Screen[i].neew,
740 Screen_Cols * sizeof (short));
742 SL_Screen[i].flags = 0;
743 #ifndef pc_system
744 SL_Screen[i].old_hash = SL_Screen[i].new_hash;
745 #endif
748 if (point_visible (1)) SLtt_goto_rc (This_Row - Start_Row, This_Col - Start_Col);
749 SLtt_flush_output ();
750 Cls_Flag = 0;
753 static int compute_clip (int row, int n, int box_start, int box_end,
754 int *rmin, int *rmax)
756 int row_max;
758 if (n < 0) return 0;
759 if (row >= box_end) return 0;
760 row_max = row + n;
761 if (row_max <= box_start) return 0;
763 if (row < box_start) row = box_start;
764 if (row_max >= box_end) row_max = box_end;
765 *rmin = row;
766 *rmax = row_max;
767 return 1;
770 void SLsmg_touch_lines (int row, int n)
772 int i;
773 int r1, r2;
775 if (0 == compute_clip (row, n, Start_Row, Start_Row + Screen_Rows, &r1, &r2))
776 return;
778 r1 -= Start_Row;
779 r2 -= Start_Row;
780 for (i = r1; i < r2; i++)
782 SL_Screen[i].flags |= TRASHED;
786 #ifndef pc_system
787 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#";
789 static void init_alt_char_set (void)
791 int i;
792 const unsigned char *p, *pmax;
793 unsigned char 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;