libvt100

A library for heling in console programming.
git clone git://r-36.net/libvt100
Log | Files | Refs | README | LICENSE

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