Separation of term and vt100, season 1 episode 4

This commit is contained in:
Julien Palard 2011-09-20 21:26:11 +02:00
parent 09140c82d3
commit 3171d66d6f
4 changed files with 1008 additions and 1043 deletions

View File

@ -6,7 +6,7 @@
##
NAME = vt100
SRC = term.c test.c
SRC = term.c vt100.c test.c
OBJ = $(SRC:.c=.o)
CC = gcc
INCLUDE = .

1044
test.c

File diff suppressed because it is too large Load Diff

935
vt100.c Normal file
View File

@ -0,0 +1,935 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "vt100.h"
unsigned int get_mode_mask(unsigned int mode)
{
switch (mode)
{
case LNM : return MASK_LNM;
case DECCKM : return MASK_DECCKM;
case DECANM : return MASK_DECANM;
case DECCOLM : return MASK_DECCOLM;
case DECSCLM : return MASK_DECSCLM;
case DECSCNM : return MASK_DECSCNM;
case DECOM : return MASK_DECOM;
case DECAWM : return MASK_DECAWM;
case DECARM : return MASK_DECARM;
case DECINLM : return MASK_DECINLM;
default: return 0;
}
}
/*
Modes
=====
The following is a list of VT100 modes which may be changed with set
mode (SM) and reset mode (RM) controls.
ANSI Specified Modes
--------------------
Parameter Mode Mnemonic Mode Function
0 Error (ignored)
20 LNM Line feed new line mode
DEC Private Modes
=================
If the first character in the parameter string is ? (077), the
parameters are interpreted as DEC private parameters according to the
following:
Parameter Mode Mnemonic Mode Function
0 Error (ignored)
1 DECCKM Cursor key
2 DECANM ANSI/VT52
3 DECCOLM Column
4 DECSCLM Scrolling
5 DECSCNM Screen
6 DECOM Origin
7 DECAWM Auto wrap
8 DECARM Auto repeating
9 DECINLM Interlace
LNM Line Feed/New Line Mode
-----------------------------
This is a parameter applicable to set mode (SM) and reset mode (RM)
control sequences. The reset state causes the interpretation of the
line feed (LF), defined in ANSI Standard X3.4-1977, to imply only
vertical movement of the active position and causes the RETURN key
(CR) to send the single code CR. The set state causes the LF to imply
movement to the first position of the following line and causes the
RETURN key to send the two codes (CR, LF). This is the New Line (NL)
option.
This mode does not affect the index (IND), or next line (NEL) format
effectors.
DECCKM Cursor Keys Mode (DEC Private)
---------------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. This mode is only effective when the terminal
is in keypad application mode (see DECKPAM) and the ANSI/VT52 mode
(DECANM) is set (see DECANM). Under these conditions, if the cursor
key mode is reset, the four cursor function keys will send ANSI cursor
control commands. If cursor key mode is set, the four cursor function
keys will send application functions.
DECANM ANSI/VT52 Mode (DEC Private)
-------------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state causes only VT52 compatible
escape sequences to be interpreted and executed. The set state causes
only ANSI "compatible" escape and control sequences to be interpreted
and executed.
DECCOLM Column Mode (DEC Private)
-----------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state causes a maximum of 80 columns
on the screen. The set state causes a maximum of 132 columns on the
screen.
DECSCLM Scrolling Mode (DEC Private)
--------------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state causes scrolls to "jump"
instantaneously. The set state causes scrolls to be "smooth" at a
maximum rate of six lines per second.
DECSCNM Screen Mode (DEC Private)
-----------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state causes the screen to be black
with white characters. The set state causes the screen to be white
with black characters.
DECOM Origin Mode (DEC Private)
---------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state causes the origin to be at the
upper-left character position on the screen. Line and column numbers
are, therefore, independent of current margin settings. The cursor may
be positioned outside the margins with a cursor position (CUP) or
horizontal and vertical position (HVP) control.
The set state causes the origin to be at the upper-left character
position within the margins. Line and column numbers are therefore
relative to the current margin settings. The cursor is not allowed to
be positioned outside the margins.
The cursor is moved to the new home position when this mode is set or
reset.
Lines and columns are numbered consecutively, with the origin being
line 1, column 1.
DECAWM Autowrap Mode (DEC Private)
------------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state causes any displayable
characters received when the cursor is at the right margin to replace
any previous characters there. The set state causes these characters
to advance to the start of the next line, doing a scroll up if
required and permitted.
DECARM Auto Repeat Mode (DEC Private)
---------------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state causes no keyboard keys to
auto-repeat. The set state causes certain keyboard keys to auto-repeat.
DECINLM Interlace Mode (DEC Private)
--------------------------------------
This is a private parameter applicable to set mode (SM) and reset mode
(RM) control sequences. The reset state (non-interlace) causes the video
processor to display 240 scan lines per frame. The set state (interlace)
causes the video processor to display 480 scan lines per frame. There is
no increase in character resolution.
*/
#define SCREEN_PTR(vt100, x, y) \
((vt100->top_line * vt100->width + x + vt100->width * y) \
% (vt100->width * SCROLLBACK * vt100->height))
#define FROZEN_SCREEN_PTR(vt100, x, y) \
((x + vt100->width * y) \
% (vt100->width * SCROLLBACK * vt100->height))
void set(struct vt100_term *headless_term,
unsigned int x, unsigned int y,
char c)
{
if (y < headless_term->margin_top || y > headless_term->margin_bottom)
headless_term->frozen_screen[FROZEN_SCREEN_PTR(headless_term, x, y)] = c;
else
headless_term->screen[SCREEN_PTR(headless_term, x, y)] = c;
}
char get(struct vt100_term *vt100, unsigned int x, unsigned int y)
{
if (y < vt100->margin_top || y > vt100->margin_bottom)
return vt100->frozen_screen[FROZEN_SCREEN_PTR(vt100, x, y)];
else
return vt100->screen[SCREEN_PTR(vt100, x, y)];
}
void froze_line(struct vt100_term *vt100, unsigned int y)
{
memcpy(vt100->frozen_screen + vt100->width * y,
vt100->screen + SCREEN_PTR(vt100, 0, y),
vt100->width);
}
void unfroze_line(struct vt100_term *vt100, unsigned int y)
{
memcpy(vt100->screen + SCREEN_PTR(vt100, 0, y),
vt100->frozen_screen + vt100->width * y,
vt100->width);
}
void blank_screen(struct vt100_term *vt100_term)
{
unsigned int x;
unsigned int y;
for (x = 0; x < vt100_term->width; ++x)
for (y = 0; y < vt100_term->height; ++y)
set(vt100_term, x, y, '\0');
}
/*
DECSC Save Cursor (DEC Private)
ESC 7
This sequence causes the cursor position, graphic rendition, and
character set to be saved. (See DECRC).
*/
void DECSC(struct term_emul *term_emul)
{
/*TODO: Save graphic rendition and charset.*/
struct vt100_term *vt100;
vt100 = (struct vt100_term *)term_emul->user_data;
vt100->saved_x = vt100->x;
vt100->saved_y = vt100->y;
}
/*
RM Reset Mode
ESC [ Ps ; Ps ; . . . ; Ps l
Resets one or more VT100 modes as specified by each selective
parameter in the parameter string. Each mode to be reset is specified
by a separate parameter. [See Set Mode (SM) control sequence]. (See
Modes following this section).
*/
void RM(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int mode;
vt100 = (struct vt100_term *)term_emul->user_data;
if (term_emul->argc > 0)
{
mode = term_emul->argv[0];
if (mode == DECCOLM)
{
vt100->width = 80;
vt100->x = vt100->y = 0;
blank_screen(vt100);
}
UNSET_MODE(vt100, mode);
}
}
/*
CUP Cursor Position
ESC [ Pn ; Pn H default value: 1
The CUP sequence moves the active position to the position specified
by the parameters. This sequence has two parameter values, the first
specifying the line position and the second specifying the column
position. A parameter value of zero or one for the first or second
parameter moves the active position to the first line or column in the
display, respectively. The default condition with no parameters
present is equivalent to a cursor to home action. In the VT100, this
control behaves identically with its format effector counterpart,
HVP. Editor Function
The numbering of lines depends on the state of the Origin Mode
(DECOM).
*/
void CUP(struct term_emul *term_emul)
{
struct vt100_term *vt100;
int arg0;
int arg1;
vt100 = (struct vt100_term *)term_emul->user_data;
arg0 = 0;
arg1 = 0;
if (term_emul->argc > 0)
arg0 = term_emul->argv[0] - 1;
if (term_emul->argc > 1)
arg1 = term_emul->argv[1] - 1;
if (arg0 < 0)
arg0 = 0;
if (arg1 < 0)
arg1 = 0;
if (MODE_IS_SET(vt100, DECOM))
{
arg0 += vt100->margin_top;
if ((unsigned int)arg0 > vt100->margin_bottom)
arg0 = vt100->margin_bottom;
}
vt100->y = arg0;
vt100->x = arg1;
}
/*
SM Set Mode
ESC [ Ps ; . . . ; Ps h
Causes one or more modes to be set within the VT100 as specified by
each selective parameter in the parameter string. Each mode to be set
is specified by a separate parameter. A mode is considered set until
it is reset by a reset mode (RM) control sequence.
*/
void SM(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int mode;
unsigned int saved_argc;
vt100 = (struct vt100_term *)term_emul->user_data;
if (term_emul->argc > 0)
{
mode = term_emul->argv[0];
SET_MODE(vt100, mode);
if (mode == DECANM)
{
/* TODO: Support vt52 mode */
return ;
}
if (mode == DECCOLM)
{
vt100->width = 132;
vt100->x = vt100->y = 0;
blank_screen(vt100);
}
if (mode == DECOM)
{
saved_argc = term_emul->argc;
term_emul->argc = 0;
CUP(term_emul);
term_emul->argc = saved_argc;
}
}
}
/*
DECSTBM Set Top and Bottom Margins (DEC Private)
ESC [ Pn; Pn r
This sequence sets the top and bottom margins to define the scrolling
region. The first parameter is the line number of the first line in
the scrolling region; the second parameter is the line number of the
bottom line in the scrolling region. Default is the entire screen (no
margins). The minimum size of the scrolling region allowed is two
lines, i.e., the top margin must be less than the bottom margin. The
cursor is placed in the home position (see Origin Mode DECOM).
*/
void DECSTBM(struct term_emul *term_emul)
{
unsigned int margin_top;
unsigned int margin_bottom;
struct vt100_term *vt100;
unsigned int line;
vt100 = (struct vt100_term *)term_emul->user_data;
if (term_emul->argc == 2)
{
margin_top = term_emul->argv[0] - 1;
margin_bottom = term_emul->argv[1] - 1;
if (margin_bottom >= vt100->height)
return ;
if (margin_bottom - margin_top <= 0)
return ;
}
else
{
margin_top = 0;
margin_bottom = vt100->height - 1;
}
for (line = vt100->margin_top; line < margin_top; ++line)
froze_line(vt100, line);
for (line = vt100->margin_bottom; line < margin_bottom; ++line)
unfroze_line(vt100, line);
for (line = margin_top; line < vt100->margin_top; ++line)
unfroze_line(vt100, line);
for (line = margin_bottom; line < vt100->margin_bottom; ++line)
froze_line(vt100, line);
vt100->margin_bottom = margin_bottom;
vt100->margin_top = margin_top;
term_emul->argc = 0;
CUP(term_emul);
}
/*
SGR Select Graphic Rendition
ESC [ Ps ; . . . ; Ps m
Invoke the graphic rendition specified by the parameter(s). All
following characters transmitted to the VT100 are rendered according
to the parameter(s) until the next occurrence of SGR. Format Effector
Parameter Parameter Meaning
0 Attributes off
1 Bold or increased intensity
4 Underscore
5 Blink
7 Negative (reverse) image
All other parameter values are ignored.
With the Advanced Video Option, only one type of character attribute
is possible as determined by the cursor selection; in that case
specifying either the underscore or the reverse attribute will
activate the currently selected attribute. (See cursor selection in
Chapter 1).
*/
void SGR(struct term_emul *term_emul)
{
term_emul = term_emul;
/* Just ignore them for now, we are rendering pure text only */
}
/*
DA Device Attributes
ESC [ Pn c
The host requests the VT100 to send a device attributes (DA) control
sequence to identify itself by sending the DA control sequence with
either no parameter or a parameter of 0. Response to the request
described above (VT100 to host) is generated by the VT100 as a DA
control sequence with the numeric parameters as follows:
Option Present Sequence Sent
No options ESC [?1;0c
Processor option (STP) ESC [?1;1c
Advanced video option (AVO) ESC [?1;2c
AVO and STP ESC [?1;3c
Graphics option (GPO) ESC [?1;4c
GPO and STP ESC [?1;5c
GPO and AVO ESC [?1;6c
GPO, STP and AVO ESC [?1;7c
*/
void DA(struct term_emul *term_emul)
{
struct vt100_term *vt100;
vt100 = (struct vt100_term *)term_emul->user_data;
write(term_emul->fd, "\033[?1;0c", 7); /* Do not write directly ? */
}
/*
DECRC Restore Cursor (DEC Private)
ESC 8
This sequence causes the previously saved cursor position, graphic
rendition, and character set to be restored.
*/
void DECRC(struct term_emul *term_emul)
{
/*TODO Save graphic rendition and charset */
struct vt100_term *vt100;
vt100 = (struct vt100_term *)term_emul->user_data;
vt100->x = vt100->saved_x;
vt100->y = vt100->saved_y;
}
/*
DECALN Screen Alignment Display (DEC Private)
ESC # 8
This command fills the entire screen area with uppercase Es for screen
focus and alignment. This command is used by DEC manufacturing and
Field Service personnel.
*/
void DECALN(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int x;
unsigned int y;
vt100 = (struct vt100_term *)term_emul->user_data;
for (x = 0; x < vt100->width; ++x)
for (y = 0; y < vt100->height; ++y)
set(vt100, x, y, 'E');
}
/*
IND Index
ESC D
This sequence causes the active position to move downward one line
without changing the column position. If the active position is at the
bottom margin, a scroll up is performed. Format Effector
*/
void IND(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int x;
vt100 = (struct vt100_term *)term_emul->user_data;
if (vt100->y >= vt100->margin_bottom)
{
/* SCROLL */
vt100->top_line = (vt100->top_line + 1) % (vt100->height * SCROLLBACK);
for (x = 0; x < vt100->width; ++x)
set(vt100, x, vt100->margin_bottom, '\0');
}
else
{
/* Do not scroll, just move downward on the current display space */
vt100->y += 1;
}
}
/*
RI Reverse Index
ESC M
Move the active position to the same horizontal position on the
preceding line. If the active position is at the top margin, a scroll
down is performed. Format Effector
*/
void RI(struct term_emul *term_emul)
{
struct vt100_term *vt100;
vt100 = (struct vt100_term *)term_emul->user_data;
if (vt100->y == 0)
{
/* SCROLL */
vt100->top_line = (vt100->top_line - 1) % (vt100->height * SCROLLBACK);
}
else
{
/* Do not scroll, just move upward on the current display space */
vt100->y -= 1;
}
}
/*
NEL Next Line
ESC E
This sequence causes the active position to move to the first position
on the next line downward. If the active position is at the bottom
margin, a scroll up is performed. Format Effector
*/
void NEL(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int x;
vt100 = (struct vt100_term *)term_emul->user_data;
if (vt100->y >= vt100->margin_bottom)
{
/* SCROLL */
vt100->top_line = (vt100->top_line + 1) % (vt100->height * SCROLLBACK);
for (x = 0; x < vt100->width; ++x)
set(vt100, x, vt100->margin_bottom, '\0');
}
else
{
/* Do not scroll, just move downward on the current display space */
vt100->y += 1;
}
vt100->x = 0;
}
/*
CUU Cursor Up Host to VT100 and VT100 to Host
ESC [ Pn A default value: 1
Moves the active position upward without altering the column
position. The number of lines moved is determined by the parameter. A
parameter value of zero or one moves the active position one line
upward. A parameter value of n moves the active position n lines
upward. If an attempt is made to move the cursor above the top margin,
the cursor stops at the top margin. Editor Function
*/
void CUU(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int arg0;
vt100 = (struct vt100_term *)term_emul->user_data;
arg0 = 1;
if (term_emul->argc > 0)
arg0 = term_emul->argv[0];
if (arg0 == 0)
arg0 = 1;
if (arg0 <= vt100->y)
vt100->y -= arg0;
else
vt100->y = 0;
}
/*
CUD Cursor Down Host to VT100 and VT100 to Host
ESC [ Pn B default value: 1
The CUD sequence moves the active position downward without altering
the column position. The number of lines moved is determined by the
parameter. If the parameter value is zero or one, the active position
is moved one line downward. If the parameter value is n, the active
position is moved n lines downward. In an attempt is made to move the
cursor below the bottom margin, the cursor stops at the bottom
margin. Editor Function
*/
void CUD(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int arg0;
vt100 = (struct vt100_term *)term_emul->user_data;
arg0 = 1;
if (term_emul->argc > 0)
arg0 = term_emul->argv[0];
if (arg0 == 0)
arg0 = 1;
vt100->y += arg0;
if (vt100->y >= vt100->height)
vt100->y = vt100->height - 1;
}
/*
CUF Cursor Forward Host to VT100 and VT100 to Host
ESC [ Pn C default value: 1
The CUF sequence moves the active position to the right. The distance
moved is determined by the parameter. A parameter value of zero or one
moves the active position one position to the right. A parameter value
of n moves the active position n positions to the right. If an attempt
is made to move the cursor to the right of the right margin, the
cursor stops at the right margin. Editor Function
*/
void CUF(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int arg0;
vt100 = (struct vt100_term *)term_emul->user_data;
arg0 = 1;
if (term_emul->argc > 0)
arg0 = term_emul->argv[0];
if (arg0 == 0)
arg0 = 1;
vt100->x += arg0;
if (vt100->x >= vt100->width)
vt100->x = vt100->width - 1;
}
/*
CUB Cursor Backward Host to VT100 and VT100 to Host
ESC [ Pn D default value: 1
The CUB sequence moves the active position to the left. The distance
moved is determined by the parameter. If the parameter value is zero
or one, the active position is moved one position to the left. If the
parameter value is n, the active position is moved n positions to the
left. If an attempt is made to move the cursor to the left of the left
margin, the cursor stops at the left margin. Editor Function
*/
void CUB(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int arg0;
vt100 = (struct vt100_term *)term_emul->user_data;
arg0 = 1;
if (term_emul->argc > 0)
arg0 = term_emul->argv[0];
if (arg0 == 0)
arg0 = 1;
if (arg0 < vt100->x)
vt100->x -= arg0;
else
vt100->x = 0;
}
/*
ED Erase In Display
ESC [ Ps J default value: 0
This sequence erases some or all of the characters in the display
according to the parameter. Any complete line erased by this sequence
will return that line to single width mode. Editor Function
Parameter Parameter Meaning
0 Erase from the active position to the end of the screen,
inclusive (default)
1 Erase from start of the screen to the active position, inclusive
2 Erase all of the display all lines are erased, changed to
single-width, and the cursor does not move.
*/
void ED(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int arg0;
unsigned int x;
unsigned int y;
vt100 = (struct vt100_term *)term_emul->user_data;
arg0 = 0;
if (term_emul->argc > 0)
arg0 = term_emul->argv[0];
if (arg0 == 0)
{
for (x = vt100->x; x < vt100->width; ++x)
set(vt100, x, vt100->y, '\0');
for (x = 0 ; x < vt100->width; ++x)
for (y = vt100->y + 1; y < vt100->height; ++y)
set(vt100, x, y, '\0');
}
else if (arg0 == 1)
{
for (x = 0 ; x < vt100->width; ++x)
for (y = 0; y < vt100->y; ++y)
set(vt100, x, y, '\0');
for (x = 0; x <= vt100->x; ++x)
set(vt100, x, vt100->y, '\0');
}
else if (arg0 == 2)
{
for (x = 0 ; x < vt100->width; ++x)
for (y = 0; y < vt100->height; ++y)
set(vt100, x, y, '\0');
}
}
/*
EL Erase In Line
ESC [ Ps K default value: 0
Erases some or all characters in the active line according to the
parameter. Editor Function
Parameter Parameter Meaning
0 Erase from the active position to the end of the line, inclusive
(default)
1 Erase from the start of the screen to the active position, inclusive
2 Erase all of the line, inclusive
*/
void EL(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int arg0;
unsigned int x;
vt100 = (struct vt100_term *)term_emul->user_data;
arg0 = 0;
if (term_emul->argc > 0)
arg0 = term_emul->argv[0];
if (arg0 == 0)
{
for (x = vt100->x; x < vt100->width; ++x)
set(vt100, x, vt100->y, '\0');
}
else if (arg0 == 1)
{
for (x = 0; x <= vt100->x; ++x)
set(vt100, x, vt100->y, '\0');
}
else if (arg0 == 2)
{
for (x = 0; x < vt100->width; ++x)
set(vt100, x, vt100->y, '\0');
}
}
/*
HVP Horizontal and Vertical Position
ESC [ Pn ; Pn f default value: 1
Moves the active position to the position specified by the
parameters. This sequence has two parameter values, the first
specifying the line position and the second specifying the column. A
parameter value of either zero or one causes the active position to
move to the first line or column in the display, respectively. The
default condition with no parameters present moves the active position
to the home position. In the VT100, this control behaves identically
with its editor function counterpart, CUP. The numbering of lines and
columns depends on the reset or set state of the origin mode
(DECOM). Format Effector
*/
void HVP(struct term_emul *term_emul)
{
CUP(term_emul);
}
void TBC(struct term_emul *term_emul)
{
struct vt100_term *vt100;
unsigned int i;
vt100 = (struct vt100_term *)term_emul->user_data;
if (term_emul->argc == 0 || term_emul->argv[0] == 0)
{
vt100->tabulations[vt100->x] = '-';
}
else if (term_emul->argc == 1 && term_emul->argv[0] == 3)
{
for (i = 0; i < 132; ++i)
vt100->tabulations[i] = '-';
}
}
void HTS(struct term_emul *term_emul)
{
struct vt100_term *vt100;
vt100 = (struct vt100_term *)term_emul->user_data;
vt100->tabulations[vt100->x] = '|';
}
static void vt100_write(struct term_emul *term_emul, char c __attribute__((unused)))
{
struct vt100_term *vt100;
vt100 = (struct vt100_term *)term_emul->user_data;
if (c == '\r')
{
vt100->x = 0;
return ;
}
if (c == '\n' || c == '\013' || c == '\014')
{
if (MODE_IS_SET(vt100, LNM))
NEL(term_emul);
else
IND(term_emul);
return ;
}
if (c == '\010' && vt100->x > 0)
{
if (vt100->x == vt100->width)
vt100->x -= 1;
vt100->x -= 1;
return ;
}
if (c == '\t')
{
do
{
set(vt100, vt100->x, vt100->y, ' ');
vt100->x += 1;
} while (vt100->x < vt100->width && vt100->tabulations[vt100->x] == '-');
return ;
}
if (c == '\016')
{
vt100->selected_charset = 0;
return ;
}
if (c == '\017')
{
vt100->selected_charset = 1;
return ;
}
if (vt100->x == vt100->width)
{
if (MODE_IS_SET(vt100, DECAWM))
NEL(term_emul);
else
vt100->x -= 1;
}
set(vt100, vt100->x, vt100->y, c);
vt100->x += 1;
}
struct term_emul *vt100_init(void (*unimplemented)(struct term_emul* term_emul, char *seq, char chr))
{
struct term_emul *term;
struct vt100_term *vt100;
vt100 = calloc(1, sizeof(*vt100));
if (vt100 == NULL)
return NULL;
vt100->height = 24;
vt100->width = 80;
vt100->screen = calloc(132 * SCROLLBACK * vt100->height,
sizeof(*vt100->screen));
vt100->frozen_screen = calloc(132 * vt100->height,
sizeof(*vt100->frozen_screen));
vt100->tabulations = malloc(132);
if (vt100->tabulations == NULL)
return NULL; /* Need to free before returning ... */
vt100->margin_top = 0;
vt100->margin_bottom = vt100->height - 1;
vt100->selected_charset = 0;
vt100->x = 0;
vt100->y = 0;
vt100->modes = MASK_DECANM;
vt100->top_line = 0;
term = term_init(80, 24, vt100_write);
term->callbacks.csi.f = HVP;
term->callbacks.csi.K = EL;
term->callbacks.csi.c = DA;
term->callbacks.csi.h = SM;
term->callbacks.csi.l = RM;
term->callbacks.csi.J = ED;
term->callbacks.csi.H = CUP;
term->callbacks.csi.C = CUF;
term->callbacks.csi.B = CUD;
term->callbacks.csi.r = DECSTBM;
term->callbacks.csi.m = SGR;
term->callbacks.csi.A = CUU;
term->callbacks.csi.g = TBC;
term->callbacks.esc.H = HTS;
term->callbacks.csi.D = CUB;
term->callbacks.esc.E = NEL;
term->callbacks.esc.D = IND;
term->callbacks.esc.M = RI;
term->callbacks.esc.n8 = DECRC;
term->callbacks.esc.n7 = DECSC;
term->callbacks.hash.n8 = DECALN;
term->user_data = vt100;
term->unimplemented = unimplemented;
return term;
}

70
vt100.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef __VT100_H__
#define __VT100_H__
#include "term.h"
/*
* Source : http://vt100.net/docs/vt100-ug/chapter3.html
http://vt100.net/docs/tp83/appendixb.html
* It's a vt100 implementation, that implements ANSI control function.
*/
#define CHILD 0
#define SCROLLBACK 3
#define MASK_LNM 1
#define MASK_DECCKM 2
#define MASK_DECANM 4
#define MASK_DECCOLM 8
#define MASK_DECSCLM 16
#define MASK_DECSCNM 32
#define MASK_DECOM 64
#define MASK_DECAWM 128
#define MASK_DECARM 256
#define MASK_DECINLM 512
#define LNM 20
#define DECCKM 1
#define DECANM 2
#define DECCOLM 3
#define DECSCLM 4
#define DECSCNM 5
#define DECOM 6
#define DECAWM 7
#define DECARM 8
#define DECINLM 9
#define SET_MODE(vt100, mode) ((vt100)->modes |= get_mode_mask(mode))
#define UNSET_MODE(vt100, mode) ((vt100)->modes &= ~get_mode_mask(mode))
#define MODE_IS_SET(vt100, mode) ((vt100)->modes & get_mode_mask(mode))
/*
** frozen_screen is the frozen part of the screen
** when margins are set.
** The top of the frozen_screen holds the top margin
** while the bottom holds the bottom margin.
*/
struct vt100_term
{
unsigned int width;
unsigned int height;
unsigned int x;
unsigned int y;
unsigned int saved_x;
unsigned int saved_y;
unsigned int margin_top;
unsigned int margin_bottom;
unsigned int top_line; /* Line at the top of the display */
char *screen;
char *frozen_screen;
char *tabulations;
unsigned int selected_charset;
unsigned int modes;
};
struct term_emul *vt100_init(void (*unimplemented)(struct term_emul* term_emul, char *seq, char chr));
char get(struct vt100_term *vt100, unsigned int x, unsigned int y);
#endif