Print this page
8368 remove warlock leftovers from usr/src/uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/tem_safe.c
+++ new/usr/src/uts/common/io/tem_safe.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Copyright 2016 Joyent, Inc.
29 29 */
30 30
31 31 /*
32 32 * Polled I/O safe ANSI terminal emulator module;
33 33 * Supporting TERM types 'sun' and 'sun-color, parsing
34 34 * ANSI x3.64 escape sequences, and the like. (See wscons(7d)
35 35 * for more information).
36 36 *
37 37 * IMPORTANT:
38 38 *
39 39 * The functions in this file *must* be able to function in
40 40 * standalone mode, ie. on a quiesced system. In that state,
41 41 * access is single threaded, only one CPU is running.
42 42 * System services are NOT available.
43 43 *
44 44 * The following restrictions pertain to every function
45 45 * in this file:
46 46 *
47 47 * - CANNOT use the DDI or LDI interfaces
48 48 * - CANNOT call system services
49 49 * - CANNOT use mutexes
50 50 * - CANNOT wait for interrupts
51 51 * - CANNOT allocate memory
52 52 *
53 53 * All non-static functions in this file which:
54 54 * - Operates on tems and tem_vt_state
55 55 * - Not only called from standalone mode, i.e. has
56 56 * a "calledfrom" argument
57 57 * should assert this at the beginning:
58 58 *
59 59 * ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
60 60 * called_from == CALLED_FROM_STANDALONE);
61 61 */
62 62
63 63 #include <sys/types.h>
64 64 #include <sys/ascii.h>
65 65 #include <sys/visual_io.h>
66 66 #include <sys/font.h>
67 67 #include <sys/tem.h>
68 68 #include <sys/tem_impl.h>
69 69 #include <sys/ksynch.h>
70 70 #include <sys/sysmacros.h>
71 71 #include <sys/mutex.h>
72 72 #include <sys/note.h>
73 73 #include <sys/t_lock.h>
74 74
75 75 tem_safe_callbacks_t tem_safe_text_callbacks = {
76 76 &tem_safe_text_display,
77 77 &tem_safe_text_copy,
78 78 &tem_safe_text_cursor,
79 79 NULL,
80 80 &tem_safe_text_cls
81 81 };
82 82 tem_safe_callbacks_t tem_safe_pix_callbacks = {
83 83 &tem_safe_pix_display,
84 84 &tem_safe_pix_copy,
85 85 &tem_safe_pix_cursor,
86 86 &tem_safe_pix_bit2pix,
87 87 &tem_safe_pix_cls
88 88 };
89 89
90 90
91 91 static void tem_safe_control(struct tem_vt_state *, uchar_t,
92 92 cred_t *, enum called_from);
93 93 static void tem_safe_setparam(struct tem_vt_state *, int, int);
94 94 static void tem_safe_selgraph(struct tem_vt_state *);
95 95 static void tem_safe_chkparam(struct tem_vt_state *, uchar_t,
96 96 cred_t *, enum called_from);
97 97 static void tem_safe_getparams(struct tem_vt_state *, uchar_t,
98 98 cred_t *, enum called_from);
99 99 static void tem_safe_outch(struct tem_vt_state *, uchar_t,
100 100 cred_t *, enum called_from);
101 101 static void tem_safe_parse(struct tem_vt_state *, uchar_t,
102 102 cred_t *, enum called_from);
103 103
104 104 static void tem_safe_new_line(struct tem_vt_state *,
105 105 cred_t *, enum called_from);
106 106 static void tem_safe_cr(struct tem_vt_state *);
107 107 static void tem_safe_lf(struct tem_vt_state *,
108 108 cred_t *, enum called_from);
109 109 static void tem_safe_send_data(struct tem_vt_state *, cred_t *,
110 110 enum called_from);
111 111 static void tem_safe_cls(struct tem_vt_state *,
112 112 cred_t *, enum called_from);
113 113 static void tem_safe_tab(struct tem_vt_state *,
114 114 cred_t *, enum called_from);
115 115 static void tem_safe_back_tab(struct tem_vt_state *,
116 116 cred_t *, enum called_from);
117 117 static void tem_safe_clear_tabs(struct tem_vt_state *, int);
118 118 static void tem_safe_set_tab(struct tem_vt_state *);
119 119 static void tem_safe_mv_cursor(struct tem_vt_state *, int, int,
120 120 cred_t *, enum called_from);
121 121 static void tem_safe_shift(struct tem_vt_state *, int, int,
122 122 cred_t *, enum called_from);
123 123 static void tem_safe_scroll(struct tem_vt_state *, int, int,
124 124 int, int, cred_t *, enum called_from);
125 125 static void tem_safe_clear_chars(struct tem_vt_state *tem,
126 126 int count, screen_pos_t row, screen_pos_t col,
127 127 cred_t *credp, enum called_from called_from);
128 128 static void tem_safe_copy_area(struct tem_vt_state *tem,
129 129 screen_pos_t s_col, screen_pos_t s_row,
130 130 screen_pos_t e_col, screen_pos_t e_row,
131 131 screen_pos_t t_col, screen_pos_t t_row,
132 132 cred_t *credp, enum called_from called_from);
133 133 static void tem_safe_image_display(struct tem_vt_state *, uchar_t *,
134 134 int, int, screen_pos_t, screen_pos_t,
135 135 cred_t *, enum called_from);
136 136 static void tem_safe_bell(struct tem_vt_state *tem,
137 137 enum called_from called_from);
138 138 static void tem_safe_pix_clear_prom_output(struct tem_vt_state *tem,
139 139 cred_t *credp, enum called_from called_from);
140 140
141 141 static void tem_safe_virtual_cls(struct tem_vt_state *, int, screen_pos_t,
142 142 screen_pos_t);
143 143 static void tem_safe_virtual_display(struct tem_vt_state *,
144 144 unsigned char *, int, screen_pos_t, screen_pos_t,
145 145 text_color_t, text_color_t);
146 146 static void tem_safe_virtual_copy(struct tem_vt_state *, screen_pos_t,
147 147 screen_pos_t, screen_pos_t, screen_pos_t,
148 148 screen_pos_t, screen_pos_t);
149 149 static void tem_safe_align_cursor(struct tem_vt_state *tem);
150 150 static void bit_to_pix4(struct tem_vt_state *tem, uchar_t c,
151 151 text_color_t fg_color, text_color_t bg_color);
152 152 static void bit_to_pix8(struct tem_vt_state *tem, uchar_t c,
153 153 text_color_t fg_color, text_color_t bg_color);
154 154 static void bit_to_pix24(struct tem_vt_state *tem, uchar_t c,
155 155 text_color_t fg_color, text_color_t bg_color);
156 156
157 157 /* BEGIN CSTYLED */
158 158 /* Bk Rd Gr Br Bl Mg Cy Wh */
159 159 static text_color_t dim_xlate[] = { 1, 5, 3, 7, 2, 6, 4, 8 };
160 160 static text_color_t brt_xlate[] = { 9, 13, 11, 15, 10, 14, 12, 0 };
161 161 /* END CSTYLED */
162 162
163 163
164 164 text_cmap_t cmap4_to_24 = {
165 165 /* BEGIN CSTYLED */
166 166 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
167 167 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */
168 168 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff,
169 169 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff,
170 170 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
171 171 /* END CSTYLED */
172 172 };
173 173
174 174 #define PIX4TO32(pix4) (uint32_t)( \
175 175 cmap4_to_24.red[pix4] << 16 | \
176 176 cmap4_to_24.green[pix4] << 8 | \
177 177 cmap4_to_24.blue[pix4])
178 178
179 179 #define INVERSE(ch) (ch ^ 0xff)
180 180
181 181 #define tem_safe_callback_display (*tems.ts_callbacks->tsc_display)
182 182 #define tem_safe_callback_copy (*tems.ts_callbacks->tsc_copy)
183 183 #define tem_safe_callback_cursor (*tems.ts_callbacks->tsc_cursor)
184 184 #define tem_safe_callback_cls (*tems.ts_callbacks->tsc_cls)
185 185 #define tem_safe_callback_bit2pix(tem, c, fg, bg) { \
186 186 ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL); \
187 187 (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
188 188 }
189 189
190 190 void
191 191 tem_safe_check_first_time(
192 192 struct tem_vt_state *tem,
193 193 cred_t *credp,
194 194 enum called_from called_from)
195 195 {
196 196 static int first_time = 1;
197 197
198 198 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
199 199 called_from == CALLED_FROM_STANDALONE);
200 200
201 201 /*
202 202 * Realign the console cursor. We did this in tem_init().
203 203 * However, drivers in the console stream may emit additional
204 204 * messages before we are ready. This causes text overwrite
205 205 * on the screen. This is a workaround.
206 206 */
207 207 if (!first_time)
208 208 return;
209 209
210 210 first_time = 0;
211 211 if (tems.ts_display_mode == VIS_TEXT) {
212 212 tem_safe_text_cursor(tem, VIS_GET_CURSOR, credp, called_from);
213 213 tem_safe_align_cursor(tem);
214 214 }
215 215 }
216 216
217 217 /*
218 218 * This entry point handles output requests from restricted contexts like
219 219 * kmdb, where services like mutexes are not available. This function
220 220 * is entered when OBP or when a kernel debugger (such as kmdb)
221 221 * are generating console output. In those cases, power management
222 222 * concerns are handled by the abort sequence initiation (ie. when
223 223 * the user hits L1+A or the equivalent to enter OBP or the debugger.).
↓ open down ↓ |
223 lines elided |
↑ open up ↑ |
224 224 * It is also entered when the kernel is panicing.
225 225 */
226 226 void
227 227 tem_safe_polled_write(
228 228 tem_vt_state_t tem_arg,
229 229 uchar_t *buf,
230 230 int len)
231 231 {
232 232 struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
233 233
234 -#ifdef __lock_lint
235 - _NOTE(NO_COMPETING_THREADS_NOW)
236 - _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT)
237 -#endif
238 -
239 234 if (!tem->tvs_initialized) {
240 235 return;
241 236 }
242 237
243 238 tem_safe_check_first_time(tem, kcred, CALLED_FROM_STANDALONE);
244 239 tem_safe_terminal_emulate(tem, buf, len, NULL, CALLED_FROM_STANDALONE);
245 240 }
246 241
247 242 /* Process partial UTF-8 sequence. */
248 243 static void
249 244 tem_safe_input_partial(struct tem_vt_state *tem, cred_t *credp,
250 245 enum called_from called_from)
251 246 {
252 247 int i;
253 248 uint8_t c;
254 249
255 250 if (tem->tvs_utf8_left == 0)
256 251 return;
257 252
258 253 for (i = 0; i < sizeof (tem->tvs_utf8_partial); i++) {
259 254 c = (tem->tvs_utf8_partial >> (24 - (i << 3))) & 0xff;
260 255 if (c != 0) {
261 256 tem_safe_parse(tem, c, credp, called_from);
262 257 }
263 258 }
264 259 tem->tvs_utf8_left = 0;
265 260 tem->tvs_utf8_partial = 0;
266 261 }
267 262
268 263 /*
269 264 * Handle UTF-8 sequences.
270 265 */
271 266 static void
272 267 tem_safe_input_byte(struct tem_vt_state *tem, uchar_t c, cred_t *credp,
273 268 enum called_from called_from)
274 269 {
275 270 /*
276 271 * Check for UTF-8 code points. In case of error fall back to
277 272 * 8-bit code. As we only have 8859-1 fonts for console, this will set
278 273 * the limits on what chars we actually can display, therefore we
279 274 * have to return to this code once we have solved the font issue.
280 275 */
281 276 if ((c & 0x80) == 0x00) {
282 277 /* One-byte sequence. */
283 278 tem_safe_input_partial(tem, credp, called_from);
284 279 tem_safe_parse(tem, c, credp, called_from);
285 280 return;
286 281 }
287 282 if ((c & 0xe0) == 0xc0) {
288 283 /* Two-byte sequence. */
289 284 tem_safe_input_partial(tem, credp, called_from);
290 285 tem->tvs_utf8_left = 1;
291 286 tem->tvs_utf8_partial = c;
292 287 return;
293 288 }
294 289 if ((c & 0xf0) == 0xe0) {
295 290 /* Three-byte sequence. */
296 291 tem_safe_input_partial(tem, credp, called_from);
297 292 tem->tvs_utf8_left = 2;
298 293 tem->tvs_utf8_partial = c;
299 294 return;
300 295 }
301 296 if ((c & 0xf8) == 0xf0) {
302 297 /* Four-byte sequence. */
303 298 tem_safe_input_partial(tem, credp, called_from);
304 299 tem->tvs_utf8_left = 3;
305 300 tem->tvs_utf8_partial = c;
306 301 return;
307 302 }
308 303 if ((c & 0xc0) == 0x80) {
309 304 /* Invalid state? */
310 305 if (tem->tvs_utf8_left == 0) {
311 306 tem_safe_parse(tem, c, credp, called_from);
312 307 return;
313 308 }
314 309 tem->tvs_utf8_left--;
315 310 tem->tvs_utf8_partial = (tem->tvs_utf8_partial << 8) | c;
316 311 if (tem->tvs_utf8_left == 0) {
317 312 tem_char_t v, u;
318 313 uint8_t b;
319 314
320 315 /*
321 316 * Transform the sequence of 2 to 4 bytes to
322 317 * unicode number.
323 318 */
324 319 v = 0;
325 320 u = tem->tvs_utf8_partial;
326 321 b = (u >> 24) & 0xff;
327 322 if (b != 0) { /* Four-byte sequence */
328 323 v = b & 0x07;
329 324 b = (u >> 16) & 0xff;
330 325 v = (v << 6) | (b & 0x3f);
331 326 b = (u >> 8) & 0xff;
332 327 v = (v << 6) | (b & 0x3f);
333 328 b = u & 0xff;
334 329 v = (v << 6) | (b & 0x3f);
335 330 } else if ((b = (u >> 16) & 0xff) != 0) {
336 331 v = b & 0x0f; /* Three-byte sequence */
337 332 b = (u >> 8) & 0xff;
338 333 v = (v << 6) | (b & 0x3f);
339 334 b = u & 0xff;
340 335 v = (v << 6) | (b & 0x3f);
341 336 } else if ((b = (u >> 8) & 0xff) != 0) {
342 337 v = b & 0x1f; /* Two-byte sequence */
343 338 b = u & 0xff;
344 339 v = (v << 6) | (b & 0x3f);
345 340 }
346 341
347 342 /* Use '?' as replacement if needed. */
348 343 if (v > 0xff)
349 344 v = '?';
350 345 tem_safe_parse(tem, v, credp, called_from);
351 346 tem->tvs_utf8_partial = 0;
352 347 }
353 348 return;
354 349 }
355 350 /* Anything left is illegal in UTF-8 sequence. */
356 351 tem_safe_input_partial(tem, credp, called_from);
357 352 tem_safe_parse(tem, c, credp, called_from);
358 353 }
359 354
360 355 /*
361 356 * This is the main entry point into the terminal emulator.
362 357 *
363 358 * For each data message coming downstream, ANSI assumes that it is composed
364 359 * of ASCII characters, which are treated as a byte-stream input to the
365 360 * parsing state machine. All data is parsed immediately -- there is
366 361 * no enqueing.
367 362 */
368 363 void
369 364 tem_safe_terminal_emulate(
370 365 struct tem_vt_state *tem,
371 366 uchar_t *buf,
372 367 int len,
373 368 cred_t *credp,
374 369 enum called_from called_from)
375 370 {
376 371
377 372 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
378 373 called_from == CALLED_FROM_STANDALONE);
379 374
380 375 if (tem->tvs_isactive)
381 376 tem_safe_callback_cursor(tem,
382 377 VIS_HIDE_CURSOR, credp, called_from);
383 378
384 379 for (; len > 0; len--, buf++)
385 380 tem_safe_input_byte(tem, *buf, credp, called_from);
386 381
387 382 /*
388 383 * Send the data we just got to the framebuffer.
389 384 */
390 385 tem_safe_send_data(tem, credp, called_from);
391 386
392 387 if (tem->tvs_isactive)
393 388 tem_safe_callback_cursor(tem,
394 389 VIS_DISPLAY_CURSOR, credp, called_from);
395 390 }
396 391
397 392 /*
398 393 * Display an rectangular image on the frame buffer using the
399 394 * mechanism appropriate for the system state being called
400 395 * from quiesced or normal (ie. use polled I/O vs. layered ioctls)
401 396 */
402 397 static void
403 398 tems_safe_display(struct vis_consdisplay *pda, cred_t *credp,
404 399 enum called_from called_from)
405 400 {
406 401 if (called_from == CALLED_FROM_STANDALONE)
407 402 tems.ts_fb_polledio->display(tems.ts_fb_polledio->arg, pda);
408 403 else
409 404 tems_display_layered(pda, credp);
410 405 }
411 406
412 407 /*
413 408 * Copy a rectangle from one location to another on the frame buffer
414 409 * using the mechanism appropriate for the system state being called
415 410 * from, quiesced or normal (ie. use polled I/O vs. layered ioctls)
416 411 */
417 412 void
418 413 tems_safe_copy(struct vis_conscopy *pca, cred_t *credp,
419 414 enum called_from called_from)
420 415 {
421 416 if (called_from == CALLED_FROM_STANDALONE)
422 417 tems.ts_fb_polledio->copy(tems.ts_fb_polledio->arg, pca);
423 418 else
424 419 tems_copy_layered(pca, credp);
425 420 }
426 421
427 422 /*
428 423 * Display or hide a rectangular block text cursor of a specificsize
429 424 * at a specific location on frame buffer* using the mechanism
430 425 * appropriate for the system state being called from, quisced or
431 426 * normal (ie. use polled I/O vs. layered ioctls).
432 427 */
433 428 static void
434 429 tems_safe_cursor(struct vis_conscursor *pca, cred_t *credp,
435 430 enum called_from called_from)
436 431 {
437 432 if (called_from == CALLED_FROM_STANDALONE)
438 433 tems.ts_fb_polledio->cursor(tems.ts_fb_polledio->arg, pca);
439 434 else
440 435 tems_cursor_layered(pca, credp);
441 436 }
442 437
443 438 /*
444 439 * send the appropriate control message or set state based on the
445 440 * value of the control character ch
446 441 */
447 442
448 443 static void
449 444 tem_safe_control(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
450 445 enum called_from called_from)
451 446 {
452 447 tem->tvs_state = A_STATE_START;
453 448 switch (ch) {
454 449 case A_BEL:
455 450 tem_safe_bell(tem, called_from);
456 451 break;
457 452
458 453 case A_BS:
459 454 tem_safe_mv_cursor(tem,
460 455 tem->tvs_c_cursor.row,
461 456 tem->tvs_c_cursor.col - 1,
462 457 credp, called_from);
463 458 break;
464 459
465 460 case A_HT:
466 461 tem_safe_tab(tem, credp, called_from);
467 462 break;
468 463
469 464 case A_NL:
470 465 /*
471 466 * tem_safe_send_data(tem, credp, called_from);
472 467 * tem_safe_new_line(tem, credp, called_from);
473 468 * break;
474 469 */
475 470
476 471 case A_VT:
477 472 tem_safe_send_data(tem, credp, called_from);
478 473 tem_safe_lf(tem, credp, called_from);
479 474 break;
480 475
481 476 case A_FF:
482 477 tem_safe_send_data(tem, credp, called_from);
483 478 tem_safe_cls(tem, credp, called_from);
484 479 break;
485 480
486 481 case A_CR:
487 482 tem_safe_send_data(tem, credp, called_from);
488 483 tem_safe_cr(tem);
489 484 break;
490 485
491 486 case A_ESC:
492 487 tem->tvs_state = A_STATE_ESC;
493 488 break;
494 489
495 490 case A_CSI:
496 491 {
497 492 int i;
498 493 tem->tvs_curparam = 0;
499 494 tem->tvs_paramval = 0;
500 495 tem->tvs_gotparam = B_FALSE;
501 496 /* clear the parameters */
502 497 for (i = 0; i < TEM_MAXPARAMS; i++)
503 498 tem->tvs_params[i] = -1;
504 499 tem->tvs_state = A_STATE_CSI;
505 500 }
506 501 break;
507 502
508 503 case A_GS:
509 504 tem_safe_back_tab(tem, credp, called_from);
510 505 break;
511 506
512 507 default:
513 508 break;
514 509 }
515 510 }
516 511
517 512
518 513 /*
519 514 * if parameters [0..count - 1] are not set, set them to the value
520 515 * of newparam.
521 516 */
522 517
523 518 static void
524 519 tem_safe_setparam(struct tem_vt_state *tem, int count, int newparam)
525 520 {
526 521 int i;
527 522
528 523 for (i = 0; i < count; i++) {
529 524 if (tem->tvs_params[i] == -1)
530 525 tem->tvs_params[i] = newparam;
531 526 }
532 527 }
533 528
534 529
535 530 /*
536 531 * select graphics mode based on the param vals stored in a_params
537 532 */
538 533 static void
539 534 tem_safe_selgraph(struct tem_vt_state *tem)
540 535 {
541 536 int curparam;
542 537 int count = 0;
543 538 int param;
544 539
545 540 tem->tvs_state = A_STATE_START;
546 541
547 542 curparam = tem->tvs_curparam;
548 543 do {
549 544 param = tem->tvs_params[count];
550 545
551 546 switch (param) {
552 547 case -1:
553 548 case 0:
554 549 /* reset to initial normal settings */
555 550 tem->tvs_fg_color = tems.ts_init_color.fg_color;
556 551 tem->tvs_bg_color = tems.ts_init_color.bg_color;
557 552 tem->tvs_flags = tems.ts_init_color.a_flags;
558 553 break;
559 554
560 555 case 1: /* Bold Intense */
561 556 tem->tvs_flags |= TEM_ATTR_BOLD;
562 557 break;
563 558
564 559 case 2: /* Faint Intense */
565 560 tem->tvs_flags &= ~TEM_ATTR_BOLD;
566 561 break;
567 562
568 563 case 5: /* Blink */
569 564 tem->tvs_flags |= TEM_ATTR_BLINK;
570 565 break;
571 566
572 567 case 7: /* Reverse video */
573 568 if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
574 569 tem->tvs_flags &= ~TEM_ATTR_REVERSE;
575 570 } else {
576 571 tem->tvs_flags |= TEM_ATTR_REVERSE;
577 572 }
578 573 break;
579 574
580 575 case 30: /* black (grey) foreground */
581 576 case 31: /* red (light red) foreground */
582 577 case 32: /* green (light green) foreground */
583 578 case 33: /* brown (yellow) foreground */
584 579 case 34: /* blue (light blue) foreground */
585 580 case 35: /* magenta (light magenta) foreground */
586 581 case 36: /* cyan (light cyan) foreground */
587 582 case 37: /* white (bright white) foreground */
588 583 tem->tvs_fg_color = param - 30;
589 584 tem->tvs_flags &= ~TEM_ATTR_BRIGHT_FG;
590 585 break;
591 586
592 587 case 39:
593 588 /*
594 589 * Reset the foreground colour and brightness.
595 590 */
596 591 tem->tvs_fg_color = tems.ts_init_color.fg_color;
597 592 if (tems.ts_init_color.a_flags & TEM_ATTR_BRIGHT_FG)
598 593 tem->tvs_flags |= TEM_ATTR_BRIGHT_FG;
599 594 else
600 595 tem->tvs_flags &= ~TEM_ATTR_BRIGHT_FG;
601 596 break;
602 597
603 598 case 40: /* black (grey) background */
604 599 case 41: /* red (light red) background */
605 600 case 42: /* green (light green) background */
606 601 case 43: /* brown (yellow) background */
607 602 case 44: /* blue (light blue) background */
608 603 case 45: /* magenta (light magenta) background */
609 604 case 46: /* cyan (light cyan) background */
610 605 case 47: /* white (bright white) background */
611 606 tem->tvs_bg_color = param - 40;
612 607 tem->tvs_flags &= ~TEM_ATTR_BRIGHT_BG;
613 608 break;
614 609
615 610 case 49:
616 611 /*
617 612 * Reset the background colour and brightness.
618 613 */
619 614 tem->tvs_bg_color = tems.ts_init_color.bg_color;
620 615 if (tems.ts_init_color.a_flags & TEM_ATTR_BRIGHT_BG)
621 616 tem->tvs_flags |= TEM_ATTR_BRIGHT_BG;
622 617 else
623 618 tem->tvs_flags &= ~TEM_ATTR_BRIGHT_BG;
624 619 break;
625 620
626 621 case 90: /* black (grey) foreground */
627 622 case 91: /* red (light red) foreground */
628 623 case 92: /* green (light green) foreground */
629 624 case 93: /* brown (yellow) foreground */
630 625 case 94: /* blue (light blue) foreground */
631 626 case 95: /* magenta (light magenta) foreground */
632 627 case 96: /* cyan (light cyan) foreground */
633 628 case 97: /* white (bright white) foreground */
634 629 tem->tvs_fg_color = param - 90;
635 630 tem->tvs_flags |= TEM_ATTR_BRIGHT_FG;
636 631 break;
637 632
638 633 case 100: /* black (grey) background */
639 634 case 101: /* red (light red) background */
640 635 case 102: /* green (light green) background */
641 636 case 103: /* brown (yellow) background */
642 637 case 104: /* blue (light blue) background */
643 638 case 105: /* magenta (light magenta) background */
644 639 case 106: /* cyan (light cyan) background */
645 640 case 107: /* white (bright white) background */
646 641 tem->tvs_bg_color = param - 100;
647 642 tem->tvs_flags |= TEM_ATTR_BRIGHT_BG;
648 643 break;
649 644
650 645 default:
651 646 break;
652 647 }
653 648 count++;
654 649 curparam--;
655 650
656 651 } while (curparam > 0);
657 652 }
658 653
659 654 /*
660 655 * perform the appropriate action for the escape sequence
661 656 *
662 657 * General rule: This code does not validate the arguments passed.
663 658 * It assumes that the next lower level will do so.
664 659 */
665 660 static void
666 661 tem_safe_chkparam(struct tem_vt_state *tem, uchar_t ch, cred_t *credp,
667 662 enum called_from called_from)
668 663 {
669 664 int i;
670 665 int row;
671 666 int col;
672 667
673 668 ASSERT((called_from == CALLED_FROM_STANDALONE) ||
674 669 MUTEX_HELD(&tem->tvs_lock));
675 670
676 671 row = tem->tvs_c_cursor.row;
677 672 col = tem->tvs_c_cursor.col;
678 673
679 674 switch (ch) {
680 675
681 676 case 'm': /* select terminal graphics mode */
682 677 tem_safe_send_data(tem, credp, called_from);
683 678 tem_safe_selgraph(tem);
684 679 break;
685 680
686 681 case '@': /* insert char */
687 682 tem_safe_setparam(tem, 1, 1);
688 683 tem_safe_shift(tem, tem->tvs_params[0], TEM_SHIFT_RIGHT,
689 684 credp, called_from);
690 685 break;
691 686
692 687 case 'A': /* cursor up */
693 688 tem_safe_setparam(tem, 1, 1);
694 689 tem_safe_mv_cursor(tem, row - tem->tvs_params[0], col,
695 690 credp, called_from);
696 691 break;
697 692
698 693 case 'd': /* VPA - vertical position absolute */
699 694 tem_safe_setparam(tem, 1, 1);
700 695 tem_safe_mv_cursor(tem, tem->tvs_params[0] - 1, col,
701 696 credp, called_from);
702 697 break;
703 698
704 699 case 'e': /* VPR - vertical position relative */
705 700 case 'B': /* cursor down */
706 701 tem_safe_setparam(tem, 1, 1);
707 702 tem_safe_mv_cursor(tem, row + tem->tvs_params[0], col,
708 703 credp, called_from);
709 704 break;
710 705
711 706 case 'a': /* HPR - horizontal position relative */
712 707 case 'C': /* cursor right */
713 708 tem_safe_setparam(tem, 1, 1);
714 709 tem_safe_mv_cursor(tem, row, col + tem->tvs_params[0],
715 710 credp, called_from);
716 711 break;
717 712
718 713 case '`': /* HPA - horizontal position absolute */
719 714 tem_safe_setparam(tem, 1, 1);
720 715 tem_safe_mv_cursor(tem, row, tem->tvs_params[0] - 1,
721 716 credp, called_from);
722 717 break;
723 718
724 719 case 'D': /* cursor left */
725 720 tem_safe_setparam(tem, 1, 1);
726 721 tem_safe_mv_cursor(tem, row, col - tem->tvs_params[0],
727 722 credp, called_from);
728 723 break;
729 724
730 725 case 'E': /* CNL cursor next line */
731 726 tem_safe_setparam(tem, 1, 1);
732 727 tem_safe_mv_cursor(tem, row + tem->tvs_params[0], 0,
733 728 credp, called_from);
734 729 break;
735 730
736 731 case 'F': /* CPL cursor previous line */
737 732 tem_safe_setparam(tem, 1, 1);
738 733 tem_safe_mv_cursor(tem, row - tem->tvs_params[0], 0,
739 734 credp, called_from);
740 735 break;
741 736
742 737 case 'G': /* cursor horizontal position */
743 738 tem_safe_setparam(tem, 1, 1);
744 739 tem_safe_mv_cursor(tem, row, tem->tvs_params[0] - 1,
745 740 credp, called_from);
746 741 break;
747 742
748 743 case 'g': /* clear tabs */
749 744 tem_safe_setparam(tem, 1, 0);
750 745 tem_safe_clear_tabs(tem, tem->tvs_params[0]);
751 746 break;
752 747
753 748 case 'f': /* HVP Horizontal and Vertical Position */
754 749 case 'H': /* CUP position cursor */
755 750 tem_safe_setparam(tem, 2, 1);
756 751 tem_safe_mv_cursor(tem,
757 752 tem->tvs_params[0] - 1,
758 753 tem->tvs_params[1] - 1,
759 754 credp, called_from);
760 755 break;
761 756
762 757 case 'I': /* CHT - Cursor Horizontal Tab */
763 758 /* Not implemented */
764 759 break;
765 760
766 761 case 'J': /* ED - Erase in Display */
767 762 tem_safe_send_data(tem, credp, called_from);
768 763 tem_safe_setparam(tem, 1, 0);
769 764 switch (tem->tvs_params[0]) {
770 765 case 0:
771 766 /* erase cursor to end of screen */
772 767 /* FIRST erase cursor to end of line */
773 768 tem_safe_clear_chars(tem,
774 769 tems.ts_c_dimension.width -
775 770 tem->tvs_c_cursor.col,
776 771 tem->tvs_c_cursor.row,
777 772 tem->tvs_c_cursor.col, credp, called_from);
778 773
779 774 /* THEN erase lines below the cursor */
780 775 for (row = tem->tvs_c_cursor.row + 1;
781 776 row < tems.ts_c_dimension.height;
782 777 row++) {
783 778 tem_safe_clear_chars(tem,
784 779 tems.ts_c_dimension.width,
785 780 row, 0, credp, called_from);
786 781 }
787 782 break;
788 783
789 784 case 1:
790 785 /* erase beginning of screen to cursor */
791 786 /* FIRST erase lines above the cursor */
792 787 for (row = 0;
793 788 row < tem->tvs_c_cursor.row;
794 789 row++) {
795 790 tem_safe_clear_chars(tem,
796 791 tems.ts_c_dimension.width,
797 792 row, 0, credp, called_from);
798 793 }
799 794 /* THEN erase beginning of line to cursor */
800 795 tem_safe_clear_chars(tem,
801 796 tem->tvs_c_cursor.col + 1,
802 797 tem->tvs_c_cursor.row,
803 798 0, credp, called_from);
804 799 break;
805 800
806 801 case 2:
807 802 /* erase whole screen */
808 803 for (row = 0;
809 804 row < tems.ts_c_dimension.height;
810 805 row++) {
811 806 tem_safe_clear_chars(tem,
812 807 tems.ts_c_dimension.width,
813 808 row, 0, credp, called_from);
814 809 }
815 810 break;
816 811 }
817 812 break;
818 813
819 814 case 'K': /* EL - Erase in Line */
820 815 tem_safe_send_data(tem, credp, called_from);
821 816 tem_safe_setparam(tem, 1, 0);
822 817 switch (tem->tvs_params[0]) {
823 818 case 0:
824 819 /* erase cursor to end of line */
825 820 tem_safe_clear_chars(tem,
826 821 (tems.ts_c_dimension.width -
827 822 tem->tvs_c_cursor.col),
828 823 tem->tvs_c_cursor.row,
829 824 tem->tvs_c_cursor.col,
830 825 credp, called_from);
831 826 break;
832 827
833 828 case 1:
834 829 /* erase beginning of line to cursor */
835 830 tem_safe_clear_chars(tem,
836 831 tem->tvs_c_cursor.col + 1,
837 832 tem->tvs_c_cursor.row,
838 833 0, credp, called_from);
839 834 break;
840 835
841 836 case 2:
842 837 /* erase whole line */
843 838 tem_safe_clear_chars(tem,
844 839 tems.ts_c_dimension.width,
845 840 tem->tvs_c_cursor.row,
846 841 0, credp, called_from);
847 842 break;
848 843 }
849 844 break;
850 845
851 846 case 'L': /* insert line */
852 847 tem_safe_send_data(tem, credp, called_from);
853 848 tem_safe_setparam(tem, 1, 1);
854 849 tem_safe_scroll(tem,
855 850 tem->tvs_c_cursor.row,
856 851 tems.ts_c_dimension.height - 1,
857 852 tem->tvs_params[0], TEM_SCROLL_DOWN,
858 853 credp, called_from);
859 854 break;
860 855
861 856 case 'M': /* delete line */
862 857 tem_safe_send_data(tem, credp, called_from);
863 858 tem_safe_setparam(tem, 1, 1);
864 859 tem_safe_scroll(tem,
865 860 tem->tvs_c_cursor.row,
866 861 tems.ts_c_dimension.height - 1,
867 862 tem->tvs_params[0], TEM_SCROLL_UP,
868 863 credp, called_from);
869 864 break;
870 865
871 866 case 'P': /* DCH - delete char */
872 867 tem_safe_setparam(tem, 1, 1);
873 868 tem_safe_shift(tem, tem->tvs_params[0], TEM_SHIFT_LEFT,
874 869 credp, called_from);
875 870 break;
876 871
877 872 case 'S': /* scroll up */
878 873 tem_safe_send_data(tem, credp, called_from);
879 874 tem_safe_setparam(tem, 1, 1);
880 875 tem_safe_scroll(tem, 0,
881 876 tems.ts_c_dimension.height - 1,
882 877 tem->tvs_params[0], TEM_SCROLL_UP,
883 878 credp, called_from);
884 879 break;
885 880
886 881 case 'T': /* scroll down */
887 882 tem_safe_send_data(tem, credp, called_from);
888 883 tem_safe_setparam(tem, 1, 1);
889 884 tem_safe_scroll(tem, 0,
890 885 tems.ts_c_dimension.height - 1,
891 886 tem->tvs_params[0], TEM_SCROLL_DOWN,
892 887 credp, called_from);
893 888 break;
894 889
895 890 case 'X': /* erase char */
896 891 tem_safe_setparam(tem, 1, 1);
897 892 tem_safe_clear_chars(tem,
898 893 tem->tvs_params[0],
899 894 tem->tvs_c_cursor.row,
900 895 tem->tvs_c_cursor.col,
901 896 credp, called_from);
902 897 break;
903 898
904 899 case 'Z': /* cursor backward tabulation */
905 900 tem_safe_setparam(tem, 1, 1);
906 901
907 902 /*
908 903 * Rule exception - We do sanity checking here.
909 904 *
910 905 * Restrict the count to a sane value to keep from
911 906 * looping for a long time. There can't be more than one
912 907 * tab stop per column, so use that as a limit.
913 908 */
914 909 if (tem->tvs_params[0] > tems.ts_c_dimension.width)
915 910 tem->tvs_params[0] = tems.ts_c_dimension.width;
916 911
917 912 for (i = 0; i < tem->tvs_params[0]; i++)
918 913 tem_safe_back_tab(tem, credp, called_from);
919 914 break;
920 915 }
921 916 tem->tvs_state = A_STATE_START;
922 917 }
923 918
924 919
925 920 /*
926 921 * Gather the parameters of an ANSI escape sequence
927 922 */
928 923 static void
929 924 tem_safe_getparams(struct tem_vt_state *tem, uchar_t ch,
930 925 cred_t *credp, enum called_from called_from)
931 926 {
932 927 ASSERT((called_from == CALLED_FROM_STANDALONE) ||
933 928 MUTEX_HELD(&tem->tvs_lock));
934 929
935 930 if (ch >= '0' && ch <= '9') {
936 931 tem->tvs_paramval = ((tem->tvs_paramval * 10) + (ch - '0'));
937 932 tem->tvs_gotparam = B_TRUE; /* Remember got parameter */
938 933 return; /* Return immediately */
939 934 } else if (tem->tvs_state == A_STATE_CSI_EQUAL ||
940 935 tem->tvs_state == A_STATE_CSI_QMARK) {
941 936 tem->tvs_state = A_STATE_START;
942 937 } else {
943 938 if (tem->tvs_curparam < TEM_MAXPARAMS) {
944 939 if (tem->tvs_gotparam) {
945 940 /* get the parameter value */
946 941 tem->tvs_params[tem->tvs_curparam] =
947 942 tem->tvs_paramval;
948 943 }
949 944 tem->tvs_curparam++;
950 945 }
951 946
952 947 if (ch == ';') {
953 948 /* Restart parameter search */
954 949 tem->tvs_gotparam = B_FALSE;
955 950 tem->tvs_paramval = 0; /* No parame value yet */
956 951 } else {
957 952 /* Handle escape sequence */
958 953 tem_safe_chkparam(tem, ch, credp, called_from);
959 954 }
960 955 }
961 956 }
962 957
963 958 /*
964 959 * Add character to internal buffer.
965 960 * When its full, send it to the next layer.
966 961 */
967 962
968 963 static void
969 964 tem_safe_outch(struct tem_vt_state *tem, uchar_t ch,
970 965 cred_t *credp, enum called_from called_from)
971 966 {
972 967
973 968 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
974 969 called_from == CALLED_FROM_STANDALONE);
975 970
976 971 /* buffer up the character until later */
977 972
978 973 tem->tvs_outbuf[tem->tvs_outindex++] = ch;
979 974 tem->tvs_c_cursor.col++;
980 975 if (tem->tvs_c_cursor.col >= tems.ts_c_dimension.width) {
981 976 tem_safe_send_data(tem, credp, called_from);
982 977 tem_safe_new_line(tem, credp, called_from);
983 978 }
984 979 }
985 980
986 981 static void
987 982 tem_safe_new_line(struct tem_vt_state *tem,
988 983 cred_t *credp, enum called_from called_from)
989 984 {
990 985 tem_safe_cr(tem);
991 986 tem_safe_lf(tem, credp, called_from);
992 987 }
993 988
994 989 static void
995 990 tem_safe_cr(struct tem_vt_state *tem)
996 991 {
997 992 tem->tvs_c_cursor.col = 0;
998 993 tem_safe_align_cursor(tem);
999 994 }
1000 995
1001 996 static void
1002 997 tem_safe_lf(struct tem_vt_state *tem,
1003 998 cred_t *credp, enum called_from called_from)
1004 999 {
1005 1000 int row;
1006 1001
1007 1002 ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1008 1003 MUTEX_HELD(&tem->tvs_lock));
1009 1004
1010 1005 /*
1011 1006 * Sanity checking notes:
1012 1007 * . a_nscroll was validated when it was set.
1013 1008 * . Regardless of that, tem_safe_scroll and tem_safe_mv_cursor
1014 1009 * will prevent anything bad from happening.
1015 1010 */
1016 1011 row = tem->tvs_c_cursor.row + 1;
1017 1012
1018 1013 if (row >= tems.ts_c_dimension.height) {
1019 1014 if (tem->tvs_nscroll != 0) {
1020 1015 tem_safe_scroll(tem, 0,
1021 1016 tems.ts_c_dimension.height - 1,
1022 1017 tem->tvs_nscroll, TEM_SCROLL_UP,
1023 1018 credp, called_from);
1024 1019 row = tems.ts_c_dimension.height -
1025 1020 tem->tvs_nscroll;
1026 1021 } else { /* no scroll */
1027 1022 /*
1028 1023 * implement Esc[#r when # is zero. This means no
1029 1024 * scroll but just return cursor to top of screen,
1030 1025 * do not clear screen.
1031 1026 */
1032 1027 row = 0;
1033 1028 }
1034 1029 }
1035 1030
1036 1031 tem_safe_mv_cursor(tem, row, tem->tvs_c_cursor.col,
1037 1032 credp, called_from);
1038 1033
1039 1034 if (tem->tvs_nscroll == 0) {
1040 1035 /* erase rest of cursor line */
1041 1036 tem_safe_clear_chars(tem,
1042 1037 tems.ts_c_dimension.width -
1043 1038 tem->tvs_c_cursor.col,
1044 1039 tem->tvs_c_cursor.row,
1045 1040 tem->tvs_c_cursor.col,
1046 1041 credp, called_from);
1047 1042
1048 1043 }
1049 1044
1050 1045 tem_safe_align_cursor(tem);
1051 1046 }
1052 1047
1053 1048 static void
1054 1049 tem_safe_send_data(struct tem_vt_state *tem, cred_t *credp,
1055 1050 enum called_from called_from)
1056 1051 {
1057 1052 text_color_t fg_color;
1058 1053 text_color_t bg_color;
1059 1054
1060 1055 ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1061 1056 MUTEX_HELD(&tem->tvs_lock));
1062 1057
1063 1058 if (tem->tvs_outindex == 0) {
1064 1059 tem_safe_align_cursor(tem);
1065 1060 return;
1066 1061 }
1067 1062
1068 1063 tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_REVERSE);
1069 1064 tem_safe_virtual_display(tem,
1070 1065 tem->tvs_outbuf, tem->tvs_outindex,
1071 1066 tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
1072 1067 fg_color, bg_color);
1073 1068
1074 1069 if (tem->tvs_isactive) {
1075 1070 /*
1076 1071 * Call the primitive to render this data.
1077 1072 */
1078 1073 tem_safe_callback_display(tem,
1079 1074 tem->tvs_outbuf, tem->tvs_outindex,
1080 1075 tem->tvs_s_cursor.row, tem->tvs_s_cursor.col,
1081 1076 fg_color, bg_color,
1082 1077 credp, called_from);
1083 1078 }
1084 1079
1085 1080 tem->tvs_outindex = 0;
1086 1081
1087 1082 tem_safe_align_cursor(tem);
1088 1083 }
1089 1084
1090 1085
1091 1086 /*
1092 1087 * We have just done something to the current output point. Reset the start
1093 1088 * point for the buffered data in a_outbuf. There shouldn't be any data
1094 1089 * buffered yet.
1095 1090 */
1096 1091 static void
1097 1092 tem_safe_align_cursor(struct tem_vt_state *tem)
1098 1093 {
1099 1094 tem->tvs_s_cursor.row = tem->tvs_c_cursor.row;
1100 1095 tem->tvs_s_cursor.col = tem->tvs_c_cursor.col;
1101 1096 }
1102 1097
1103 1098 /*
1104 1099 * State machine parser based on the current state and character input
1105 1100 * major terminations are to control character or normal character
1106 1101 */
1107 1102
1108 1103 static void
1109 1104 tem_safe_parse(struct tem_vt_state *tem, uchar_t ch,
1110 1105 cred_t *credp, enum called_from called_from)
1111 1106 {
1112 1107 int i;
1113 1108
1114 1109 ASSERT((called_from == CALLED_FROM_STANDALONE) ||
1115 1110 MUTEX_HELD(&tem->tvs_lock));
1116 1111
1117 1112 if (tem->tvs_state == A_STATE_START) { /* Normal state? */
1118 1113 if (ch == A_CSI || ch == A_ESC || ch < ' ') {
1119 1114 /* Control */
1120 1115 tem_safe_control(tem, ch, credp, called_from);
1121 1116 } else {
1122 1117 /* Display */
1123 1118 tem_safe_outch(tem, ch, credp, called_from);
1124 1119 }
1125 1120 return;
1126 1121 }
1127 1122
1128 1123 /* In <ESC> sequence */
1129 1124 if (tem->tvs_state != A_STATE_ESC) { /* Need to get parameters? */
1130 1125 if (tem->tvs_state != A_STATE_CSI) {
1131 1126 tem_safe_getparams(tem, ch, credp, called_from);
1132 1127 return;
1133 1128 }
1134 1129
1135 1130 switch (ch) {
1136 1131 case '?':
1137 1132 tem->tvs_state = A_STATE_CSI_QMARK;
1138 1133 return;
1139 1134 case '=':
1140 1135 tem->tvs_state = A_STATE_CSI_EQUAL;
1141 1136 return;
1142 1137 case 's':
1143 1138 /*
1144 1139 * As defined below, this sequence
1145 1140 * saves the cursor. However, Sun
1146 1141 * defines ESC[s as reset. We resolved
1147 1142 * the conflict by selecting reset as it
1148 1143 * is exported in the termcap file for
1149 1144 * sun-mon, while the "save cursor"
1150 1145 * definition does not exist anywhere in
1151 1146 * /etc/termcap.
1152 1147 * However, having no coherent
1153 1148 * definition of reset, we have not
1154 1149 * implemented it.
1155 1150 */
1156 1151
1157 1152 /*
1158 1153 * Original code
1159 1154 * tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1160 1155 * tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1161 1156 * tem->tvs_state = A_STATE_START;
1162 1157 */
1163 1158
1164 1159 tem->tvs_state = A_STATE_START;
1165 1160 return;
1166 1161 case 'u':
1167 1162 tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row,
1168 1163 tem->tvs_r_cursor.col, credp, called_from);
1169 1164 tem->tvs_state = A_STATE_START;
1170 1165 return;
1171 1166 case 'p': /* sunbow */
1172 1167 tem_safe_send_data(tem, credp, called_from);
1173 1168 /*
1174 1169 * Don't set anything if we are
1175 1170 * already as we want to be.
1176 1171 */
1177 1172 if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) {
1178 1173 tem->tvs_flags &= ~TEM_ATTR_SCREEN_REVERSE;
1179 1174 /*
1180 1175 * If we have switched the characters to be the
1181 1176 * inverse from the screen, then switch them as
1182 1177 * well to keep them the inverse of the screen.
1183 1178 */
1184 1179 if (tem->tvs_flags & TEM_ATTR_REVERSE)
1185 1180 tem->tvs_flags &= ~TEM_ATTR_REVERSE;
1186 1181 else
1187 1182 tem->tvs_flags |= TEM_ATTR_REVERSE;
1188 1183 }
1189 1184 tem_safe_cls(tem, credp, called_from);
1190 1185 tem->tvs_state = A_STATE_START;
1191 1186 return;
1192 1187 case 'q': /* sunwob */
1193 1188 tem_safe_send_data(tem, credp, called_from);
1194 1189 /*
1195 1190 * Don't set anything if we are
1196 1191 * already where as we want to be.
1197 1192 */
1198 1193 if (!(tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE)) {
1199 1194 tem->tvs_flags |= TEM_ATTR_SCREEN_REVERSE;
1200 1195 /*
1201 1196 * If we have switched the characters to be the
1202 1197 * inverse from the screen, then switch them as
1203 1198 * well to keep them the inverse of the screen.
1204 1199 */
1205 1200 if (!(tem->tvs_flags & TEM_ATTR_REVERSE))
1206 1201 tem->tvs_flags |= TEM_ATTR_REVERSE;
1207 1202 else
1208 1203 tem->tvs_flags &= ~TEM_ATTR_REVERSE;
1209 1204 }
1210 1205
1211 1206 tem_safe_cls(tem, credp, called_from);
1212 1207 tem->tvs_state = A_STATE_START;
1213 1208 return;
1214 1209 case 'r': /* sunscrl */
1215 1210 /*
1216 1211 * Rule exception: check for validity here.
1217 1212 */
1218 1213 tem->tvs_nscroll = tem->tvs_paramval;
1219 1214 if (tem->tvs_nscroll > tems.ts_c_dimension.height)
1220 1215 tem->tvs_nscroll = tems.ts_c_dimension.height;
1221 1216 if (tem->tvs_nscroll < 0)
1222 1217 tem->tvs_nscroll = 1;
1223 1218 tem->tvs_state = A_STATE_START;
1224 1219 return;
1225 1220 default:
1226 1221 tem_safe_getparams(tem, ch, credp, called_from);
1227 1222 return;
1228 1223 }
1229 1224 }
1230 1225
1231 1226 /* Previous char was <ESC> */
1232 1227 if (ch == '[') {
1233 1228 tem->tvs_curparam = 0;
1234 1229 tem->tvs_paramval = 0;
1235 1230 tem->tvs_gotparam = B_FALSE;
1236 1231 /* clear the parameters */
1237 1232 for (i = 0; i < TEM_MAXPARAMS; i++)
1238 1233 tem->tvs_params[i] = -1;
1239 1234 tem->tvs_state = A_STATE_CSI;
1240 1235 } else if (ch == 'Q') { /* <ESC>Q ? */
1241 1236 tem->tvs_state = A_STATE_START;
1242 1237 } else if (ch == 'C') { /* <ESC>C ? */
1243 1238 tem->tvs_state = A_STATE_START;
1244 1239 } else {
1245 1240 tem->tvs_state = A_STATE_START;
1246 1241 if (ch == 'c') {
1247 1242 /* ESC c resets display */
1248 1243 tem_safe_reset_display(tem, credp, called_from,
1249 1244 B_TRUE, B_TRUE);
1250 1245 } else if (ch == 'H') {
1251 1246 /* ESC H sets a tab */
1252 1247 tem_safe_set_tab(tem);
1253 1248 } else if (ch == '7') {
1254 1249 /* ESC 7 Save Cursor position */
1255 1250 tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1256 1251 tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1257 1252 } else if (ch == '8') {
1258 1253 /* ESC 8 Restore Cursor position */
1259 1254 tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row,
1260 1255 tem->tvs_r_cursor.col, credp, called_from);
1261 1256 /* check for control chars */
1262 1257 } else if (ch < ' ') {
1263 1258 tem_safe_control(tem, ch, credp, called_from);
1264 1259 } else {
1265 1260 tem_safe_outch(tem, ch, credp, called_from);
1266 1261 }
1267 1262 }
1268 1263 }
1269 1264
1270 1265 /* ARGSUSED */
1271 1266 static void
1272 1267 tem_safe_bell(struct tem_vt_state *tem, enum called_from called_from)
1273 1268 {
1274 1269 if (called_from == CALLED_FROM_STANDALONE)
1275 1270 (void) beep_polled(BEEP_CONSOLE);
1276 1271 else
1277 1272 (void) beep(BEEP_CONSOLE);
1278 1273 }
1279 1274
1280 1275
1281 1276 static void
1282 1277 tem_safe_scroll(struct tem_vt_state *tem, int start, int end, int count,
1283 1278 int direction, cred_t *credp, enum called_from called_from)
1284 1279 {
1285 1280 int row;
1286 1281 int lines_affected;
1287 1282
1288 1283 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1289 1284 called_from == CALLED_FROM_STANDALONE);
1290 1285
1291 1286 lines_affected = end - start + 1;
1292 1287 if (count > lines_affected)
1293 1288 count = lines_affected;
1294 1289 if (count <= 0)
1295 1290 return;
1296 1291
1297 1292 switch (direction) {
1298 1293 case TEM_SCROLL_UP:
1299 1294 if (count < lines_affected) {
1300 1295 tem_safe_copy_area(tem, 0, start + count,
1301 1296 tems.ts_c_dimension.width - 1, end,
1302 1297 0, start, credp, called_from);
1303 1298 }
1304 1299 for (row = (end - count) + 1; row <= end; row++) {
1305 1300 tem_safe_clear_chars(tem, tems.ts_c_dimension.width,
1306 1301 row, 0, credp, called_from);
1307 1302 }
1308 1303 break;
1309 1304
1310 1305 case TEM_SCROLL_DOWN:
1311 1306 if (count < lines_affected) {
1312 1307 tem_safe_copy_area(tem, 0, start,
1313 1308 tems.ts_c_dimension.width - 1,
1314 1309 end - count, 0, start + count,
1315 1310 credp, called_from);
1316 1311 }
1317 1312 for (row = start; row < start + count; row++) {
1318 1313 tem_safe_clear_chars(tem, tems.ts_c_dimension.width,
1319 1314 row, 0, credp, called_from);
1320 1315 }
1321 1316 break;
1322 1317 }
1323 1318 }
1324 1319
1325 1320 static void
1326 1321 tem_safe_copy_area(struct tem_vt_state *tem,
1327 1322 screen_pos_t s_col, screen_pos_t s_row,
1328 1323 screen_pos_t e_col, screen_pos_t e_row,
1329 1324 screen_pos_t t_col, screen_pos_t t_row,
1330 1325 cred_t *credp, enum called_from called_from)
1331 1326 {
1332 1327 int rows;
1333 1328 int cols;
1334 1329
1335 1330 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1336 1331 called_from == CALLED_FROM_STANDALONE);
1337 1332
1338 1333 if (s_col < 0 || s_row < 0 ||
1339 1334 e_col < 0 || e_row < 0 ||
1340 1335 t_col < 0 || t_row < 0 ||
1341 1336 s_col >= tems.ts_c_dimension.width ||
1342 1337 e_col >= tems.ts_c_dimension.width ||
1343 1338 t_col >= tems.ts_c_dimension.width ||
1344 1339 s_row >= tems.ts_c_dimension.height ||
1345 1340 e_row >= tems.ts_c_dimension.height ||
1346 1341 t_row >= tems.ts_c_dimension.height)
1347 1342 return;
1348 1343
1349 1344 if (s_row > e_row || s_col > e_col)
1350 1345 return;
1351 1346
1352 1347 rows = e_row - s_row + 1;
1353 1348 cols = e_col - s_col + 1;
1354 1349 if (t_row + rows > tems.ts_c_dimension.height ||
1355 1350 t_col + cols > tems.ts_c_dimension.width)
1356 1351 return;
1357 1352
1358 1353 tem_safe_virtual_copy(tem,
1359 1354 s_col, s_row,
1360 1355 e_col, e_row,
1361 1356 t_col, t_row);
1362 1357
1363 1358 if (!tem->tvs_isactive)
1364 1359 return;
1365 1360
1366 1361 tem_safe_callback_copy(tem, s_col, s_row,
1367 1362 e_col, e_row, t_col, t_row, credp, called_from);
1368 1363 }
1369 1364
1370 1365 static void
1371 1366 tem_safe_clear_chars(struct tem_vt_state *tem, int count, screen_pos_t row,
1372 1367 screen_pos_t col, cred_t *credp, enum called_from called_from)
1373 1368 {
1374 1369 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1375 1370 called_from == CALLED_FROM_STANDALONE);
1376 1371
1377 1372 if (row < 0 || row >= tems.ts_c_dimension.height ||
1378 1373 col < 0 || col >= tems.ts_c_dimension.width ||
1379 1374 count < 0)
1380 1375 return;
1381 1376
1382 1377 /*
1383 1378 * Note that very large values of "count" could cause col+count
1384 1379 * to overflow, so we check "count" independently.
1385 1380 */
1386 1381 if (count > tems.ts_c_dimension.width ||
1387 1382 col + count > tems.ts_c_dimension.width)
1388 1383 count = tems.ts_c_dimension.width - col;
1389 1384
1390 1385 tem_safe_virtual_cls(tem, count, row, col);
1391 1386
1392 1387 if (!tem->tvs_isactive)
1393 1388 return;
1394 1389
1395 1390 tem_safe_callback_cls(tem, count, row, col, credp, called_from);
1396 1391 }
1397 1392
1398 1393 /*ARGSUSED*/
1399 1394 void
1400 1395 tem_safe_text_display(struct tem_vt_state *tem, uchar_t *string,
1401 1396 int count, screen_pos_t row, screen_pos_t col,
1402 1397 text_color_t fg_color, text_color_t bg_color,
1403 1398 cred_t *credp, enum called_from called_from)
1404 1399 {
1405 1400 struct vis_consdisplay da;
1406 1401
1407 1402 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1408 1403 called_from == CALLED_FROM_STANDALONE);
1409 1404
1410 1405 da.data = string;
1411 1406 da.width = (screen_size_t)count;
1412 1407 da.row = row;
1413 1408 da.col = col;
1414 1409
1415 1410 da.fg_color = fg_color;
1416 1411 da.bg_color = bg_color;
1417 1412
1418 1413 tems_safe_display(&da, credp, called_from);
1419 1414 }
1420 1415
1421 1416 /*
1422 1417 * This function is used to blit a rectangular color image,
1423 1418 * unperturbed on the underlying framebuffer, to render
1424 1419 * icons and pictures. The data is a pixel pattern that
1425 1420 * fills a rectangle bounded to the width and height parameters.
1426 1421 * The color pixel data must to be pre-adjusted by the caller
1427 1422 * for the current video depth.
1428 1423 *
1429 1424 * This function is unused now.
1430 1425 */
1431 1426 /*ARGSUSED*/
1432 1427 static void
1433 1428 tem_safe_image_display(struct tem_vt_state *tem, uchar_t *image,
1434 1429 int height, int width, screen_pos_t row, screen_pos_t col,
1435 1430 cred_t *credp, enum called_from called_from)
1436 1431 {
1437 1432 struct vis_consdisplay da;
1438 1433
1439 1434 mutex_enter(&tems.ts_lock);
1440 1435 mutex_enter(&tem->tvs_lock);
1441 1436
1442 1437 da.data = image;
1443 1438 da.width = (screen_size_t)width;
1444 1439 da.height = (screen_size_t)height;
1445 1440 da.row = row;
1446 1441 da.col = col;
1447 1442
1448 1443 tems_safe_display(&da, credp, called_from);
1449 1444
1450 1445 mutex_exit(&tem->tvs_lock);
1451 1446 mutex_exit(&tems.ts_lock);
1452 1447 }
1453 1448
1454 1449
1455 1450 /*ARGSUSED*/
1456 1451 void
1457 1452 tem_safe_text_copy(struct tem_vt_state *tem,
1458 1453 screen_pos_t s_col, screen_pos_t s_row,
1459 1454 screen_pos_t e_col, screen_pos_t e_row,
1460 1455 screen_pos_t t_col, screen_pos_t t_row,
1461 1456 cred_t *credp, enum called_from called_from)
1462 1457 {
1463 1458 struct vis_conscopy da;
1464 1459
1465 1460 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1466 1461 called_from == CALLED_FROM_STANDALONE);
1467 1462
1468 1463 da.s_row = s_row;
1469 1464 da.s_col = s_col;
1470 1465 da.e_row = e_row;
1471 1466 da.e_col = e_col;
1472 1467 da.t_row = t_row;
1473 1468 da.t_col = t_col;
1474 1469
1475 1470 tems_safe_copy(&da, credp, called_from);
1476 1471 }
1477 1472
1478 1473 void
1479 1474 tem_safe_text_cls(struct tem_vt_state *tem,
1480 1475 int count, screen_pos_t row, screen_pos_t col, cred_t *credp,
1481 1476 enum called_from called_from)
1482 1477 {
1483 1478 struct vis_consdisplay da;
1484 1479
1485 1480 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1486 1481 called_from == CALLED_FROM_STANDALONE);
1487 1482
1488 1483 da.data = tems.ts_blank_line;
1489 1484 da.width = (screen_size_t)count;
1490 1485 da.row = row;
1491 1486 da.col = col;
1492 1487
1493 1488 tem_safe_get_color(tem, &da.fg_color, &da.bg_color,
1494 1489 TEM_ATTR_SCREEN_REVERSE);
1495 1490 tems_safe_display(&da, credp, called_from);
1496 1491 }
1497 1492
1498 1493 void
1499 1494 tem_safe_pix_display(struct tem_vt_state *tem,
1500 1495 uchar_t *string, int count,
1501 1496 screen_pos_t row, screen_pos_t col,
1502 1497 text_color_t fg_color, text_color_t bg_color,
1503 1498 cred_t *credp, enum called_from called_from)
1504 1499 {
1505 1500 struct vis_consdisplay da;
1506 1501 int i;
1507 1502
1508 1503 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1509 1504 called_from == CALLED_FROM_STANDALONE);
1510 1505
1511 1506 da.data = (uchar_t *)tem->tvs_pix_data;
1512 1507 da.width = tems.ts_font.width;
1513 1508 da.height = tems.ts_font.height;
1514 1509 da.row = (row * da.height) + tems.ts_p_offset.y;
1515 1510 da.col = (col * da.width) + tems.ts_p_offset.x;
1516 1511
1517 1512 for (i = 0; i < count; i++) {
1518 1513 tem_safe_callback_bit2pix(tem, string[i], fg_color, bg_color);
1519 1514 tems_safe_display(&da, credp, called_from);
1520 1515 da.col += da.width;
1521 1516 }
1522 1517 }
1523 1518
1524 1519 void
1525 1520 tem_safe_pix_copy(struct tem_vt_state *tem,
1526 1521 screen_pos_t s_col, screen_pos_t s_row,
1527 1522 screen_pos_t e_col, screen_pos_t e_row,
1528 1523 screen_pos_t t_col, screen_pos_t t_row,
1529 1524 cred_t *credp,
1530 1525 enum called_from called_from)
1531 1526 {
1532 1527 struct vis_conscopy ma;
1533 1528 static boolean_t need_clear = B_TRUE;
1534 1529
1535 1530 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1536 1531 called_from == CALLED_FROM_STANDALONE);
1537 1532
1538 1533 if (need_clear && tem->tvs_first_line > 0) {
1539 1534 /*
1540 1535 * Clear OBP output above our kernel console term
1541 1536 * when our kernel console term begins to scroll up,
1542 1537 * we hope it is user friendly.
1543 1538 * (Also see comments on tem_safe_pix_clear_prom_output)
1544 1539 *
1545 1540 * This is only one time call.
1546 1541 */
1547 1542 tem_safe_pix_clear_prom_output(tem, credp, called_from);
1548 1543 }
1549 1544 need_clear = B_FALSE;
1550 1545
1551 1546 ma.s_row = s_row * tems.ts_font.height + tems.ts_p_offset.y;
1552 1547 ma.e_row = (e_row + 1) * tems.ts_font.height + tems.ts_p_offset.y - 1;
1553 1548 ma.t_row = t_row * tems.ts_font.height + tems.ts_p_offset.y;
1554 1549
1555 1550 /*
1556 1551 * Check if we're in process of clearing OBP's columns area,
1557 1552 * which only happens when term scrolls up a whole line.
1558 1553 */
1559 1554 if (tem->tvs_first_line > 0 && t_row < s_row && t_col == 0 &&
1560 1555 e_col == tems.ts_c_dimension.width - 1) {
1561 1556 /*
1562 1557 * We need to clear OBP's columns area outside our kernel
1563 1558 * console term. So that we set ma.e_col to entire row here.
1564 1559 */
1565 1560 ma.s_col = s_col * tems.ts_font.width;
1566 1561 ma.e_col = tems.ts_p_dimension.width - 1;
1567 1562
1568 1563 ma.t_col = t_col * tems.ts_font.width;
1569 1564 } else {
1570 1565 ma.s_col = s_col * tems.ts_font.width + tems.ts_p_offset.x;
1571 1566 ma.e_col = (e_col + 1) * tems.ts_font.width +
1572 1567 tems.ts_p_offset.x - 1;
1573 1568 ma.t_col = t_col * tems.ts_font.width + tems.ts_p_offset.x;
1574 1569 }
1575 1570
1576 1571 tems_safe_copy(&ma, credp, called_from);
1577 1572
1578 1573 if (tem->tvs_first_line > 0 && t_row < s_row) {
1579 1574 /* We have scrolled up (s_row - t_row) rows. */
1580 1575 tem->tvs_first_line -= (s_row - t_row);
1581 1576 if (tem->tvs_first_line <= 0) {
1582 1577 /* All OBP rows have been cleared. */
1583 1578 tem->tvs_first_line = 0;
1584 1579 }
1585 1580 }
1586 1581
1587 1582 }
1588 1583
1589 1584 void
1590 1585 tem_safe_pix_bit2pix(struct tem_vt_state *tem, unsigned char c,
1591 1586 unsigned char fg, unsigned char bg)
1592 1587 {
1593 1588 void (*fp)(struct tem_vt_state *, unsigned char,
1594 1589 unsigned char, unsigned char);
1595 1590
1596 1591 switch (tems.ts_pdepth) {
1597 1592 case 4:
1598 1593 fp = bit_to_pix4;
1599 1594 break;
1600 1595 case 8:
1601 1596 fp = bit_to_pix8;
1602 1597 break;
1603 1598 case 24:
1604 1599 case 32:
1605 1600 fp = bit_to_pix24;
1606 1601 }
1607 1602
1608 1603 fp(tem, c, fg, bg);
1609 1604 }
1610 1605
1611 1606
1612 1607 /*
1613 1608 * This function only clears count of columns in one row
1614 1609 */
1615 1610 void
1616 1611 tem_safe_pix_cls(struct tem_vt_state *tem, int count,
1617 1612 screen_pos_t row, screen_pos_t col, cred_t *credp,
1618 1613 enum called_from called_from)
1619 1614 {
1620 1615 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1621 1616 called_from == CALLED_FROM_STANDALONE);
1622 1617
1623 1618 tem_safe_pix_cls_range(tem, row, 1, tems.ts_p_offset.y,
1624 1619 col, count, tems.ts_p_offset.x, B_FALSE, credp, called_from);
1625 1620 }
1626 1621
1627 1622 /*
1628 1623 * This function clears OBP output above our kernel console term area
1629 1624 * because OBP's term may have a bigger terminal window than that of
1630 1625 * our kernel console term. So we need to clear OBP output garbage outside
1631 1626 * of our kernel console term at a proper time, which is when the first
1632 1627 * row output of our kernel console term scrolls at the first screen line.
1633 1628 *
1634 1629 * _________________________________
1635 1630 * | _____________________ | ---> OBP's bigger term window
1636 1631 * | | | |
1637 1632 * |___| | |
1638 1633 * | | | | |
1639 1634 * | | | | |
1640 1635 * |_|_|___________________|_______|
1641 1636 * | | | ---> first line
1642 1637 * | |___________________|---> our kernel console term window
1643 1638 * |
1644 1639 * |---> columns area to be cleared
1645 1640 *
1646 1641 * This function only takes care of the output above our kernel console term,
1647 1642 * and tem_prom_scroll_up takes care of columns area outside of our kernel
1648 1643 * console term.
1649 1644 */
1650 1645 static void
1651 1646 tem_safe_pix_clear_prom_output(struct tem_vt_state *tem, cred_t *credp,
1652 1647 enum called_from called_from)
1653 1648 {
1654 1649 int nrows, ncols, width, height;
1655 1650
1656 1651 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1657 1652 called_from == CALLED_FROM_STANDALONE);
1658 1653
1659 1654 width = tems.ts_font.width;
1660 1655 height = tems.ts_font.height;
1661 1656
1662 1657 nrows = (tems.ts_p_offset.y + (height - 1))/ height;
1663 1658 ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1664 1659
1665 1660 tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,
1666 1661 B_FALSE, credp, called_from);
1667 1662 }
1668 1663
1669 1664 /*
1670 1665 * clear the whole screen for pixel mode, just clear the
1671 1666 * physical screen.
1672 1667 */
1673 1668 void
1674 1669 tem_safe_pix_clear_entire_screen(struct tem_vt_state *tem, cred_t *credp,
1675 1670 enum called_from called_from)
1676 1671 {
1677 1672 int nrows, ncols, width, height;
1678 1673
1679 1674 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1680 1675 called_from == CALLED_FROM_STANDALONE);
1681 1676
1682 1677 width = tems.ts_font.width;
1683 1678 height = tems.ts_font.height;
1684 1679
1685 1680 nrows = (tems.ts_p_dimension.height + (height - 1))/ height;
1686 1681 ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
1687 1682
1688 1683 tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0,
1689 1684 B_FALSE, credp, called_from);
1690 1685
1691 1686 /*
1692 1687 * Since the whole screen is cleared, we don't need
1693 1688 * to clear OBP output later.
1694 1689 */
1695 1690 if (tem->tvs_first_line > 0)
1696 1691 tem->tvs_first_line = 0;
1697 1692 }
1698 1693
1699 1694 /*
1700 1695 * clear the whole screen, including the virtual screen buffer,
1701 1696 * and reset the cursor to start point.
1702 1697 */
1703 1698 static void
1704 1699 tem_safe_cls(struct tem_vt_state *tem,
1705 1700 cred_t *credp, enum called_from called_from)
1706 1701 {
1707 1702 int row;
1708 1703
1709 1704 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1710 1705 called_from == CALLED_FROM_STANDALONE);
1711 1706
1712 1707 if (tems.ts_display_mode == VIS_TEXT) {
1713 1708 for (row = 0; row < tems.ts_c_dimension.height; row++) {
1714 1709 tem_safe_clear_chars(tem, tems.ts_c_dimension.width,
1715 1710 row, 0, credp, called_from);
1716 1711 }
1717 1712 tem->tvs_c_cursor.row = 0;
1718 1713 tem->tvs_c_cursor.col = 0;
1719 1714 tem_safe_align_cursor(tem);
1720 1715 return;
1721 1716 }
1722 1717
1723 1718 ASSERT(tems.ts_display_mode == VIS_PIXEL);
1724 1719
1725 1720 for (row = 0; row < tems.ts_c_dimension.height; row++) {
1726 1721 tem_safe_virtual_cls(tem, tems.ts_c_dimension.width, row, 0);
1727 1722 }
1728 1723 tem->tvs_c_cursor.row = 0;
1729 1724 tem->tvs_c_cursor.col = 0;
1730 1725 tem_safe_align_cursor(tem);
1731 1726
1732 1727 if (!tem->tvs_isactive)
1733 1728 return;
1734 1729
1735 1730 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
1736 1731 }
1737 1732
1738 1733 static void
1739 1734 tem_safe_back_tab(struct tem_vt_state *tem,
1740 1735 cred_t *credp, enum called_from called_from)
1741 1736 {
1742 1737 int i;
1743 1738 screen_pos_t tabstop;
1744 1739
1745 1740 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1746 1741 called_from == CALLED_FROM_STANDALONE);
1747 1742
1748 1743 tabstop = 0;
1749 1744
1750 1745 for (i = tem->tvs_ntabs - 1; i >= 0; i--) {
1751 1746 if (tem->tvs_tabs[i] < tem->tvs_c_cursor.col) {
1752 1747 tabstop = tem->tvs_tabs[i];
1753 1748 break;
1754 1749 }
1755 1750 }
1756 1751
1757 1752 tem_safe_mv_cursor(tem, tem->tvs_c_cursor.row,
1758 1753 tabstop, credp, called_from);
1759 1754 }
1760 1755
1761 1756 static void
1762 1757 tem_safe_tab(struct tem_vt_state *tem,
1763 1758 cred_t *credp, enum called_from called_from)
1764 1759 {
1765 1760 int i;
1766 1761 screen_pos_t tabstop;
1767 1762
1768 1763 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1769 1764 called_from == CALLED_FROM_STANDALONE);
1770 1765
1771 1766 tabstop = tems.ts_c_dimension.width - 1;
1772 1767
1773 1768 for (i = 0; i < tem->tvs_ntabs; i++) {
1774 1769 if (tem->tvs_tabs[i] > tem->tvs_c_cursor.col) {
1775 1770 tabstop = tem->tvs_tabs[i];
1776 1771 break;
1777 1772 }
1778 1773 }
1779 1774
1780 1775 tem_safe_mv_cursor(tem, tem->tvs_c_cursor.row,
1781 1776 tabstop, credp, called_from);
1782 1777 }
1783 1778
1784 1779 static void
1785 1780 tem_safe_set_tab(struct tem_vt_state *tem)
1786 1781 {
1787 1782 int i;
1788 1783 int j;
1789 1784
1790 1785 if (tem->tvs_ntabs == TEM_MAXTAB)
1791 1786 return;
1792 1787 if (tem->tvs_ntabs == 0 ||
1793 1788 tem->tvs_tabs[tem->tvs_ntabs] < tem->tvs_c_cursor.col) {
1794 1789 tem->tvs_tabs[tem->tvs_ntabs++] = tem->tvs_c_cursor.col;
1795 1790 return;
1796 1791 }
1797 1792 for (i = 0; i < tem->tvs_ntabs; i++) {
1798 1793 if (tem->tvs_tabs[i] == tem->tvs_c_cursor.col)
1799 1794 return;
1800 1795 if (tem->tvs_tabs[i] > tem->tvs_c_cursor.col) {
1801 1796 for (j = tem->tvs_ntabs - 1; j >= i; j--)
1802 1797 tem->tvs_tabs[j+ 1] = tem->tvs_tabs[j];
1803 1798 tem->tvs_tabs[i] = tem->tvs_c_cursor.col;
1804 1799 tem->tvs_ntabs++;
1805 1800 return;
1806 1801 }
1807 1802 }
1808 1803 }
1809 1804
1810 1805 static void
1811 1806 tem_safe_clear_tabs(struct tem_vt_state *tem, int action)
1812 1807 {
1813 1808 int i;
1814 1809 int j;
1815 1810
1816 1811 switch (action) {
1817 1812 case 3: /* clear all tabs */
1818 1813 tem->tvs_ntabs = 0;
1819 1814 break;
1820 1815 case 0: /* clr tab at cursor */
1821 1816
1822 1817 for (i = 0; i < tem->tvs_ntabs; i++) {
1823 1818 if (tem->tvs_tabs[i] == tem->tvs_c_cursor.col) {
1824 1819 tem->tvs_ntabs--;
1825 1820 for (j = i; j < tem->tvs_ntabs; j++)
1826 1821 tem->tvs_tabs[j] = tem->tvs_tabs[j + 1];
1827 1822 return;
1828 1823 }
1829 1824 }
1830 1825 break;
1831 1826 }
1832 1827 }
1833 1828
1834 1829 static void
1835 1830 tem_safe_mv_cursor(struct tem_vt_state *tem, int row, int col,
1836 1831 cred_t *credp, enum called_from called_from)
1837 1832 {
1838 1833 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1839 1834 called_from == CALLED_FROM_STANDALONE);
1840 1835
1841 1836 /*
1842 1837 * Sanity check and bounds enforcement. Out of bounds requests are
1843 1838 * clipped to the screen boundaries. This seems to be what SPARC
1844 1839 * does.
1845 1840 */
1846 1841 if (row < 0)
1847 1842 row = 0;
1848 1843 if (row >= tems.ts_c_dimension.height)
1849 1844 row = tems.ts_c_dimension.height - 1;
1850 1845 if (col < 0)
1851 1846 col = 0;
1852 1847 if (col >= tems.ts_c_dimension.width)
1853 1848 col = tems.ts_c_dimension.width - 1;
1854 1849
1855 1850 tem_safe_send_data(tem, credp, called_from);
1856 1851 tem->tvs_c_cursor.row = (screen_pos_t)row;
1857 1852 tem->tvs_c_cursor.col = (screen_pos_t)col;
1858 1853 tem_safe_align_cursor(tem);
1859 1854 }
1860 1855
1861 1856 /* ARGSUSED */
1862 1857 void
1863 1858 tem_safe_reset_emulator(struct tem_vt_state *tem,
1864 1859 cred_t *credp, enum called_from called_from,
1865 1860 boolean_t init_color)
1866 1861 {
1867 1862 int j;
1868 1863
1869 1864 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1870 1865 called_from == CALLED_FROM_STANDALONE);
1871 1866
1872 1867 tem->tvs_c_cursor.row = 0;
1873 1868 tem->tvs_c_cursor.col = 0;
1874 1869 tem->tvs_r_cursor.row = 0;
1875 1870 tem->tvs_r_cursor.col = 0;
1876 1871 tem->tvs_s_cursor.row = 0;
1877 1872 tem->tvs_s_cursor.col = 0;
1878 1873 tem->tvs_outindex = 0;
1879 1874 tem->tvs_state = A_STATE_START;
1880 1875 tem->tvs_gotparam = B_FALSE;
1881 1876 tem->tvs_curparam = 0;
1882 1877 tem->tvs_paramval = 0;
1883 1878 tem->tvs_nscroll = 1;
1884 1879
1885 1880 if (init_color) {
1886 1881 /* use initial settings */
1887 1882 tem->tvs_fg_color = tems.ts_init_color.fg_color;
1888 1883 tem->tvs_bg_color = tems.ts_init_color.bg_color;
1889 1884 tem->tvs_flags = tems.ts_init_color.a_flags;
1890 1885 }
1891 1886
1892 1887 /*
1893 1888 * set up the initial tab stops
1894 1889 */
1895 1890 tem->tvs_ntabs = 0;
1896 1891 for (j = 8; j < tems.ts_c_dimension.width; j += 8)
1897 1892 tem->tvs_tabs[tem->tvs_ntabs++] = (screen_pos_t)j;
1898 1893
1899 1894 for (j = 0; j < TEM_MAXPARAMS; j++)
1900 1895 tem->tvs_params[j] = 0;
1901 1896 }
1902 1897
1903 1898 void
1904 1899 tem_safe_reset_display(struct tem_vt_state *tem,
1905 1900 cred_t *credp, enum called_from called_from,
1906 1901 boolean_t clear_txt, boolean_t init_color)
1907 1902 {
1908 1903 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1909 1904 called_from == CALLED_FROM_STANDALONE);
1910 1905
1911 1906 tem_safe_reset_emulator(tem, credp, called_from, init_color);
1912 1907
1913 1908 if (clear_txt) {
1914 1909 if (tem->tvs_isactive)
1915 1910 tem_safe_callback_cursor(tem,
1916 1911 VIS_HIDE_CURSOR, credp, called_from);
1917 1912
1918 1913 tem_safe_cls(tem, credp, called_from);
1919 1914
1920 1915 if (tem->tvs_isactive)
1921 1916 tem_safe_callback_cursor(tem,
1922 1917 VIS_DISPLAY_CURSOR, credp, called_from);
1923 1918 }
1924 1919 }
1925 1920
1926 1921 static void
1927 1922 tem_safe_shift(
1928 1923 struct tem_vt_state *tem,
1929 1924 int count,
1930 1925 int direction,
1931 1926 cred_t *credp,
1932 1927 enum called_from called_from)
1933 1928 {
1934 1929 int rest_of_line;
1935 1930
1936 1931 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1937 1932 called_from == CALLED_FROM_STANDALONE);
1938 1933
1939 1934 rest_of_line = tems.ts_c_dimension.width - tem->tvs_c_cursor.col;
1940 1935 if (count > rest_of_line)
1941 1936 count = rest_of_line;
1942 1937
1943 1938 if (count <= 0)
1944 1939 return;
1945 1940
1946 1941 switch (direction) {
1947 1942 case TEM_SHIFT_LEFT:
1948 1943 if (count < rest_of_line) {
1949 1944 tem_safe_copy_area(tem,
1950 1945 tem->tvs_c_cursor.col + count,
1951 1946 tem->tvs_c_cursor.row,
1952 1947 tems.ts_c_dimension.width - 1,
1953 1948 tem->tvs_c_cursor.row,
1954 1949 tem->tvs_c_cursor.col,
1955 1950 tem->tvs_c_cursor.row,
1956 1951 credp, called_from);
1957 1952 }
1958 1953
1959 1954 tem_safe_clear_chars(tem, count, tem->tvs_c_cursor.row,
1960 1955 (tems.ts_c_dimension.width - count), credp,
1961 1956 called_from);
1962 1957 break;
1963 1958 case TEM_SHIFT_RIGHT:
1964 1959 if (count < rest_of_line) {
1965 1960 tem_safe_copy_area(tem,
1966 1961 tem->tvs_c_cursor.col,
1967 1962 tem->tvs_c_cursor.row,
1968 1963 tems.ts_c_dimension.width - count - 1,
1969 1964 tem->tvs_c_cursor.row,
1970 1965 tem->tvs_c_cursor.col + count,
1971 1966 tem->tvs_c_cursor.row,
1972 1967 credp, called_from);
1973 1968 }
1974 1969
1975 1970 tem_safe_clear_chars(tem, count, tem->tvs_c_cursor.row,
1976 1971 tem->tvs_c_cursor.col, credp, called_from);
1977 1972 break;
1978 1973 }
1979 1974 }
1980 1975
1981 1976 void
1982 1977 tem_safe_text_cursor(struct tem_vt_state *tem, short action,
1983 1978 cred_t *credp, enum called_from called_from)
1984 1979 {
1985 1980 struct vis_conscursor ca;
1986 1981
1987 1982 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
1988 1983 called_from == CALLED_FROM_STANDALONE);
1989 1984
1990 1985 ca.row = tem->tvs_c_cursor.row;
1991 1986 ca.col = tem->tvs_c_cursor.col;
1992 1987 ca.action = action;
1993 1988
1994 1989 tems_safe_cursor(&ca, credp, called_from);
1995 1990
1996 1991 if (action == VIS_GET_CURSOR) {
1997 1992 tem->tvs_c_cursor.row = ca.row;
1998 1993 tem->tvs_c_cursor.col = ca.col;
1999 1994 }
2000 1995 }
2001 1996
2002 1997 void
2003 1998 tem_safe_pix_cursor(struct tem_vt_state *tem, short action,
2004 1999 cred_t *credp, enum called_from called_from)
2005 2000 {
2006 2001 struct vis_conscursor ca;
2007 2002
2008 2003 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2009 2004 called_from == CALLED_FROM_STANDALONE);
2010 2005
2011 2006 ca.row = tem->tvs_c_cursor.row * tems.ts_font.height +
2012 2007 tems.ts_p_offset.y;
2013 2008 ca.col = tem->tvs_c_cursor.col * tems.ts_font.width +
2014 2009 tems.ts_p_offset.x;
2015 2010 ca.width = tems.ts_font.width;
2016 2011 ca.height = tems.ts_font.height;
2017 2012 if (tems.ts_pdepth == 8 || tems.ts_pdepth == 4) {
2018 2013 if (tem->tvs_flags & TEM_ATTR_REVERSE) {
2019 2014 ca.fg_color.mono = TEM_TEXT_WHITE;
2020 2015 ca.bg_color.mono = TEM_TEXT_BLACK;
2021 2016 } else {
2022 2017 ca.fg_color.mono = TEM_TEXT_BLACK;
2023 2018 ca.bg_color.mono = TEM_TEXT_WHITE;
2024 2019 }
2025 2020 } else if (tems.ts_pdepth == 24 || tems.ts_pdepth == 32) {
2026 2021 if (tem->tvs_flags & TEM_ATTR_REVERSE) {
2027 2022 ca.fg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2028 2023 ca.fg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2029 2024 ca.fg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2030 2025
2031 2026 ca.bg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2032 2027 ca.bg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2033 2028 ca.bg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2034 2029 } else {
2035 2030 ca.fg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED;
2036 2031 ca.fg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN;
2037 2032 ca.fg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE;
2038 2033
2039 2034 ca.bg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED;
2040 2035 ca.bg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN;
2041 2036 ca.bg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE;
2042 2037 }
2043 2038 }
2044 2039
2045 2040 ca.action = action;
2046 2041
2047 2042 tems_safe_cursor(&ca, credp, called_from);
2048 2043 }
2049 2044
2050 2045 static void
2051 2046 bit_to_pix4(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
2052 2047 text_color_t bg_color)
2053 2048 {
2054 2049 uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
2055 2050 font_bit_to_pix4(&tems.ts_font, dest, c, fg_color, bg_color);
2056 2051 }
2057 2052
2058 2053 static void
2059 2054 bit_to_pix8(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color,
2060 2055 text_color_t bg_color)
2061 2056 {
2062 2057 uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
2063 2058 font_bit_to_pix8(&tems.ts_font, dest, c, fg_color, bg_color);
2064 2059 }
2065 2060
2066 2061 static void
2067 2062 bit_to_pix24(struct tem_vt_state *tem, uchar_t c, text_color_t fg_color4,
2068 2063 text_color_t bg_color4)
2069 2064 {
2070 2065 uint32_t fg_color32, bg_color32, *dest;
2071 2066
2072 2067 ASSERT(fg_color4 < 16 && bg_color4 < 16);
2073 2068
2074 2069 fg_color32 = PIX4TO32(fg_color4);
2075 2070 bg_color32 = PIX4TO32(bg_color4);
2076 2071
2077 2072 dest = (uint32_t *)tem->tvs_pix_data;
2078 2073 font_bit_to_pix24(&tems.ts_font, dest, c, fg_color32, bg_color32);
2079 2074 }
2080 2075
2081 2076 static text_color_t
2082 2077 ansi_bg_to_solaris(struct tem_vt_state *tem, int ansi)
2083 2078 {
2084 2079 if (tem->tvs_flags & TEM_ATTR_BRIGHT_BG)
2085 2080 return (brt_xlate[ansi]);
2086 2081 else
2087 2082 return (dim_xlate[ansi]);
2088 2083 }
2089 2084
2090 2085 static text_color_t
2091 2086 ansi_fg_to_solaris(struct tem_vt_state *tem, int ansi)
2092 2087 {
2093 2088 if (tem->tvs_flags & TEM_ATTR_BRIGHT_FG ||
2094 2089 tem->tvs_flags & TEM_ATTR_BOLD) {
2095 2090 return (brt_xlate[ansi]);
2096 2091 } else {
2097 2092 return (dim_xlate[ansi]);
2098 2093 }
2099 2094 }
2100 2095
2101 2096 /*
2102 2097 * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2103 2098 */
2104 2099 void
2105 2100 tem_safe_get_color(struct tem_vt_state *tem, text_color_t *fg,
2106 2101 text_color_t *bg, uint8_t flag)
2107 2102 {
2108 2103 if (tem->tvs_flags & flag) {
2109 2104 *fg = ansi_fg_to_solaris(tem,
2110 2105 tem->tvs_bg_color);
2111 2106 *bg = ansi_bg_to_solaris(tem,
2112 2107 tem->tvs_fg_color);
2113 2108 } else {
2114 2109 *fg = ansi_fg_to_solaris(tem,
2115 2110 tem->tvs_fg_color);
2116 2111 *bg = ansi_bg_to_solaris(tem,
2117 2112 tem->tvs_bg_color);
2118 2113 }
2119 2114 }
2120 2115
2121 2116 /*
2122 2117 * Clear a rectangle of screen for pixel mode.
2123 2118 *
2124 2119 * arguments:
2125 2120 * row: start row#
2126 2121 * nrows: the number of rows to clear
2127 2122 * offset_y: the offset of height in pixels to begin clear
2128 2123 * col: start col#
2129 2124 * ncols: the number of cols to clear
2130 2125 * offset_x: the offset of width in pixels to begin clear
2131 2126 * scroll_up: whether this function is called during sroll up,
2132 2127 * which is called only once.
2133 2128 */
2134 2129 void
2135 2130 tem_safe_pix_cls_range(struct tem_vt_state *tem,
2136 2131 screen_pos_t row, int nrows, int offset_y,
2137 2132 screen_pos_t col, int ncols, int offset_x,
2138 2133 boolean_t sroll_up, cred_t *credp,
2139 2134 enum called_from called_from)
2140 2135 {
2141 2136 struct vis_consdisplay da;
2142 2137 int i, j;
2143 2138 int row_add = 0;
2144 2139 text_color_t fg_color;
2145 2140 text_color_t bg_color;
2146 2141
2147 2142 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2148 2143 called_from == CALLED_FROM_STANDALONE);
2149 2144
2150 2145 if (sroll_up)
2151 2146 row_add = tems.ts_c_dimension.height - 1;
2152 2147
2153 2148 da.width = tems.ts_font.width;
2154 2149 da.height = tems.ts_font.height;
2155 2150
2156 2151 tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE);
2157 2152
2158 2153 tem_safe_callback_bit2pix(tem, ' ', fg_color, bg_color);
2159 2154 da.data = (uchar_t *)tem->tvs_pix_data;
2160 2155
2161 2156 for (i = 0; i < nrows; i++, row++) {
2162 2157 da.row = (row + row_add) * da.height + offset_y;
2163 2158 da.col = col * da.width + offset_x;
2164 2159 for (j = 0; j < ncols; j++) {
2165 2160 tems_safe_display(&da, credp, called_from);
2166 2161 da.col += da.width;
2167 2162 }
2168 2163 }
2169 2164 }
2170 2165
2171 2166 /*
2172 2167 * virtual screen operations
2173 2168 */
2174 2169 static void
2175 2170 tem_safe_virtual_display(struct tem_vt_state *tem, unsigned char *string,
2176 2171 int count, screen_pos_t row, screen_pos_t col,
2177 2172 text_color_t fg_color, text_color_t bg_color)
2178 2173 {
2179 2174 int i, width;
2180 2175 unsigned char *addr;
2181 2176 text_color_t *pfgcolor;
2182 2177 text_color_t *pbgcolor;
2183 2178
2184 2179 if (row < 0 || row >= tems.ts_c_dimension.height ||
2185 2180 col < 0 || col >= tems.ts_c_dimension.width ||
2186 2181 col + count > tems.ts_c_dimension.width)
2187 2182 return;
2188 2183
2189 2184 width = tems.ts_c_dimension.width;
2190 2185 addr = tem->tvs_screen_buf + (row * width + col);
2191 2186 pfgcolor = tem->tvs_fg_buf + (row * width + col);
2192 2187 pbgcolor = tem->tvs_bg_buf + (row * width + col);
2193 2188 for (i = 0; i < count; i++) {
2194 2189 *addr++ = string[i];
2195 2190 *pfgcolor++ = fg_color;
2196 2191 *pbgcolor++ = bg_color;
2197 2192 }
2198 2193 }
2199 2194
2200 2195 static void
2201 2196 i_virtual_copy(unsigned char *base,
2202 2197 screen_pos_t s_col, screen_pos_t s_row,
2203 2198 screen_pos_t e_col, screen_pos_t e_row,
2204 2199 screen_pos_t t_col, screen_pos_t t_row)
2205 2200 {
2206 2201 unsigned char *from;
2207 2202 unsigned char *to;
2208 2203 int cnt;
2209 2204 screen_size_t chars_per_row;
2210 2205 unsigned char *to_row_start;
2211 2206 unsigned char *from_row_start;
2212 2207 screen_size_t rows_to_move;
2213 2208 int cols = tems.ts_c_dimension.width;
2214 2209
2215 2210 chars_per_row = e_col - s_col + 1;
2216 2211 rows_to_move = e_row - s_row + 1;
2217 2212
2218 2213 to_row_start = base + ((t_row * cols) + t_col);
2219 2214 from_row_start = base + ((s_row * cols) + s_col);
2220 2215
2221 2216 if (to_row_start < from_row_start) {
2222 2217 while (rows_to_move-- > 0) {
2223 2218 to = to_row_start;
2224 2219 from = from_row_start;
2225 2220 to_row_start += cols;
2226 2221 from_row_start += cols;
2227 2222 for (cnt = chars_per_row; cnt-- > 0; )
2228 2223 *to++ = *from++;
2229 2224 }
2230 2225 } else {
2231 2226 /*
2232 2227 * Offset to the end of the region and copy backwards.
2233 2228 */
2234 2229 cnt = rows_to_move * cols + chars_per_row;
2235 2230 to_row_start += cnt;
2236 2231 from_row_start += cnt;
2237 2232
2238 2233 while (rows_to_move-- > 0) {
2239 2234 to_row_start -= cols;
2240 2235 from_row_start -= cols;
2241 2236 to = to_row_start;
2242 2237 from = from_row_start;
2243 2238 for (cnt = chars_per_row; cnt-- > 0; )
2244 2239 *--to = *--from;
2245 2240 }
2246 2241 }
2247 2242 }
2248 2243
2249 2244 static void
2250 2245 tem_safe_virtual_copy(struct tem_vt_state *tem,
2251 2246 screen_pos_t s_col, screen_pos_t s_row,
2252 2247 screen_pos_t e_col, screen_pos_t e_row,
2253 2248 screen_pos_t t_col, screen_pos_t t_row)
2254 2249 {
2255 2250 screen_size_t chars_per_row;
2256 2251 screen_size_t rows_to_move;
2257 2252 int rows = tems.ts_c_dimension.height;
2258 2253 int cols = tems.ts_c_dimension.width;
2259 2254
2260 2255 if (s_col < 0 || s_col >= cols ||
2261 2256 s_row < 0 || s_row >= rows ||
2262 2257 e_col < 0 || e_col >= cols ||
2263 2258 e_row < 0 || e_row >= rows ||
2264 2259 t_col < 0 || t_col >= cols ||
2265 2260 t_row < 0 || t_row >= rows ||
2266 2261 s_col > e_col ||
2267 2262 s_row > e_row)
2268 2263 return;
2269 2264
2270 2265 chars_per_row = e_col - s_col + 1;
2271 2266 rows_to_move = e_row - s_row + 1;
2272 2267
2273 2268 /* More sanity checks. */
2274 2269 if (t_row + rows_to_move > rows ||
2275 2270 t_col + chars_per_row > cols)
2276 2271 return;
2277 2272
2278 2273 i_virtual_copy(tem->tvs_screen_buf, s_col, s_row,
2279 2274 e_col, e_row, t_col, t_row);
2280 2275
2281 2276 /* text_color_t is the same size as char */
2282 2277 i_virtual_copy((unsigned char *)tem->tvs_fg_buf,
2283 2278 s_col, s_row, e_col, e_row, t_col, t_row);
2284 2279 i_virtual_copy((unsigned char *)tem->tvs_bg_buf,
2285 2280 s_col, s_row, e_col, e_row, t_col, t_row);
2286 2281
2287 2282 }
2288 2283
2289 2284 static void
2290 2285 tem_safe_virtual_cls(struct tem_vt_state *tem,
2291 2286 int count, screen_pos_t row, screen_pos_t col)
2292 2287 {
2293 2288 text_color_t fg_color;
2294 2289 text_color_t bg_color;
2295 2290
2296 2291 tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE);
2297 2292 tem_safe_virtual_display(tem, tems.ts_blank_line, count, row, col,
2298 2293 fg_color, bg_color);
2299 2294 }
2300 2295
2301 2296 /*
2302 2297 * only blank screen, not clear our screen buffer
2303 2298 */
2304 2299 void
2305 2300 tem_safe_blank_screen(struct tem_vt_state *tem, cred_t *credp,
2306 2301 enum called_from called_from)
2307 2302 {
2308 2303 int row;
2309 2304
2310 2305 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2311 2306 called_from == CALLED_FROM_STANDALONE);
2312 2307
2313 2308 if (tems.ts_display_mode == VIS_PIXEL) {
2314 2309 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2315 2310 return;
2316 2311 }
2317 2312
2318 2313 for (row = 0; row < tems.ts_c_dimension.height; row++) {
2319 2314 tem_safe_callback_cls(tem,
2320 2315 tems.ts_c_dimension.width,
2321 2316 row, 0, credp, called_from);
2322 2317 }
2323 2318 }
2324 2319
2325 2320 /*
2326 2321 * unblank screen with associated tem from its screen buffer
2327 2322 */
2328 2323 void
2329 2324 tem_safe_unblank_screen(struct tem_vt_state *tem, cred_t *credp,
2330 2325 enum called_from called_from)
2331 2326 {
2332 2327 text_color_t fg_color, fg_last;
2333 2328 text_color_t bg_color, bg_last;
2334 2329 size_t tc_size = sizeof (text_color_t);
2335 2330 int row, col, count, col_start;
2336 2331 int width;
2337 2332 unsigned char *buf;
2338 2333
2339 2334 ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
2340 2335 called_from == CALLED_FROM_STANDALONE);
2341 2336
2342 2337 if (tems.ts_display_mode == VIS_PIXEL)
2343 2338 tem_safe_pix_clear_entire_screen(tem, credp, called_from);
2344 2339
2345 2340 tem_safe_callback_cursor(tem, VIS_HIDE_CURSOR, credp, called_from);
2346 2341
2347 2342 width = tems.ts_c_dimension.width;
2348 2343
2349 2344 /*
2350 2345 * Display data in tvs_screen_buf to the actual framebuffer in a
2351 2346 * row by row way.
2352 2347 * When dealing with one row, output data with the same foreground
2353 2348 * and background color all together.
2354 2349 */
2355 2350 for (row = 0; row < tems.ts_c_dimension.height; row++) {
2356 2351 buf = tem->tvs_screen_buf + (row * width);
2357 2352 count = col_start = 0;
2358 2353 for (col = 0; col < width; col++) {
2359 2354 fg_color =
2360 2355 tem->tvs_fg_buf[(row * width + col) * tc_size];
2361 2356 bg_color =
2362 2357 tem->tvs_bg_buf[(row * width + col) * tc_size];
2363 2358 if (col == 0) {
2364 2359 fg_last = fg_color;
2365 2360 bg_last = bg_color;
2366 2361 }
2367 2362
2368 2363 if ((fg_color != fg_last) || (bg_color != bg_last)) {
2369 2364 /*
2370 2365 * Call the primitive to render this data.
2371 2366 */
2372 2367 tem_safe_callback_display(tem,
2373 2368 buf, count, row, col_start,
2374 2369 fg_last, bg_last, credp, called_from);
2375 2370 buf += count;
2376 2371 count = 1;
2377 2372 col_start = col;
2378 2373 fg_last = fg_color;
2379 2374 bg_last = bg_color;
2380 2375 } else {
2381 2376 count++;
2382 2377 }
2383 2378 }
2384 2379
2385 2380 if (col_start == (width - 1))
2386 2381 continue;
2387 2382
2388 2383 /*
2389 2384 * Call the primitive to render this data.
2390 2385 */
2391 2386 tem_safe_callback_display(tem,
2392 2387 buf, count, row, col_start,
2393 2388 fg_last, bg_last, credp, called_from);
2394 2389 }
2395 2390
2396 2391 tem_safe_callback_cursor(tem, VIS_DISPLAY_CURSOR, credp, called_from);
2397 2392 }
↓ open down ↓ |
2149 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX