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