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