mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 9.0.0772: the libvterm code is outdated
Problem: The libvterm code is outdated. Solution: Include libvterm changes from revision 790 to 801.
This commit is contained in:
@@ -8,7 +8,7 @@ The original can be found:
|
|||||||
|
|
||||||
Modifications:
|
Modifications:
|
||||||
- Add a .gitignore file.
|
- Add a .gitignore file.
|
||||||
- Convert from C99 to C90.
|
- Convert some code from C99 to C90.
|
||||||
- Other changes to support embedding in Vim.
|
- Other changes to support embedding in Vim.
|
||||||
|
|
||||||
To get the latest version of libvterm you need the "bzr" command and do:
|
To get the latest version of libvterm you need the "bzr" command and do:
|
||||||
|
@@ -132,6 +132,7 @@ x = xterm
|
|||||||
1 or 2 = block
|
1 or 2 = block
|
||||||
3 or 4 = underline
|
3 or 4 = underline
|
||||||
5 or 6 = I-beam to left
|
5 or 6 = I-beam to left
|
||||||
|
x CSI > q = XTVERSION, request version string
|
||||||
23x CSI " q = DECSCA, select character attributes
|
23x CSI " q = DECSCA, select character attributes
|
||||||
123x CSI r = DECSTBM
|
123x CSI r = DECSTBM
|
||||||
x CSI s = DECSLRM
|
x CSI s = DECSLRM
|
||||||
|
@@ -26,6 +26,11 @@ typedef unsigned int uint32_t;
|
|||||||
#define VTERM_CHECK_VERSION \
|
#define VTERM_CHECK_VERSION \
|
||||||
vterm_check_version(VTERM_VERSION_MAJOR, VTERM_VERSION_MINOR)
|
vterm_check_version(VTERM_VERSION_MAJOR, VTERM_VERSION_MINOR)
|
||||||
|
|
||||||
|
/* Any cell can contain at most one basic printing character and 5 combining
|
||||||
|
* characters. This number could be changed but will be ABI-incompatible if
|
||||||
|
* you do */
|
||||||
|
#define VTERM_MAX_CHARS_PER_CELL 6
|
||||||
|
|
||||||
typedef struct VTerm VTerm;
|
typedef struct VTerm VTerm;
|
||||||
typedef struct VTermState VTermState;
|
typedef struct VTermState VTermState;
|
||||||
typedef struct VTermScreen VTermScreen;
|
typedef struct VTermScreen VTermScreen;
|
||||||
@@ -297,6 +302,7 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VTermPos pos; /* current cursor position */
|
VTermPos pos; /* current cursor position */
|
||||||
|
VTermLineInfo *lineinfos[2]; /* [1] may be NULL */
|
||||||
} VTermStateFields;
|
} VTermStateFields;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -306,11 +312,30 @@ typedef struct {
|
|||||||
void (*free)(void *ptr, void *allocdata);
|
void (*free)(void *ptr, void *allocdata);
|
||||||
} VTermAllocatorFunctions;
|
} VTermAllocatorFunctions;
|
||||||
|
|
||||||
|
/* A convenient shortcut for default cases */
|
||||||
void vterm_check_version(int major, int minor);
|
void vterm_check_version(int major, int minor);
|
||||||
|
|
||||||
|
struct VTermBuilder {
|
||||||
|
int ver; /* currently unused but reserved for some sort of ABI version flag */
|
||||||
|
|
||||||
|
int rows, cols;
|
||||||
|
|
||||||
|
const VTermAllocatorFunctions *allocator;
|
||||||
|
void *allocdata;
|
||||||
|
|
||||||
|
/* Override default sizes for various structures */
|
||||||
|
size_t outbuffer_len; /* default: 4096 */
|
||||||
|
size_t tmpbuffer_len; /* default: 4096 */
|
||||||
|
};
|
||||||
|
|
||||||
|
VTerm *vterm_build(const struct VTermBuilder *builder);
|
||||||
|
|
||||||
|
/* A convenient shortcut for default cases */
|
||||||
// Allocate and initialize a new terminal with default allocators.
|
// Allocate and initialize a new terminal with default allocators.
|
||||||
VTerm *vterm_new(int rows, int cols);
|
VTerm *vterm_new(int rows, int cols);
|
||||||
|
|
||||||
|
/* These shortcuts are generally discouraged in favour of just using vterm_build() */
|
||||||
|
|
||||||
// Allocate and initialize a new terminal with specified allocators.
|
// Allocate and initialize a new terminal with specified allocators.
|
||||||
VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata);
|
VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata);
|
||||||
|
|
||||||
@@ -507,7 +532,6 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#define VTERM_MAX_CHARS_PER_CELL 6
|
|
||||||
uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
|
uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
|
||||||
char width;
|
char width;
|
||||||
VTermScreenCellAttrs attrs;
|
VTermScreenCellAttrs attrs;
|
||||||
|
@@ -502,7 +502,10 @@ static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new
|
|||||||
int old_cols = screen->cols;
|
int old_cols = screen->cols;
|
||||||
|
|
||||||
ScreenCell *old_buffer = screen->buffers[bufidx];
|
ScreenCell *old_buffer = screen->buffers[bufidx];
|
||||||
|
VTermLineInfo *old_lineinfo = statefields->lineinfos[bufidx];
|
||||||
|
|
||||||
ScreenCell *new_buffer = vterm_allocator_malloc(screen->vt, sizeof(ScreenCell) * new_rows * new_cols);
|
ScreenCell *new_buffer = vterm_allocator_malloc(screen->vt, sizeof(ScreenCell) * new_rows * new_cols);
|
||||||
|
VTermLineInfo *new_lineinfo = vterm_allocator_malloc(screen->vt, sizeof(new_lineinfo[0]) * new_rows);
|
||||||
|
|
||||||
// Find the final row of old buffer content
|
// Find the final row of old buffer content
|
||||||
int old_row = old_rows - 1;
|
int old_row = old_rows - 1;
|
||||||
@@ -515,6 +518,8 @@ static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new
|
|||||||
for( ; col < new_cols; col++)
|
for( ; col < new_cols; col++)
|
||||||
clearcell(screen, &new_buffer[new_row * new_cols + col]);
|
clearcell(screen, &new_buffer[new_row * new_cols + col]);
|
||||||
|
|
||||||
|
new_lineinfo[new_row] = old_lineinfo[old_row];
|
||||||
|
|
||||||
old_row--;
|
old_row--;
|
||||||
new_row--;
|
new_row--;
|
||||||
|
|
||||||
@@ -584,15 +589,21 @@ static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new
|
|||||||
/* Scroll new rows back up to the top and fill in blanks at the bottom */
|
/* Scroll new rows back up to the top and fill in blanks at the bottom */
|
||||||
int moverows = new_rows - new_row - 1;
|
int moverows = new_rows - new_row - 1;
|
||||||
memmove(&new_buffer[0], &new_buffer[(new_row + 1) * new_cols], moverows * new_cols * sizeof(ScreenCell));
|
memmove(&new_buffer[0], &new_buffer[(new_row + 1) * new_cols], moverows * new_cols * sizeof(ScreenCell));
|
||||||
|
memmove(&new_lineinfo[0], &new_lineinfo[new_row + 1], moverows * sizeof(new_lineinfo[0]));
|
||||||
|
|
||||||
for(new_row = moverows; new_row < new_rows; new_row++)
|
for(new_row = moverows; new_row < new_rows; new_row++) {
|
||||||
for(col = 0; col < new_cols; col++)
|
for(col = 0; col < new_cols; col++)
|
||||||
clearcell(screen, &new_buffer[new_row * new_cols + col]);
|
clearcell(screen, &new_buffer[new_row * new_cols + col]);
|
||||||
|
new_lineinfo[new_row] = (VTermLineInfo){ 0 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vterm_allocator_free(screen->vt, old_buffer);
|
vterm_allocator_free(screen->vt, old_buffer);
|
||||||
screen->buffers[bufidx] = new_buffer;
|
screen->buffers[bufidx] = new_buffer;
|
||||||
|
|
||||||
|
vterm_allocator_free(screen->vt, old_lineinfo);
|
||||||
|
statefields->lineinfos[bufidx] = new_lineinfo;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* REFLOW TODO:
|
/* REFLOW TODO:
|
||||||
@@ -606,6 +617,7 @@ static int resize(int new_rows, int new_cols, VTermStateFields *fields, void *us
|
|||||||
|
|
||||||
int altscreen_active = (screen->buffers[BUFIDX_ALTSCREEN] && screen->buffer == screen->buffers[BUFIDX_ALTSCREEN]);
|
int altscreen_active = (screen->buffers[BUFIDX_ALTSCREEN] && screen->buffer == screen->buffers[BUFIDX_ALTSCREEN]);
|
||||||
|
|
||||||
|
int old_rows = screen->rows;
|
||||||
int old_cols = screen->cols;
|
int old_cols = screen->cols;
|
||||||
|
|
||||||
if(new_cols > old_cols) {
|
if(new_cols > old_cols) {
|
||||||
@@ -619,6 +631,17 @@ static int resize(int new_rows, int new_cols, VTermStateFields *fields, void *us
|
|||||||
resize_buffer(screen, 0, new_rows, new_cols, !altscreen_active, fields);
|
resize_buffer(screen, 0, new_rows, new_cols, !altscreen_active, fields);
|
||||||
if(screen->buffers[BUFIDX_ALTSCREEN])
|
if(screen->buffers[BUFIDX_ALTSCREEN])
|
||||||
resize_buffer(screen, 1, new_rows, new_cols, altscreen_active, fields);
|
resize_buffer(screen, 1, new_rows, new_cols, altscreen_active, fields);
|
||||||
|
else if(new_rows != old_rows) {
|
||||||
|
/* We don't need a full resize of the altscreen because it isn't enabled
|
||||||
|
* but we should at least keep the lineinfo the right size */
|
||||||
|
vterm_allocator_free(screen->vt, fields->lineinfos[BUFIDX_ALTSCREEN]);
|
||||||
|
|
||||||
|
VTermLineInfo *new_lineinfo = vterm_allocator_malloc(screen->vt, sizeof(new_lineinfo[0]) * new_rows);
|
||||||
|
for(int row = 0; row < new_rows; row++)
|
||||||
|
new_lineinfo[row] = (VTermLineInfo){ 0 };
|
||||||
|
|
||||||
|
fields->lineinfos[BUFIDX_ALTSCREEN] = new_lineinfo;
|
||||||
|
}
|
||||||
|
|
||||||
screen->buffer = altscreen_active ? screen->buffers[BUFIDX_ALTSCREEN] : screen->buffers[BUFIDX_PRIMARY];
|
screen->buffer = altscreen_active ? screen->buffers[BUFIDX_ALTSCREEN] : screen->buffers[BUFIDX_PRIMARY];
|
||||||
|
|
||||||
|
@@ -280,7 +280,6 @@ static void set_lineinfo(VTermState *state, int row, int force, int dwl, int dhl
|
|||||||
static int on_text(const char bytes[], size_t len, void *user)
|
static int on_text(const char bytes[], size_t len, void *user)
|
||||||
{
|
{
|
||||||
VTermState *state = user;
|
VTermState *state = user;
|
||||||
uint32_t *codepoints;
|
|
||||||
int npoints = 0;
|
int npoints = 0;
|
||||||
size_t eaten = 0;
|
size_t eaten = 0;
|
||||||
VTermEncodingInstance *encoding;
|
VTermEncodingInstance *encoding;
|
||||||
@@ -290,9 +289,8 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
|
|
||||||
// We'll have at most len codepoints, plus one from a previous incomplete
|
// We'll have at most len codepoints, plus one from a previous incomplete
|
||||||
// sequence.
|
// sequence.
|
||||||
codepoints = vterm_allocator_malloc(state->vt, (len + 1) * sizeof(uint32_t));
|
uint32_t *codepoints = (uint32_t *)(state->vt->tmpbuffer);
|
||||||
if (codepoints == NULL)
|
size_t maxpoints = (state->vt->tmpbuffer_len) / sizeof(uint32_t);
|
||||||
return 0;
|
|
||||||
|
|
||||||
encoding =
|
encoding =
|
||||||
state->gsingle_set ? &state->encoding[state->gsingle_set] :
|
state->gsingle_set ? &state->encoding[state->gsingle_set] :
|
||||||
@@ -301,7 +299,7 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
&state->encoding[state->gr_set];
|
&state->encoding[state->gr_set];
|
||||||
|
|
||||||
(*encoding->enc->decode)(encoding->enc, encoding->data,
|
(*encoding->enc->decode)(encoding->enc, encoding->data,
|
||||||
codepoints, &npoints, state->gsingle_set ? 1 : (int)len,
|
codepoints, &npoints, state->gsingle_set ? 1 : (int)maxpoints,
|
||||||
bytes, &eaten, len);
|
bytes, &eaten, len);
|
||||||
|
|
||||||
/* There's a chance an encoding (e.g. UTF-8) hasn't found enough bytes yet
|
/* There's a chance an encoding (e.g. UTF-8) hasn't found enough bytes yet
|
||||||
@@ -309,7 +307,6 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
*/
|
*/
|
||||||
if(!npoints)
|
if(!npoints)
|
||||||
{
|
{
|
||||||
vterm_allocator_free(state->vt, codepoints);
|
|
||||||
return (int)eaten;
|
return (int)eaten;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,13 +360,14 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
int glyph_starts = i;
|
int glyph_starts = i;
|
||||||
int glyph_ends;
|
int glyph_ends;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
uint32_t *chars;
|
|
||||||
|
|
||||||
for(glyph_ends = i + 1; glyph_ends < npoints; glyph_ends++)
|
for(glyph_ends = i + 1;
|
||||||
|
(glyph_ends < npoints) && (glyph_ends < glyph_starts + VTERM_MAX_CHARS_PER_CELL);
|
||||||
|
glyph_ends++)
|
||||||
if(!vterm_unicode_is_combining(codepoints[glyph_ends]))
|
if(!vterm_unicode_is_combining(codepoints[glyph_ends]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
chars = vterm_allocator_malloc(state->vt, (glyph_ends - glyph_starts + 1) * sizeof(uint32_t));
|
uint32_t *chars = vterm_allocator_malloc(state->vt, (VTERM_MAX_CHARS_PER_CELL + 1) * sizeof(uint32_t));
|
||||||
if (chars == NULL)
|
if (chars == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -461,7 +459,6 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vterm_allocator_free(state->vt, codepoints);
|
|
||||||
return (int)eaten;
|
return (int)eaten;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,6 +949,12 @@ static void request_dec_mode(VTermState *state, int num)
|
|||||||
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "?%d;%d$y", num, reply ? 1 : 2);
|
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "?%d;%d$y", num, reply ? 1 : 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void request_version_string(VTermState *state)
|
||||||
|
{
|
||||||
|
vterm_push_output_sprintf_str(state->vt, C1_DCS, TRUE, ">|libvterm(%d.%d)",
|
||||||
|
VTERM_VERSION_MAJOR, VTERM_VERSION_MINOR);
|
||||||
|
}
|
||||||
|
|
||||||
static int on_csi(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user)
|
static int on_csi(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user)
|
||||||
{
|
{
|
||||||
VTermState *state = user;
|
VTermState *state = user;
|
||||||
@@ -1423,6 +1426,10 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
|
|||||||
request_dec_mode(state, CSI_ARG(args[0]));
|
request_dec_mode(state, CSI_ARG(args[0]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LEADER('>', 0x71): // XTVERSION - xterm query version string
|
||||||
|
request_version_string(state);
|
||||||
|
break;
|
||||||
|
|
||||||
case INTERMED(' ', 0x71): // DECSCUSR - DEC set cursor shape
|
case INTERMED(' ', 0x71): // DECSCUSR - DEC set cursor shape
|
||||||
val = CSI_ARG_OR(args[0], 1);
|
val = CSI_ARG_OR(args[0], 1);
|
||||||
|
|
||||||
@@ -2018,33 +2025,6 @@ static int on_resize(int rows, int cols, void *user)
|
|||||||
state->tabstops = newtabstops;
|
state->tabstops = newtabstops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rows != state->rows) {
|
|
||||||
int bufidx;
|
|
||||||
for(bufidx = BUFIDX_PRIMARY; bufidx <= BUFIDX_ALTSCREEN; bufidx++) {
|
|
||||||
int row;
|
|
||||||
VTermLineInfo *oldlineinfo = state->lineinfos[bufidx];
|
|
||||||
VTermLineInfo *newlineinfo;
|
|
||||||
if(!oldlineinfo)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
newlineinfo = vterm_allocator_malloc(state->vt, rows * sizeof(VTermLineInfo));
|
|
||||||
|
|
||||||
for(row = 0; row < state->rows && row < rows; row++) {
|
|
||||||
newlineinfo[row] = oldlineinfo[row];
|
|
||||||
}
|
|
||||||
|
|
||||||
for( ; row < rows; row++) {
|
|
||||||
VTermLineInfo lineInfo = {0x0};
|
|
||||||
newlineinfo[row] = lineInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
vterm_allocator_free(state->vt, state->lineinfos[bufidx]);
|
|
||||||
state->lineinfos[bufidx] = newlineinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->lineinfo = state->lineinfos[state->mode.alt_screen ? BUFIDX_ALTSCREEN : BUFIDX_PRIMARY];
|
|
||||||
}
|
|
||||||
|
|
||||||
state->rows = rows;
|
state->rows = rows;
|
||||||
state->cols = cols;
|
state->cols = cols;
|
||||||
|
|
||||||
@@ -2054,12 +2034,45 @@ static int on_resize(int rows, int cols, void *user)
|
|||||||
UBOUND(state->scrollregion_right, state->cols);
|
UBOUND(state->scrollregion_right, state->cols);
|
||||||
|
|
||||||
fields.pos = state->pos;
|
fields.pos = state->pos;
|
||||||
|
fields.lineinfos[0] = state->lineinfos[0];
|
||||||
|
fields.lineinfos[1] = state->lineinfos[1];
|
||||||
|
|
||||||
if(state->callbacks && state->callbacks->resize)
|
if(state->callbacks && state->callbacks->resize) {
|
||||||
(*state->callbacks->resize)(rows, cols, &fields, state->cbdata);
|
(*state->callbacks->resize)(rows, cols, &fields, state->cbdata);
|
||||||
|
|
||||||
state->pos = fields.pos;
|
state->pos = fields.pos;
|
||||||
|
|
||||||
|
state->lineinfos[0] = fields.lineinfos[0];
|
||||||
|
state->lineinfos[1] = fields.lineinfos[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(rows != state->rows) {
|
||||||
|
for(int bufidx = BUFIDX_PRIMARY; bufidx <= BUFIDX_ALTSCREEN; bufidx++) {
|
||||||
|
VTermLineInfo *oldlineinfo = state->lineinfos[bufidx];
|
||||||
|
if(!oldlineinfo)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
VTermLineInfo *newlineinfo = vterm_allocator_malloc(state->vt, rows * sizeof(VTermLineInfo));
|
||||||
|
|
||||||
|
int row;
|
||||||
|
for(row = 0; row < state->rows && row < rows; row++) {
|
||||||
|
newlineinfo[row] = oldlineinfo[row];
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ; row < rows; row++) {
|
||||||
|
newlineinfo[row] = (VTermLineInfo){
|
||||||
|
.doublewidth = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
vterm_allocator_free(state->vt, state->lineinfos[bufidx]);
|
||||||
|
state->lineinfos[bufidx] = newlineinfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->lineinfo = state->lineinfos[state->mode.alt_screen ? BUFIDX_ALTSCREEN : BUFIDX_PRIMARY];
|
||||||
|
|
||||||
if(state->at_phantom && state->pos.col < cols-1) {
|
if(state->at_phantom && state->pos.col < cols-1) {
|
||||||
state->at_phantom = 0;
|
state->at_phantom = 0;
|
||||||
state->pos.col++;
|
state->pos.col++;
|
||||||
|
@@ -34,21 +34,39 @@ static VTermAllocatorFunctions default_allocator = {
|
|||||||
|
|
||||||
VTerm *vterm_new(int rows, int cols)
|
VTerm *vterm_new(int rows, int cols)
|
||||||
{
|
{
|
||||||
return vterm_new_with_allocator(rows, cols, &default_allocator, NULL);
|
struct VTermBuilder builder;
|
||||||
|
memset(&builder, 0, sizeof(builder));
|
||||||
|
builder.rows = rows;
|
||||||
|
builder.cols = cols;
|
||||||
|
return vterm_build(&builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata)
|
VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata)
|
||||||
{
|
{
|
||||||
|
struct VTermBuilder builder;
|
||||||
|
memset(&builder, 0, sizeof(builder));
|
||||||
|
builder.rows = rows;
|
||||||
|
builder.cols = cols;
|
||||||
|
builder.allocator = funcs;
|
||||||
|
builder.allocdata = allocdata;
|
||||||
|
return vterm_build(&builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A handy macro for defaulting values out of builder fields */
|
||||||
|
#define DEFAULT(v, def) ((v) ? (v) : (def))
|
||||||
|
|
||||||
|
VTerm *vterm_build(const struct VTermBuilder *builder)
|
||||||
|
{
|
||||||
|
const VTermAllocatorFunctions *allocator = DEFAULT(builder->allocator, &default_allocator);
|
||||||
|
|
||||||
/* Need to bootstrap using the allocator function directly */
|
/* Need to bootstrap using the allocator function directly */
|
||||||
VTerm *vt = (*funcs->malloc)(sizeof(VTerm), allocdata);
|
VTerm *vt = (*allocator->malloc)(sizeof(VTerm), builder->allocdata);
|
||||||
|
|
||||||
if (vt == NULL)
|
vt->allocator = allocator;
|
||||||
return NULL;
|
vt->allocdata = builder->allocdata;
|
||||||
vt->allocator = funcs;
|
|
||||||
vt->allocdata = allocdata;
|
|
||||||
|
|
||||||
vt->rows = rows;
|
vt->rows = builder->rows;
|
||||||
vt->cols = cols;
|
vt->cols = builder->cols;
|
||||||
|
|
||||||
vt->parser.state = NORMAL;
|
vt->parser.state = NORMAL;
|
||||||
|
|
||||||
@@ -58,11 +76,11 @@ VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *fun
|
|||||||
vt->outfunc = NULL;
|
vt->outfunc = NULL;
|
||||||
vt->outdata = NULL;
|
vt->outdata = NULL;
|
||||||
|
|
||||||
vt->outbuffer_len = 200;
|
vt->outbuffer_len = DEFAULT(builder->outbuffer_len, 4096);
|
||||||
vt->outbuffer_cur = 0;
|
vt->outbuffer_cur = 0;
|
||||||
vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len);
|
vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len);
|
||||||
|
|
||||||
vt->tmpbuffer_len = 64;
|
vt->tmpbuffer_len = DEFAULT(builder->tmpbuffer_len, 4096);
|
||||||
vt->tmpbuffer = vterm_allocator_malloc(vt, vt->tmpbuffer_len);
|
vt->tmpbuffer = vterm_allocator_malloc(vt, vt->tmpbuffer_len);
|
||||||
|
|
||||||
if (vt->tmpbuffer == NULL
|
if (vt->tmpbuffer == NULL
|
||||||
|
@@ -182,7 +182,7 @@ struct VTermState
|
|||||||
|
|
||||||
struct VTerm
|
struct VTerm
|
||||||
{
|
{
|
||||||
VTermAllocatorFunctions *allocator;
|
const VTermAllocatorFunctions *allocator;
|
||||||
void *allocdata;
|
void *allocdata;
|
||||||
|
|
||||||
int rows;
|
int rows;
|
||||||
|
@@ -6,6 +6,11 @@ RESET
|
|||||||
PUSH "\e[c"
|
PUSH "\e[c"
|
||||||
output "\e[?1;2c"
|
output "\e[?1;2c"
|
||||||
|
|
||||||
|
!XTVERSION
|
||||||
|
RESET
|
||||||
|
PUSH "\e[>q"
|
||||||
|
output "\eP>|libvterm(0.2)\e\\"
|
||||||
|
|
||||||
!DSR
|
!DSR
|
||||||
RESET
|
RESET
|
||||||
PUSH "\e[5n"
|
PUSH "\e[5n"
|
||||||
@@ -57,6 +62,6 @@ PUSH "\e[5n"
|
|||||||
output "\x{9b}0n"
|
output "\x{9b}0n"
|
||||||
PUSH "\e F"
|
PUSH "\e F"
|
||||||
|
|
||||||
!Truncation on attempted buffer overflow
|
#!Truncation on attempted buffer overflow
|
||||||
PUSH "\e[6n" x 30
|
#PUSH "\e[6n" x 30
|
||||||
output "\e[10;10R" x 25
|
# output "\e[10;10R" x 25
|
||||||
|
@@ -18,11 +18,11 @@ PUSH "ABC"
|
|||||||
?screen_eol 0,3 = 1
|
?screen_eol 0,3 = 1
|
||||||
PUSH "\e[H"
|
PUSH "\e[H"
|
||||||
movecursor 0,0
|
movecursor 0,0
|
||||||
?screen_chars 0,0,1,80 = "ABC"
|
?screen_row 0 = "ABC"
|
||||||
?screen_text 0,0,1,80 = 0x41,0x42,0x43
|
?screen_text 0,0,1,80 = 0x41,0x42,0x43
|
||||||
PUSH "E"
|
PUSH "E"
|
||||||
movecursor 0,1
|
movecursor 0,1
|
||||||
?screen_chars 0,0,1,80 = "EBC"
|
?screen_row 0 = "EBC"
|
||||||
?screen_text 0,0,1,80 = 0x45,0x42,0x43
|
?screen_text 0,0,1,80 = 0x45,0x42,0x43
|
||||||
|
|
||||||
WANTSCREEN -c
|
WANTSCREEN -c
|
||||||
@@ -30,14 +30,14 @@ WANTSCREEN -c
|
|||||||
!Erase
|
!Erase
|
||||||
RESET
|
RESET
|
||||||
PUSH "ABCDE\e[H\e[K"
|
PUSH "ABCDE\e[H\e[K"
|
||||||
?screen_chars 0,0,1,80 =
|
?screen_row 0 = ""
|
||||||
?screen_text 0,0,1,80 =
|
?screen_text 0,0,1,80 =
|
||||||
|
|
||||||
!Copycell
|
!Copycell
|
||||||
RESET
|
RESET
|
||||||
PUSH "ABC\e[H\e[@"
|
PUSH "ABC\e[H\e[@"
|
||||||
PUSH "1"
|
PUSH "1"
|
||||||
?screen_chars 0,0,1,80 = "1ABC"
|
?screen_row 0 = "1ABC"
|
||||||
|
|
||||||
RESET
|
RESET
|
||||||
PUSH "ABC\e[H\e[P"
|
PUSH "ABC\e[H\e[P"
|
||||||
@@ -48,7 +48,7 @@ PUSH "ABC\e[H\e[P"
|
|||||||
!Space padding
|
!Space padding
|
||||||
RESET
|
RESET
|
||||||
PUSH "Hello\e[CWorld"
|
PUSH "Hello\e[CWorld"
|
||||||
?screen_chars 0,0,1,80 = "Hello World"
|
?screen_row 0 = "Hello World"
|
||||||
?screen_text 0,0,1,80 = 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64
|
?screen_text 0,0,1,80 = 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64
|
||||||
|
|
||||||
!Linefeed padding
|
!Linefeed padding
|
||||||
@@ -60,10 +60,10 @@ PUSH "Hello\r\nWorld"
|
|||||||
!Altscreen
|
!Altscreen
|
||||||
RESET
|
RESET
|
||||||
PUSH "P"
|
PUSH "P"
|
||||||
?screen_chars 0,0,1,80 = "P"
|
?screen_row 0 = "P"
|
||||||
PUSH "\e[?1049h"
|
PUSH "\e[?1049h"
|
||||||
?screen_chars 0,0,1,80 =
|
?screen_row 0 = ""
|
||||||
PUSH "\e[2K\e[HA"
|
PUSH "\e[2K\e[HA"
|
||||||
?screen_chars 0,0,1,80 = "A"
|
?screen_row 0 = "A"
|
||||||
PUSH "\e[?1049l"
|
PUSH "\e[?1049l"
|
||||||
?screen_chars 0,0,1,80 = "P"
|
?screen_row 0 = "P"
|
||||||
|
@@ -7,7 +7,7 @@ WANTSCREEN
|
|||||||
# U+00E9 = 0xC3 0xA9 name: LATIN SMALL LETTER E WITH ACUTE
|
# U+00E9 = 0xC3 0xA9 name: LATIN SMALL LETTER E WITH ACUTE
|
||||||
RESET
|
RESET
|
||||||
PUSH "\xC3\x81\xC3\xA9"
|
PUSH "\xC3\x81\xC3\xA9"
|
||||||
?screen_chars 0,0,1,80 = 0xc1,0xe9
|
?screen_row 0 = 0xc1,0xe9
|
||||||
?screen_text 0,0,1,80 = 0xc3,0x81,0xc3,0xa9
|
?screen_text 0,0,1,80 = 0xc3,0x81,0xc3,0xa9
|
||||||
?screen_cell 0,0 = {0xc1} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
|
?screen_cell 0,0 = {0xc1} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ PUSH "\xC3\x81\xC3\xA9"
|
|||||||
RESET
|
RESET
|
||||||
PUSH "0123\e[H"
|
PUSH "0123\e[H"
|
||||||
PUSH "\xEF\xBC\x90"
|
PUSH "\xEF\xBC\x90"
|
||||||
?screen_chars 0,0,1,80 = 0xff10,0x32,0x33
|
?screen_row 0 = 0xff10,0x32,0x33
|
||||||
?screen_text 0,0,1,80 = 0xef,0xbc,0x90,0x32,0x33
|
?screen_text 0,0,1,80 = 0xef,0xbc,0x90,0x32,0x33
|
||||||
?screen_cell 0,0 = {0xff10} width=2 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
|
?screen_cell 0,0 = {0xff10} width=2 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ PUSH "\xEF\xBC\x90"
|
|||||||
RESET
|
RESET
|
||||||
PUSH "0123\e[H"
|
PUSH "0123\e[H"
|
||||||
PUSH "e\xCC\x81"
|
PUSH "e\xCC\x81"
|
||||||
?screen_chars 0,0,1,80 = 0x65,0x301,0x31,0x32,0x33
|
?screen_row 0 = 0x65,0x301,0x31,0x32,0x33
|
||||||
?screen_text 0,0,1,80 = 0x65,0xcc,0x81,0x31,0x32,0x33
|
?screen_text 0,0,1,80 = 0x65,0xcc,0x81,0x31,0x32,0x33
|
||||||
?screen_cell 0,0 = {0x65,0x301} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
|
?screen_cell 0,0 = {0x65,0x301} width=1 attrs={} fg=rgb(240,240,240) bg=rgb(0,0,0)
|
||||||
|
|
||||||
|
@@ -152,4 +152,4 @@ PUSH "\e[25H\r\nABCDE\b\b\b\e[2P\r\n"
|
|||||||
DAMAGEFLUSH
|
DAMAGEFLUSH
|
||||||
moverect 1..25,0..80 -> 0..24,0..80
|
moverect 1..25,0..80 -> 0..24,0..80
|
||||||
damage 24..25,0..80
|
damage 24..25,0..80
|
||||||
?screen_chars 23,0,24,5 = "ABE"
|
?screen_row 23 = "ABE"
|
||||||
|
@@ -28,20 +28,20 @@ PUSH "E"
|
|||||||
RESET
|
RESET
|
||||||
RESIZE 25,80
|
RESIZE 25,80
|
||||||
PUSH "Top\e[10HLine 10"
|
PUSH "Top\e[10HLine 10"
|
||||||
?screen_chars 0,0,1,80 = "Top"
|
?screen_row 0 = "Top"
|
||||||
?screen_chars 9,0,10,80 = "Line 10"
|
?screen_row 9 = "Line 10"
|
||||||
?cursor = 9,7
|
?cursor = 9,7
|
||||||
RESIZE 20,80
|
RESIZE 20,80
|
||||||
?screen_chars 0,0,1,80 = "Top"
|
?screen_row 0 = "Top"
|
||||||
?screen_chars 9,0,10,80 = "Line 10"
|
?screen_row 9 = "Line 10"
|
||||||
?cursor = 9,7
|
?cursor = 9,7
|
||||||
|
|
||||||
!Resize shorter with content must scroll
|
!Resize shorter with content must scroll
|
||||||
RESET
|
RESET
|
||||||
RESIZE 25,80
|
RESIZE 25,80
|
||||||
PUSH "Top\e[25HLine 25\e[15H"
|
PUSH "Top\e[25HLine 25\e[15H"
|
||||||
?screen_chars 0,0,1,80 = "Top"
|
?screen_row 0 = "Top"
|
||||||
?screen_chars 24,0,25,80 = "Line 25"
|
?screen_row 24 = "Line 25"
|
||||||
?cursor = 14,0
|
?cursor = 14,0
|
||||||
WANTSCREEN b
|
WANTSCREEN b
|
||||||
RESIZE 20,80
|
RESIZE 20,80
|
||||||
@@ -50,8 +50,8 @@ RESIZE 20,80
|
|||||||
sb_pushline 80 =
|
sb_pushline 80 =
|
||||||
sb_pushline 80 =
|
sb_pushline 80 =
|
||||||
sb_pushline 80 =
|
sb_pushline 80 =
|
||||||
?screen_chars 0,0,1,80 =
|
?screen_row 0 = ""
|
||||||
?screen_chars 19,0,20,80 = "Line 25"
|
?screen_row 19 = "Line 25"
|
||||||
?cursor = 9,0
|
?cursor = 9,0
|
||||||
|
|
||||||
!Resize shorter does not lose line with cursor
|
!Resize shorter does not lose line with cursor
|
||||||
@@ -62,11 +62,11 @@ RESIZE 25,80
|
|||||||
WANTSCREEN b
|
WANTSCREEN b
|
||||||
PUSH "\e[24HLine 24\r\nLine 25\r\n"
|
PUSH "\e[24HLine 24\r\nLine 25\r\n"
|
||||||
sb_pushline 80 =
|
sb_pushline 80 =
|
||||||
?screen_chars 23,0,24,10 = "Line 25"
|
?screen_row 23 = "Line 25"
|
||||||
?cursor = 24,0
|
?cursor = 24,0
|
||||||
RESIZE 24,80
|
RESIZE 24,80
|
||||||
sb_pushline 80 =
|
sb_pushline 80 =
|
||||||
?screen_chars 22,0,23,10 = "Line 25"
|
?screen_row 22 = "Line 25"
|
||||||
?cursor = 23,0
|
?cursor = 23,0
|
||||||
|
|
||||||
!Resize shorter does not send the cursor to a negative row
|
!Resize shorter does not send the cursor to a negative row
|
||||||
@@ -90,8 +90,8 @@ RESET
|
|||||||
WANTSCREEN -b
|
WANTSCREEN -b
|
||||||
RESIZE 25,80
|
RESIZE 25,80
|
||||||
PUSH "Line 1\e[25HBottom\e[15H"
|
PUSH "Line 1\e[25HBottom\e[15H"
|
||||||
?screen_chars 0,0,1,80 = "Line 1"
|
?screen_row 0 = "Line 1"
|
||||||
?screen_chars 24,0,25,80 = "Bottom"
|
?screen_row 24 = "Bottom"
|
||||||
?cursor = 14,0
|
?cursor = 14,0
|
||||||
WANTSCREEN b
|
WANTSCREEN b
|
||||||
RESIZE 30,80
|
RESIZE 30,80
|
||||||
@@ -100,9 +100,9 @@ RESIZE 30,80
|
|||||||
sb_popline 80
|
sb_popline 80
|
||||||
sb_popline 80
|
sb_popline 80
|
||||||
sb_popline 80
|
sb_popline 80
|
||||||
?screen_chars 0,0,1,80 = "ABCDE"
|
?screen_row 0 = "ABCDE"
|
||||||
?screen_chars 5,0,6,80 = "Line 1"
|
?screen_row 5 = "Line 1"
|
||||||
?screen_chars 29,0,30,80 = "Bottom"
|
?screen_row 29 = "Bottom"
|
||||||
?cursor = 19,0
|
?cursor = 19,0
|
||||||
WANTSCREEN -b
|
WANTSCREEN -b
|
||||||
|
|
||||||
@@ -112,6 +112,6 @@ WANTSCREEN a
|
|||||||
RESIZE 25,80
|
RESIZE 25,80
|
||||||
PUSH "Main screen\e[?1049h\e[HAlt screen"
|
PUSH "Main screen\e[?1049h\e[HAlt screen"
|
||||||
RESIZE 30,80
|
RESIZE 30,80
|
||||||
?screen_chars 0,0,1,3 = "Alt"
|
?screen_row 0 = "Alt screen"
|
||||||
PUSH "\e[?1049l"
|
PUSH "\e[?1049l"
|
||||||
?screen_chars 0,0,1,3 = "Mai"
|
?screen_row 0 = "Main screen"
|
||||||
|
@@ -4,13 +4,13 @@ WANTSCREEN
|
|||||||
!Selective erase
|
!Selective erase
|
||||||
RESET
|
RESET
|
||||||
PUSH "A\e[1\"qB\e[\"qC"
|
PUSH "A\e[1\"qB\e[\"qC"
|
||||||
?screen_chars 0,0,1,3 = 0x41,0x42,0x43
|
?screen_row 0 = "ABC"
|
||||||
PUSH "\e[G\e[?J"
|
PUSH "\e[G\e[?J"
|
||||||
?screen_chars 0,0,1,3 = 0x20,0x42
|
?screen_row 0 = " B"
|
||||||
|
|
||||||
!Non-selective erase
|
!Non-selective erase
|
||||||
RESET
|
RESET
|
||||||
PUSH "A\e[1\"qB\e[\"qC"
|
PUSH "A\e[1\"qB\e[\"qC"
|
||||||
?screen_chars 0,0,1,3 = 0x41,0x42,0x43
|
?screen_row 0 = "ABC"
|
||||||
PUSH "\e[G\e[J"
|
PUSH "\e[G\e[J"
|
||||||
?screen_chars 0,0,1,3 =
|
?screen_row 0 = ""
|
||||||
|
@@ -1001,7 +1001,14 @@ int main(int argc UNUSED, char **argv UNUSED)
|
|||||||
size_t len;
|
size_t len;
|
||||||
while(linep[0] == ' ')
|
while(linep[0] == ' ')
|
||||||
linep++;
|
linep++;
|
||||||
if(sscanf(linep, "%d,%d,%d,%d", &rect.start_row, &rect.start_col, &rect.end_row, &rect.end_col) < 4) {
|
if(sscanf(linep, "%d,%d,%d,%d", &rect.start_row, &rect.start_col, &rect.end_row, &rect.end_col) == 4)
|
||||||
|
; // fine
|
||||||
|
else if(sscanf(linep, "%d", &rect.start_row) == 1) {
|
||||||
|
rect.end_row = rect.start_row + 1;
|
||||||
|
rect.start_col = 0;
|
||||||
|
vterm_get_size(vt, NULL, &rect.end_col);
|
||||||
|
}
|
||||||
|
else {
|
||||||
printf("! screen_chars unrecognised input\n");
|
printf("! screen_chars unrecognised input\n");
|
||||||
goto abort_line;
|
goto abort_line;
|
||||||
}
|
}
|
||||||
|
@@ -139,17 +139,23 @@ sub do_line
|
|||||||
# ?screen_row assertion is emulated here
|
# ?screen_row assertion is emulated here
|
||||||
elsif( $line =~ s/^\?screen_row\s+(\d+)\s*=\s*// ) {
|
elsif( $line =~ s/^\?screen_row\s+(\d+)\s*=\s*// ) {
|
||||||
my $row = $1;
|
my $row = $1;
|
||||||
my $row1 = $row + 1;
|
my $want;
|
||||||
my $want = eval($line);
|
|
||||||
|
if( $line =~ m/^"/ ) {
|
||||||
|
$want = eval($line);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Turn 0xDD,0xDD,... directly into bytes
|
||||||
|
$want = pack "C*", map { hex } split m/,/, $line;
|
||||||
|
}
|
||||||
|
|
||||||
do_onetest if defined $command;
|
do_onetest if defined $command;
|
||||||
|
|
||||||
# TODO: may not be 80
|
$hin->print( "\?screen_chars $row\n" );
|
||||||
$hin->print( "\?screen_chars $row,0,$row1,80\n" );
|
|
||||||
my $response = <$hout>;
|
my $response = <$hout>;
|
||||||
chomp $response;
|
chomp $response;
|
||||||
|
|
||||||
$response = pack "C*", map hex, split m/,/, $response;
|
$response = pack "C*", map { hex } split m/,/, $response;
|
||||||
if( $response ne $want ) {
|
if( $response ne $want ) {
|
||||||
print "# line $linenum: Assert ?screen_row $row failed:\n" .
|
print "# line $linenum: Assert ?screen_row $row failed:\n" .
|
||||||
"# Expected: $want\n" .
|
"# Expected: $want\n" .
|
||||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
772,
|
||||||
/**/
|
/**/
|
||||||
771,
|
771,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user