vt100.c (13317B)
1 /* $Id: //depot/blt/srv/console2/vt100.c#1 $ */ 2 /* VT100 Engine Copyright 1997 Daniel Marks <dmarks@uiuc.edu> */ 3 4 #include "vt100.h" 5 #include <stdlib.h> 6 7 #define STRICT_VT100 8 9 /* struct virtscreen newscr; */ 10 11 void std_interpret_char(struct virtscreen *cur, unsigned char ch); 12 void std_interpret_ansi(struct virtscreen *cur, unsigned char ch); 13 void special_reading_ansi(struct virtscreen *cur, unsigned char ch); 14 void special_ansi_charset_0(struct virtscreen *cur, unsigned char ch); 15 void special_ansi_charset_1(struct virtscreen *cur, unsigned char ch); 16 17 void clear_region(struct virtscreen *cur, int y1, int x1, int y2, int x2, int atrb); 18 19 int init_virtscreen(struct virtscreen *cur, int rows, int columns) 20 { 21 22 cur->num_bytes = ((sizeof(unsigned short) * rows * columns)); 23 24 if (!(cur->data=malloc(cur->num_bytes))) 25 return (-1); 26 27 cur->data_off_scr = cur->data; 28 29 cur->bottom_scroll = cur->rows = rows; 30 cur->columns = columns; 31 cur->cur_ansi_number = cur->top_scroll = 0; 32 cur->ansi_elements = cur->ansi_reading_number = 0; 33 cur->next_char_send = std_interpret_char; 34 cur->old_attrib = cur->attrib = 0x07; 35 cur->next_char_send = std_interpret_char; 36 clear_region(cur,0,0,rows-1,columns-1,cur->attrib); 37 cur->old_xpos = cur->old_ypos = 0; 38 39 return (0); 40 } 41 42 void clear_region(struct virtscreen *cur, int y1, int x1, int y2, int x2, int atrb) 43 { 44 ushort *ch = loc_in_virtscreen(cur,y1,x1); 45 ushort *tr = loc_in_virtscreen(cur,y2,x2); 46 int dt = 0x20 | (atrb << 8); 47 48 while (ch<=tr) 49 *ch++ = dt; 50 } 51 52 void clear_virtscreen(struct virtscreen *cur, int mode) 53 { 54 switch (mode) 55 { 56 case 0: clear_region(cur,cur->ypos,cur->xpos, 57 cur->rows-1,cur->columns-1,cur->attrib); 58 break; 59 case 1: clear_region(cur,0,0,cur->ypos,cur->xpos,cur->attrib); 60 break; 61 default: clear_region(cur,0,0,cur->rows-1,cur->columns-1,cur->attrib); 62 cur->xpos = cur->ypos = 0; 63 break; 64 } 65 } 66 67 void clear_to_eol(struct virtscreen *cur, int mode) 68 { 69 switch(mode) 70 { 71 case 0: 72 clear_region(cur,cur->ypos,cur->xpos,cur->ypos, 73 cur->columns-1,cur->attrib); 74 break; 75 case 1: 76 clear_region(cur,cur->ypos,0,cur->ypos,cur->xpos, 77 cur->attrib); 78 break; 79 default: 80 clear_region(cur,cur->ypos,0,cur->ypos,cur->columns-1, 81 cur->attrib); 82 } 83 } 84 85 86 void move_cursor(struct virtscreen *cur); 87 /* 88 { 89 } 90 */ 91 92 void position_console(struct virtscreen *cur, int ypos, int xpos, int rel) 93 { 94 if (rel) 95 { 96 cur->xpos += xpos; 97 cur->ypos += ypos; 98 } else 99 { 100 cur->xpos = xpos; 101 cur->ypos = ypos; 102 } 103 if (cur->xpos < 0) cur->xpos = 0; 104 if (cur->xpos >= cur->columns) cur->xpos = cur->columns-1; 105 if (cur->ypos < 0) cur->ypos = 0; 106 if (cur->ypos >= cur->rows) cur->ypos = cur->rows-1; 107 move_cursor(cur); 108 } 109 110 void delete_chars_in_line(struct virtscreen *cur, int char_move) 111 { 112 ushort *next_move; 113 ushort *end_move; 114 ushort *start_move; 115 ushort clr_with; 116 117 clr_with = (cur->attrib << 8) | 0x20; 118 start_move = loc_in_virtscreen(cur,cur->ypos,cur->xpos); 119 end_move = loc_in_virtscreen(cur,cur->ypos,cur->columns); 120 if ((cur->xpos + char_move) < cur->columns) 121 { 122 next_move = loc_in_virtscreen(cur,cur->ypos,cur->xpos+char_move); 123 while (next_move<end_move) 124 *start_move++ = *next_move++; 125 } 126 while (start_move<end_move) *start_move++ = clr_with; 127 } 128 129 void scroll_virt_up_at_cursor(struct virtscreen *cur, int dir) 130 { 131 ushort clr_with; 132 ushort *beginScr; 133 ushort *endofScr; 134 ushort *lastLine; 135 ushort *nextLine; 136 unsigned int real_scroll_length; 137 138 if ((cur->ypos >= cur->top_scroll) && 139 (cur->ypos < cur->bottom_scroll)) 140 { 141 clr_with = (cur->attrib << 8) | 0x20; 142 beginScr = loc_in_virtscreen(cur,cur->ypos,0); 143 endofScr = loc_in_virtscreen(cur,cur->bottom_scroll,0); 144 lastLine = endofScr - cur->columns; 145 nextLine = beginScr + cur->columns; 146 real_scroll_length = ((unsigned int) lastLine) - 147 ((unsigned int) beginScr); 148 149 if (dir) 150 { 151 memmove(beginScr,nextLine,real_scroll_length); 152 while (lastLine < endofScr) 153 *lastLine++ = clr_with; 154 } else 155 { 156 memmove(nextLine,beginScr,real_scroll_length); 157 while (beginScr < nextLine) 158 *beginScr++ = clr_with; 159 } 160 } 161 } 162 163 void scroll_virtscreen(struct virtscreen *cur) 164 { 165 int clr_with = (cur->attrib << 8) | 0x20; 166 ushort *beginScr = loc_in_virtscreen(cur,cur->top_scroll,0); 167 ushort *endofScr = loc_in_virtscreen(cur,cur->bottom_scroll,0); 168 ushort *lastLine = endofScr - cur->columns; 169 ushort *nextLine = beginScr + cur->columns; 170 unsigned int real_scroll_length = ((unsigned int) lastLine) - 171 ((unsigned int) beginScr); 172 173 memmove(beginScr,nextLine,real_scroll_length); 174 while (lastLine < endofScr) 175 *lastLine++ = clr_with; 176 }; 177 178 void set_scroll_region(struct virtscreen *cur, int low, int high) 179 { 180 low--; 181 high = (high >= cur->rows) ? cur->rows : high; 182 low = (low < 0) ? 0 : low; 183 184 cur->top_scroll = low; 185 cur->bottom_scroll = high; 186 } 187 188 void change_attribute(struct virtscreen *cur, int attrib) 189 { 190 cur->attrib = attrib; 191 } 192 193 void change_character(struct virtscreen *cur, int ch) 194 { 195 *(loc_in_virtscreen(cur,cur->ypos,cur->xpos)) = 196 ch | (cur->attrib << 8); 197 } 198 199 void special_ansi_charset_0(struct virtscreen *cur, unsigned char ch) 200 { 201 cur->next_char_send = std_interpret_char; 202 } 203 204 void special_ansi_charset_1(struct virtscreen *cur, unsigned char ch) 205 { 206 cur->next_char_send = std_interpret_char; 207 } 208 209 void std_interpret_ansi(struct virtscreen *cur, unsigned char ch) 210 { 211 switch (ch) 212 { 213 case '(': cur->next_char_send = special_ansi_charset_0; 214 return; 215 case ')': cur->next_char_send = special_ansi_charset_1; 216 return; 217 case '[': cur->cur_ansi_number = 0; 218 cur->ansi_elements = 0; 219 cur->ansi_reading_number = 0; 220 cur->next_char_send = special_reading_ansi; 221 return; 222 case '7': cur->old_attrib = cur->attrib; 223 cur->old_xpos = cur->xpos; 224 cur->old_ypos = cur->ypos; 225 break; 226 case '8': change_attribute(cur,cur->old_attrib); 227 position_console(cur,cur->ypos,cur->xpos,0); 228 break; 229 case 'E': cur->xpos = 0; 230 case 'D': cur->ypos++; 231 if (cur->ypos >= cur->bottom_scroll) 232 { 233 scroll_virtscreen(cur); 234 cur->ypos--; 235 } 236 move_cursor(cur); 237 break; 238 case 'M': cur->ypos--; 239 if (cur->ypos < cur->top_scroll) 240 { 241 cur->ypos++; 242 scroll_virt_up_at_cursor(cur,0); 243 } 244 move_cursor(cur); 245 break; /* recalculate screen pos */ 246 } 247 if (ch != 27) 248 cur->next_char_send = std_interpret_char; 249 } 250 251 void std_interpret_char(struct virtscreen *cur, unsigned char ch) 252 { 253 switch (ch) 254 { 255 case 27: cur->next_char_send = std_interpret_ansi; 256 return; 257 case 12: clear_virtscreen(cur,2); 258 break; 259 case 13: cur->xpos = 0; /* return = back to begin */ 260 break; 261 case 10: cur->ypos++; 262 if (cur->ypos >= cur->bottom_scroll) 263 /* if we're at bottom */ 264 { 265 if (cur->ypos == cur->bottom_scroll) 266 scroll_virtscreen(cur); /* and scroll it! */ 267 cur->ypos--; /* go back up a line */ 268 } 269 cur->xpos=0; 270 break; 271 case 9: position_console(cur,cur->ypos,cur->xpos+(8-(cur->xpos % 8)),0); 272 break; 273 case 8: cur->xpos--; /* backspace on screen */ 274 if (cur->xpos<0) 275 { 276 cur->xpos = cur->columns - 1; 277 cur->ypos; 278 if (cur->ypos<0) 279 cur->ypos=0; 280 } 281 break; 282 default: if (!ch) 283 break; 284 change_character(cur,ch); 285 cur->xpos++; 286 if (cur->xpos >= cur->columns) 287 { 288 #ifdef STRICT_VT100 289 cur->xpos = cur->columns-1; 290 #else 291 cur->xpos = 0; 292 cur->ypos++; 293 if (cur->ypos == cur->bottom_scroll) 294 { 295 cur->ypos--; 296 scroll_virtscreen(cur); 297 } 298 #endif 299 } 300 break; 301 } 302 move_cursor(cur); 303 } 304 305 void special_reading_ansi(struct virtscreen *cur, unsigned char ch) 306 { 307 if ((ch>='0') && (ch<='9')) 308 { 309 cur->cur_ansi_number = (cur->cur_ansi_number * 10) + (ch - '0'); 310 cur->ansi_reading_number = 1; 311 return; 312 } 313 314 if ((cur->ansi_reading_number) || (ch == ';')) 315 { 316 if (cur->ansi_elements<MAX_ANSI_ELEMENTS) 317 cur->ansi_element[cur->ansi_elements++] = cur->cur_ansi_number; 318 cur->ansi_reading_number = 0; 319 } 320 cur->cur_ansi_number = 0; 321 switch (ch) 322 { 323 case '?': 324 case ';': return; 325 case 'D': position_console(cur,0,(cur->ansi_elements) ? 326 -cur->ansi_element[0] : -1,1); 327 break; 328 case 'a': 329 case 'C': position_console(cur,0,(cur->ansi_elements) ? 330 cur->ansi_element[0] : 1,1); 331 break; 332 case 'A': position_console(cur,(cur->ansi_elements) ? 333 -cur->ansi_element[0] : -1,0,1); 334 break; 335 case 'e': 336 case 'B': position_console(cur,(cur->ansi_elements) ? 337 cur->ansi_element[0] : 1,0,1); 338 break; 339 case '`': 340 case 'G': 341 { 342 int temp = cur->ansi_elements ? cur->ansi_element[0] : 1; 343 if (temp) 344 temp--; 345 position_console(cur,cur->ypos,temp,0); 346 } 347 break; 348 case 'E': position_console(cur,cur->ypos + 349 ((cur->ansi_elements) ? cur->ansi_element[0] : 1), 350 0,0); 351 break; 352 case 'F': position_console(cur,cur->ypos - 353 ((cur->ansi_elements) ? cur->ansi_element[0] : 1), 354 0,0); 355 break; 356 case 'd': 357 { 358 int temp = cur->ansi_elements ? cur->ansi_element[0] : 1; 359 if (temp) 360 temp--; 361 position_console(cur,temp,cur->xpos,0); 362 } 363 break; 364 case 'f': 365 case 'H': 366 { 367 int row = (cur->ansi_elements > 0) ? cur->ansi_element[0] : 1; 368 int col = (cur->ansi_elements > 1) ? cur->ansi_element[1] : 1; 369 if (row) 370 row--; 371 if (col) 372 col--; 373 position_console(cur,row,col,0); 374 } 375 break; 376 case 'J': clear_virtscreen(cur,(cur->ansi_elements) ? 377 cur->ansi_element[0]: 0); 378 break; 379 case 'L': { 380 int lines = (cur->ansi_elements) ? 381 cur->ansi_element[0] : 1; 382 while (lines>0) 383 { 384 scroll_virt_up_at_cursor(cur,0); 385 lines--; 386 } 387 } 388 break; 389 case 'M': { 390 int lines = (cur->ansi_elements) ? 391 cur->ansi_element[0] : 1; 392 while (lines>0) 393 { 394 scroll_virt_up_at_cursor(cur,1); 395 lines--; 396 } 397 } 398 break; 399 case 'P': delete_chars_in_line(cur,(cur->ansi_elements) ? 400 cur->ansi_element[0] : 1); 401 break; 402 case 'K': clear_to_eol(cur,cur->ansi_elements ? 403 cur->ansi_element[0] : 0); 404 break; 405 case 's': cur->old_xpos = cur->xpos; 406 cur->old_ypos = cur->ypos; 407 break; 408 case 'u': position_console(cur,cur->old_ypos,cur->old_xpos,0); 409 break; 410 case 'r': { 411 int low = (cur->ansi_elements > 0) ? 412 cur->ansi_element[0] : 1; 413 int high = (cur->ansi_elements > 1) ? 414 cur->ansi_element[1] : cur->rows; 415 if (low<=high) 416 set_scroll_region(cur,low,high); 417 } 418 break; 419 case 'm': 420 { 421 int count = 0; 422 int cthing; 423 if (!cur->ansi_elements) 424 change_attribute(cur,0x07); 425 while (count < cur->ansi_elements) 426 { 427 cthing = cur->ansi_element[count]; 428 switch (cthing) 429 { 430 case 0: 431 case 27: change_attribute(cur,0x07); 432 break; 433 case 1: change_attribute(cur,cur->attrib | 0x08); 434 break; 435 case 5: change_attribute(cur,cur->attrib | 0x80); 436 break; 437 case 7: change_attribute(cur,0x70); 438 break; 439 case 21: 440 case 22: change_attribute(cur,cur->attrib & 0xF7); 441 break; 442 case 25: change_attribute(cur,cur->attrib & 0x7F); 443 break; 444 default: 445 if ((cthing>=30) && (cthing<=37)) 446 { 447 change_attribute(cur,(cur->attrib & 0xF8) | (cthing-30)); 448 } 449 if ((cthing>=40) && (cthing<=47)) 450 { 451 change_attribute(cur,(cur->attrib & 0x8F) | 452 ((cthing-40) << 4)); 453 } 454 break; 455 } 456 count++; 457 } 458 } 459 break; 460 461 } 462 cur->next_char_send = std_interpret_char; 463 } 464