4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright 2016 Joyent, Inc.
32 * Polled I/O safe ANSI terminal emulator module;
33 * Supporting TERM types 'sun' and 'sun-color, parsing
34 * ANSI x3.64 escape sequences, and the like. (See wscons(7d)
35 * for more information).
39 * The functions in this file *must* be able to function in
40 * standalone mode, ie. on a quiesced system. In that state,
41 * access is single threaded, only one CPU is running.
42 * System services are NOT available.
44 * The following restrictions pertain to every function
47 * - CANNOT use the DDI or LDI interfaces
48 * - CANNOT call system services
49 * - CANNOT use mutexes
50 * - CANNOT wait for interrupts
51 * - CANNOT allocate memory
53 * All non-static functions in this file which:
54 * - Operates on tems and tem_vt_state
55 * - Not only called from standalone mode, i.e. has
56 * a "calledfrom" argument
57 * should assert this at the beginning:
59 * ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
60 * called_from == CALLED_FROM_STANDALONE);
63 #include <sys/types.h>
64 #include <sys/ascii.h>
65 #include <sys/visual_io.h>
68 #include <sys/tem_impl.h>
69 #include <sys/ksynch.h>
70 #include <sys/sysmacros.h>
71 #include <sys/mutex.h>
73 #include <sys/t_lock.h>
75 tem_safe_callbacks_t tem_safe_text_callbacks
= {
76 &tem_safe_text_display
,
78 &tem_safe_text_cursor
,
82 tem_safe_callbacks_t tem_safe_pix_callbacks
= {
83 &tem_safe_pix_display
,
86 &tem_safe_pix_bit2pix
,
91 static void tem_safe_control(struct tem_vt_state
*, uchar_t
,
92 cred_t
*, enum called_from
);
93 static void tem_safe_setparam(struct tem_vt_state
*, int, int);
94 static void tem_safe_selgraph(struct tem_vt_state
*);
95 static void tem_safe_chkparam(struct tem_vt_state
*, uchar_t
,
96 cred_t
*, enum called_from
);
97 static void tem_safe_getparams(struct tem_vt_state
*, uchar_t
,
98 cred_t
*, enum called_from
);
99 static void tem_safe_outch(struct tem_vt_state
*, uchar_t
,
100 cred_t
*, enum called_from
);
101 static void tem_safe_parse(struct tem_vt_state
*, uchar_t
,
102 cred_t
*, enum called_from
);
104 static void tem_safe_new_line(struct tem_vt_state
*,
105 cred_t
*, enum called_from
);
106 static void tem_safe_cr(struct tem_vt_state
*);
107 static void tem_safe_lf(struct tem_vt_state
*,
108 cred_t
*, enum called_from
);
109 static void tem_safe_send_data(struct tem_vt_state
*, cred_t
*,
111 static void tem_safe_cls(struct tem_vt_state
*,
112 cred_t
*, enum called_from
);
113 static void tem_safe_tab(struct tem_vt_state
*,
114 cred_t
*, enum called_from
);
115 static void tem_safe_back_tab(struct tem_vt_state
*,
116 cred_t
*, enum called_from
);
117 static void tem_safe_clear_tabs(struct tem_vt_state
*, int);
118 static void tem_safe_set_tab(struct tem_vt_state
*);
119 static void tem_safe_mv_cursor(struct tem_vt_state
*, int, int,
120 cred_t
*, enum called_from
);
121 static void tem_safe_shift(struct tem_vt_state
*, int, int,
122 cred_t
*, enum called_from
);
123 static void tem_safe_scroll(struct tem_vt_state
*, int, int,
124 int, int, cred_t
*, enum called_from
);
125 static void tem_safe_clear_chars(struct tem_vt_state
*tem
,
126 int count
, screen_pos_t row
, screen_pos_t col
,
127 cred_t
*credp
, enum called_from called_from
);
128 static void tem_safe_copy_area(struct tem_vt_state
*tem
,
129 screen_pos_t s_col
, screen_pos_t s_row
,
130 screen_pos_t e_col
, screen_pos_t e_row
,
131 screen_pos_t t_col
, screen_pos_t t_row
,
132 cred_t
*credp
, enum called_from called_from
);
133 static void tem_safe_image_display(struct tem_vt_state
*, uchar_t
*,
134 int, int, screen_pos_t
, screen_pos_t
,
135 cred_t
*, enum called_from
);
136 static void tem_safe_bell(struct tem_vt_state
*tem
,
137 enum called_from called_from
);
138 static void tem_safe_pix_clear_prom_output(struct tem_vt_state
*tem
,
139 cred_t
*credp
, enum called_from called_from
);
141 static void tem_safe_virtual_cls(struct tem_vt_state
*, int, screen_pos_t
,
143 static void tem_safe_virtual_display(struct tem_vt_state
*,
144 unsigned char *, int, screen_pos_t
, screen_pos_t
,
145 text_color_t
, text_color_t
);
146 static void tem_safe_virtual_copy(struct tem_vt_state
*, screen_pos_t
,
147 screen_pos_t
, screen_pos_t
, screen_pos_t
,
148 screen_pos_t
, screen_pos_t
);
149 static void tem_safe_align_cursor(struct tem_vt_state
*tem
);
150 static void bit_to_pix4(struct tem_vt_state
*tem
, uchar_t c
,
151 text_color_t fg_color
, text_color_t bg_color
);
152 static void bit_to_pix8(struct tem_vt_state
*tem
, uchar_t c
,
153 text_color_t fg_color
, text_color_t bg_color
);
154 static void bit_to_pix24(struct tem_vt_state
*tem
, uchar_t c
,
155 text_color_t fg_color
, text_color_t bg_color
);
156 static void bit_to_pix32(struct tem_vt_state
*tem
, uchar_t c
,
157 text_color_t fg_color
, text_color_t bg_color
);
160 /* Bk Rd Gr Br Bl Mg Cy Wh */
161 static text_color_t dim_xlate
[] = { 1, 5, 3, 7, 2, 6, 4, 8 };
162 static text_color_t brt_xlate
[] = { 9, 13, 11, 15, 10, 14, 12, 0 };
166 text_cmap_t cmap4_to_24
= {
168 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
169 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */
170 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff,
171 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff,
172 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
176 #define PIX4TO32(pix4) (uint32_t)( \
177 cmap4_to_24.red[pix4] << 16 | \
178 cmap4_to_24.green[pix4] << 8 | \
179 cmap4_to_24.blue[pix4])
181 #define INVERSE(ch) (ch ^ 0xff)
183 #define tem_safe_callback_display (*tems.ts_callbacks->tsc_display)
184 #define tem_safe_callback_copy (*tems.ts_callbacks->tsc_copy)
185 #define tem_safe_callback_cursor (*tems.ts_callbacks->tsc_cursor)
186 #define tem_safe_callback_cls (*tems.ts_callbacks->tsc_cls)
187 #define tem_safe_callback_bit2pix(tem, c, fg, bg) { \
188 ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL); \
189 (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
193 tem_safe_check_first_time(
194 struct tem_vt_state
*tem
,
196 enum called_from called_from
)
198 static int first_time
= 1;
200 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
201 called_from
== CALLED_FROM_STANDALONE
);
204 * Realign the console cursor. We did this in tem_init().
205 * However, drivers in the console stream may emit additional
206 * messages before we are ready. This causes text overwrite
207 * on the screen. This is a workaround.
213 if (tems
.ts_display_mode
== VIS_TEXT
) {
214 tem_safe_text_cursor(tem
, VIS_GET_CURSOR
, credp
, called_from
);
215 tem_safe_align_cursor(tem
);
220 * This entry point handles output requests from restricted contexts like
221 * kmdb, where services like mutexes are not available. This function
222 * is entered when OBP or when a kernel debugger (such as kmdb)
223 * are generating console output. In those cases, power management
224 * concerns are handled by the abort sequence initiation (ie. when
225 * the user hits L1+A or the equivalent to enter OBP or the debugger.).
226 * It is also entered when the kernel is panicing.
229 tem_safe_polled_write(
230 tem_vt_state_t tem_arg
,
234 struct tem_vt_state
*tem
= (struct tem_vt_state
*)tem_arg
;
237 _NOTE(NO_COMPETING_THREADS_NOW
)
238 _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT
)
241 if (!tem
->tvs_initialized
) {
245 tem_safe_check_first_time(tem
, kcred
, CALLED_FROM_STANDALONE
);
246 tem_safe_terminal_emulate(tem
, buf
, len
, NULL
, CALLED_FROM_STANDALONE
);
249 /* Process partial UTF-8 sequence. */
251 tem_safe_input_partial(struct tem_vt_state
*tem
, cred_t
*credp
,
252 enum called_from called_from
)
257 if (tem
->tvs_utf8_left
== 0)
260 for (i
= 0; i
< sizeof (tem
->tvs_utf8_partial
); i
++) {
261 c
= (tem
->tvs_utf8_partial
>> (24 - (i
<< 3))) & 0xff;
263 tem_safe_parse(tem
, c
, credp
, called_from
);
266 tem
->tvs_utf8_left
= 0;
267 tem
->tvs_utf8_partial
= 0;
271 * Handle UTF-8 sequences.
274 tem_safe_input_byte(struct tem_vt_state
*tem
, uchar_t c
, cred_t
*credp
,
275 enum called_from called_from
)
278 * Check for UTF-8 code points. In case of error fall back to
279 * 8-bit code. As we only have 8859-1 fonts for console, this will set
280 * the limits on what chars we actually can display, therefore we
281 * have to return to this code once we have solved the font issue.
283 if ((c
& 0x80) == 0x00) {
284 /* One-byte sequence. */
285 tem_safe_input_partial(tem
, credp
, called_from
);
286 tem_safe_parse(tem
, c
, credp
, called_from
);
289 if ((c
& 0xe0) == 0xc0) {
290 /* Two-byte sequence. */
291 tem_safe_input_partial(tem
, credp
, called_from
);
292 tem
->tvs_utf8_left
= 1;
293 tem
->tvs_utf8_partial
= c
;
296 if ((c
& 0xf0) == 0xe0) {
297 /* Three-byte sequence. */
298 tem_safe_input_partial(tem
, credp
, called_from
);
299 tem
->tvs_utf8_left
= 2;
300 tem
->tvs_utf8_partial
= c
;
303 if ((c
& 0xf8) == 0xf0) {
304 /* Four-byte sequence. */
305 tem_safe_input_partial(tem
, credp
, called_from
);
306 tem
->tvs_utf8_left
= 3;
307 tem
->tvs_utf8_partial
= c
;
310 if ((c
& 0xc0) == 0x80) {
312 if (tem
->tvs_utf8_left
== 0) {
313 tem_safe_parse(tem
, c
, credp
, called_from
);
316 tem
->tvs_utf8_left
--;
317 tem
->tvs_utf8_partial
= (tem
->tvs_utf8_partial
<< 8) | c
;
318 if (tem
->tvs_utf8_left
== 0) {
323 * Transform the sequence of 2 to 4 bytes to
327 u
= tem
->tvs_utf8_partial
;
328 b
= (u
>> 24) & 0xff;
329 if (b
!= 0) { /* Four-byte sequence */
331 b
= (u
>> 16) & 0xff;
332 v
= (v
<< 6) | (b
& 0x3f);
334 v
= (v
<< 6) | (b
& 0x3f);
336 v
= (v
<< 6) | (b
& 0x3f);
337 } else if ((b
= (u
>> 16) & 0xff) != 0) {
338 v
= b
& 0x0f; /* Three-byte sequence */
340 v
= (v
<< 6) | (b
& 0x3f);
342 v
= (v
<< 6) | (b
& 0x3f);
343 } else if ((b
= (u
>> 8) & 0xff) != 0) {
344 v
= b
& 0x1f; /* Two-byte sequence */
346 v
= (v
<< 6) | (b
& 0x3f);
349 /* Use '?' as replacement if needed. */
352 tem_safe_parse(tem
, v
, credp
, called_from
);
353 tem
->tvs_utf8_partial
= 0;
357 /* Anything left is illegal in UTF-8 sequence. */
358 tem_safe_input_partial(tem
, credp
, called_from
);
359 tem_safe_parse(tem
, c
, credp
, called_from
);
363 * This is the main entry point into the terminal emulator.
365 * For each data message coming downstream, ANSI assumes that it is composed
366 * of ASCII characters, which are treated as a byte-stream input to the
367 * parsing state machine. All data is parsed immediately -- there is
371 tem_safe_terminal_emulate(
372 struct tem_vt_state
*tem
,
376 enum called_from called_from
)
379 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
380 called_from
== CALLED_FROM_STANDALONE
);
382 if (tem
->tvs_isactive
)
383 tem_safe_callback_cursor(tem
,
384 VIS_HIDE_CURSOR
, credp
, called_from
);
386 for (; len
> 0; len
--, buf
++)
387 tem_safe_input_byte(tem
, *buf
, credp
, called_from
);
390 * Send the data we just got to the framebuffer.
392 tem_safe_send_data(tem
, credp
, called_from
);
394 if (tem
->tvs_isactive
)
395 tem_safe_callback_cursor(tem
,
396 VIS_DISPLAY_CURSOR
, credp
, called_from
);
400 * Display an rectangular image on the frame buffer using the
401 * mechanism appropriate for the system state being called
402 * from quiesced or normal (ie. use polled I/O vs. layered ioctls)
405 tems_safe_display(struct vis_consdisplay
*pda
, cred_t
*credp
,
406 enum called_from called_from
)
408 if (called_from
== CALLED_FROM_STANDALONE
)
409 tems
.ts_fb_polledio
->display(tems
.ts_fb_polledio
->arg
, pda
);
411 tems_display_layered(pda
, credp
);
415 * Copy a rectangle from one location to another on the frame buffer
416 * using the mechanism appropriate for the system state being called
417 * from, quiesced or normal (ie. use polled I/O vs. layered ioctls)
420 tems_safe_copy(struct vis_conscopy
*pca
, cred_t
*credp
,
421 enum called_from called_from
)
423 if (called_from
== CALLED_FROM_STANDALONE
)
424 tems
.ts_fb_polledio
->copy(tems
.ts_fb_polledio
->arg
, pca
);
426 tems_copy_layered(pca
, credp
);
430 * Display or hide a rectangular block text cursor of a specificsize
431 * at a specific location on frame buffer* using the mechanism
432 * appropriate for the system state being called from, quisced or
433 * normal (ie. use polled I/O vs. layered ioctls).
436 tems_safe_cursor(struct vis_conscursor
*pca
, cred_t
*credp
,
437 enum called_from called_from
)
439 if (called_from
== CALLED_FROM_STANDALONE
)
440 tems
.ts_fb_polledio
->cursor(tems
.ts_fb_polledio
->arg
, pca
);
442 tems_cursor_layered(pca
, credp
);
446 * send the appropriate control message or set state based on the
447 * value of the control character ch
451 tem_safe_control(struct tem_vt_state
*tem
, uchar_t ch
, cred_t
*credp
,
452 enum called_from called_from
)
454 tem
->tvs_state
= A_STATE_START
;
457 tem_safe_bell(tem
, called_from
);
461 tem_safe_mv_cursor(tem
,
462 tem
->tvs_c_cursor
.row
,
463 tem
->tvs_c_cursor
.col
- 1,
468 tem_safe_tab(tem
, credp
, called_from
);
473 * tem_safe_send_data(tem, credp, called_from);
474 * tem_safe_new_line(tem, credp, called_from);
479 tem_safe_send_data(tem
, credp
, called_from
);
480 tem_safe_lf(tem
, credp
, called_from
);
484 tem_safe_send_data(tem
, credp
, called_from
);
485 tem_safe_cls(tem
, credp
, called_from
);
489 tem_safe_send_data(tem
, credp
, called_from
);
494 tem
->tvs_state
= A_STATE_ESC
;
500 tem
->tvs_curparam
= 0;
501 tem
->tvs_paramval
= 0;
502 tem
->tvs_gotparam
= B_FALSE
;
503 /* clear the parameters */
504 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
505 tem
->tvs_params
[i
] = -1;
506 tem
->tvs_state
= A_STATE_CSI
;
511 tem_safe_back_tab(tem
, credp
, called_from
);
521 * if parameters [0..count - 1] are not set, set them to the value
526 tem_safe_setparam(struct tem_vt_state
*tem
, int count
, int newparam
)
530 for (i
= 0; i
< count
; i
++) {
531 if (tem
->tvs_params
[i
] == -1)
532 tem
->tvs_params
[i
] = newparam
;
538 * select graphics mode based on the param vals stored in a_params
541 tem_safe_selgraph(struct tem_vt_state
*tem
)
547 tem
->tvs_state
= A_STATE_START
;
549 curparam
= tem
->tvs_curparam
;
551 param
= tem
->tvs_params
[count
];
556 /* reset to initial normal settings */
557 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
558 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
559 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
562 case 1: /* Bold Intense */
563 tem
->tvs_flags
|= TEM_ATTR_BOLD
;
566 case 2: /* Faint Intense */
567 tem
->tvs_flags
&= ~TEM_ATTR_BOLD
;
571 tem
->tvs_flags
|= TEM_ATTR_BLINK
;
574 case 7: /* Reverse video */
575 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
576 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
578 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
582 case 30: /* black (grey) foreground */
583 case 31: /* red (light red) foreground */
584 case 32: /* green (light green) foreground */
585 case 33: /* brown (yellow) foreground */
586 case 34: /* blue (light blue) foreground */
587 case 35: /* magenta (light magenta) foreground */
588 case 36: /* cyan (light cyan) foreground */
589 case 37: /* white (bright white) foreground */
590 tem
->tvs_fg_color
= param
- 30;
591 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_FG
;
596 * Reset the foreground colour and brightness.
598 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
599 if (tems
.ts_init_color
.a_flags
& TEM_ATTR_BRIGHT_FG
)
600 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_FG
;
602 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_FG
;
605 case 40: /* black (grey) background */
606 case 41: /* red (light red) background */
607 case 42: /* green (light green) background */
608 case 43: /* brown (yellow) background */
609 case 44: /* blue (light blue) background */
610 case 45: /* magenta (light magenta) background */
611 case 46: /* cyan (light cyan) background */
612 case 47: /* white (bright white) background */
613 tem
->tvs_bg_color
= param
- 40;
614 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_BG
;
619 * Reset the background colour and brightness.
621 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
622 if (tems
.ts_init_color
.a_flags
& TEM_ATTR_BRIGHT_BG
)
623 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_BG
;
625 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_BG
;
628 case 90: /* black (grey) foreground */
629 case 91: /* red (light red) foreground */
630 case 92: /* green (light green) foreground */
631 case 93: /* brown (yellow) foreground */
632 case 94: /* blue (light blue) foreground */
633 case 95: /* magenta (light magenta) foreground */
634 case 96: /* cyan (light cyan) foreground */
635 case 97: /* white (bright white) foreground */
636 tem
->tvs_fg_color
= param
- 90;
637 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_FG
;
640 case 100: /* black (grey) background */
641 case 101: /* red (light red) background */
642 case 102: /* green (light green) background */
643 case 103: /* brown (yellow) background */
644 case 104: /* blue (light blue) background */
645 case 105: /* magenta (light magenta) background */
646 case 106: /* cyan (light cyan) background */
647 case 107: /* white (bright white) background */
648 tem
->tvs_bg_color
= param
- 100;
649 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_BG
;
658 } while (curparam
> 0);
662 * perform the appropriate action for the escape sequence
664 * General rule: This code does not validate the arguments passed.
665 * It assumes that the next lower level will do so.
668 tem_safe_chkparam(struct tem_vt_state
*tem
, uchar_t ch
, cred_t
*credp
,
669 enum called_from called_from
)
675 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
676 MUTEX_HELD(&tem
->tvs_lock
));
678 row
= tem
->tvs_c_cursor
.row
;
679 col
= tem
->tvs_c_cursor
.col
;
683 case 'm': /* select terminal graphics mode */
684 tem_safe_send_data(tem
, credp
, called_from
);
685 tem_safe_selgraph(tem
);
688 case '@': /* insert char */
689 tem_safe_setparam(tem
, 1, 1);
690 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_RIGHT
,
694 case 'A': /* cursor up */
695 tem_safe_setparam(tem
, 1, 1);
696 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], col
,
700 case 'd': /* VPA - vertical position absolute */
701 tem_safe_setparam(tem
, 1, 1);
702 tem_safe_mv_cursor(tem
, tem
->tvs_params
[0] - 1, col
,
706 case 'e': /* VPR - vertical position relative */
707 case 'B': /* cursor down */
708 tem_safe_setparam(tem
, 1, 1);
709 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], col
,
713 case 'a': /* HPR - horizontal position relative */
714 case 'C': /* cursor right */
715 tem_safe_setparam(tem
, 1, 1);
716 tem_safe_mv_cursor(tem
, row
, col
+ tem
->tvs_params
[0],
720 case '`': /* HPA - horizontal position absolute */
721 tem_safe_setparam(tem
, 1, 1);
722 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
726 case 'D': /* cursor left */
727 tem_safe_setparam(tem
, 1, 1);
728 tem_safe_mv_cursor(tem
, row
, col
- tem
->tvs_params
[0],
732 case 'E': /* CNL cursor next line */
733 tem_safe_setparam(tem
, 1, 1);
734 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], 0,
738 case 'F': /* CPL cursor previous line */
739 tem_safe_setparam(tem
, 1, 1);
740 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], 0,
744 case 'G': /* cursor horizontal position */
745 tem_safe_setparam(tem
, 1, 1);
746 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
750 case 'g': /* clear tabs */
751 tem_safe_setparam(tem
, 1, 0);
752 tem_safe_clear_tabs(tem
, tem
->tvs_params
[0]);
755 case 'f': /* HVP Horizontal and Vertical Position */
756 case 'H': /* CUP position cursor */
757 tem_safe_setparam(tem
, 2, 1);
758 tem_safe_mv_cursor(tem
,
759 tem
->tvs_params
[0] - 1,
760 tem
->tvs_params
[1] - 1,
764 case 'I': /* CHT - Cursor Horizontal Tab */
765 /* Not implemented */
768 case 'J': /* ED - Erase in Display */
769 tem_safe_send_data(tem
, credp
, called_from
);
770 tem_safe_setparam(tem
, 1, 0);
771 switch (tem
->tvs_params
[0]) {
773 /* erase cursor to end of screen */
774 /* FIRST erase cursor to end of line */
775 tem_safe_clear_chars(tem
,
776 tems
.ts_c_dimension
.width
-
777 tem
->tvs_c_cursor
.col
,
778 tem
->tvs_c_cursor
.row
,
779 tem
->tvs_c_cursor
.col
, credp
, called_from
);
781 /* THEN erase lines below the cursor */
782 for (row
= tem
->tvs_c_cursor
.row
+ 1;
783 row
< tems
.ts_c_dimension
.height
;
785 tem_safe_clear_chars(tem
,
786 tems
.ts_c_dimension
.width
,
787 row
, 0, credp
, called_from
);
792 /* erase beginning of screen to cursor */
793 /* FIRST erase lines above the cursor */
795 row
< tem
->tvs_c_cursor
.row
;
797 tem_safe_clear_chars(tem
,
798 tems
.ts_c_dimension
.width
,
799 row
, 0, credp
, called_from
);
801 /* THEN erase beginning of line to cursor */
802 tem_safe_clear_chars(tem
,
803 tem
->tvs_c_cursor
.col
+ 1,
804 tem
->tvs_c_cursor
.row
,
805 0, credp
, called_from
);
809 /* erase whole screen */
811 row
< tems
.ts_c_dimension
.height
;
813 tem_safe_clear_chars(tem
,
814 tems
.ts_c_dimension
.width
,
815 row
, 0, credp
, called_from
);
821 case 'K': /* EL - Erase in Line */
822 tem_safe_send_data(tem
, credp
, called_from
);
823 tem_safe_setparam(tem
, 1, 0);
824 switch (tem
->tvs_params
[0]) {
826 /* erase cursor to end of line */
827 tem_safe_clear_chars(tem
,
828 (tems
.ts_c_dimension
.width
-
829 tem
->tvs_c_cursor
.col
),
830 tem
->tvs_c_cursor
.row
,
831 tem
->tvs_c_cursor
.col
,
836 /* erase beginning of line to cursor */
837 tem_safe_clear_chars(tem
,
838 tem
->tvs_c_cursor
.col
+ 1,
839 tem
->tvs_c_cursor
.row
,
840 0, credp
, called_from
);
844 /* erase whole line */
845 tem_safe_clear_chars(tem
,
846 tems
.ts_c_dimension
.width
,
847 tem
->tvs_c_cursor
.row
,
848 0, credp
, called_from
);
853 case 'L': /* insert line */
854 tem_safe_send_data(tem
, credp
, called_from
);
855 tem_safe_setparam(tem
, 1, 1);
857 tem
->tvs_c_cursor
.row
,
858 tems
.ts_c_dimension
.height
- 1,
859 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
863 case 'M': /* delete line */
864 tem_safe_send_data(tem
, credp
, called_from
);
865 tem_safe_setparam(tem
, 1, 1);
867 tem
->tvs_c_cursor
.row
,
868 tems
.ts_c_dimension
.height
- 1,
869 tem
->tvs_params
[0], TEM_SCROLL_UP
,
873 case 'P': /* DCH - delete char */
874 tem_safe_setparam(tem
, 1, 1);
875 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_LEFT
,
879 case 'S': /* scroll up */
880 tem_safe_send_data(tem
, credp
, called_from
);
881 tem_safe_setparam(tem
, 1, 1);
882 tem_safe_scroll(tem
, 0,
883 tems
.ts_c_dimension
.height
- 1,
884 tem
->tvs_params
[0], TEM_SCROLL_UP
,
888 case 'T': /* scroll down */
889 tem_safe_send_data(tem
, credp
, called_from
);
890 tem_safe_setparam(tem
, 1, 1);
891 tem_safe_scroll(tem
, 0,
892 tems
.ts_c_dimension
.height
- 1,
893 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
897 case 'X': /* erase char */
898 tem_safe_setparam(tem
, 1, 1);
899 tem_safe_clear_chars(tem
,
901 tem
->tvs_c_cursor
.row
,
902 tem
->tvs_c_cursor
.col
,
906 case 'Z': /* cursor backward tabulation */
907 tem_safe_setparam(tem
, 1, 1);
910 * Rule exception - We do sanity checking here.
912 * Restrict the count to a sane value to keep from
913 * looping for a long time. There can't be more than one
914 * tab stop per column, so use that as a limit.
916 if (tem
->tvs_params
[0] > tems
.ts_c_dimension
.width
)
917 tem
->tvs_params
[0] = tems
.ts_c_dimension
.width
;
919 for (i
= 0; i
< tem
->tvs_params
[0]; i
++)
920 tem_safe_back_tab(tem
, credp
, called_from
);
923 tem
->tvs_state
= A_STATE_START
;
928 * Gather the parameters of an ANSI escape sequence
931 tem_safe_getparams(struct tem_vt_state
*tem
, uchar_t ch
,
932 cred_t
*credp
, enum called_from called_from
)
934 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
935 MUTEX_HELD(&tem
->tvs_lock
));
937 if (ch
>= '0' && ch
<= '9') {
938 tem
->tvs_paramval
= ((tem
->tvs_paramval
* 10) + (ch
- '0'));
939 tem
->tvs_gotparam
= B_TRUE
; /* Remember got parameter */
940 return; /* Return immediately */
941 } else if (tem
->tvs_state
== A_STATE_CSI_EQUAL
||
942 tem
->tvs_state
== A_STATE_CSI_QMARK
) {
943 tem
->tvs_state
= A_STATE_START
;
945 if (tem
->tvs_curparam
< TEM_MAXPARAMS
) {
946 if (tem
->tvs_gotparam
) {
947 /* get the parameter value */
948 tem
->tvs_params
[tem
->tvs_curparam
] =
955 /* Restart parameter search */
956 tem
->tvs_gotparam
= B_FALSE
;
957 tem
->tvs_paramval
= 0; /* No parame value yet */
959 /* Handle escape sequence */
960 tem_safe_chkparam(tem
, ch
, credp
, called_from
);
966 * Add character to internal buffer.
967 * When its full, send it to the next layer.
971 tem_safe_outch(struct tem_vt_state
*tem
, uchar_t ch
,
972 cred_t
*credp
, enum called_from called_from
)
975 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
976 called_from
== CALLED_FROM_STANDALONE
);
978 /* buffer up the character until later */
980 tem
->tvs_outbuf
[tem
->tvs_outindex
++] = ch
;
981 tem
->tvs_c_cursor
.col
++;
982 if (tem
->tvs_c_cursor
.col
>= tems
.ts_c_dimension
.width
) {
983 tem_safe_send_data(tem
, credp
, called_from
);
984 tem_safe_new_line(tem
, credp
, called_from
);
989 tem_safe_new_line(struct tem_vt_state
*tem
,
990 cred_t
*credp
, enum called_from called_from
)
993 tem_safe_lf(tem
, credp
, called_from
);
997 tem_safe_cr(struct tem_vt_state
*tem
)
999 tem
->tvs_c_cursor
.col
= 0;
1000 tem_safe_align_cursor(tem
);
1004 tem_safe_lf(struct tem_vt_state
*tem
,
1005 cred_t
*credp
, enum called_from called_from
)
1009 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
1010 MUTEX_HELD(&tem
->tvs_lock
));
1013 * Sanity checking notes:
1014 * . a_nscroll was validated when it was set.
1015 * . Regardless of that, tem_safe_scroll and tem_safe_mv_cursor
1016 * will prevent anything bad from happening.
1018 row
= tem
->tvs_c_cursor
.row
+ 1;
1020 if (row
>= tems
.ts_c_dimension
.height
) {
1021 if (tem
->tvs_nscroll
!= 0) {
1022 tem_safe_scroll(tem
, 0,
1023 tems
.ts_c_dimension
.height
- 1,
1024 tem
->tvs_nscroll
, TEM_SCROLL_UP
,
1025 credp
, called_from
);
1026 row
= tems
.ts_c_dimension
.height
-
1028 } else { /* no scroll */
1030 * implement Esc[#r when # is zero. This means no
1031 * scroll but just return cursor to top of screen,
1032 * do not clear screen.
1038 tem_safe_mv_cursor(tem
, row
, tem
->tvs_c_cursor
.col
,
1039 credp
, called_from
);
1041 if (tem
->tvs_nscroll
== 0) {
1042 /* erase rest of cursor line */
1043 tem_safe_clear_chars(tem
,
1044 tems
.ts_c_dimension
.width
-
1045 tem
->tvs_c_cursor
.col
,
1046 tem
->tvs_c_cursor
.row
,
1047 tem
->tvs_c_cursor
.col
,
1048 credp
, called_from
);
1052 tem_safe_align_cursor(tem
);
1056 tem_safe_send_data(struct tem_vt_state
*tem
, cred_t
*credp
,
1057 enum called_from called_from
)
1059 text_color_t fg_color
;
1060 text_color_t bg_color
;
1062 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
1063 MUTEX_HELD(&tem
->tvs_lock
));
1065 if (tem
->tvs_outindex
== 0) {
1066 tem_safe_align_cursor(tem
);
1070 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_REVERSE
);
1071 tem_safe_virtual_display(tem
,
1072 tem
->tvs_outbuf
, tem
->tvs_outindex
,
1073 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
1074 fg_color
, bg_color
);
1076 if (tem
->tvs_isactive
) {
1078 * Call the primitive to render this data.
1080 tem_safe_callback_display(tem
,
1081 tem
->tvs_outbuf
, tem
->tvs_outindex
,
1082 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
1084 credp
, called_from
);
1087 tem
->tvs_outindex
= 0;
1089 tem_safe_align_cursor(tem
);
1094 * We have just done something to the current output point. Reset the start
1095 * point for the buffered data in a_outbuf. There shouldn't be any data
1099 tem_safe_align_cursor(struct tem_vt_state
*tem
)
1101 tem
->tvs_s_cursor
.row
= tem
->tvs_c_cursor
.row
;
1102 tem
->tvs_s_cursor
.col
= tem
->tvs_c_cursor
.col
;
1106 * State machine parser based on the current state and character input
1107 * major terminations are to control character or normal character
1111 tem_safe_parse(struct tem_vt_state
*tem
, uchar_t ch
,
1112 cred_t
*credp
, enum called_from called_from
)
1116 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
1117 MUTEX_HELD(&tem
->tvs_lock
));
1119 if (tem
->tvs_state
== A_STATE_START
) { /* Normal state? */
1120 if (ch
== A_CSI
|| ch
== A_ESC
|| ch
< ' ') {
1122 tem_safe_control(tem
, ch
, credp
, called_from
);
1125 tem_safe_outch(tem
, ch
, credp
, called_from
);
1130 /* In <ESC> sequence */
1131 if (tem
->tvs_state
!= A_STATE_ESC
) { /* Need to get parameters? */
1132 if (tem
->tvs_state
!= A_STATE_CSI
) {
1133 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1139 tem
->tvs_state
= A_STATE_CSI_QMARK
;
1142 tem
->tvs_state
= A_STATE_CSI_EQUAL
;
1146 * As defined below, this sequence
1147 * saves the cursor. However, Sun
1148 * defines ESC[s as reset. We resolved
1149 * the conflict by selecting reset as it
1150 * is exported in the termcap file for
1151 * sun-mon, while the "save cursor"
1152 * definition does not exist anywhere in
1154 * However, having no coherent
1155 * definition of reset, we have not
1161 * tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1162 * tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1163 * tem->tvs_state = A_STATE_START;
1166 tem
->tvs_state
= A_STATE_START
;
1169 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1170 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1171 tem
->tvs_state
= A_STATE_START
;
1173 case 'p': /* sunbow */
1174 tem_safe_send_data(tem
, credp
, called_from
);
1176 * Don't set anything if we are
1177 * already as we want to be.
1179 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
1180 tem
->tvs_flags
&= ~TEM_ATTR_SCREEN_REVERSE
;
1182 * If we have switched the characters to be the
1183 * inverse from the screen, then switch them as
1184 * well to keep them the inverse of the screen.
1186 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
)
1187 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1189 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1191 tem_safe_cls(tem
, credp
, called_from
);
1192 tem
->tvs_state
= A_STATE_START
;
1194 case 'q': /* sunwob */
1195 tem_safe_send_data(tem
, credp
, called_from
);
1197 * Don't set anything if we are
1198 * already where as we want to be.
1200 if (!(tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
)) {
1201 tem
->tvs_flags
|= TEM_ATTR_SCREEN_REVERSE
;
1203 * If we have switched the characters to be the
1204 * inverse from the screen, then switch them as
1205 * well to keep them the inverse of the screen.
1207 if (!(tem
->tvs_flags
& TEM_ATTR_REVERSE
))
1208 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1210 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1213 tem_safe_cls(tem
, credp
, called_from
);
1214 tem
->tvs_state
= A_STATE_START
;
1216 case 'r': /* sunscrl */
1218 * Rule exception: check for validity here.
1220 tem
->tvs_nscroll
= tem
->tvs_paramval
;
1221 if (tem
->tvs_nscroll
> tems
.ts_c_dimension
.height
)
1222 tem
->tvs_nscroll
= tems
.ts_c_dimension
.height
;
1223 if (tem
->tvs_nscroll
< 0)
1224 tem
->tvs_nscroll
= 1;
1225 tem
->tvs_state
= A_STATE_START
;
1228 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1233 /* Previous char was <ESC> */
1235 tem
->tvs_curparam
= 0;
1236 tem
->tvs_paramval
= 0;
1237 tem
->tvs_gotparam
= B_FALSE
;
1238 /* clear the parameters */
1239 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
1240 tem
->tvs_params
[i
] = -1;
1241 tem
->tvs_state
= A_STATE_CSI
;
1242 } else if (ch
== 'Q') { /* <ESC>Q ? */
1243 tem
->tvs_state
= A_STATE_START
;
1244 } else if (ch
== 'C') { /* <ESC>C ? */
1245 tem
->tvs_state
= A_STATE_START
;
1247 tem
->tvs_state
= A_STATE_START
;
1249 /* ESC c resets display */
1250 tem_safe_reset_display(tem
, credp
, called_from
,
1252 } else if (ch
== 'H') {
1253 /* ESC H sets a tab */
1254 tem_safe_set_tab(tem
);
1255 } else if (ch
== '7') {
1256 /* ESC 7 Save Cursor position */
1257 tem
->tvs_r_cursor
.row
= tem
->tvs_c_cursor
.row
;
1258 tem
->tvs_r_cursor
.col
= tem
->tvs_c_cursor
.col
;
1259 } else if (ch
== '8') {
1260 /* ESC 8 Restore Cursor position */
1261 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1262 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1263 /* check for control chars */
1264 } else if (ch
< ' ') {
1265 tem_safe_control(tem
, ch
, credp
, called_from
);
1267 tem_safe_outch(tem
, ch
, credp
, called_from
);
1274 tem_safe_bell(struct tem_vt_state
*tem
, enum called_from called_from
)
1276 if (called_from
== CALLED_FROM_STANDALONE
)
1277 (void) beep_polled(BEEP_CONSOLE
);
1279 (void) beep(BEEP_CONSOLE
);
1284 tem_safe_scroll(struct tem_vt_state
*tem
, int start
, int end
, int count
,
1285 int direction
, cred_t
*credp
, enum called_from called_from
)
1290 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1291 called_from
== CALLED_FROM_STANDALONE
);
1293 lines_affected
= end
- start
+ 1;
1294 if (count
> lines_affected
)
1295 count
= lines_affected
;
1299 switch (direction
) {
1301 if (count
< lines_affected
) {
1302 tem_safe_copy_area(tem
, 0, start
+ count
,
1303 tems
.ts_c_dimension
.width
- 1, end
,
1304 0, start
, credp
, called_from
);
1306 for (row
= (end
- count
) + 1; row
<= end
; row
++) {
1307 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1308 row
, 0, credp
, called_from
);
1312 case TEM_SCROLL_DOWN
:
1313 if (count
< lines_affected
) {
1314 tem_safe_copy_area(tem
, 0, start
,
1315 tems
.ts_c_dimension
.width
- 1,
1316 end
- count
, 0, start
+ count
,
1317 credp
, called_from
);
1319 for (row
= start
; row
< start
+ count
; row
++) {
1320 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1321 row
, 0, credp
, called_from
);
1328 tem_safe_copy_area(struct tem_vt_state
*tem
,
1329 screen_pos_t s_col
, screen_pos_t s_row
,
1330 screen_pos_t e_col
, screen_pos_t e_row
,
1331 screen_pos_t t_col
, screen_pos_t t_row
,
1332 cred_t
*credp
, enum called_from called_from
)
1337 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1338 called_from
== CALLED_FROM_STANDALONE
);
1340 if (s_col
< 0 || s_row
< 0 ||
1341 e_col
< 0 || e_row
< 0 ||
1342 t_col
< 0 || t_row
< 0 ||
1343 s_col
>= tems
.ts_c_dimension
.width
||
1344 e_col
>= tems
.ts_c_dimension
.width
||
1345 t_col
>= tems
.ts_c_dimension
.width
||
1346 s_row
>= tems
.ts_c_dimension
.height
||
1347 e_row
>= tems
.ts_c_dimension
.height
||
1348 t_row
>= tems
.ts_c_dimension
.height
)
1351 if (s_row
> e_row
|| s_col
> e_col
)
1354 rows
= e_row
- s_row
+ 1;
1355 cols
= e_col
- s_col
+ 1;
1356 if (t_row
+ rows
> tems
.ts_c_dimension
.height
||
1357 t_col
+ cols
> tems
.ts_c_dimension
.width
)
1360 tem_safe_virtual_copy(tem
,
1365 if (!tem
->tvs_isactive
)
1368 tem_safe_callback_copy(tem
, s_col
, s_row
,
1369 e_col
, e_row
, t_col
, t_row
, credp
, called_from
);
1373 tem_safe_clear_chars(struct tem_vt_state
*tem
, int count
, screen_pos_t row
,
1374 screen_pos_t col
, cred_t
*credp
, enum called_from called_from
)
1376 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1377 called_from
== CALLED_FROM_STANDALONE
);
1379 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
1380 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
1385 * Note that very large values of "count" could cause col+count
1386 * to overflow, so we check "count" independently.
1388 if (count
> tems
.ts_c_dimension
.width
||
1389 col
+ count
> tems
.ts_c_dimension
.width
)
1390 count
= tems
.ts_c_dimension
.width
- col
;
1392 tem_safe_virtual_cls(tem
, count
, row
, col
);
1394 if (!tem
->tvs_isactive
)
1397 tem_safe_callback_cls(tem
, count
, row
, col
, credp
, called_from
);
1402 tem_safe_text_display(struct tem_vt_state
*tem
, uchar_t
*string
,
1403 int count
, screen_pos_t row
, screen_pos_t col
,
1404 text_color_t fg_color
, text_color_t bg_color
,
1405 cred_t
*credp
, enum called_from called_from
)
1407 struct vis_consdisplay da
;
1409 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1410 called_from
== CALLED_FROM_STANDALONE
);
1413 da
.width
= (screen_size_t
)count
;
1417 da
.fg_color
= fg_color
;
1418 da
.bg_color
= bg_color
;
1420 tems_safe_display(&da
, credp
, called_from
);
1424 * This function is used to blit a rectangular color image,
1425 * unperturbed on the underlying framebuffer, to render
1426 * icons and pictures. The data is a pixel pattern that
1427 * fills a rectangle bounded to the width and height parameters.
1428 * The color pixel data must to be pre-adjusted by the caller
1429 * for the current video depth.
1431 * This function is unused now.
1435 tem_safe_image_display(struct tem_vt_state
*tem
, uchar_t
*image
,
1436 int height
, int width
, screen_pos_t row
, screen_pos_t col
,
1437 cred_t
*credp
, enum called_from called_from
)
1439 struct vis_consdisplay da
;
1441 mutex_enter(&tems
.ts_lock
);
1442 mutex_enter(&tem
->tvs_lock
);
1445 da
.width
= (screen_size_t
)width
;
1446 da
.height
= (screen_size_t
)height
;
1450 tems_safe_display(&da
, credp
, called_from
);
1452 mutex_exit(&tem
->tvs_lock
);
1453 mutex_exit(&tems
.ts_lock
);
1459 tem_safe_text_copy(struct tem_vt_state
*tem
,
1460 screen_pos_t s_col
, screen_pos_t s_row
,
1461 screen_pos_t e_col
, screen_pos_t e_row
,
1462 screen_pos_t t_col
, screen_pos_t t_row
,
1463 cred_t
*credp
, enum called_from called_from
)
1465 struct vis_conscopy da
;
1467 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1468 called_from
== CALLED_FROM_STANDALONE
);
1477 tems_safe_copy(&da
, credp
, called_from
);
1481 tem_safe_text_cls(struct tem_vt_state
*tem
,
1482 int count
, screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1483 enum called_from called_from
)
1485 struct vis_consdisplay da
;
1487 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1488 called_from
== CALLED_FROM_STANDALONE
);
1490 da
.data
= tems
.ts_blank_line
;
1491 da
.width
= (screen_size_t
)count
;
1495 tem_safe_get_color(tem
, &da
.fg_color
, &da
.bg_color
,
1496 TEM_ATTR_SCREEN_REVERSE
);
1497 tems_safe_display(&da
, credp
, called_from
);
1501 tem_safe_pix_display(struct tem_vt_state
*tem
,
1502 uchar_t
*string
, int count
,
1503 screen_pos_t row
, screen_pos_t col
,
1504 text_color_t fg_color
, text_color_t bg_color
,
1505 cred_t
*credp
, enum called_from called_from
)
1507 struct vis_consdisplay da
;
1510 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1511 called_from
== CALLED_FROM_STANDALONE
);
1513 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
1514 da
.width
= tems
.ts_font
.width
;
1515 da
.height
= tems
.ts_font
.height
;
1516 da
.row
= (row
* da
.height
) + tems
.ts_p_offset
.y
;
1517 da
.col
= (col
* da
.width
) + tems
.ts_p_offset
.x
;
1519 for (i
= 0; i
< count
; i
++) {
1520 tem_safe_callback_bit2pix(tem
, string
[i
], fg_color
, bg_color
);
1521 tems_safe_display(&da
, credp
, called_from
);
1527 tem_safe_pix_copy(struct tem_vt_state
*tem
,
1528 screen_pos_t s_col
, screen_pos_t s_row
,
1529 screen_pos_t e_col
, screen_pos_t e_row
,
1530 screen_pos_t t_col
, screen_pos_t t_row
,
1532 enum called_from called_from
)
1534 struct vis_conscopy ma
;
1535 static boolean_t need_clear
= B_TRUE
;
1537 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1538 called_from
== CALLED_FROM_STANDALONE
);
1540 if (need_clear
&& tem
->tvs_first_line
> 0) {
1542 * Clear OBP output above our kernel console term
1543 * when our kernel console term begins to scroll up,
1544 * we hope it is user friendly.
1545 * (Also see comments on tem_safe_pix_clear_prom_output)
1547 * This is only one time call.
1549 tem_safe_pix_clear_prom_output(tem
, credp
, called_from
);
1551 need_clear
= B_FALSE
;
1553 ma
.s_row
= s_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1554 ma
.e_row
= (e_row
+ 1) * tems
.ts_font
.height
+ tems
.ts_p_offset
.y
- 1;
1555 ma
.t_row
= t_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1558 * Check if we're in process of clearing OBP's columns area,
1559 * which only happens when term scrolls up a whole line.
1561 if (tem
->tvs_first_line
> 0 && t_row
< s_row
&& t_col
== 0 &&
1562 e_col
== tems
.ts_c_dimension
.width
- 1) {
1564 * We need to clear OBP's columns area outside our kernel
1565 * console term. So that we set ma.e_col to entire row here.
1567 ma
.s_col
= s_col
* tems
.ts_font
.width
;
1568 ma
.e_col
= tems
.ts_p_dimension
.width
- 1;
1570 ma
.t_col
= t_col
* tems
.ts_font
.width
;
1572 ma
.s_col
= s_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1573 ma
.e_col
= (e_col
+ 1) * tems
.ts_font
.width
+
1574 tems
.ts_p_offset
.x
- 1;
1575 ma
.t_col
= t_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1578 tems_safe_copy(&ma
, credp
, called_from
);
1580 if (tem
->tvs_first_line
> 0 && t_row
< s_row
) {
1581 /* We have scrolled up (s_row - t_row) rows. */
1582 tem
->tvs_first_line
-= (s_row
- t_row
);
1583 if (tem
->tvs_first_line
<= 0) {
1584 /* All OBP rows have been cleared. */
1585 tem
->tvs_first_line
= 0;
1592 tem_safe_pix_bit2pix(struct tem_vt_state
*tem
, unsigned char c
,
1593 unsigned char fg
, unsigned char bg
)
1595 void (*fp
)(struct tem_vt_state
*, unsigned char,
1596 unsigned char, unsigned char);
1598 switch (tems
.ts_pdepth
) {
1620 * This function only clears count of columns in one row
1623 tem_safe_pix_cls(struct tem_vt_state
*tem
, int count
,
1624 screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1625 enum called_from called_from
)
1627 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1628 called_from
== CALLED_FROM_STANDALONE
);
1630 tem_safe_pix_cls_range(tem
, row
, 1, tems
.ts_p_offset
.y
,
1631 col
, count
, tems
.ts_p_offset
.x
, B_FALSE
, credp
, called_from
);
1635 * This function clears OBP output above our kernel console term area
1636 * because OBP's term may have a bigger terminal window than that of
1637 * our kernel console term. So we need to clear OBP output garbage outside
1638 * of our kernel console term at a proper time, which is when the first
1639 * row output of our kernel console term scrolls at the first screen line.
1641 * _________________________________
1642 * | _____________________ | ---> OBP's bigger term window
1647 * |_|_|___________________|_______|
1648 * | | | ---> first line
1649 * | |___________________|---> our kernel console term window
1651 * |---> columns area to be cleared
1653 * This function only takes care of the output above our kernel console term,
1654 * and tem_prom_scroll_up takes care of columns area outside of our kernel
1658 tem_safe_pix_clear_prom_output(struct tem_vt_state
*tem
, cred_t
*credp
,
1659 enum called_from called_from
)
1661 int nrows
, ncols
, width
, height
;
1663 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1664 called_from
== CALLED_FROM_STANDALONE
);
1666 width
= tems
.ts_font
.width
;
1667 height
= tems
.ts_font
.height
;
1669 nrows
= (tems
.ts_p_offset
.y
+ (height
- 1))/ height
;
1670 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1672 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1673 B_FALSE
, credp
, called_from
);
1677 * clear the whole screen for pixel mode, just clear the
1681 tem_safe_pix_clear_entire_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
1682 enum called_from called_from
)
1684 int nrows
, ncols
, width
, height
;
1686 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1687 called_from
== CALLED_FROM_STANDALONE
);
1689 width
= tems
.ts_font
.width
;
1690 height
= tems
.ts_font
.height
;
1692 nrows
= (tems
.ts_p_dimension
.height
+ (height
- 1))/ height
;
1693 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1695 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1696 B_FALSE
, credp
, called_from
);
1699 * Since the whole screen is cleared, we don't need
1700 * to clear OBP output later.
1702 if (tem
->tvs_first_line
> 0)
1703 tem
->tvs_first_line
= 0;
1707 * clear the whole screen, including the virtual screen buffer,
1708 * and reset the cursor to start point.
1711 tem_safe_cls(struct tem_vt_state
*tem
,
1712 cred_t
*credp
, enum called_from called_from
)
1716 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1717 called_from
== CALLED_FROM_STANDALONE
);
1719 if (tems
.ts_display_mode
== VIS_TEXT
) {
1720 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1721 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1722 row
, 0, credp
, called_from
);
1724 tem
->tvs_c_cursor
.row
= 0;
1725 tem
->tvs_c_cursor
.col
= 0;
1726 tem_safe_align_cursor(tem
);
1730 ASSERT(tems
.ts_display_mode
== VIS_PIXEL
);
1732 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1733 tem_safe_virtual_cls(tem
, tems
.ts_c_dimension
.width
, row
, 0);
1735 tem
->tvs_c_cursor
.row
= 0;
1736 tem
->tvs_c_cursor
.col
= 0;
1737 tem_safe_align_cursor(tem
);
1739 if (!tem
->tvs_isactive
)
1742 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
1746 tem_safe_back_tab(struct tem_vt_state
*tem
,
1747 cred_t
*credp
, enum called_from called_from
)
1750 screen_pos_t tabstop
;
1752 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1753 called_from
== CALLED_FROM_STANDALONE
);
1757 for (i
= tem
->tvs_ntabs
- 1; i
>= 0; i
--) {
1758 if (tem
->tvs_tabs
[i
] < tem
->tvs_c_cursor
.col
) {
1759 tabstop
= tem
->tvs_tabs
[i
];
1764 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1765 tabstop
, credp
, called_from
);
1769 tem_safe_tab(struct tem_vt_state
*tem
,
1770 cred_t
*credp
, enum called_from called_from
)
1773 screen_pos_t tabstop
;
1775 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1776 called_from
== CALLED_FROM_STANDALONE
);
1778 tabstop
= tems
.ts_c_dimension
.width
- 1;
1780 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1781 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1782 tabstop
= tem
->tvs_tabs
[i
];
1787 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1788 tabstop
, credp
, called_from
);
1792 tem_safe_set_tab(struct tem_vt_state
*tem
)
1797 if (tem
->tvs_ntabs
== TEM_MAXTAB
)
1799 if (tem
->tvs_ntabs
== 0 ||
1800 tem
->tvs_tabs
[tem
->tvs_ntabs
] < tem
->tvs_c_cursor
.col
) {
1801 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = tem
->tvs_c_cursor
.col
;
1804 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1805 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
)
1807 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1808 for (j
= tem
->tvs_ntabs
- 1; j
>= i
; j
--)
1809 tem
->tvs_tabs
[j
+ 1] = tem
->tvs_tabs
[j
];
1810 tem
->tvs_tabs
[i
] = tem
->tvs_c_cursor
.col
;
1818 tem_safe_clear_tabs(struct tem_vt_state
*tem
, int action
)
1824 case 3: /* clear all tabs */
1827 case 0: /* clr tab at cursor */
1829 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1830 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
) {
1832 for (j
= i
; j
< tem
->tvs_ntabs
; j
++)
1833 tem
->tvs_tabs
[j
] = tem
->tvs_tabs
[j
+ 1];
1842 tem_safe_mv_cursor(struct tem_vt_state
*tem
, int row
, int col
,
1843 cred_t
*credp
, enum called_from called_from
)
1845 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1846 called_from
== CALLED_FROM_STANDALONE
);
1849 * Sanity check and bounds enforcement. Out of bounds requests are
1850 * clipped to the screen boundaries. This seems to be what SPARC
1855 if (row
>= tems
.ts_c_dimension
.height
)
1856 row
= tems
.ts_c_dimension
.height
- 1;
1859 if (col
>= tems
.ts_c_dimension
.width
)
1860 col
= tems
.ts_c_dimension
.width
- 1;
1862 tem_safe_send_data(tem
, credp
, called_from
);
1863 tem
->tvs_c_cursor
.row
= (screen_pos_t
)row
;
1864 tem
->tvs_c_cursor
.col
= (screen_pos_t
)col
;
1865 tem_safe_align_cursor(tem
);
1870 tem_safe_reset_emulator(struct tem_vt_state
*tem
,
1871 cred_t
*credp
, enum called_from called_from
,
1872 boolean_t init_color
)
1876 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1877 called_from
== CALLED_FROM_STANDALONE
);
1879 tem
->tvs_c_cursor
.row
= 0;
1880 tem
->tvs_c_cursor
.col
= 0;
1881 tem
->tvs_r_cursor
.row
= 0;
1882 tem
->tvs_r_cursor
.col
= 0;
1883 tem
->tvs_s_cursor
.row
= 0;
1884 tem
->tvs_s_cursor
.col
= 0;
1885 tem
->tvs_outindex
= 0;
1886 tem
->tvs_state
= A_STATE_START
;
1887 tem
->tvs_gotparam
= B_FALSE
;
1888 tem
->tvs_curparam
= 0;
1889 tem
->tvs_paramval
= 0;
1890 tem
->tvs_nscroll
= 1;
1893 /* use initial settings */
1894 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
1895 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
1896 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
1900 * set up the initial tab stops
1903 for (j
= 8; j
< tems
.ts_c_dimension
.width
; j
+= 8)
1904 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = (screen_pos_t
)j
;
1906 for (j
= 0; j
< TEM_MAXPARAMS
; j
++)
1907 tem
->tvs_params
[j
] = 0;
1911 tem_safe_reset_display(struct tem_vt_state
*tem
,
1912 cred_t
*credp
, enum called_from called_from
,
1913 boolean_t clear_txt
, boolean_t init_color
)
1915 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1916 called_from
== CALLED_FROM_STANDALONE
);
1918 tem_safe_reset_emulator(tem
, credp
, called_from
, init_color
);
1921 if (tem
->tvs_isactive
)
1922 tem_safe_callback_cursor(tem
,
1923 VIS_HIDE_CURSOR
, credp
, called_from
);
1925 tem_safe_cls(tem
, credp
, called_from
);
1927 if (tem
->tvs_isactive
)
1928 tem_safe_callback_cursor(tem
,
1929 VIS_DISPLAY_CURSOR
, credp
, called_from
);
1935 struct tem_vt_state
*tem
,
1939 enum called_from called_from
)
1943 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1944 called_from
== CALLED_FROM_STANDALONE
);
1946 rest_of_line
= tems
.ts_c_dimension
.width
- tem
->tvs_c_cursor
.col
;
1947 if (count
> rest_of_line
)
1948 count
= rest_of_line
;
1953 switch (direction
) {
1954 case TEM_SHIFT_LEFT
:
1955 if (count
< rest_of_line
) {
1956 tem_safe_copy_area(tem
,
1957 tem
->tvs_c_cursor
.col
+ count
,
1958 tem
->tvs_c_cursor
.row
,
1959 tems
.ts_c_dimension
.width
- 1,
1960 tem
->tvs_c_cursor
.row
,
1961 tem
->tvs_c_cursor
.col
,
1962 tem
->tvs_c_cursor
.row
,
1963 credp
, called_from
);
1966 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1967 (tems
.ts_c_dimension
.width
- count
), credp
,
1970 case TEM_SHIFT_RIGHT
:
1971 if (count
< rest_of_line
) {
1972 tem_safe_copy_area(tem
,
1973 tem
->tvs_c_cursor
.col
,
1974 tem
->tvs_c_cursor
.row
,
1975 tems
.ts_c_dimension
.width
- count
- 1,
1976 tem
->tvs_c_cursor
.row
,
1977 tem
->tvs_c_cursor
.col
+ count
,
1978 tem
->tvs_c_cursor
.row
,
1979 credp
, called_from
);
1982 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1983 tem
->tvs_c_cursor
.col
, credp
, called_from
);
1989 tem_safe_text_cursor(struct tem_vt_state
*tem
, short action
,
1990 cred_t
*credp
, enum called_from called_from
)
1992 struct vis_conscursor ca
;
1994 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1995 called_from
== CALLED_FROM_STANDALONE
);
1997 ca
.row
= tem
->tvs_c_cursor
.row
;
1998 ca
.col
= tem
->tvs_c_cursor
.col
;
2001 tems_safe_cursor(&ca
, credp
, called_from
);
2003 if (action
== VIS_GET_CURSOR
) {
2004 tem
->tvs_c_cursor
.row
= ca
.row
;
2005 tem
->tvs_c_cursor
.col
= ca
.col
;
2010 tem_safe_pix_cursor(struct tem_vt_state
*tem
, short action
,
2011 cred_t
*credp
, enum called_from called_from
)
2013 struct vis_conscursor ca
;
2015 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2016 called_from
== CALLED_FROM_STANDALONE
);
2018 ca
.row
= tem
->tvs_c_cursor
.row
* tems
.ts_font
.height
+
2020 ca
.col
= tem
->tvs_c_cursor
.col
* tems
.ts_font
.width
+
2022 ca
.width
= tems
.ts_font
.width
;
2023 ca
.height
= tems
.ts_font
.height
;
2024 if (tems
.ts_pdepth
== 8 || tems
.ts_pdepth
== 4) {
2025 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
2026 ca
.fg_color
.mono
= TEM_TEXT_WHITE
;
2027 ca
.bg_color
.mono
= TEM_TEXT_BLACK
;
2029 ca
.fg_color
.mono
= TEM_TEXT_BLACK
;
2030 ca
.bg_color
.mono
= TEM_TEXT_WHITE
;
2032 } else if (tems
.ts_pdepth
== 24 || tems
.ts_pdepth
== 32) {
2033 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
2034 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
2035 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
2036 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
2038 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
2039 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
2040 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
2042 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
2043 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
2044 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
2046 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
2047 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
2048 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
2054 tems_safe_cursor(&ca
, credp
, called_from
);
2058 bit_to_pix4(struct tem_vt_state
*tem
, uchar_t c
, text_color_t fg_color
,
2059 text_color_t bg_color
)
2061 uint8_t *dest
= (uint8_t *)tem
->tvs_pix_data
;
2062 font_bit_to_pix4(&tems
.ts_font
, dest
, c
, fg_color
, bg_color
);
2066 bit_to_pix8(struct tem_vt_state
*tem
, uchar_t c
, text_color_t fg_color
,
2067 text_color_t bg_color
)
2069 uint8_t *dest
= (uint8_t *)tem
->tvs_pix_data
;
2070 font_bit_to_pix8(&tems
.ts_font
, dest
, c
, fg_color
, bg_color
);
2074 bit_to_pix24(struct tem_vt_state
*tem
, uchar_t c
, text_color_t fg_color4
,
2075 text_color_t bg_color4
)
2077 uint32_t fg_color32
, bg_color32
;
2080 ASSERT(fg_color4
< 16 && bg_color4
< 16);
2082 fg_color32
= PIX4TO32(fg_color4
);
2083 bg_color32
= PIX4TO32(bg_color4
);
2085 dest
= (uint8_t *)tem
->tvs_pix_data
;
2086 font_bit_to_pix24(&tems
.ts_font
, dest
, c
, fg_color32
, bg_color32
);
2090 bit_to_pix32(struct tem_vt_state
*tem
, uchar_t c
, text_color_t fg_color4
,
2091 text_color_t bg_color4
)
2093 uint32_t fg_color32
, bg_color32
, *dest
;
2095 ASSERT(fg_color4
< 16 && bg_color4
< 16);
2097 fg_color32
= PIX4TO32(fg_color4
);
2098 bg_color32
= PIX4TO32(bg_color4
);
2100 dest
= (uint32_t *)tem
->tvs_pix_data
;
2101 font_bit_to_pix32(&tems
.ts_font
, dest
, c
, fg_color32
, bg_color32
);
2105 ansi_bg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2107 if (tem
->tvs_flags
& TEM_ATTR_BRIGHT_BG
)
2108 return (brt_xlate
[ansi
]);
2110 return (dim_xlate
[ansi
]);
2114 ansi_fg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2116 if (tem
->tvs_flags
& TEM_ATTR_BRIGHT_FG
||
2117 tem
->tvs_flags
& TEM_ATTR_BOLD
) {
2118 return (brt_xlate
[ansi
]);
2120 return (dim_xlate
[ansi
]);
2125 * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2128 tem_safe_get_color(struct tem_vt_state
*tem
, text_color_t
*fg
,
2129 text_color_t
*bg
, uint8_t flag
)
2131 if (tem
->tvs_flags
& flag
) {
2132 *fg
= ansi_fg_to_solaris(tem
,
2134 *bg
= ansi_bg_to_solaris(tem
,
2137 *fg
= ansi_fg_to_solaris(tem
,
2139 *bg
= ansi_bg_to_solaris(tem
,
2145 * Clear a rectangle of screen for pixel mode.
2149 * nrows: the number of rows to clear
2150 * offset_y: the offset of height in pixels to begin clear
2152 * ncols: the number of cols to clear
2153 * offset_x: the offset of width in pixels to begin clear
2154 * scroll_up: whether this function is called during sroll up,
2155 * which is called only once.
2158 tem_safe_pix_cls_range(struct tem_vt_state
*tem
,
2159 screen_pos_t row
, int nrows
, int offset_y
,
2160 screen_pos_t col
, int ncols
, int offset_x
,
2161 boolean_t sroll_up
, cred_t
*credp
,
2162 enum called_from called_from
)
2164 struct vis_consdisplay da
;
2167 text_color_t fg_color
;
2168 text_color_t bg_color
;
2170 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2171 called_from
== CALLED_FROM_STANDALONE
);
2174 row_add
= tems
.ts_c_dimension
.height
- 1;
2176 da
.width
= tems
.ts_font
.width
;
2177 da
.height
= tems
.ts_font
.height
;
2179 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2181 tem_safe_callback_bit2pix(tem
, ' ', fg_color
, bg_color
);
2182 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
2184 for (i
= 0; i
< nrows
; i
++, row
++) {
2185 da
.row
= (row
+ row_add
) * da
.height
+ offset_y
;
2186 da
.col
= col
* da
.width
+ offset_x
;
2187 for (j
= 0; j
< ncols
; j
++) {
2188 tems_safe_display(&da
, credp
, called_from
);
2195 * virtual screen operations
2198 tem_safe_virtual_display(struct tem_vt_state
*tem
, unsigned char *string
,
2199 int count
, screen_pos_t row
, screen_pos_t col
,
2200 text_color_t fg_color
, text_color_t bg_color
)
2203 unsigned char *addr
;
2204 text_color_t
*pfgcolor
;
2205 text_color_t
*pbgcolor
;
2207 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
2208 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
2209 col
+ count
> tems
.ts_c_dimension
.width
)
2212 width
= tems
.ts_c_dimension
.width
;
2213 addr
= tem
->tvs_screen_buf
+ (row
* width
+ col
);
2214 pfgcolor
= tem
->tvs_fg_buf
+ (row
* width
+ col
);
2215 pbgcolor
= tem
->tvs_bg_buf
+ (row
* width
+ col
);
2216 for (i
= 0; i
< count
; i
++) {
2217 *addr
++ = string
[i
];
2218 *pfgcolor
++ = fg_color
;
2219 *pbgcolor
++ = bg_color
;
2224 i_virtual_copy(unsigned char *base
,
2225 screen_pos_t s_col
, screen_pos_t s_row
,
2226 screen_pos_t e_col
, screen_pos_t e_row
,
2227 screen_pos_t t_col
, screen_pos_t t_row
)
2229 unsigned char *from
;
2232 screen_size_t chars_per_row
;
2233 unsigned char *to_row_start
;
2234 unsigned char *from_row_start
;
2235 screen_size_t rows_to_move
;
2236 int cols
= tems
.ts_c_dimension
.width
;
2238 chars_per_row
= e_col
- s_col
+ 1;
2239 rows_to_move
= e_row
- s_row
+ 1;
2241 to_row_start
= base
+ ((t_row
* cols
) + t_col
);
2242 from_row_start
= base
+ ((s_row
* cols
) + s_col
);
2244 if (to_row_start
< from_row_start
) {
2245 while (rows_to_move
-- > 0) {
2247 from
= from_row_start
;
2248 to_row_start
+= cols
;
2249 from_row_start
+= cols
;
2250 for (cnt
= chars_per_row
; cnt
-- > 0; )
2255 * Offset to the end of the region and copy backwards.
2257 cnt
= rows_to_move
* cols
+ chars_per_row
;
2258 to_row_start
+= cnt
;
2259 from_row_start
+= cnt
;
2261 while (rows_to_move
-- > 0) {
2262 to_row_start
-= cols
;
2263 from_row_start
-= cols
;
2265 from
= from_row_start
;
2266 for (cnt
= chars_per_row
; cnt
-- > 0; )
2273 tem_safe_virtual_copy(struct tem_vt_state
*tem
,
2274 screen_pos_t s_col
, screen_pos_t s_row
,
2275 screen_pos_t e_col
, screen_pos_t e_row
,
2276 screen_pos_t t_col
, screen_pos_t t_row
)
2278 screen_size_t chars_per_row
;
2279 screen_size_t rows_to_move
;
2280 int rows
= tems
.ts_c_dimension
.height
;
2281 int cols
= tems
.ts_c_dimension
.width
;
2283 if (s_col
< 0 || s_col
>= cols
||
2284 s_row
< 0 || s_row
>= rows
||
2285 e_col
< 0 || e_col
>= cols
||
2286 e_row
< 0 || e_row
>= rows
||
2287 t_col
< 0 || t_col
>= cols
||
2288 t_row
< 0 || t_row
>= rows
||
2293 chars_per_row
= e_col
- s_col
+ 1;
2294 rows_to_move
= e_row
- s_row
+ 1;
2296 /* More sanity checks. */
2297 if (t_row
+ rows_to_move
> rows
||
2298 t_col
+ chars_per_row
> cols
)
2301 i_virtual_copy(tem
->tvs_screen_buf
, s_col
, s_row
,
2302 e_col
, e_row
, t_col
, t_row
);
2304 /* text_color_t is the same size as char */
2305 i_virtual_copy((unsigned char *)tem
->tvs_fg_buf
,
2306 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2307 i_virtual_copy((unsigned char *)tem
->tvs_bg_buf
,
2308 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2313 tem_safe_virtual_cls(struct tem_vt_state
*tem
,
2314 int count
, screen_pos_t row
, screen_pos_t col
)
2316 text_color_t fg_color
;
2317 text_color_t bg_color
;
2319 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2320 tem_safe_virtual_display(tem
, tems
.ts_blank_line
, count
, row
, col
,
2321 fg_color
, bg_color
);
2325 * only blank screen, not clear our screen buffer
2328 tem_safe_blank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2329 enum called_from called_from
)
2333 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2334 called_from
== CALLED_FROM_STANDALONE
);
2336 if (tems
.ts_display_mode
== VIS_PIXEL
) {
2337 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2341 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2342 tem_safe_callback_cls(tem
,
2343 tems
.ts_c_dimension
.width
,
2344 row
, 0, credp
, called_from
);
2349 * unblank screen with associated tem from its screen buffer
2352 tem_safe_unblank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2353 enum called_from called_from
)
2355 text_color_t fg_color
, fg_last
;
2356 text_color_t bg_color
, bg_last
;
2357 size_t tc_size
= sizeof (text_color_t
);
2358 int row
, col
, count
, col_start
;
2362 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2363 called_from
== CALLED_FROM_STANDALONE
);
2365 if (tems
.ts_display_mode
== VIS_PIXEL
)
2366 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2368 tem_safe_callback_cursor(tem
, VIS_HIDE_CURSOR
, credp
, called_from
);
2370 width
= tems
.ts_c_dimension
.width
;
2373 * Display data in tvs_screen_buf to the actual framebuffer in a
2375 * When dealing with one row, output data with the same foreground
2376 * and background color all together.
2378 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2379 buf
= tem
->tvs_screen_buf
+ (row
* width
);
2380 count
= col_start
= 0;
2381 for (col
= 0; col
< width
; col
++) {
2383 tem
->tvs_fg_buf
[(row
* width
+ col
) * tc_size
];
2385 tem
->tvs_bg_buf
[(row
* width
+ col
) * tc_size
];
2391 if ((fg_color
!= fg_last
) || (bg_color
!= bg_last
)) {
2393 * Call the primitive to render this data.
2395 tem_safe_callback_display(tem
,
2396 buf
, count
, row
, col_start
,
2397 fg_last
, bg_last
, credp
, called_from
);
2408 if (col_start
== (width
- 1))
2412 * Call the primitive to render this data.
2414 tem_safe_callback_display(tem
,
2415 buf
, count
, row
, col_start
,
2416 fg_last
, bg_last
, credp
, called_from
);
2419 tem_safe_callback_cursor(tem
, VIS_DISPLAY_CURSOR
, credp
, called_from
);