Adding test file and preliminary window support. - libvt100 - A library for heling in console programming.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 6b9753d15ac98f38375c0f1b8ed4ae950a89894c
 (DIR) parent 6ffddc2a6352ed97d31522ff646d433248efdd19
 (HTM) 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(-)
       ---
 (DIR) diff --git a/vt100.c b/vt100.c
       @@ -13,47 +13,211 @@
        
        #include "vt100.h"
        
       -int termrows;
       -int termcols;
       +ttermwin_t *
       +ttermwin_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
       +ttermwin_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);
       +}
       +
       +tterm_t *
       +tterm_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
       +tterm_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
        tterm_setpos(int row, int col)
        {
       -        printf("\003[%d;%dH", row, col);
       +        printf("\033[%d;%dH", row, col);
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_up(int rows)
       +{
       +        printf("\033[%dA", rows);
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_down(int rows)
       +{
       +        printf("\033[%dB", rows);
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_forward(int cols)
       +{
       +        printf("\033[%dC", cols);
       +        fflush(stdout);
        }
        
        void
       -tterm_erasepos(void)
       +tterm_backward(int cols)
        {
       +        printf("\033[%dD", cols);
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_erasepos(int row, int col)
       +{
       +        term_setpos(row, col);
                printf("\033[OK");
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_eraserow(int row)
       +{
       +        term_setpos(row, 0);
       +        printf("\033[K0");
       +        fflush(stdout);
        }
        
        void
       -tterm_clrscr(void)
       +tterm_erasescreen(void)
        {
                printf("\033[2J");
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_backspace(void)
       +{
       +        term_backward(2);
       +}
       +
       +void
       +tterm_setscrolling(int start, int end)
       +{
       +        printf("\x033[%d;%dr", start, end);
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_scrollup(int times)
       +{
       +        int i;
       +
       +        for (i = 0; i < times; i++) {
       +                printf("\x033");
       +                printf("D");
       +        }
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_scrolldown(int times)
       +{
       +        int i;
       +
       +        for (i = 0; i < times; i++)
       +                printf("\x033H");
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_showcursor(void)
       +{
       +        printf("\033[?25h");
       +        fflush(stdout);
       +}
       +
       +void
       +tterm_hidecursor(void)
       +{
       +        printf("\033[?25l");
       +        fflush(stdout);
        }
        
        void
       -tterm_clrrow(int row)
       +tterm_blinkcursor(void)
        {
       -        printf("\033[%dC|\n\r", row);
       +        printf("\033[?12h");
       +        fflush(stdout);
        }
        
        void
       -tterm_rst(void)
       +tterm_staticursor(void)
        {
       -        printf("\x033[?47l");
       -        printf("\x033[%d;1H", termrows);
       -        tcsetattr(0, TCSANOW, &tioin);
       -        tcsetattr(1, TCSANOW, &tioout);
       +        printf("\033[?12l");
       +        fflush(stdout);
        }
        
        void
       -tterm_init(void)
       +tterm_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
       +tterm_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
       -tterm_error(char *fmt, ...)
       +tterm_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
       +tterm_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
       +tterm_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
       +tterm_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
       +ttermwin_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
       +ttermwin_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
       +ttermwin_up(termwin_t *win, int rows)
       +{
       +        win->cr -= rows;
       +        if (win->cr < 1)
       +                win->cr = 11;
       +}
       +
       +void
       +ttermwin_down(termwin_t *win, int rows)
       +{
       +        win->cr += rows;
       +        if (win->cr > win->drows)
       +                win->cr = win->drows;
       +}
       +
       +void
       +ttermwin_forward(termwin_t *win, int cols)
       +{
       +        win->cc += cols;
       +        if (win->cc > win->dcols)
       +                win->cc = win->dcols;
       +}
       +
       +void
       +ttermwin_backward(termwin_t *win, int cols)
       +{
       +        win->cc -= cols;
       +        if (win->cc < 1)
       +                win->cc = 1;
       +}
       +
       +void
       +ttermwin_erasepos(termwin_t *win, int row, int col)
       +{
       +        if (termwin_inwindow(win, row, col))
       +                term_printf(win->dr + row, win->dc + col, " ");
       +}
       +
       +
       +void
       +ttermwin_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
       +ttermwin_erasewin(termwin_t *win)
       +{
       +        term_fillrectangle(win->term, win->dr, win->dc, win->dr + win->drows,
       +                        win->dc + win->dcols, ' ');
       +}
       +
       +void
       +ttermwin_backspace(termwin_t *win)
       +{
       +        termwin_backward(win, 2);
       +}
       +
       +
 (DIR) 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>
        
       +ttypedef struct term_t term_t;
        ttypedef 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;
        };
        
       -ttypedef 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;
        };
        
       +ttermwin_t *termwin_new(term_t *term, int r, int c, int rows, int cols);
       +void termwin_free(term_t *term, termwin_t *win);
       +
       +tterm_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
        
 (DIR) 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;
       +}
       +