Sort order diaolg box trim.
[midnight-commander.git] / slang / slsmg.c
blobb891c0ec96021fc40f3944ebf5823ef16e2dd707
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 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 unsigned char *p, *pmax, ch;
794 if (Alt_Char_Set[128] == 128) return;
796 i = 32;
797 memset ((char *)Alt_Char_Set, ' ', i);
798 while (i <= 128)
800 Alt_Char_Set [i] = i;
801 i++;
804 /* Map to VT100 */
805 if (SLtt_Has_Alt_Charset)
807 p = (unsigned char *) SLtt_Graphics_Char_Pairs;
808 if (p == NULL) return;
810 else p = (unsigned char *) Fake_Alt_Char_Pairs;
811 pmax = p + strlen ((char *) p);
813 /* Some systems have messed up entries for this */
814 while (p < pmax)
816 ch = *p++;
817 ch &= 0x7F; /* should be unnecessary */
818 Alt_Char_Set [ch] = *p;
819 p++;
822 #endif
824 #ifndef pc_system
825 # define BLOCK_SIGNALS SLsig_block_signals ();
826 # define UNBLOCK_SIGNALS SLsig_unblock_signals ();
827 #else
828 # define BLOCK_SIGNALS
829 # define UNBLOCK_SIGNALS
830 #endif
832 static int Smg_Suspended;
833 void SLsmg_suspend_smg (void)
835 BLOCK_SIGNALS
837 if (Smg_Suspended == 0)
839 SLtt_reset_video ();
840 Smg_Suspended = 1;
843 UNBLOCK_SIGNALS
846 void SLsmg_resume_smg (void)
848 int i;
849 BLOCK_SIGNALS
851 if (Smg_Suspended == 0)
853 UNBLOCK_SIGNALS
854 return;
857 Smg_Suspended = 0;
858 SLtt_init_video ();
859 Cls_Flag = 1;
860 for (i = 0; i < Screen_Rows; i++)
861 SL_Screen[i].flags |= TRASHED;
862 SLsmg_refresh ();
864 UNBLOCK_SIGNALS
867 int SLsmg_init_smg (void)
869 int i, len;
870 unsigned short *old, *neew;
871 BLOCK_SIGNALS
873 if (Smg_Inited) SLsmg_reset_smg ();
874 SLtt_init_video ();
875 Screen_Cols = SLtt_Screen_Cols;
876 Screen_Rows = SLtt_Screen_Rows;
877 This_Col = This_Row = Start_Col = Start_Row = 0;
879 This_Color = 0;
880 This_Alt_Char = 0;
881 Cls_Flag = 1;
882 #ifndef pc_system
883 init_alt_char_set ();
884 #endif
885 len = Screen_Cols + 3;
886 for (i = 0; i < Screen_Rows; i++)
888 if ((NULL == (old = (unsigned short *) SLMALLOC (sizeof(short) * len)))
889 || ((NULL == (neew = (unsigned short *) SLMALLOC (sizeof(short) * len)))))
891 SLang_Error = SL_MALLOC_ERROR;
892 UNBLOCK_SIGNALS
893 return 0;
895 blank_line (old, len, ' ');
896 blank_line (neew, len, ' ');
897 SL_Screen[i].old = old;
898 SL_Screen[i].neew = neew;
899 SL_Screen[i].flags = 0;
900 #ifndef pc_system
901 Blank_Hash = compute_hash (old, Screen_Cols);
902 SL_Screen[i].new_hash = SL_Screen[i].old_hash = Blank_Hash;
903 #endif
905 Smg_Inited = 1;
906 UNBLOCK_SIGNALS
907 return 1;
911 void SLsmg_reset_smg (void)
913 int i;
914 BLOCK_SIGNALS
916 if (Smg_Inited == 0)
918 UNBLOCK_SIGNALS
919 return;
921 for (i = 0; i < Screen_Rows; i++)
923 if (SL_Screen[i].old != NULL) SLFREE (SL_Screen[i].old);
924 if (SL_Screen[i].neew != NULL) SLFREE (SL_Screen[i].neew);
925 SL_Screen[i].old = SL_Screen[i].neew = NULL;
927 SLtt_reset_video ();
928 This_Alt_Char = This_Color = 0;
929 Smg_Inited = 0;
931 UNBLOCK_SIGNALS
935 unsigned short SLsmg_char_at (void)
937 if (point_visible (1))
939 return SL_Screen[This_Row - Start_Row].neew[This_Col - Start_Col];
941 return 0;
945 void SLsmg_vprintf (char *fmt, va_list ap)
947 char p[1000];
949 (void) g_vsnprintf(p, sizeof (p), fmt, ap);
951 SLsmg_write_string (p);
954 void SLsmg_set_screen_start (int *r, int *c)
956 int or = Start_Row, oc = Start_Col;
958 if (c == NULL) Start_Col = 0;
959 else
961 Start_Col = *c;
962 *c = oc;
964 if (r == NULL) Start_Row = 0;
965 else
967 Start_Row = *r;
968 *r = or;
972 void SLsmg_draw_object (int r, int c, unsigned char object)
974 This_Row = r; This_Col = c;
976 if (point_visible (1))
978 int color = This_Color;
979 This_Color |= ALT_CHAR_FLAG;
980 SLsmg_write_char (object);
981 This_Color = color;
984 This_Col = c + 1;
987 void SLsmg_draw_hline (int n)
989 static unsigned char hbuf[16];
990 int count;
991 int cmin, cmax;
992 int final_col = This_Col + n;
993 int save_color;
995 if ((This_Row < Start_Row) || (This_Row >= Start_Row + Screen_Rows)
996 || (0 == compute_clip (This_Col, n, Start_Col, Start_Col + Screen_Cols,
997 &cmin, &cmax)))
999 This_Col = final_col;
1000 return;
1003 if (hbuf[0] == 0)
1005 SLMEMSET ((char *) hbuf, SLSMG_HLINE_CHAR, 16);
1008 n = cmax - cmin;
1009 count = n / 16;
1011 save_color = This_Color;
1012 This_Color |= ALT_CHAR_FLAG;
1013 This_Col = cmin;
1015 SLsmg_write_nchars ((char *) hbuf, n % 16);
1016 while (count-- > 0)
1018 SLsmg_write_nchars ((char *) hbuf, 16);
1021 This_Color = save_color;
1022 This_Col = final_col;
1025 void SLsmg_draw_vline (int n)
1027 unsigned char ch = SLSMG_VLINE_CHAR;
1028 int c = This_Col, rmin, rmax;
1029 int final_row = This_Row + n;
1030 int save_color;
1032 if (((c < Start_Col) || (c >= Start_Col + Screen_Cols)) ||
1033 (0 == compute_clip (This_Row, n, Start_Row, Start_Row + Screen_Rows,
1034 &rmin, &rmax)))
1036 This_Row = final_row;
1037 return;
1040 save_color = This_Color;
1041 This_Color |= ALT_CHAR_FLAG;
1043 for (This_Row = rmin; This_Row < rmax; This_Row++)
1045 This_Col = c;
1046 SLsmg_write_nchars ((char *) &ch, 1);
1049 This_Col = c; This_Row = final_row;
1050 This_Color = save_color;
1053 void SLsmg_draw_box (int r, int c, int dr, int dc)
1055 if (!dr || !dc) return;
1056 This_Row = r; This_Col = c;
1057 dr--; dc--;
1058 SLsmg_draw_hline (dc);
1059 SLsmg_draw_vline (dr);
1060 This_Row = r; This_Col = c;
1061 SLsmg_draw_vline (dr);
1062 SLsmg_draw_hline (dc);
1063 SLsmg_draw_object (r, c, SLSMG_ULCORN_CHAR);
1064 SLsmg_draw_object (r, c + dc, SLSMG_URCORN_CHAR);
1065 SLsmg_draw_object (r + dr, c, SLSMG_LLCORN_CHAR);
1066 SLsmg_draw_object (r + dr, c + dc, SLSMG_LRCORN_CHAR);
1067 This_Row = r; This_Col = c;
1070 void SLsmg_fill_region (int r, int c, int dr, int dc, unsigned char ch)
1072 static unsigned char hbuf[16];
1073 int count;
1074 int dcmax, rmax;
1077 if ((dc < 0) || (dr < 0)) return;
1079 SLsmg_gotorc (r, c);
1080 r = This_Row; c = This_Col;
1082 dcmax = Screen_Cols - This_Col;
1083 if (dc > dcmax) dc = dcmax;
1085 rmax = This_Row + dr;
1086 if (rmax > Screen_Rows) rmax = Screen_Rows;
1088 #if 0
1089 ch = Alt_Char_Set[ch];
1090 #endif
1091 if (ch != hbuf[0]) SLMEMSET ((char *) hbuf, (char) ch, 16);
1093 for (This_Row = r; This_Row < rmax; This_Row++)
1095 This_Col = c;
1096 count = dc / 16;
1097 SLsmg_write_nchars ((char *) hbuf, dc % 16);
1098 while (count-- > 0)
1100 SLsmg_write_nchars ((char *) hbuf, 16);
1104 This_Row = r;
1107 void SLsmg_forward (int n)
1109 This_Col += n;
1112 void SLsmg_write_color_chars (unsigned short *s, unsigned int len)
1114 unsigned short *smax, sh;
1115 char buf[32], *b, *bmax;
1116 int color, save_color;
1118 smax = s + len;
1119 b = buf;
1120 bmax = b + sizeof (buf);
1122 save_color = This_Color;
1124 while (s < smax)
1126 sh = *s++;
1128 color = sh >> 8;
1129 if ((color != This_Color) || (b == bmax))
1131 if (b != buf)
1133 SLsmg_write_nchars (buf, (int) (b - buf));
1134 b = buf;
1136 This_Color = color;
1138 *b++ = (char) (sh & 0xFF);
1141 if (b != buf)
1142 SLsmg_write_nchars (buf, (int) (b - buf));
1144 This_Color = save_color;
1147 unsigned int SLsmg_read_raw (unsigned short *buf, unsigned int len)
1149 unsigned int r, c;
1151 if (0 == point_visible (1)) return 0;
1153 r = (unsigned int) (This_Row - Start_Row);
1154 c = (unsigned int) (This_Col - Start_Col);
1156 if (c + len > (unsigned int) Screen_Cols)
1157 len = (unsigned int) Screen_Cols - c;
1159 memcpy ((char *) buf, (char *) (SL_Screen[r].neew + c), len * sizeof (short));
1160 return len;
1163 unsigned int SLsmg_write_raw (unsigned short *buf, unsigned int len)
1165 unsigned int r, c;
1166 unsigned short *dest;
1168 if (0 == point_visible (1)) return 0;
1170 r = (unsigned int) (This_Row - Start_Row);
1171 c = (unsigned int) (This_Col - Start_Col);
1173 if (c + len > (unsigned int) Screen_Cols)
1174 len = (unsigned int) Screen_Cols - c;
1176 dest = SL_Screen[r].neew + c;
1178 if (0 != memcmp ((char *) dest, (char *) buf, len * sizeof (short)))
1180 memcpy ((char *) dest, (char *) buf, len * sizeof (short));
1181 SL_Screen[r].flags |= TOUCHED;
1183 return len;