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;
+}
+