vt100.c (6538B)
1 /* 2 * Copy me if you can. 3 * by 20h 4 */ 5 6 #include <termios.h> 7 #include <unistd.h> 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <stdarg.h> 11 #include <string.h> 12 #include <strings.h> 13 14 #include "vt100.h" 15 16 termwin_t * 17 termwin_new(term_t *term, int r, int c, int rows, int cols) 18 { 19 termwin_t *win; 20 21 win = malloc(sizeof(termwin_t)); 22 if (win == NULL) 23 return NULL; 24 bzero(win, sizeof(win)); 25 26 win->r = r; 27 win->c = c; 28 win->rows = rows; 29 win->cols = cols; 30 win->term = term; 31 32 if (term->first == NULL) 33 term->first = win; 34 else { 35 term->last->next = win; 36 win->prev = term->last; 37 term->last = win; 38 } 39 40 return win; 41 } 42 43 void 44 termwin_free(term_t *term, termwin_t *win) 45 { 46 if (term->first == win) 47 term->first = win->next; 48 if (term->last == win) 49 term->last = win->prev; 50 if (win->next != NULL) 51 win->next->prev = win->prev; 52 if (win->prev != NULL) 53 win->prev->next = win->next; 54 55 free(win); 56 } 57 58 term_t * 59 term_new(void) 60 { 61 term_t *term; 62 63 term = malloc(sizeof(term_t)); 64 if (term == NULL) 65 return NULL; 66 bzero(term, sizeof(term)); 67 68 term_init(term); 69 70 return term; 71 } 72 73 void 74 term_free(term_t *term) 75 { 76 termwin_t *win; 77 78 if (term->first != NULL) { 79 for (win = term->first; win; win = win->next) 80 termwin_free(term, win); 81 } 82 83 free(term); 84 } 85 86 void 87 term_setpos(int row, int col) 88 { 89 printf("\033[%d;%dH", row, col); 90 fflush(stdout); 91 } 92 93 void 94 term_up(int rows) 95 { 96 printf("\033[%dA", rows); 97 fflush(stdout); 98 } 99 100 void 101 term_down(int rows) 102 { 103 printf("\033[%dB", rows); 104 fflush(stdout); 105 } 106 107 void 108 term_forward(int cols) 109 { 110 printf("\033[%dC", cols); 111 fflush(stdout); 112 } 113 114 void 115 term_backward(int cols) 116 { 117 printf("\033[%dD", cols); 118 fflush(stdout); 119 } 120 121 void 122 term_erasepos(int row, int col) 123 { 124 term_setpos(row, col); 125 printf("\033[OK"); 126 fflush(stdout); 127 } 128 129 void 130 term_eraserow(int row) 131 { 132 term_setpos(row, 0); 133 printf("\033[K0"); 134 fflush(stdout); 135 } 136 137 void 138 term_erasescreen(void) 139 { 140 printf("\033[2J"); 141 fflush(stdout); 142 } 143 144 void 145 term_backspace(void) 146 { 147 term_backward(2); 148 } 149 150 void 151 term_setscrolling(int start, int end) 152 { 153 printf("\x033[%d;%dr", start, end); 154 fflush(stdout); 155 } 156 157 void 158 term_scrollup(int times) 159 { 160 int i; 161 162 for (i = 0; i < times; i++) { 163 printf("\x033"); 164 printf("D"); 165 } 166 fflush(stdout); 167 } 168 169 void 170 term_scrolldown(int times) 171 { 172 int i; 173 174 for (i = 0; i < times; i++) 175 printf("\x033H"); 176 fflush(stdout); 177 } 178 179 void 180 term_showcursor(void) 181 { 182 printf("\033[?25h"); 183 fflush(stdout); 184 } 185 186 void 187 term_hidecursor(void) 188 { 189 printf("\033[?25l"); 190 fflush(stdout); 191 } 192 193 void 194 term_blinkcursor(void) 195 { 196 printf("\033[?12h"); 197 fflush(stdout); 198 } 199 200 void 201 term_staticursor(void) 202 { 203 printf("\033[?12l"); 204 fflush(stdout); 205 } 206 207 void 208 term_reset(term_t *term) 209 { 210 printf("\033[?47l"); 211 printf("\033[%d;1H", term->rows); 212 fflush(stdout); 213 tcsetattr(0, TCSANOW, &term->tioin); 214 tcsetattr(1, TCSANOW, &term->tioout); 215 216 term_showcursor(); 217 } 218 219 void 220 term_init(term_t *term) 221 { 222 char buf[65]; 223 struct termios tio; 224 int i, ro, co; 225 226 bzero(buf, sizeof(buf)); 227 228 tcgetattr(1, &term->tioout); 229 tcgetattr(0, &tio); 230 memmove(&term->tioin, &tio, sizeof(tio)); 231 cfmakeraw(&tio); 232 tcsetattr(0, TCSAFLUSH, &tio); 233 tcgetattr(1, &tio); 234 cfmakeraw(&tio); 235 tcsetattr(1, TCSADRAIN, &tio); 236 237 /* disable line wrap. */ 238 printf("\033[7l"); 239 240 printf("\033[18t"); 241 fflush(stdout); 242 for (i = 0; read(0, &buf[i], 1) && i < sizeof(buf)-1; i++) { 243 if (buf[i] == 't') { 244 buf[i] = '\0'; 245 break; 246 } 247 } 248 if (i >= sizeof(buf)-1) { 249 term->rows = 24; 250 term->cols = 80; 251 } else { 252 sscanf(&buf[4], "%d;%d", &ro, &co); 253 term->rows = ro; 254 term->cols = co; 255 printf("\033[?37h"); 256 fflush(stdout); 257 } 258 259 term_hidecursor(); 260 term_erasescreen(); 261 } 262 263 void 264 term_error(term_t *term, char *fmt, ...) 265 { 266 va_list fmtargs; 267 268 term_eraserow(term->rows); 269 printf("\033[%d:%dH", term->rows, 1); 270 va_start(fmtargs, fmt); 271 vfprintf(stdout, fmt, fmtargs); 272 va_end(fmtargs); 273 printf("\r"); 274 fflush(stdout); 275 } 276 277 void 278 term_printf(int row, int col, char *fmt, ...) 279 { 280 va_list fmtargs; 281 282 term_setpos(row, col); 283 va_start(fmtargs, fmt); 284 vfprintf(stdout, fmt, fmtargs); 285 va_end(fmtargs); 286 printf("\n\r"); 287 fflush(stdout); 288 } 289 290 /* Bresenham's line algorithm */ 291 void 292 term_drawline(term_t *term, int r0, int c0, int r1, int c1, char line) 293 { 294 int dr, dc, sr, sc, err, err2; 295 296 dr = abs(r1 - r0); 297 dc = abs(c1 - c0); 298 sr = (r0 < r1)? 1 : -1; 299 sc = (c0 < c1)? 1 : -1; 300 err = dr - dc; 301 302 for (;;) { 303 term_printf(r0, c0, "%c", line); 304 if (r0 == r1 && c0 == c1) 305 break; 306 err2 = 2 * err; 307 if (err2 > -dc) { 308 err -= dc; 309 r0 += sr; 310 } 311 if (err2 < dr) { 312 err += dr; 313 c0 += sc; 314 } 315 } 316 fflush(stdout); 317 } 318 319 void 320 term_drawrectangle(term_t *term, int r0, int c0, int r1, int c1, 321 char hline, char vline, char uredge, char uledge, 322 char lredge, char lledge) 323 { 324 term_printf(r0, c0, "%c", uredge); 325 term_drawline(term, r0, c0+1, r0, c1-1, hline); 326 term_printf(r0, c1, "%c", uledge); 327 term_drawline(term, r0+1, c1, r1-1, c1, vline); 328 term_printf(r1, c1, "%c", lledge); 329 term_drawline(term, r1, c0+1, r1, c1-1, hline); 330 term_printf(r1, c0, "%c", lredge); 331 term_drawline(term, r0+1, c0, r1-1, c0, vline); 332 } 333 334 void 335 term_fillrectangle(term_t *term, int r0, int c0, int r1, int c1, char fill) 336 { 337 int br, be; 338 339 br = (r0 < r1)? r0 : r1; 340 be = (r0 < r1)? r1 : r0; 341 for (; br <= be; br++) 342 term_drawline(term, br, c0, br, c1, fill); 343 } 344 345 346 void 347 termwin_setpos(termwin_t *win, int row, int col) 348 { 349 if (row <= win->drows && col <= win->dcols && row > 0 && col > 0) { 350 win->cr = row; 351 win->cc = col; 352 } 353 } 354 355 int 356 termwin_inwindow(termwin_t *win, int row, int col) 357 { 358 return (row >= win->dr && row < win->dr + win->drows 359 && col >= win->dc && col < win->dc + win->dcols); 360 } 361 362 void 363 termwin_up(termwin_t *win, int rows) 364 { 365 win->cr -= rows; 366 if (win->cr < 1) 367 win->cr = 11; 368 } 369 370 void 371 termwin_down(termwin_t *win, int rows) 372 { 373 win->cr += rows; 374 if (win->cr > win->drows) 375 win->cr = win->drows; 376 } 377 378 void 379 termwin_forward(termwin_t *win, int cols) 380 { 381 win->cc += cols; 382 if (win->cc > win->dcols) 383 win->cc = win->dcols; 384 } 385 386 void 387 termwin_backward(termwin_t *win, int cols) 388 { 389 win->cc -= cols; 390 if (win->cc < 1) 391 win->cc = 1; 392 } 393 394 void 395 termwin_erasepos(termwin_t *win, int row, int col) 396 { 397 if (termwin_inwindow(win, row, col)) 398 term_printf(win->dr + row, win->dc + col, " "); 399 } 400 401 402 void 403 termwin_eraserow(termwin_t *win, int row) 404 { 405 if (row > 0 && row <= win->drows) { 406 term_drawline(win->term, win->dr + row, win->dc, 407 win->dr + row, win->dc + win->cols, ' '); 408 } 409 } 410 411 void 412 termwin_erasewin(termwin_t *win) 413 { 414 term_fillrectangle(win->term, win->dr, win->dc, win->dr + win->drows, 415 win->dc + win->dcols, ' '); 416 } 417 418 void 419 termwin_backspace(termwin_t *win) 420 { 421 termwin_backward(win, 2); 422 } 423 424