A bit of renaming (term -> terminal)
This commit is contained in:
parent
6f80a5f5cd
commit
8bb410bb7f
4
Makefile
4
Makefile
|
@ -6,7 +6,7 @@
|
|||
##
|
||||
|
||||
NAME = vt100
|
||||
SRC = term.c vt100.c test.c vt100_headless.c
|
||||
SRC = terminal.c vt100.c test.c vt100_headless.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
CC = gcc
|
||||
INCLUDE = .
|
||||
|
@ -30,4 +30,4 @@ clean:
|
|||
re: clean all
|
||||
|
||||
check-syntax:
|
||||
gcc -o /dev/null -S ${CHK_SOURCES}
|
||||
gcc -Wall -Wextra -ansi -pedantic -o /dev/null -S ${CHK_SOURCES}
|
||||
|
|
230
term.c
230
term.c
|
@ -1,230 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#ifndef NDEBUG
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "term.h"
|
||||
|
||||
|
||||
/*
|
||||
** Term implement a terminal, (vt100 like)
|
||||
** It expose an API to implement a specific terminal, actually I implement
|
||||
** vt100.
|
||||
**
|
||||
** term.c parses escape sequences like
|
||||
** \033[4;2H
|
||||
** It allows control chars to be inside the sequence like :
|
||||
** \033[4\n;2H
|
||||
** and accept variations like :
|
||||
** \033#...
|
||||
** \033(...
|
||||
**
|
||||
** The API is simple, it consists of a structure term_callbacks (see
|
||||
** term.h) where 4 members points to a ascii_callbacks structure.
|
||||
** Ascii callbacks is only a struct with some ascii chars where you
|
||||
** can plug your callbacks functions. see vt100.c as an example.
|
||||
**
|
||||
*/
|
||||
|
||||
static void term_push(struct terminal *term, char c)
|
||||
{
|
||||
if (term->stack_ptr >= TERM_STACK_SIZE)
|
||||
return ;
|
||||
term->stack[term->stack_ptr++] = c;
|
||||
}
|
||||
|
||||
static void term_parse_params(struct terminal *term)
|
||||
{
|
||||
unsigned int i;
|
||||
int got_something;
|
||||
|
||||
got_something = 0;
|
||||
term->argc = 0;
|
||||
term->argv[0] = 0;
|
||||
for (i = 0; i < term->stack_ptr; ++i)
|
||||
{
|
||||
if (term->stack[i] >= '0' && term->stack[i] <= '9')
|
||||
{
|
||||
got_something = 1;
|
||||
term->argv[term->argc] = term->argv[term->argc] * 10
|
||||
+ term->stack[i] - '0';
|
||||
}
|
||||
else if (term->stack[i] == ';')
|
||||
{
|
||||
got_something = 0;
|
||||
term->argc += 1;
|
||||
term->argv[term->argc] = 0;
|
||||
}
|
||||
}
|
||||
term->argc += got_something;
|
||||
}
|
||||
|
||||
static void term_call_CSI(struct terminal *term, char c)
|
||||
{
|
||||
term_parse_params(term);
|
||||
if (((term_action *)&term->callbacks.csi)[c - '0'] == NULL)
|
||||
{
|
||||
if (term->unimplemented != NULL)
|
||||
term->unimplemented(term, "CSI", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&term->callbacks.csi)[c - '0'](term);
|
||||
leave:
|
||||
term->state = INIT;
|
||||
term->flag = '\0';
|
||||
term->stack_ptr = 0;
|
||||
term->argc = 0;
|
||||
}
|
||||
|
||||
static void term_call_ESC(struct terminal *term, char c)
|
||||
{
|
||||
if (((term_action *)&term->callbacks.esc)[c - '0'] == NULL)
|
||||
{
|
||||
if (term->unimplemented != NULL)
|
||||
term->unimplemented(term, "ESC", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&term->callbacks.esc)[c - '0'](term);
|
||||
leave:
|
||||
term->state = INIT;
|
||||
term->stack_ptr = 0;
|
||||
term->argc = 0;
|
||||
}
|
||||
|
||||
static void term_call_HASH(struct terminal *term, char c)
|
||||
{
|
||||
if (((term_action *)&term->callbacks.hash)[c - '0'] == NULL)
|
||||
{
|
||||
if (term->unimplemented != NULL)
|
||||
term->unimplemented(term, "HASH", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&term->callbacks.hash)[c - '0'](term);
|
||||
leave:
|
||||
term->state = INIT;
|
||||
term->stack_ptr = 0;
|
||||
term->argc = 0;
|
||||
}
|
||||
|
||||
static void term_call_GSET(struct terminal *term, char c)
|
||||
{
|
||||
if (c < '0' || c > 'B'
|
||||
|| ((term_action *)&term->callbacks.scs)[c - '0'] == NULL)
|
||||
{
|
||||
if (term->unimplemented != NULL)
|
||||
term->unimplemented(term, "GSET", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&term->callbacks.scs)[c - '0'](term);
|
||||
leave:
|
||||
term->state = INIT;
|
||||
term->stack_ptr = 0;
|
||||
term->argc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** INIT
|
||||
** \_ ESC "\033"
|
||||
** | \_ CSI "\033["
|
||||
** | | \_ c == '?' : term->flag = '?'
|
||||
** | | \_ c == ';' || (c >= '0' && c <= '9') : term_push
|
||||
** | | \_ else : term_call_CSI()
|
||||
** | \_ HASH "\033#"
|
||||
** | | \_ term_call_hash()
|
||||
** | \_ G0SET "\033("
|
||||
** | | \_ term_call_GSET()
|
||||
** | \_ G1SET "\033)"
|
||||
** | | \_ term_call_GSET()
|
||||
** \_ term->write()
|
||||
*/
|
||||
void term_read(struct terminal *term, char c)
|
||||
{
|
||||
if (term->state == INIT)
|
||||
{
|
||||
if (c == '\033')
|
||||
term->state = ESC;
|
||||
else
|
||||
term->write(term, c);
|
||||
}
|
||||
else if (term->state == ESC)
|
||||
{
|
||||
if (c == '[')
|
||||
term->state = CSI;
|
||||
else if (c == '#')
|
||||
term->state = HASH;
|
||||
else if (c == '(')
|
||||
term->state = G0SET;
|
||||
else if (c == ')')
|
||||
term->state = G1SET;
|
||||
else if (c >= '0' && c <= 'z')
|
||||
term_call_ESC(term, c);
|
||||
else term->write(term, c);
|
||||
}
|
||||
else if (term->state == HASH)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
term_call_HASH(term, c);
|
||||
else
|
||||
term->write(term, c);
|
||||
}
|
||||
else if (term->state == G0SET || term->state == G1SET)
|
||||
{
|
||||
term_call_GSET(term, c);
|
||||
}
|
||||
else if (term->state == CSI)
|
||||
{
|
||||
if (c == '?')
|
||||
term->flag = '?';
|
||||
else if (c == ';' || (c >= '0' && c <= '9'))
|
||||
term_push(term, c);
|
||||
else if (c >= '?' && c <= 'z')
|
||||
term_call_CSI(term, c);
|
||||
else
|
||||
term->write(term, c);
|
||||
}
|
||||
}
|
||||
|
||||
void term_read_str(struct terminal *term, char *c)
|
||||
{
|
||||
while (*c)
|
||||
term_read(term, *c++);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void term_default_unimplemented(struct terminal* term, char *seq, char chr)
|
||||
{
|
||||
unsigned int argc;
|
||||
|
||||
fprintf(stderr, "WARNING: UNIMPLEMENTED %s (", seq);
|
||||
for (argc = 0; argc < term->argc; ++argc)
|
||||
{
|
||||
fprintf(stderr, "%d", term->argv[argc]);
|
||||
if (argc != term->argc - 1)
|
||||
fprintf(stderr, ", ");
|
||||
}
|
||||
fprintf(stderr, ")%o\n", chr);
|
||||
}
|
||||
#else
|
||||
void term_default_unimplemented(struct terminal* term, char *seq, char chr)
|
||||
{
|
||||
term = term;
|
||||
seq = seq;
|
||||
chr = chr;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct terminal *term_init(unsigned int width, unsigned int height,
|
||||
void (*vtwrite)(struct terminal *, char))
|
||||
{
|
||||
struct terminal *term;
|
||||
|
||||
term = calloc(1, sizeof(*term));
|
||||
term->width = width;
|
||||
term->height = height;
|
||||
term->cursor_pos_x = 0;
|
||||
term->cursor_pos_y = 0;
|
||||
term->stack_ptr = 0;
|
||||
term->state = INIT;
|
||||
term->write = vtwrite;
|
||||
return term;
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
#include <stdlib.h>
|
||||
#ifndef NDEBUG
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "terminal.h"
|
||||
|
||||
|
||||
/*
|
||||
** Term implement a terminal, (vt100 like)
|
||||
** It expose an API to implement a specific terminal.
|
||||
** Actually I implement vt100 in vt100.c
|
||||
**
|
||||
** term.c parses escape sequences like
|
||||
** \033[4;2H
|
||||
** It allows control chars to be inside the sequence like :
|
||||
** \033[4\n;2H
|
||||
** and accept variations like :
|
||||
** \033#...
|
||||
** \033(...
|
||||
**
|
||||
** The API is simple, it consists of a structure term_callbacks (see
|
||||
** term.h) where 4 members points to a ascii_callbacks structure.
|
||||
** Ascii callbacks is only a struct with some ascii chars where you
|
||||
** can plug your callbacks functions. see vt100.c as an example.
|
||||
**
|
||||
*/
|
||||
|
||||
static void terminal_push(struct terminal *this, char c)
|
||||
{
|
||||
if (this->stack_ptr >= TERM_STACK_SIZE)
|
||||
return ;
|
||||
this->stack[this->stack_ptr++] = c;
|
||||
}
|
||||
|
||||
static void terminal_parse_params(struct terminal *this)
|
||||
{
|
||||
unsigned int i;
|
||||
int got_something;
|
||||
|
||||
got_something = 0;
|
||||
this->argc = 0;
|
||||
this->argv[0] = 0;
|
||||
for (i = 0; i < this->stack_ptr; ++i)
|
||||
{
|
||||
if (this->stack[i] >= '0' && this->stack[i] <= '9')
|
||||
{
|
||||
got_something = 1;
|
||||
this->argv[this->argc] = this->argv[this->argc] * 10
|
||||
+ this->stack[i] - '0';
|
||||
}
|
||||
else if (this->stack[i] == ';')
|
||||
{
|
||||
got_something = 0;
|
||||
this->argc += 1;
|
||||
this->argv[this->argc] = 0;
|
||||
}
|
||||
}
|
||||
this->argc += got_something;
|
||||
}
|
||||
|
||||
static void terminal_call_CSI(struct terminal *this, char c)
|
||||
{
|
||||
terminal_parse_params(this);
|
||||
if (((term_action *)&this->callbacks.csi)[c - '0'] == NULL)
|
||||
{
|
||||
if (this->unimplemented != NULL)
|
||||
this->unimplemented(this, "CSI", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&this->callbacks.csi)[c - '0'](this);
|
||||
leave:
|
||||
this->state = INIT;
|
||||
this->flag = '\0';
|
||||
this->stack_ptr = 0;
|
||||
this->argc = 0;
|
||||
}
|
||||
|
||||
static void terminal_call_ESC(struct terminal *this, char c)
|
||||
{
|
||||
if (((term_action *)&this->callbacks.esc)[c - '0'] == NULL)
|
||||
{
|
||||
if (this->unimplemented != NULL)
|
||||
this->unimplemented(this, "ESC", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&this->callbacks.esc)[c - '0'](this);
|
||||
leave:
|
||||
this->state = INIT;
|
||||
this->stack_ptr = 0;
|
||||
this->argc = 0;
|
||||
}
|
||||
|
||||
static void terminal_call_HASH(struct terminal *this, char c)
|
||||
{
|
||||
if (((term_action *)&this->callbacks.hash)[c - '0'] == NULL)
|
||||
{
|
||||
if (this->unimplemented != NULL)
|
||||
this->unimplemented(this, "HASH", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&this->callbacks.hash)[c - '0'](this);
|
||||
leave:
|
||||
this->state = INIT;
|
||||
this->stack_ptr = 0;
|
||||
this->argc = 0;
|
||||
}
|
||||
|
||||
static void terminal_call_GSET(struct terminal *this, char c)
|
||||
{
|
||||
if (c < '0' || c > 'B'
|
||||
|| ((term_action *)&this->callbacks.scs)[c - '0'] == NULL)
|
||||
{
|
||||
if (this->unimplemented != NULL)
|
||||
this->unimplemented(this, "GSET", c);
|
||||
goto leave;
|
||||
}
|
||||
((term_action *)&this->callbacks.scs)[c - '0'](this);
|
||||
leave:
|
||||
this->state = INIT;
|
||||
this->stack_ptr = 0;
|
||||
this->argc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** INIT
|
||||
** \_ ESC "\033"
|
||||
** | \_ CSI "\033["
|
||||
** | | \_ c == '?' : term->flag = '?'
|
||||
** | | \_ c == ';' || (c >= '0' && c <= '9') : term_push
|
||||
** | | \_ else : term_call_CSI()
|
||||
** | \_ HASH "\033#"
|
||||
** | | \_ term_call_hash()
|
||||
** | \_ G0SET "\033("
|
||||
** | | \_ term_call_GSET()
|
||||
** | \_ G1SET "\033)"
|
||||
** | | \_ term_call_GSET()
|
||||
** \_ term->write()
|
||||
*/
|
||||
void terminal_read(struct terminal *this, char c)
|
||||
{
|
||||
if (this->state == INIT)
|
||||
{
|
||||
if (c == '\033')
|
||||
this->state = ESC;
|
||||
else
|
||||
this->write(this, c);
|
||||
}
|
||||
else if (this->state == ESC)
|
||||
{
|
||||
if (c == '[')
|
||||
this->state = CSI;
|
||||
else if (c == '#')
|
||||
this->state = HASH;
|
||||
else if (c == '(')
|
||||
this->state = G0SET;
|
||||
else if (c == ')')
|
||||
this->state = G1SET;
|
||||
else if (c >= '0' && c <= 'z')
|
||||
terminal_call_ESC(this, c);
|
||||
else this->write(this, c);
|
||||
}
|
||||
else if (this->state == HASH)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
terminal_call_HASH(this, c);
|
||||
else
|
||||
this->write(this, c);
|
||||
}
|
||||
else if (this->state == G0SET || this->state == G1SET)
|
||||
{
|
||||
terminal_call_GSET(this, c);
|
||||
}
|
||||
else if (this->state == CSI)
|
||||
{
|
||||
if (c == '?')
|
||||
this->flag = '?';
|
||||
else if (c == ';' || (c >= '0' && c <= '9'))
|
||||
terminal_push(this, c);
|
||||
else if (c >= '?' && c <= 'z')
|
||||
terminal_call_CSI(this, c);
|
||||
else
|
||||
this->write(this, c);
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_read_str(struct terminal *this, char *c)
|
||||
{
|
||||
while (*c)
|
||||
terminal_read(this, *c++);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void terminal_default_unimplemented(struct terminal* this, char *seq, char chr)
|
||||
{
|
||||
unsigned int argc;
|
||||
|
||||
fprintf(stderr, "WARNING: UNIMPLEMENTED %s (", seq);
|
||||
for (argc = 0; argc < this->argc; ++argc)
|
||||
{
|
||||
fprintf(stderr, "%d", this->argv[argc]);
|
||||
if (argc != this->argc - 1)
|
||||
fprintf(stderr, ", ");
|
||||
}
|
||||
fprintf(stderr, ")%o\n", chr);
|
||||
}
|
||||
#else
|
||||
void terminal_default_unimplemented(struct terminal* this, char *seq, char chr)
|
||||
{
|
||||
this = this;
|
||||
seq = seq;
|
||||
chr = chr;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct terminal *terminal_init(void)
|
||||
{
|
||||
return calloc(1, sizeof(struct terminal));
|
||||
}
|
|
@ -128,10 +128,9 @@ struct terminal
|
|||
int fd;
|
||||
};
|
||||
|
||||
struct terminal *term_init(unsigned int width, unsigned int height,
|
||||
void (*write)(struct terminal *, char));
|
||||
void term_default_unimplemented(struct terminal* term, char *seq, char chr);
|
||||
void term_read(struct terminal *term, char c);
|
||||
void term_read_str(struct terminal *term, char *c);
|
||||
struct terminal *terminal_init(void);
|
||||
void terminal_default_unimplemented(struct terminal* term, char *seq, char chr);
|
||||
void terminal_read(struct terminal *term, char c);
|
||||
void terminal_read_str(struct terminal *term, char *c);
|
||||
|
||||
#endif
|
5
vt100.c
5
vt100.c
|
@ -919,7 +919,10 @@ struct terminal *vt100_init(void (*unimplemented)(struct terminal* term_emul, ch
|
|||
vt100->y = 0;
|
||||
vt100->modes = MASK_DECANM;
|
||||
vt100->top_line = 0;
|
||||
term = term_init(80, 24, vt100_write);
|
||||
term = terminal_init();
|
||||
term->width = 80;
|
||||
term->height = 24;
|
||||
term->write = vt100_write;
|
||||
term->callbacks.csi.f = HVP;
|
||||
term->callbacks.csi.K = EL;
|
||||
term->callbacks.csi.c = DA;
|
||||
|
|
Loading…
Reference in New Issue