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