xref: /dragonfly/sys/dev/misc/syscons/sctermvar.h (revision b40e316c)
1 /*-
2  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer as
10  *    the first lines of this file unmodified.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/dev/syscons/sctermvar.h,v 1.1.2.2 2001/07/28 12:51:47 yokota Exp $
27  * $DragonFly: src/sys/dev/misc/syscons/sctermvar.h,v 1.2 2003/06/17 04:28:31 dillon Exp $
28  */
29 
30 #ifndef _DEV_SYSCONS_SCTERMVAR_H_
31 #define _DEV_SYSCONS_SCTERMVAR_H_
32 
33 /*
34  * building blocks for terminal emulator modules.
35  */
36 
37 static __inline void	sc_term_ins_line(scr_stat *scp, int y, int n, int ch,
38 					 int attr, int tail);
39 static __inline void	sc_term_del_line(scr_stat *scp, int y, int n, int ch,
40 					 int attr, int tail);
41 static __inline void	sc_term_ins_char(scr_stat *scp, int n, int ch,
42 					 int attr);
43 static __inline void	sc_term_del_char(scr_stat *scp, int n, int ch,
44 					 int attr);
45 static __inline void	sc_term_col(scr_stat *scp, int n);
46 static __inline void	sc_term_row(scr_stat *scp, int n);
47 static __inline void	sc_term_up(scr_stat *scp, int n, int head);
48 static __inline void	sc_term_down(scr_stat *scp, int n, int tail);
49 static __inline void	sc_term_left(scr_stat *scp, int n);
50 static __inline void	sc_term_right(scr_stat *scp, int n);
51 static __inline void	sc_term_up_scroll(scr_stat *scp, int n, int ch,
52 					  int attr, int head, int tail);
53 static __inline void	sc_term_down_scroll(scr_stat *scp, int n, int ch,
54 					    int attr, int head, int tail);
55 static __inline void	sc_term_clr_eos(scr_stat *scp, int n, int ch, int attr);
56 static __inline void	sc_term_clr_eol(scr_stat *scp, int n, int ch, int attr);
57 static __inline void	sc_term_tab(scr_stat *scp, int n);
58 static __inline void	sc_term_backtab(scr_stat *scp, int n);
59 static __inline void	sc_term_respond(scr_stat *scp, u_char *s);
60 static __inline void	sc_term_gen_print(scr_stat *scp, u_char **buf, int *len,
61 					  int attr);
62 static __inline void	sc_term_gen_scroll(scr_stat *scp, int ch, int attr);
63 
64 static __inline void
65 sc_term_ins_line(scr_stat *scp, int y, int n, int ch, int attr, int tail)
66 {
67 	if (tail <= 0)
68 		tail = scp->ysize;
69 	if (n < 1)
70 		n = 1;
71 	if (n > tail - y)
72 		n = tail - y;
73 	sc_vtb_ins(&scp->vtb, y*scp->xsize, n*scp->xsize, ch, attr);
74 	mark_for_update(scp, y*scp->xsize);
75 	mark_for_update(scp, scp->xsize*tail - 1);
76 }
77 
78 static __inline void
79 sc_term_del_line(scr_stat *scp, int y, int n, int ch, int attr, int tail)
80 {
81 	if (tail <= 0)
82 		tail = scp->ysize;
83 	if (n < 1)
84 		n = 1;
85 	if (n > tail - y)
86 		n = tail - y;
87 	sc_vtb_delete(&scp->vtb, y*scp->xsize, n*scp->xsize, ch, attr);
88 	mark_for_update(scp, y*scp->xsize);
89 	mark_for_update(scp, scp->xsize*tail - 1);
90 }
91 
92 static __inline void
93 sc_term_ins_char(scr_stat *scp, int n, int ch, int attr)
94 {
95 	int count;
96 
97 	if (n < 1)
98 		n = 1;
99 	if (n > scp->xsize - scp->xpos)
100 		n = scp->xsize - scp->xpos;
101 	count = scp->xsize - (scp->xpos + n);
102 	sc_vtb_move(&scp->vtb, scp->cursor_pos, scp->cursor_pos + n, count);
103 	sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, ch, attr);
104 	mark_for_update(scp, scp->cursor_pos);
105 	mark_for_update(scp, scp->cursor_pos + n + count - 1);
106 }
107 
108 static __inline void
109 sc_term_del_char(scr_stat *scp, int n, int ch, int attr)
110 {
111 	int count;
112 
113 	if (n < 1)
114 		n = 1;
115 	if (n > scp->xsize - scp->xpos)
116 		n = scp->xsize - scp->xpos;
117 	count = scp->xsize - (scp->xpos + n);
118 	sc_vtb_move(&scp->vtb, scp->cursor_pos + n, scp->cursor_pos, count);
119 	sc_vtb_erase(&scp->vtb, scp->cursor_pos + count, n, ch, attr);
120 	mark_for_update(scp, scp->cursor_pos);
121 	mark_for_update(scp, scp->cursor_pos + n + count - 1);
122 }
123 
124 static __inline void
125 sc_term_col(scr_stat *scp, int n)
126 {
127 	if (n < 1)
128 		n = 1;
129 	sc_move_cursor(scp, n - 1, scp->ypos);
130 }
131 
132 static __inline void
133 sc_term_row(scr_stat *scp, int n)
134 {
135 	if (n < 1)
136 		n = 1;
137 	sc_move_cursor(scp, scp->xpos, n - 1);
138 }
139 
140 static __inline void
141 sc_term_up(scr_stat *scp, int n, int head)
142 {
143 	if (n < 1)
144 		n = 1;
145 	n = imin(n, scp->ypos - head);
146 	if (n <= 0)
147 		return;
148 	sc_move_cursor(scp, scp->xpos, scp->ypos - n);
149 }
150 
151 static __inline void
152 sc_term_down(scr_stat *scp, int n, int tail)
153 {
154 	if (tail <= 0)
155 		tail = scp->ysize;
156 	if (n < 1)
157 		n = 1;
158 	n = imin(n, tail - scp->ypos - 1);
159 	if (n <= 0)
160 		return;
161 	sc_move_cursor(scp, scp->xpos, scp->ypos + n);
162 }
163 
164 static __inline void
165 sc_term_left(scr_stat *scp, int n)
166 {
167 	if (n < 1)
168 		n = 1;
169 	sc_move_cursor(scp, scp->xpos - n, scp->ypos);
170 }
171 
172 static __inline void
173 sc_term_right(scr_stat *scp, int n)
174 {
175 	if (n < 1)
176 		n = 1;
177 	sc_move_cursor(scp, scp->xpos + n, scp->ypos);
178 }
179 
180 static __inline void
181 sc_term_up_scroll(scr_stat *scp, int n, int ch, int attr, int head, int tail)
182 {
183 	if (tail <= 0)
184 		tail = scp->ysize;
185 	if (n < 1)
186 		n = 1;
187 	if (n <= scp->ypos - head) {
188 		sc_move_cursor(scp, scp->xpos, scp->ypos - n);
189 	} else {
190 		sc_term_ins_line(scp, head, n - (scp->ypos - head),
191 				 ch, attr, tail);
192 		sc_move_cursor(scp, scp->xpos, head);
193 	}
194 }
195 
196 static __inline void
197 sc_term_down_scroll(scr_stat *scp, int n, int ch, int attr, int head, int tail)
198 {
199 	if (tail <= 0)
200 		tail = scp->ysize;
201 	if (n < 1)
202 		n = 1;
203 	if (n < tail - scp->ypos) {
204 		sc_move_cursor(scp, scp->xpos, scp->ypos + n);
205 	} else {
206 		sc_term_del_line(scp, head, n - (tail - scp->ypos) + 1,
207 				 ch, attr, tail);
208 		sc_move_cursor(scp, scp->xpos, tail - 1);
209 	}
210 }
211 
212 static __inline void
213 sc_term_clr_eos(scr_stat *scp, int n, int ch, int attr)
214 {
215 	switch (n) {
216 	case 0: /* clear form cursor to end of display */
217 		sc_vtb_erase(&scp->vtb, scp->cursor_pos,
218 			     scp->xsize*scp->ysize - scp->cursor_pos,
219 			     ch, attr);
220 		mark_for_update(scp, scp->cursor_pos);
221 		mark_for_update(scp, scp->xsize*scp->ysize - 1);
222 		sc_remove_cutmarking(scp);
223 		break;
224 	case 1: /* clear from beginning of display to cursor */
225 		sc_vtb_erase(&scp->vtb, 0, scp->cursor_pos + 1, ch, attr);
226 		mark_for_update(scp, 0);
227 		mark_for_update(scp, scp->cursor_pos);
228 		sc_remove_cutmarking(scp);
229 		break;
230 	case 2: /* clear entire display */
231 		sc_vtb_erase(&scp->vtb, 0, scp->xsize*scp->ysize, ch, attr);
232 		mark_for_update(scp, 0);
233 		mark_for_update(scp, scp->xsize*scp->ysize - 1);
234 		sc_remove_cutmarking(scp);
235 		break;
236 	}
237 }
238 
239 static __inline void
240 sc_term_clr_eol(scr_stat *scp, int n, int ch, int attr)
241 {
242 	switch (n) {
243 	case 0: /* clear form cursor to end of line */
244 		sc_vtb_erase(&scp->vtb, scp->cursor_pos,
245 			     scp->xsize - scp->xpos, ch, attr);
246 		mark_for_update(scp, scp->cursor_pos);
247 		mark_for_update(scp, scp->cursor_pos +
248 				scp->xsize - 1 - scp->xpos);
249 		break;
250 	case 1: /* clear from beginning of line to cursor */
251 		sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos,
252 			     scp->xpos + 1, ch, attr);
253 		mark_for_update(scp, scp->ypos*scp->xsize);
254 		mark_for_update(scp, scp->cursor_pos);
255 		break;
256 	case 2: /* clear entire line */
257 		sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos,
258 			     scp->xsize, ch, attr);
259 		mark_for_update(scp, scp->ypos*scp->xsize);
260 		mark_for_update(scp, (scp->ypos + 1)*scp->xsize - 1);
261 		break;
262 	}
263 }
264 
265 static __inline void
266 sc_term_tab(scr_stat *scp, int n)
267 {
268 	int i;
269 
270 	if (n < 1)
271 		n = 1;
272 	i = (scp->xpos & ~7) + 8*n;
273 	if (i >= scp->xsize) {
274 		if (scp->ypos >= scp->ysize - 1) {
275 			scp->xpos = 0;
276 			scp->ypos++;
277 			scp->cursor_pos = scp->ypos*scp->xsize;
278 		} else
279 			sc_move_cursor(scp, 0, scp->ypos + 1);
280 	} else
281 		sc_move_cursor(scp, i, scp->ypos);
282 }
283 
284 static __inline void
285 sc_term_backtab(scr_stat *scp, int n)
286 {
287 	int i;
288 
289 	if (n < 1)
290 		n = 1;
291 	if ((i = scp->xpos & ~7) == scp->xpos)
292 		i -= 8*n;
293 	else
294 		i -= 8*(n - 1);
295 	if (i < 0)
296 		i = 0;
297 	sc_move_cursor(scp, i, scp->ypos);
298 }
299 
300 static __inline void
301 sc_term_respond(scr_stat *scp, u_char *s)
302 {
303 	sc_paste(scp, s, strlen(s));	/* XXX: not correct, don't use rmap */
304 }
305 
306 static __inline void
307 sc_term_gen_print(scr_stat *scp, u_char **buf, int *len, int attr)
308 {
309 	vm_offset_t p;
310 	u_char *ptr;
311 	u_char *map;
312  	int cnt;
313 	int l;
314 	int i;
315 
316 	ptr = *buf;
317 	l = *len;
318 
319 	if (PRINTABLE(*ptr)) {
320 		p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
321 		map = scp->sc->scr_map;
322 
323 		cnt = imin(l, scp->xsize - scp->xpos);
324 		i = cnt;
325 		do {
326 			/*
327 			 * gcc-2.6.3 generates poor (un)sign extension code.
328 			 * Casting the pointers in the following to volatile
329 			 * should have no effect, but in fact speeds up this
330 			 * inner loop from 26 to 18 cycles (+ cache misses)
331 			 * on i486's.
332 			 * XXX: out of date?
333 			 */
334 #define	UCVP(ucp)	((u_char volatile *)(ucp))
335 			p = sc_vtb_putchar(&scp->vtb, p,
336 					   UCVP(map)[*UCVP(ptr)], attr);
337 			++ptr;
338 			--i;
339 		} while ((i > 0) && PRINTABLE(*ptr));
340 
341 		l -= cnt - i;
342 		mark_for_update(scp, scp->cursor_pos);
343 		scp->cursor_pos += cnt - i;
344 		mark_for_update(scp, scp->cursor_pos - 1);
345 		scp->xpos += cnt - i;
346 
347 		if (scp->xpos >= scp->xsize) {
348 			scp->xpos = 0;
349 			scp->ypos++;
350 			/* we may have to scroll the screen */
351 		}
352 	} else {
353 		switch(*ptr) {
354 		case 0x07:
355 			sc_bell(scp, scp->bell_pitch, scp->bell_duration);
356 			break;
357 
358 		case 0x08:	/* non-destructive backspace */
359 			/* XXX */
360 			if (scp->cursor_pos > 0) {
361 #if 0
362 				mark_for_update(scp, scp->cursor_pos);
363 				scp->cursor_pos--;
364 				mark_for_update(scp, scp->cursor_pos);
365 #else
366 				scp->cursor_pos--;
367 #endif
368 				if (scp->xpos > 0) {
369 					scp->xpos--;
370 				} else {
371 					scp->xpos += scp->xsize - 1;
372 					scp->ypos--;
373 				}
374 			}
375 			break;
376 
377 		case 0x09:	/* non-destructive tab */
378 			sc_term_tab(scp, 1);
379 			/* we may have to scroll the screen */
380 #if 0
381 			mark_for_update(scp, scp->cursor_pos);
382 			scp->cursor_pos += (8 - scp->xpos % 8u);
383 			mark_for_update(scp, scp->cursor_pos);
384 			scp->xpos += (8 - scp->xpos % 8u);
385 			if (scp->xpos >= scp->xsize) {
386 				scp->xpos = 0;
387 				scp->ypos++;
388 			}
389 #endif
390 			break;
391 
392 		case 0x0a:	/* newline, same pos */
393 #if 0
394 			mark_for_update(scp, scp->cursor_pos);
395 			scp->cursor_pos += scp->xsize;
396 			mark_for_update(scp, scp->cursor_pos);
397 #else
398 			scp->cursor_pos += scp->xsize;
399 			/* we may have to scroll the screen */
400 #endif
401 			scp->ypos++;
402 			break;
403 
404 		case 0x0c:	/* form feed, clears screen */
405 			sc_clear_screen(scp);
406 			break;
407 
408 		case 0x0d:	/* return, return to pos 0 */
409 #if 0
410 			mark_for_update(scp, scp->cursor_pos);
411 			scp->cursor_pos -= scp->xpos;
412 			mark_for_update(scp, scp->cursor_pos);
413 #else
414 			scp->cursor_pos -= scp->xpos;
415 #endif
416 			scp->xpos = 0;
417 			break;
418 		}
419 		ptr++; l--;
420 	}
421 
422 	*buf = ptr;
423 	*len = l;
424 }
425 
426 static __inline void
427 sc_term_gen_scroll(scr_stat *scp, int ch, int attr)
428 {
429 	/* do we have to scroll ?? */
430 	if (scp->cursor_pos >= scp->ysize*scp->xsize) {
431 		sc_remove_cutmarking(scp);		/* XXX */
432 #ifndef SC_NO_HISTORY
433 		if (scp->history != NULL)
434 			sc_hist_save_one_line(scp, 0);	/* XXX */
435 #endif
436 		sc_vtb_delete(&scp->vtb, 0, scp->xsize, ch, attr);
437 		scp->cursor_pos -= scp->xsize;
438 		scp->ypos--;
439 		mark_all(scp);
440 	}
441 }
442 
443 #endif /* _DEV_SYSCONS_SCTERMVAR_H_ */
444