vt100.c - libvt100 - A library for heling in console programming.
 (HTM) git clone git://r-36.net/libvt100
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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