1 /* -*- mode: C; mode: fold; -*- */
2 /* Copyright (c) 1992, 1998, 2000, 2002, 2003, 2004, 2005, 2006 John E. Davis
3  * This file is part of JED editor library source.
4  *
5  * You may distribute this file under the terms the GNU General Public
6  * License.  See the file COPYING for more information.
7  */
8 #include "config.h"
9 #include "jed-feat.h"
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <slang.h>
14 
15 #include "vterm.h"
16 #include "misc.h"
17 
18 /* This is a virtual terminal used by the window system displays. */
19 
20 #if SLANG_VERSION < 20000
21 typedef unsigned short SLsmg_Color_Type;
22 #endif
23 
24 int VTerm_Num_Rows, VTerm_Num_Cols;
25 SLsmg_Char_Type **VTerm_Display;
26 int VTerm_Suspend_Update;
27 
28 static int Scroll_R1, Scroll_R2;
29 static SLsmg_Color_Type Current_Color;
30 static int Current_Row;
31 static int Current_Col;
32 
33 /* Note: In my opinion, area clearing operations should use the current color.
34  * Unfortunately, window systems clear using the default color.  So, that must
35  * be mimicked here.  This means that the color argument to this function
36  * should be 0.  Sigh.
37  */
blank_line(SLsmg_Char_Type * s,int len,int color)38 static void blank_line (SLsmg_Char_Type *s, int len, int color)
39 {
40 #if SLANG_VERSION < 20000
41    SLsmg_Char_Type c;
42    SLsmg_Char_Type *smax;
43 
44    c = (SLsmg_Char_Type) SLSMG_BUILD_CHAR(' ', color);
45 
46    smax = s + len;
47    while (s < smax)
48      *s++ = c;
49 #else
50    SLsmg_Char_Type *smax = s + len;
51    memset ((char *)s, 0, len * sizeof (SLsmg_Char_Type));
52    while (s < smax)
53      {
54 	s->nchars = 1;
55 	s->color = color;
56 	s->wchars[0] = ' ';
57 	s++;
58      }
59 #endif
60 }
61 
62 
vterm_reset_display(void)63 int vterm_reset_display (void)
64 {
65    int r;
66 
67    if (VTerm_Suspend_Update) return 0;
68 
69    Current_Col = Current_Row = 0;
70    Current_Color = 0;
71    Scroll_R2 = Scroll_R1 = 0;
72 
73    if (VTerm_Display == NULL)
74      return 0;
75 
76    for (r = 0; r < VTerm_Num_Rows; r++)
77      SLfree ((char *) VTerm_Display [r]);
78 
79    SLfree ((char *)VTerm_Display);
80    VTerm_Display = NULL;
81 
82    return 0;
83 }
84 
vterm_init_display(int rows,int cols)85 int vterm_init_display (int rows, int cols)
86 {
87    int r;
88 
89    if (VTerm_Suspend_Update) return 0;
90 
91    vterm_reset_display ();
92 
93    if ((rows == 0) || (cols == 0))
94      {
95 	rows = 24;
96 	cols = 80;
97      }
98 
99    VTerm_Num_Cols = cols;
100    VTerm_Num_Rows = rows;
101 
102    VTerm_Display = (SLsmg_Char_Type **)jed_malloc0 (rows * sizeof (SLsmg_Char_Type *));
103    if (VTerm_Display == NULL)
104      return -1;
105 
106    for (r = 0; r < rows; r++)
107      {
108 	SLsmg_Char_Type *s;
109 
110 	if (NULL == (s = (SLsmg_Char_Type *) SLmalloc (cols * sizeof (SLsmg_Char_Type))))
111 	  {
112 	     vterm_reset_display ();
113 	     return -1;
114 	  }
115 
116 	VTerm_Display[r] = s;
117      }
118 
119    vterm_set_scroll_region (0, VTerm_Num_Rows - 1);
120    vterm_reverse_video (0);
121    vterm_goto_rc (0, 0);
122    vterm_cls ();
123 
124    return 0;
125 }
126 
vterm_set_scroll_region(int r1,int r2)127 void vterm_set_scroll_region (int r1, int r2)
128 {
129    if (VTerm_Suspend_Update) return;
130 
131    if (r1 >= VTerm_Num_Rows) r1 = VTerm_Num_Rows - 1;
132    if (r1 < 0) r1 = 0;
133 
134    if (r2 >= VTerm_Num_Rows) r2 = VTerm_Num_Rows - 1;
135    if (r2 < 0) r2 = 0;
136 
137    Scroll_R1 = r1;
138    Scroll_R2 = r2;
139 }
140 
vterm_delete_nlines(int n)141 void vterm_delete_nlines (int n)
142 {
143    if (VTerm_Suspend_Update) return;
144 
145    if (VTerm_Display == NULL)
146      return;
147 
148    if (n > Scroll_R2 - Scroll_R1) n = 1 + Scroll_R2 - Scroll_R1;
149 
150    while (n > 0)
151      {
152 	SLsmg_Char_Type *s;
153 	int r;
154 
155 	s = VTerm_Display[Scroll_R1];
156 
157 	for (r = Scroll_R1; r < Scroll_R2; r++)
158 	  VTerm_Display[r] = VTerm_Display[r + 1];
159 
160 	VTerm_Display[Scroll_R2] = s;
161         blank_line (s, VTerm_Num_Cols, 0);
162 	n--;
163      }
164 }
165 
vterm_reverse_index(int n)166 void vterm_reverse_index (int n)
167 {
168    if (VTerm_Suspend_Update) return;
169 
170    if (VTerm_Display == NULL)
171      return;
172 
173    if (n > Scroll_R2 - Scroll_R1) n = 1 + Scroll_R2 - Scroll_R1;
174 
175    while (n > 0)
176      {
177 	SLsmg_Char_Type *s;
178 	int r;
179 
180 	s = VTerm_Display[Scroll_R2];
181 
182 	for (r = Scroll_R2; r > Scroll_R1; r--)
183 	  VTerm_Display[r] = VTerm_Display[r - 1];
184 
185 	VTerm_Display[Scroll_R1] = s;
186         blank_line (s, VTerm_Num_Cols, 0);
187 	n--;
188      }
189 }
190 
191 
vterm_del_eol(void)192 void vterm_del_eol (void)
193 {
194    if (VTerm_Suspend_Update) return;
195 
196    if (VTerm_Display == NULL)
197      return;
198 
199    blank_line (VTerm_Display[Current_Row] + Current_Col,
200 	       VTerm_Num_Cols - Current_Col, 0);
201 }
202 
vterm_goto_rc(int r,int c)203 void vterm_goto_rc (int r, int c)
204 {
205    if (VTerm_Suspend_Update) return;
206 
207    r += Scroll_R1;
208 
209    if (r >= VTerm_Num_Rows) r = VTerm_Num_Rows - 1;
210    if (r < 0) r = 0;
211 
212    if (c >= VTerm_Num_Cols) c = VTerm_Num_Cols - 1;
213    if (c < 0) c = 0;
214 
215    Current_Col = c;
216    Current_Row = r;
217 }
218 
vterm_forward_cursor(int n)219 void vterm_forward_cursor (int n)
220 {
221    Current_Col += n;
222    if (Current_Col >= VTerm_Num_Cols)
223      Current_Col = VTerm_Num_Cols - 1;
224 }
225 
vterm_reverse_video(int c)226 void vterm_reverse_video (int c)
227 {
228    if (VTerm_Suspend_Update) return;
229    Current_Color = c;
230 }
231 
vterm_cls(void)232 void vterm_cls (void)
233 {
234    int r;
235 
236    if (VTerm_Suspend_Update) return;
237 
238    if (VTerm_Display == NULL)
239      return;
240 
241    for (r = 0; r < VTerm_Num_Rows; r++)
242      blank_line (VTerm_Display[r], VTerm_Num_Cols, 0);
243 }
244 
245 
vterm_write_nchars(char * s,unsigned int len)246 void vterm_write_nchars (char *s, unsigned int len)
247 {
248    SLsmg_Char_Type *p, *pmax;
249    char *smax;
250    SLsmg_Color_Type color;
251 
252    if (VTerm_Suspend_Update) return;
253 
254    if (VTerm_Display == NULL)
255      return;
256 
257    p = VTerm_Display[Current_Row];
258    pmax = p + VTerm_Num_Cols;
259    p += Current_Col;
260 
261 #if SLANG_VERSION >= 20000
262    if (p + len >= pmax)
263      memset ((char *) p, 0, (pmax - p) * sizeof (SLsmg_Char_Type));
264    else
265      memset ((char *) p, 0, len * sizeof (SLsmg_Char_Type));
266 #endif
267 
268    color = Current_Color;
269    smax = s + len;
270    while ((p < pmax) && (s < smax))
271      {
272 #if SLANG_VERSION < 20000
273 	*p = SLSMG_BUILD_CHAR(*s, color);
274 #else
275 	p->color = color;
276 	p->nchars = 1;
277 	p->wchars[0] = (unsigned char) *s;
278 #endif
279 	p++;
280 	s++;
281      }
282 
283    vterm_forward_cursor (len);
284 }
285 
286 #if SLANG_VERSION >= 20000
287 /* This is commented out until I can test it.  It was submitted by */
288 #if 0
289 /* // return number of wide characters written */
290 int vterm_write_nbytes (char *s, unsigned int len)
291 {
292    SLsmg_Char_Type *p, *pmin, *pmax;
293    char *smax, *s1;
294    int ncons;
295    SLsmg_Color_Type color;
296    SLwchar_Type wch;
297 
298    if (VTerm_Suspend_Update) return 0;
299 
300    if (VTerm_Display == NULL)
301       return 0;
302 
303    p = VTerm_Display[Current_Row];
304    pmax = p + VTerm_Num_Cols;
305    p += Current_Col;
306    pmin = p;
307 
308    memset ((char *) p, 0, (pmax - p) * sizeof (SLsmg_Char_Type));
309 
310    color = Current_Color;
311    smax = s + len;
312    while ((p < pmax) && (s < smax))
313    {
314       s1 = SLutf8_decode (s, smax, &wch, &ncons);
315       if (s1 == NULL)
316       {
317          vterm_forward_cursor (p - pmin);
318          vterm_write_nchars(s, smax - s);
319          return (p - pmin) + (smax - s);
320       }
321       else
322       {
323          p->color = color;
324          p->nchars = 1;
325          p->wchars[0] = wch;
326          p++;
327          s = s1;
328       }
329    }
330 
331    vterm_forward_cursor (p - pmin);
332 
333    return (p - pmin);
334 }
335 #endif
336 #endif
337