libvt100

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

commit 6b9753d15ac98f38375c0f1b8ed4ae950a89894c
parent 6ffddc2a6352ed97d31522ff646d433248efdd19
Author: Christoph Lohmann <20h@r-36.net>
Date:   Fri,  8 Apr 2011 12:45:22 +0200

Adding test file and preliminary window support.

Diffstat:
vt100.c | 360+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
vt100.h | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
vt100test.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 452 insertions(+), 33 deletions(-)

diff --git a/vt100.c b/vt100.c @@ -13,47 +13,211 @@ #include "vt100.h" -int termrows; -int termcols; +termwin_t * +termwin_new(term_t *term, int r, int c, int rows, int cols) +{ + termwin_t *win; + + win = malloc(sizeof(termwin_t)); + if (win == NULL) + return NULL; + bzero(win, sizeof(win)); + + win->r = r; + win->c = c; + win->rows = rows; + win->cols = cols; + win->term = term; + + if (term->first == NULL) + term->first = win; + else { + term->last->next = win; + win->prev = term->last; + term->last = win; + } + + return win; +} + +void +termwin_free(term_t *term, termwin_t *win) +{ + if (term->first == win) + term->first = win->next; + if (term->last == win) + term->last = win->prev; + if (win->next != NULL) + win->next->prev = win->prev; + if (win->prev != NULL) + win->prev->next = win->next; + + free(win); +} + +term_t * +term_new(void) +{ + term_t *term; + + term = malloc(sizeof(term_t)); + if (term == NULL) + return NULL; + bzero(term, sizeof(term)); + + term_init(term); + + return term; +} -struct termios tioin; -struct termios tioout; +void +term_free(term_t *term) +{ + termwin_t *win; + + if (term->first != NULL) { + for (win = term->first; win; win = win->next) + termwin_free(term, win); + } + + free(term); +} void term_setpos(int row, int col) { - printf("\003[%d;%dH", row, col); + printf("\033[%d;%dH", row, col); + fflush(stdout); +} + +void +term_up(int rows) +{ + printf("\033[%dA", rows); + fflush(stdout); +} + +void +term_down(int rows) +{ + printf("\033[%dB", rows); + fflush(stdout); +} + +void +term_forward(int cols) +{ + printf("\033[%dC", cols); + fflush(stdout); } void -term_erasepos(void) +term_backward(int cols) { + printf("\033[%dD", cols); + fflush(stdout); +} + +void +term_erasepos(int row, int col) +{ + term_setpos(row, col); printf("\033[OK"); + fflush(stdout); +} + +void +term_eraserow(int row) +{ + term_setpos(row, 0); + printf("\033[K0"); + fflush(stdout); } void -term_clrscr(void) +term_erasescreen(void) { printf("\033[2J"); + fflush(stdout); +} + +void +term_backspace(void) +{ + term_backward(2); +} + +void +term_setscrolling(int start, int end) +{ + printf("\x033[%d;%dr", start, end); + fflush(stdout); +} + +void +term_scrollup(int times) +{ + int i; + + for (i = 0; i < times; i++) { + printf("\x033"); + printf("D"); + } + fflush(stdout); +} + +void +term_scrolldown(int times) +{ + int i; + + for (i = 0; i < times; i++) + printf("\x033H"); + fflush(stdout); +} + +void +term_showcursor(void) +{ + printf("\033[?25h"); + fflush(stdout); +} + +void +term_hidecursor(void) +{ + printf("\033[?25l"); + fflush(stdout); } void -term_clrrow(int row) +term_blinkcursor(void) { - printf("\033[%dC|\n\r", row); + printf("\033[?12h"); + fflush(stdout); } void -term_rst(void) +term_staticursor(void) { - printf("\x033[?47l"); - printf("\x033[%d;1H", termrows); - tcsetattr(0, TCSANOW, &tioin); - tcsetattr(1, TCSANOW, &tioout); + printf("\033[?12l"); + fflush(stdout); } void -term_init(void) +term_reset(term_t *term) +{ + printf("\033[?47l"); + printf("\033[%d;1H", term->rows); + fflush(stdout); + tcsetattr(0, TCSANOW, &term->tioin); + tcsetattr(1, TCSANOW, &term->tioout); + + term_showcursor(); +} + +void +term_init(term_t *term) { char buf[65]; struct termios tio; @@ -61,43 +225,53 @@ term_init(void) bzero(buf, sizeof(buf)); - tcgetattr(1, &tioout); + tcgetattr(1, &term->tioout); tcgetattr(0, &tio); - memmove(&tioin, &tio, sizeof(tio)); + memmove(&term->tioin, &tio, sizeof(tio)); cfmakeraw(&tio); tcsetattr(0, TCSAFLUSH, &tio); tcgetattr(1, &tio); cfmakeraw(&tio); tcsetattr(1, TCSADRAIN, &tio); + /* disable line wrap. */ + printf("\033[7l"); + printf("\033[18t"); + fflush(stdout); for (i = 0; read(0, &buf[i], 1) && i < sizeof(buf)-1; i++) { - if (buf[i] == '\t') { + if (buf[i] == 't') { buf[i] = '\0'; break; } } if (i >= sizeof(buf)-1) { - termrows = 24; - termcols = 80; + term->rows = 24; + term->cols = 80; } else { sscanf(&buf[4], "%d;%d", &ro, &co); - termrows = ro; - termcols = co; + term->rows = ro; + term->cols = co; printf("\033[?37h"); + fflush(stdout); } + + term_hidecursor(); + term_erasescreen(); } void -term_error(char *fmt, ...) +term_error(term_t *term, char *fmt, ...) { va_list fmtargs; - printf("\033[%d:%dH", termrows, 1); + term_eraserow(term->rows); + printf("\033[%d:%dH", term->rows, 1); va_start(fmtargs, fmt); vfprintf(stdout, fmt, fmtargs); va_end(fmtargs); - printf("\n\r"); + printf("\r"); + fflush(stdout); } void @@ -110,5 +284,141 @@ term_printf(int row, int col, char *fmt, ...) vfprintf(stdout, fmt, fmtargs); va_end(fmtargs); printf("\n\r"); + fflush(stdout); +} + +/* Bresenham's line algorithm */ +void +term_drawline(term_t *term, int r0, int c0, int r1, int c1, char line) +{ + int dr, dc, sr, sc, err, err2; + + dr = abs(r1 - r0); + dc = abs(c1 - c0); + sr = (r0 < r1)? 1 : -1; + sc = (c0 < c1)? 1 : -1; + err = dr - dc; + + for (;;) { + term_printf(r0, c0, "%c", line); + if (r0 == r1 && c0 == c1) + break; + err2 = 2 * err; + if (err2 > -dc) { + err -= dc; + r0 += sr; + } + if (err2 < dr) { + err += dr; + c0 += sc; + } + } + fflush(stdout); +} + +void +term_drawrectangle(term_t *term, int r0, int c0, int r1, int c1, + char hline, char vline, char uredge, char uledge, + char lredge, char lledge) +{ + term_printf(r0, c0, "%c", uredge); + term_drawline(term, r0, c0+1, r0, c1-1, hline); + term_printf(r0, c1, "%c", uledge); + term_drawline(term, r0+1, c1, r1-1, c1, vline); + term_printf(r1, c1, "%c", lledge); + term_drawline(term, r1, c0+1, r1, c1-1, hline); + term_printf(r1, c0, "%c", lredge); + term_drawline(term, r0+1, c0, r1-1, c0, vline); +} + +void +term_fillrectangle(term_t *term, int r0, int c0, int r1, int c1, char fill) +{ + int br, be; + + br = (r0 < r1)? r0 : r1; + be = (r0 < r1)? r1 : r0; + for (; br <= be; br++) + term_drawline(term, br, c0, br, c1, fill); +} + + +void +termwin_setpos(termwin_t *win, int row, int col) +{ + if (row <= win->drows && col <= win->dcols && row > 0 && col > 0) { + win->cr = row; + win->cc = col; + } +} + +int +termwin_inwindow(termwin_t *win, int row, int col) +{ + return (row >= win->dr && row < win->dr + win->drows + && col >= win->dc && col < win->dc + win->dcols); } +void +termwin_up(termwin_t *win, int rows) +{ + win->cr -= rows; + if (win->cr < 1) + win->cr = 11; +} + +void +termwin_down(termwin_t *win, int rows) +{ + win->cr += rows; + if (win->cr > win->drows) + win->cr = win->drows; +} + +void +termwin_forward(termwin_t *win, int cols) +{ + win->cc += cols; + if (win->cc > win->dcols) + win->cc = win->dcols; +} + +void +termwin_backward(termwin_t *win, int cols) +{ + win->cc -= cols; + if (win->cc < 1) + win->cc = 1; +} + +void +termwin_erasepos(termwin_t *win, int row, int col) +{ + if (termwin_inwindow(win, row, col)) + term_printf(win->dr + row, win->dc + col, " "); +} + + +void +termwin_eraserow(termwin_t *win, int row) +{ + if (row > 0 && row <= win->drows) { + term_drawline(win->term, win->dr + row, win->dc, + win->dr + row, win->dc + win->cols, ' '); + } +} + +void +termwin_erasewin(termwin_t *win) +{ + term_fillrectangle(win->term, win->dr, win->dc, win->dr + win->drows, + win->dc + win->dcols, ' '); +} + +void +termwin_backspace(termwin_t *win) +{ + termwin_backward(win, 2); +} + + diff --git a/vt100.h b/vt100.h @@ -6,28 +6,89 @@ #ifndef __LIBVT100_H__ #define __LIBVT100_H__ -extern int termrows; -extern int termcols; +#include <unistd.h> +#include <termios.h> +typedef struct term_t term_t; typedef struct termwin_t termwin_t; struct termwin_t { - int br, bc, r, c; + int r, c, rows, cols; + int dr, dc, drows, dcols; int cr, cc; - int id; + int scrollc1, scrollc2, scroll; + + term_t *term; termwin_t *next; termwin_t *prev; }; -typedef struct termwm_t termwm_t; -struct termwm_t { - int n; +struct term_t { + int rows, cols; + struct termios tioin, tioout; + + int n; termwin_t *first; termwin_t *last; - termwin_t *root; }; +termwin_t *termwin_new(term_t *term, int r, int c, int rows, int cols); +void termwin_free(term_t *term, termwin_t *win); + +term_t *term_new(void); +void term_free(term_t *term); + +void term_setpos(int row, int col); +void term_up(int rows); +void term_down(int rows); +void term_forward(int cols); +void term_backward(int cols); +void term_erasepos(int row, int col); +void term_eraserow(int row); +void term_erasescreen(void); +void term_backspace(void); + +void term_setscrolling(int start, int end); +void term_scrollup(int times); +void term_scrolldown(int times); + +void term_showcursor(void); +void term_hidecursor(void); +void term_blinkcursor(void); +void term_staticursor(void); + +void term_reset(term_t *term); +void term_init(term_t *term); + +void term_error(term_t *term, char *fmt, ...); +void term_printf(int row, int col, char *fmt, ...); + +void term_drawline(term_t *term, int r0, int c0, int r1, int c1, char sym); +void term_drawrectangle(term_t *term, int r0, int c0, int r1, int c1, + char hline, char vline, char uredge, char uledge, + char lredge, char lledge); +void term_fillrectangle(term_t *term, int r0, int c0, int r1, int c1, + char fill); + +void termwin_setpos(termwin_t *win, int row, int col); +int temwin_inwindow(termwin_t *win, int row, int col); +void termwin_up(termwin_t *win, int rows); +void termwin_down(termwin_t *win, int rows); +void termwin_forward(termwin_t *win, int cols); +void termwin_backward(termwin_t *win, int cols); +void termwin_erasepos(termwin_t *win, int row, int col); +void termwin_eraserow(termwin_t *win, int row); +void termwin_erasewin(termwin_t *win); +void termwin_backspace(termwin_t *win); + +void termwin_setscrolling(termwin_t *win, int start, int end); +void termwin_scrollup(termwin_t *win, int times); +void termwin_scrolldown(termwin_t *win, int times); + +void termwin_error(termwin_t *win, char *fmt, ...); +void termwin_printf(termwin_t *win, int row, int col, char *fmt, ...); + #endif diff --git a/vt100test.c b/vt100test.c @@ -0,0 +1,48 @@ +/* + * Copy me if you can. + * by 20h + */ + +#include <unistd.h> +#include <time.h> +#include <string.h> +#include <stdlib.h> + +#include "vt100.h" + +int +main(void) +{ + char *str; + term_t *term; + + term = term_new(); + + term_fillrectangle(term, 1, 1, term->rows-1, term->cols-1, '.'); + + term_drawrectangle(term, 1, 1, term->rows-1, term->cols-1, '#', '#', + '#', '#', '#', '#'); + term_drawrectangle(term, 2, 2, 20, 30, '-', '|', '+', '+', '+', + '+'); + term_fillrectangle(term, 3, 3, 19, 29, ' '); + + term_printf(3, 3, "Hello here ..."); + term_printf(5, 3, "Another one ..."); + term_error(term, "Something bad happened."); + term_printf(8, 3, "termrows: %d, termcols: %d", term->rows, term->cols); + term_printf(10, 3, "sleeping for 1s ..."); + + sleep(1); + + term_printf(5, 3, "It changed!"); + term_error(term, "Another bad one ..."); + sleep(1); + + term_error(term, "Oh, another one"); + sleep(2); + + term_reset(term); + + return 0; +} +