xref: /freebsd/sys/dev/syscons/sctermvar.h (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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$
27  */
28 
29 #ifndef _DEV_SYSCONS_SCTERMVAR_H_
30 #define _DEV_SYSCONS_SCTERMVAR_H_
31 
32 /*
33  * building blocks for terminal emulator modules.
34  */
35 
36 static __inline void	sc_term_ins_line(scr_stat *scp, int y, int n, int ch,
37 					 int attr, int tail);
38 static __inline void	sc_term_del_line(scr_stat *scp, int y, int n, int ch,
39 					 int attr, int tail);
40 static __inline void	sc_term_ins_char(scr_stat *scp, int n, int ch,
41 					 int attr);
42 static __inline void	sc_term_del_char(scr_stat *scp, int n, int ch,
43 					 int attr);
44 static __inline void	sc_term_col(scr_stat *scp, int n);
45 static __inline void	sc_term_row(scr_stat *scp, int n);
46 static __inline void	sc_term_up(scr_stat *scp, int n, int head);
47 static __inline void	sc_term_down(scr_stat *scp, int n, int tail);
48 static __inline void	sc_term_left(scr_stat *scp, int n);
49 static __inline void	sc_term_right(scr_stat *scp, int n);
50 static __inline void	sc_term_up_scroll(scr_stat *scp, int n, int ch,
51 					  int attr, int head, int tail);
52 static __inline void	sc_term_down_scroll(scr_stat *scp, int n, int ch,
53 					    int attr, int head, int tail);
54 static __inline void	sc_term_clr_eos(scr_stat *scp, int n, int ch, int attr);
55 static __inline void	sc_term_clr_eol(scr_stat *scp, int n, int ch, int attr);
56 static __inline void	sc_term_tab(scr_stat *scp, int n);
57 static __inline void	sc_term_backtab(scr_stat *scp, int n);
58 static __inline void	sc_term_respond(scr_stat *scp, u_char *s);
59 static __inline void	sc_term_gen_print(scr_stat *scp, u_char **buf, int *len,
60 					  int attr);
61 static __inline void	sc_term_gen_scroll(scr_stat *scp, int ch, int attr);
62 
63 static __inline void
64 sc_term_ins_line(scr_stat *scp, int y, int n, int ch, int attr, int tail)
65 {
66 	if (tail <= 0)
67 		tail = scp->ysize;
68 	if (n < 1)
69 		n = 1;
70 	if (n > tail - y)
71 		n = tail - y;
72 	sc_vtb_ins(&scp->vtb, y*scp->xsize, n*scp->xsize, ch, attr);
73 	mark_for_update(scp, y*scp->xsize);
74 	mark_for_update(scp, scp->xsize*tail - 1);
75 }
76 
77 static __inline void
78 sc_term_del_line(scr_stat *scp, int y, int n, int ch, int attr, int tail)
79 {
80 	if (tail <= 0)
81 		tail = scp->ysize;
82 	if (n < 1)
83 		n = 1;
84 	if (n > tail - y)
85 		n = tail - y;
86 	sc_vtb_delete(&scp->vtb, y*scp->xsize, n*scp->xsize, ch, attr);
87 	mark_for_update(scp, y*scp->xsize);
88 	mark_for_update(scp, scp->xsize*tail - 1);
89 }
90 
91 static __inline void
92 sc_term_ins_char(scr_stat *scp, int n, int ch, int attr)
93 {
94 	int count;
95 
96 	if (n < 1)
97 		n = 1;
98 	if (n > scp->xsize - scp->xpos)
99 		n = scp->xsize - scp->xpos;
100 	count = scp->xsize - (scp->xpos + n);
101 	sc_vtb_move(&scp->vtb, scp->cursor_pos, scp->cursor_pos + n, count);
102 	sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, ch, attr);
103 	mark_for_update(scp, scp->cursor_pos);
104 	mark_for_update(scp, scp->cursor_pos + n + count - 1);
105 }
106 
107 static __inline void
108 sc_term_del_char(scr_stat *scp, int n, int ch, int attr)
109 {
110 	int count;
111 
112 	if (n < 1)
113 		n = 1;
114 	if (n > scp->xsize - scp->xpos)
115 		n = scp->xsize - scp->xpos;
116 	count = scp->xsize - (scp->xpos + n);
117 	sc_vtb_move(&scp->vtb, scp->cursor_pos + n, scp->cursor_pos, count);
118 	sc_vtb_erase(&scp->vtb, scp->cursor_pos + count, n, ch, attr);
119 	mark_for_update(scp, scp->cursor_pos);
120 	mark_for_update(scp, scp->cursor_pos + n + count - 1);
121 }
122 
123 static __inline void
124 sc_term_col(scr_stat *scp, int n)
125 {
126 	if (n < 1)
127 		n = 1;
128 	sc_move_cursor(scp, n - 1, scp->ypos);
129 }
130 
131 static __inline void
132 sc_term_row(scr_stat *scp, int n)
133 {
134 	if (n < 1)
135 		n = 1;
136 	sc_move_cursor(scp, scp->xpos, n - 1);
137 }
138 
139 static __inline void
140 sc_term_up(scr_stat *scp, int n, int head)
141 {
142 	if (n < 1)
143 		n = 1;
144 	n = imin(n, scp->ypos - head);
145 	if (n <= 0)
146 		return;
147 	sc_move_cursor(scp, scp->xpos, scp->ypos - n);
148 }
149 
150 static __inline void
151 sc_term_down(scr_stat *scp, int n, int tail)
152 {
153 	if (tail <= 0)
154 		tail = scp->ysize;
155 	if (n < 1)
156 		n = 1;
157 	n = imin(n, tail - scp->ypos - 1);
158 	if (n <= 0)
159 		return;
160 	sc_move_cursor(scp, scp->xpos, scp->ypos + n);
161 }
162 
163 static __inline void
164 sc_term_left(scr_stat *scp, int n)
165 {
166 	if (n < 1)
167 		n = 1;
168 	sc_move_cursor(scp, scp->xpos - n, scp->ypos);
169 }
170 
171 static __inline void
172 sc_term_right(scr_stat *scp, int n)
173 {
174 	if (n < 1)
175 		n = 1;
176 	sc_move_cursor(scp, scp->xpos + n, scp->ypos);
177 }
178 
179 static __inline void
180 sc_term_up_scroll(scr_stat *scp, int n, int ch, int attr, int head, int tail)
181 {
182 	if (tail <= 0)
183 		tail = scp->ysize;
184 	if (n < 1)
185 		n = 1;
186 	if (n <= scp->ypos - head) {
187 		sc_move_cursor(scp, scp->xpos, scp->ypos - n);
188 	} else {
189 		sc_term_ins_line(scp, head, n - (scp->ypos - head),
190 				 ch, attr, tail);
191 		sc_move_cursor(scp, scp->xpos, head);
192 	}
193 }
194 
195 static __inline void
196 sc_term_down_scroll(scr_stat *scp, int n, int ch, int attr, int head, int tail)
197 {
198 	if (tail <= 0)
199 		tail = scp->ysize;
200 	if (n < 1)
201 		n = 1;
202 	if (n < tail - scp->ypos) {
203 		sc_move_cursor(scp, scp->xpos, scp->ypos + n);
204 	} else {
205 		sc_term_del_line(scp, head, n - (tail - scp->ypos) + 1,
206 				 ch, attr, tail);
207 		sc_move_cursor(scp, scp->xpos, tail - 1);
208 	}
209 }
210 
211 static __inline void
212 sc_term_clr_eos(scr_stat *scp, int n, int ch, int attr)
213 {
214 	switch (n) {
215 	case 0: /* clear form cursor to end of display */
216 		sc_vtb_erase(&scp->vtb, scp->cursor_pos,
217 			     scp->xsize*scp->ysize - scp->cursor_pos,
218 			     ch, attr);
219 		mark_for_update(scp, scp->cursor_pos);
220 		mark_for_update(scp, scp->xsize*scp->ysize - 1);
221 		sc_remove_cutmarking(scp);
222 		break;
223 	case 1: /* clear from beginning of display to cursor */
224 		sc_vtb_erase(&scp->vtb, 0, scp->cursor_pos, ch, attr);
225 		mark_for_update(scp, 0);
226 		mark_for_update(scp, scp->cursor_pos);
227 		sc_remove_cutmarking(scp);
228 		break;
229 	case 2: /* clear entire display */
230 		sc_vtb_erase(&scp->vtb, 0, scp->xsize*scp->ysize, ch, attr);
231 		mark_for_update(scp, 0);
232 		mark_for_update(scp, scp->xsize*scp->ysize - 1);
233 		sc_remove_cutmarking(scp);
234 		break;
235 	}
236 }
237 
238 static __inline void
239 sc_term_clr_eol(scr_stat *scp, int n, int ch, int attr)
240 {
241 	switch (n) {
242 	case 0: /* clear form cursor to end of line */
243 		sc_vtb_erase(&scp->vtb, scp->cursor_pos,
244 			     scp->xsize - scp->xpos, ch, attr);
245 		mark_for_update(scp, scp->cursor_pos);
246 		mark_for_update(scp, scp->cursor_pos +
247 				scp->xsize - 1 - scp->xpos);
248 		break;
249 	case 1: /* clear from beginning of line to cursor */
250 		sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos,
251 			     scp->xpos + 1, ch, attr);
252 		mark_for_update(scp, scp->ypos*scp->xsize);
253 		mark_for_update(scp, scp->cursor_pos);
254 		break;
255 	case 2: /* clear entire line */
256 		sc_vtb_erase(&scp->vtb, scp->cursor_pos - scp->xpos,
257 			     scp->xsize, ch, attr);
258 		mark_for_update(scp, scp->ypos*scp->xsize);
259 		mark_for_update(scp, (scp->ypos + 1)*scp->xsize - 1);
260 		break;
261 	}
262 }
263 
264 static __inline void
265 sc_term_tab(scr_stat *scp, int n)
266 {
267 	int i;
268 
269 	if (n < 1)
270 		n = 1;
271 	i = (scp->xpos & ~7) + 8*n;
272 	if (i >= scp->xsize)
273 		sc_move_cursor(scp, 0, scp->ypos + 1);
274 	else
275 		sc_move_cursor(scp, i, scp->ypos);
276 }
277 
278 static __inline void
279 sc_term_backtab(scr_stat *scp, int n)
280 {
281 	int i;
282 
283 	if (n < 1)
284 		n = 1;
285 	if ((i = scp->xpos & ~7) == scp->xpos)
286 		i -= 8*n;
287 	else
288 		i -= 8*(n - 1);
289 	if (i < 0)
290 		i = 0;
291 	sc_move_cursor(scp, i, scp->ypos);
292 }
293 
294 static __inline void
295 sc_term_respond(scr_stat *scp, u_char *s)
296 {
297 	sc_paste(scp, s, strlen(s));	/* XXX: not correct, don't use rmap */
298 }
299 
300 static __inline void
301 sc_term_gen_print(scr_stat *scp, u_char **buf, int *len, int attr)
302 {
303 	vm_offset_t p;
304 	u_char *ptr;
305 	u_char *map;
306  	int cnt;
307 	int l;
308 	int i;
309 
310 	ptr = *buf;
311 	l = *len;
312 
313 	if (PRINTABLE(*ptr)) {
314 		p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos);
315 		map = scp->sc->scr_map;
316 
317 		cnt = imin(l, scp->xsize - scp->xpos);
318 		i = cnt;
319 		do {
320 			/*
321 			 * gcc-2.6.3 generates poor (un)sign extension code.
322 			 * Casting the pointers in the following to volatile
323 			 * should have no effect, but in fact speeds up this
324 			 * inner loop from 26 to 18 cycles (+ cache misses)
325 			 * on i486's.
326 			 * XXX: out of date?
327 			 */
328 #define	UCVP(ucp)	((u_char volatile *)(ucp))
329 			p = sc_vtb_putchar(&scp->vtb, p,
330 					   UCVP(map)[*UCVP(ptr)], attr);
331 			++ptr;
332 			--i;
333 		} while ((i > 0) && PRINTABLE(*ptr));
334 
335 		l -= cnt - i;
336 		mark_for_update(scp, scp->cursor_pos);
337 		scp->cursor_pos += cnt - i;
338 		mark_for_update(scp, scp->cursor_pos - 1);
339 		scp->xpos += cnt - i;
340 
341 		if (scp->xpos >= scp->xsize) {
342 			scp->xpos = 0;
343 			scp->ypos++;
344 			/* we may have to scroll the screen */
345 		}
346 	} else {
347 		switch(*ptr) {
348 		case 0x07:
349 			sc_bell(scp, scp->bell_pitch, scp->bell_duration);
350 			break;
351 
352 		case 0x08:	/* non-destructive backspace */
353 			/* XXX */
354 			if (scp->cursor_pos > 0) {
355 #if 0
356 				mark_for_update(scp, scp->cursor_pos);
357 				scp->cursor_pos--;
358 				mark_for_update(scp, scp->cursor_pos);
359 #else
360 				scp->cursor_pos--;
361 #endif
362 				if (scp->xpos > 0) {
363 					scp->xpos--;
364 				} else {
365 					scp->xpos += scp->xsize - 1;
366 					scp->ypos--;
367 				}
368 			}
369 			break;
370 
371 		case 0x09:	/* non-destructive tab */
372 			sc_term_tab(scp, 1);
373 			/* we may have to scroll the screen */
374 #if 0
375 			mark_for_update(scp, scp->cursor_pos);
376 			scp->cursor_pos += (8 - scp->xpos % 8u);
377 			mark_for_update(scp, scp->cursor_pos);
378 			scp->xpos += (8 - scp->xpos % 8u);
379 			if (scp->xpos >= scp->xsize) {
380 				scp->xpos = 0;
381 				scp->ypos++;
382 			}
383 #endif
384 			break;
385 
386 		case 0x0a:	/* newline, same pos */
387 #if 0
388 			mark_for_update(scp, scp->cursor_pos);
389 			scp->cursor_pos += scp->xsize;
390 			mark_for_update(scp, scp->cursor_pos);
391 #else
392 			scp->cursor_pos += scp->xsize;
393 			/* we may have to scroll the screen */
394 #endif
395 			scp->ypos++;
396 			break;
397 
398 		case 0x0c:	/* form feed, clears screen */
399 			sc_clear_screen(scp);
400 			break;
401 
402 		case 0x0d:	/* return, return to pos 0 */
403 #if 0
404 			mark_for_update(scp, scp->cursor_pos);
405 			scp->cursor_pos -= scp->xpos;
406 			mark_for_update(scp, scp->cursor_pos);
407 #else
408 			scp->cursor_pos -= scp->xpos;
409 #endif
410 			scp->xpos = 0;
411 			break;
412 		}
413 		ptr++; l--;
414 	}
415 
416 	*buf = ptr;
417 	*len = l;
418 }
419 
420 static __inline void
421 sc_term_gen_scroll(scr_stat *scp, int ch, int attr)
422 {
423 	/* do we have to scroll ?? */
424 	if (scp->cursor_pos >= scp->ysize*scp->xsize) {
425 		sc_remove_cutmarking(scp);		/* XXX */
426 #ifndef SC_NO_HISTORY
427 		if (scp->history != NULL)
428 			sc_hist_save_one_line(scp, 0);	/* XXX */
429 #endif
430 		sc_vtb_delete(&scp->vtb, 0, scp->xsize, ch, attr);
431 		scp->cursor_pos -= scp->xsize;
432 		scp->ypos--;
433 		mark_all(scp);
434 	}
435 }
436 
437 #endif /* _DEV_SYSCONS_SCTERMVAR_H_ */
438