forked from aniani/vim
patch 8.2.0813: libvterm code is slightly different from upstream
Problem: libvterm code is slightly different from upstream. Solution: Use upstream text to avoid future merge problems. Mainly comment style changes.
This commit is contained in:
@@ -35,9 +35,7 @@ typedef struct {
|
|||||||
int col;
|
int col;
|
||||||
} VTermPos;
|
} VTermPos;
|
||||||
|
|
||||||
/*
|
/* some small utility functions; we can just keep these static here */
|
||||||
* Some small utility functions; we can just keep these static here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Order points by on-screen flow order:
|
* Order points by on-screen flow order:
|
||||||
@@ -62,7 +60,7 @@ typedef struct {
|
|||||||
int end_col;
|
int end_col;
|
||||||
} VTermRect;
|
} VTermRect;
|
||||||
|
|
||||||
// Return true if the rect "r" contains the point "p".
|
/* true if the rect contains the point */
|
||||||
int vterm_rect_contains(VTermRect r, VTermPos p);
|
int vterm_rect_contains(VTermRect r, VTermPos p);
|
||||||
|
|
||||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||||
@@ -73,6 +71,7 @@ INLINE int vterm_rect_contains(VTermRect r, VTermPos p)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* move a rect */
|
||||||
// Move "rect" "row_delta" down and "col_delta" right.
|
// Move "rect" "row_delta" down and "col_delta" right.
|
||||||
// Does not check boundaries.
|
// Does not check boundaries.
|
||||||
void vterm_rect_move(VTermRect *rect, int row_delta, int col_delta);
|
void vterm_rect_move(VTermRect *rect, int row_delta, int col_delta);
|
||||||
@@ -185,9 +184,8 @@ void vterm_color_indexed(VTermColor *col, uint8_t idx);
|
|||||||
*/
|
*/
|
||||||
int vterm_color_is_equal(const VTermColor *a, const VTermColor *b);
|
int vterm_color_is_equal(const VTermColor *a, const VTermColor *b);
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
// VTERM_VALUETYPE_NONE = 0
|
/* VTERM_VALUETYPE_NONE = 0 */
|
||||||
VTERM_VALUETYPE_BOOL = 1,
|
VTERM_VALUETYPE_BOOL = 1,
|
||||||
VTERM_VALUETYPE_INT,
|
VTERM_VALUETYPE_INT,
|
||||||
VTERM_VALUETYPE_STRING,
|
VTERM_VALUETYPE_STRING,
|
||||||
@@ -211,7 +209,7 @@ typedef union {
|
|||||||
} VTermValue;
|
} VTermValue;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
// VTERM_ATTR_NONE = 0
|
/* VTERM_ATTR_NONE = 0 */
|
||||||
VTERM_ATTR_BOLD = 1, // bool: 1, 22
|
VTERM_ATTR_BOLD = 1, // bool: 1, 22
|
||||||
VTERM_ATTR_UNDERLINE, // number: 4, 21, 24
|
VTERM_ATTR_UNDERLINE, // number: 4, 21, 24
|
||||||
VTERM_ATTR_ITALIC, // bool: 3, 23
|
VTERM_ATTR_ITALIC, // bool: 3, 23
|
||||||
@@ -227,7 +225,7 @@ typedef enum {
|
|||||||
} VTermAttr;
|
} VTermAttr;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
// VTERM_PROP_NONE = 0
|
/* VTERM_PROP_NONE = 0 */
|
||||||
VTERM_PROP_CURSORVISIBLE = 1, // bool
|
VTERM_PROP_CURSORVISIBLE = 1, // bool
|
||||||
VTERM_PROP_CURSORBLINK, // bool
|
VTERM_PROP_CURSORBLINK, // bool
|
||||||
VTERM_PROP_ALTSCREEN, // bool
|
VTERM_PROP_ALTSCREEN, // bool
|
||||||
@@ -261,9 +259,9 @@ enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const uint32_t *chars;
|
const uint32_t *chars;
|
||||||
int width;
|
int width;
|
||||||
unsigned int protected_cell:1; // DECSCA-protected against DECSEL/DECSED
|
unsigned int protected_cell:1; /* DECSCA-protected against DECSEL/DECSED */
|
||||||
unsigned int dwl:1; // DECDWL or DECDHL double-width line
|
unsigned int dwl:1; /* DECDWL or DECDHL double-width line */
|
||||||
unsigned int dhl:2; // DECDHL double-height line (1=top 2=bottom)
|
unsigned int dhl:2; /* DECDHL double-height line (1=top 2=bottom) */
|
||||||
} VTermGlyphInfo;
|
} VTermGlyphInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -272,9 +270,18 @@ typedef struct {
|
|||||||
unsigned int continuation:1; /* Line is a flow continuation of the previous */
|
unsigned int continuation:1; /* Line is a flow continuation of the previous */
|
||||||
} VTermLineInfo;
|
} VTermLineInfo;
|
||||||
|
|
||||||
|
/* Copies of VTermState fields that the 'resize' callback might have reason to
|
||||||
|
* edit. 'resize' callback gets total control of these fields and may
|
||||||
|
* free-and-reallocate them if required. They will be copied back from the
|
||||||
|
* struct after the callback has returned.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// libvterm relies on the allocated memory to be zeroed out before it is
|
VTermPos pos; /* current cursor position */
|
||||||
// returned by the allocator.
|
} VTermStateFields;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* libvterm relies on this memory to be zeroed out before it is returned
|
||||||
|
* by the allocator. */
|
||||||
void *(*malloc)(size_t size, void *allocdata);
|
void *(*malloc)(size_t size, void *allocdata);
|
||||||
void (*free)(void *ptr, void *allocdata);
|
void (*free)(void *ptr, void *allocdata);
|
||||||
} VTermAllocatorFunctions;
|
} VTermAllocatorFunctions;
|
||||||
@@ -329,20 +336,21 @@ void vterm_mouse_button(VTerm *vt, int button, int pressed, VTermModifier mod);
|
|||||||
// Parser layer
|
// Parser layer
|
||||||
// ------------
|
// ------------
|
||||||
|
|
||||||
// Flag to indicate non-final subparameters in a single CSI parameter.
|
/* Flag to indicate non-final subparameters in a single CSI parameter.
|
||||||
// Consider
|
* Consider
|
||||||
// CSI 1;2:3:4;5a
|
* CSI 1;2:3:4;5a
|
||||||
// 1 4 and 5 are final.
|
* 1 4 and 5 are final.
|
||||||
// 2 and 3 are non-final and will have this bit set
|
* 2 and 3 are non-final and will have this bit set
|
||||||
//
|
*
|
||||||
// Don't confuse this with the final byte of the CSI escape; 'a' in this case.
|
* Don't confuse this with the final byte of the CSI escape; 'a' in this case.
|
||||||
|
*/
|
||||||
#define CSI_ARG_FLAG_MORE (1U<<31)
|
#define CSI_ARG_FLAG_MORE (1U<<31)
|
||||||
#define CSI_ARG_MASK (~(1U<<31))
|
#define CSI_ARG_MASK (~(1U<<31))
|
||||||
|
|
||||||
#define CSI_ARG_HAS_MORE(a) ((a) & CSI_ARG_FLAG_MORE)
|
#define CSI_ARG_HAS_MORE(a) ((a) & CSI_ARG_FLAG_MORE)
|
||||||
#define CSI_ARG(a) ((a) & CSI_ARG_MASK)
|
#define CSI_ARG(a) ((a) & CSI_ARG_MASK)
|
||||||
|
|
||||||
// Can't use -1 to indicate a missing argument; use this instead
|
/* Can't use -1 to indicate a missing argument; use this instead */
|
||||||
#define CSI_ARG_MISSING ((1<<30)-1)
|
#define CSI_ARG_MISSING ((1<<30)-1)
|
||||||
|
|
||||||
#define CSI_ARG_IS_MISSING(a) (CSI_ARG(a) == CSI_ARG_MISSING)
|
#define CSI_ARG_IS_MISSING(a) (CSI_ARG(a) == CSI_ARG_MISSING)
|
||||||
@@ -366,15 +374,6 @@ void *vterm_parser_get_cbdata(VTerm *vt);
|
|||||||
// State layer
|
// State layer
|
||||||
// -----------
|
// -----------
|
||||||
|
|
||||||
/* Copies of VTermState fields that the 'resize' callback might have reason to
|
|
||||||
* edit. 'resize' callback gets total control of these fields and may
|
|
||||||
* free-and-reallocate them if required. They will be copied back from the
|
|
||||||
* struct after the callback has returned.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
VTermPos pos; /* current cursor position */
|
|
||||||
} VTermStateFields;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int (*putglyph)(VTermGlyphInfo *info, VTermPos pos, void *user);
|
int (*putglyph)(VTermGlyphInfo *info, VTermPos pos, void *user);
|
||||||
int (*movecursor)(VTermPos pos, VTermPos oldpos, int visible, void *user);
|
int (*movecursor)(VTermPos pos, VTermPos oldpos, int visible, void *user);
|
||||||
@@ -459,9 +458,9 @@ typedef struct {
|
|||||||
unsigned int reverse : 1;
|
unsigned int reverse : 1;
|
||||||
unsigned int conceal : 1;
|
unsigned int conceal : 1;
|
||||||
unsigned int strike : 1;
|
unsigned int strike : 1;
|
||||||
unsigned int font : 4; // 0 to 9
|
unsigned int font : 4; /* 0 to 9 */
|
||||||
unsigned int dwl : 1; // On a DECDWL or DECDHL line
|
unsigned int dwl : 1; /* On a DECDWL or DECDHL line */
|
||||||
unsigned int dhl : 2; // On a DECDHL line (1=top 2=bottom)
|
unsigned int dhl : 2; /* On a DECDHL line (1=top 2=bottom) */
|
||||||
} VTermScreenCellAttrs;
|
} VTermScreenCellAttrs;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -513,10 +512,10 @@ void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen);
|
|||||||
void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen);
|
void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VTERM_DAMAGE_CELL, // every cell
|
VTERM_DAMAGE_CELL, /* every cell */
|
||||||
VTERM_DAMAGE_ROW, // entire rows
|
VTERM_DAMAGE_ROW, /* entire rows */
|
||||||
VTERM_DAMAGE_SCREEN, // entire screen
|
VTERM_DAMAGE_SCREEN, /* entire screen */
|
||||||
VTERM_DAMAGE_SCROLL, // entire screen + scrollrect
|
VTERM_DAMAGE_SCROLL, /* entire screen + scrollrect */
|
||||||
|
|
||||||
VTERM_N_DAMAGES
|
VTERM_N_DAMAGES
|
||||||
} VTermDamageSize;
|
} VTermDamageSize;
|
||||||
@@ -532,7 +531,7 @@ void vterm_screen_set_damage_merge(VTermScreen *screen, VTermDamageSize size);
|
|||||||
*/
|
*/
|
||||||
void vterm_screen_reset(VTermScreen *screen, int hard);
|
void vterm_screen_reset(VTermScreen *screen, int hard);
|
||||||
|
|
||||||
// Neither of these functions NUL-terminate the buffer
|
/* Neither of these functions NUL-terminate the buffer */
|
||||||
size_t vterm_screen_get_chars(const VTermScreen *screen, uint32_t *chars, size_t len, const VTermRect rect);
|
size_t vterm_screen_get_chars(const VTermScreen *screen, uint32_t *chars, size_t len, const VTermRect rect);
|
||||||
size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, const VTermRect rect);
|
size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, const VTermRect rect);
|
||||||
|
|
||||||
|
@@ -223,7 +223,7 @@ encodings[] = {
|
|||||||
{ 0, 0, NULL },
|
{ 0, 0, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
// This ought to be INTERNAL but isn't because it's used by unit testing
|
/* This ought to be INTERNAL but isn't because it's used by unit testing */
|
||||||
VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation)
|
VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@@ -19,8 +19,9 @@ void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The shift modifier is never important for Unicode characters
|
/* The shift modifier is never important for Unicode characters
|
||||||
// apart from Space
|
* apart from Space
|
||||||
|
*/
|
||||||
if(c != ' ')
|
if(c != ' ')
|
||||||
mod &= ~VTERM_MOD_SHIFT;
|
mod &= ~VTERM_MOD_SHIFT;
|
||||||
|
|
||||||
@@ -33,24 +34,24 @@ void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch(c) {
|
switch(c) {
|
||||||
// Special Ctrl- letters that can't be represented elsewise
|
/* Special Ctrl- letters that can't be represented elsewise */
|
||||||
case 'i': case 'j': case 'm': case '[':
|
case 'i': case 'j': case 'm': case '[':
|
||||||
needs_CSIu = 1;
|
needs_CSIu = 1;
|
||||||
break;
|
break;
|
||||||
// Ctrl-\ ] ^ _ don't need CSUu
|
/* Ctrl-\ ] ^ _ don't need CSUu */
|
||||||
case '\\': case ']': case '^': case '_':
|
case '\\': case ']': case '^': case '_':
|
||||||
needs_CSIu = 0;
|
needs_CSIu = 0;
|
||||||
break;
|
break;
|
||||||
// Shift-space needs CSIu
|
/* Shift-space needs CSIu */
|
||||||
case ' ':
|
case ' ':
|
||||||
needs_CSIu = !!(mod & VTERM_MOD_SHIFT);
|
needs_CSIu = !!(mod & VTERM_MOD_SHIFT);
|
||||||
break;
|
break;
|
||||||
// All other characters needs CSIu except for letters a-z
|
/* All other characters needs CSIu except for letters a-z */
|
||||||
default:
|
default:
|
||||||
needs_CSIu = (c < 'a' || c > 'z');
|
needs_CSIu = (c < 'a' || c > 'z');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ALT we can just prefix with ESC; anything else requires CSI u
|
/* ALT we can just prefix with ESC; anything else requires CSI u */
|
||||||
if(needs_CSIu && (mod & ~VTERM_MOD_ALT)) {
|
if(needs_CSIu && (mod & ~VTERM_MOD_ALT)) {
|
||||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", c, mod+1);
|
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", c, mod+1);
|
||||||
return;
|
return;
|
||||||
@@ -165,7 +166,7 @@ void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case KEYCODE_TAB:
|
case KEYCODE_TAB:
|
||||||
// Shift-Tab is CSI Z but plain Tab is 0x09
|
/* Shift-Tab is CSI Z but plain Tab is 0x09 */
|
||||||
if(mod == VTERM_MOD_SHIFT)
|
if(mod == VTERM_MOD_SHIFT)
|
||||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "Z");
|
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "Z");
|
||||||
else if(mod & VTERM_MOD_SHIFT)
|
else if(mod & VTERM_MOD_SHIFT)
|
||||||
@@ -175,7 +176,7 @@ void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case KEYCODE_ENTER:
|
case KEYCODE_ENTER:
|
||||||
// Enter is CRLF in newline mode, but just LF in linefeed
|
/* Enter is CRLF in newline mode, but just LF in linefeed */
|
||||||
if(vt->state->mode.newline)
|
if(vt->state->mode.newline)
|
||||||
vterm_push_output_sprintf(vt, "\r\n");
|
vterm_push_output_sprintf(vt, "\r\n");
|
||||||
else
|
else
|
||||||
|
@@ -83,7 +83,7 @@ void vterm_mouse_button(VTerm *vt, int button, int pressed, VTermModifier mod)
|
|||||||
state->mouse_buttons &= ~(1 << (button-1));
|
state->mouse_buttons &= ~(1 << (button-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most of the time we don't get button releases from 4/5
|
/* Most of the time we don't get button releases from 4/5 */
|
||||||
if(state->mouse_buttons == old_buttons && button < 4)
|
if(state->mouse_buttons == old_buttons && button < 4)
|
||||||
return;
|
return;
|
||||||
if (!(state->mouse_flags & MOUSE_WANT_CLICK))
|
if (!(state->mouse_flags & MOUSE_WANT_CLICK))
|
||||||
|
@@ -187,23 +187,23 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
|
|||||||
|
|
||||||
switch(vt->parser.state) {
|
switch(vt->parser.state) {
|
||||||
case CSI_LEADER:
|
case CSI_LEADER:
|
||||||
// Extract leader bytes 0x3c to 0x3f
|
/* Extract leader bytes 0x3c to 0x3f */
|
||||||
if(c >= 0x3c && c <= 0x3f) {
|
if(c >= 0x3c && c <= 0x3f) {
|
||||||
if(vt->parser.v.csi.leaderlen < CSI_LEADER_MAX-1)
|
if(vt->parser.v.csi.leaderlen < CSI_LEADER_MAX-1)
|
||||||
vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen++] = c;
|
vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen++] = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// else fallthrough
|
/* else fallthrough */
|
||||||
vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen] = 0;
|
vt->parser.v.csi.leader[vt->parser.v.csi.leaderlen] = 0;
|
||||||
|
|
||||||
vt->parser.v.csi.argi = 0;
|
vt->parser.v.csi.argi = 0;
|
||||||
vt->parser.v.csi.args[0] = CSI_ARG_MISSING;
|
vt->parser.v.csi.args[0] = CSI_ARG_MISSING;
|
||||||
vt->parser.state = CSI_ARGS;
|
vt->parser.state = CSI_ARGS;
|
||||||
|
|
||||||
// fallthrough
|
/* fallthrough */
|
||||||
case CSI_ARGS:
|
case CSI_ARGS:
|
||||||
// Numerical value of argument
|
/* Numerical value of argument */
|
||||||
if(c >= '0' && c <= '9') {
|
if(c >= '0' && c <= '9') {
|
||||||
if(vt->parser.v.csi.args[vt->parser.v.csi.argi] == CSI_ARG_MISSING)
|
if(vt->parser.v.csi.args[vt->parser.v.csi.argi] == CSI_ARG_MISSING)
|
||||||
vt->parser.v.csi.args[vt->parser.v.csi.argi] = 0;
|
vt->parser.v.csi.args[vt->parser.v.csi.argi] = 0;
|
||||||
@@ -221,7 +221,7 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// else fallthrough
|
/* else fallthrough */
|
||||||
vt->parser.v.csi.argi++;
|
vt->parser.v.csi.argi++;
|
||||||
vt->parser.intermedlen = 0;
|
vt->parser.intermedlen = 0;
|
||||||
vt->parser.state = CSI_INTERMED;
|
vt->parser.state = CSI_INTERMED;
|
||||||
@@ -233,13 +233,13 @@ size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(c == 0x1b) {
|
else if(c == 0x1b) {
|
||||||
// ESC in CSI cancels
|
/* ESC in CSI cancels */
|
||||||
}
|
}
|
||||||
else if(c >= 0x40 && c <= 0x7e) {
|
else if(c >= 0x40 && c <= 0x7e) {
|
||||||
vt->parser.intermed[vt->parser.intermedlen] = 0;
|
vt->parser.intermed[vt->parser.intermedlen] = 0;
|
||||||
do_csi(vt, c);
|
do_csi(vt, c);
|
||||||
}
|
}
|
||||||
// else was invalid CSI
|
/* else was invalid CSI */
|
||||||
|
|
||||||
ENTER_NORMAL_STATE();
|
ENTER_NORMAL_STATE();
|
||||||
break;
|
break;
|
||||||
@@ -330,7 +330,7 @@ string_state:
|
|||||||
|
|
||||||
if(!eaten) {
|
if(!eaten) {
|
||||||
DEBUG_LOG("libvterm: Text callback did not consume any input\n");
|
DEBUG_LOG("libvterm: Text callback did not consume any input\n");
|
||||||
// force it to make progress
|
/* force it to make progress */
|
||||||
eaten = 1;
|
eaten = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@ typedef struct {
|
|||||||
} VTermRGB;
|
} VTermRGB;
|
||||||
|
|
||||||
static const VTermRGB ansi_colors[] = {
|
static const VTermRGB ansi_colors[] = {
|
||||||
// R G B
|
/* R G B */
|
||||||
{ 0, 0, 0 }, // black
|
{ 0, 0, 0 }, // black
|
||||||
{ 224, 0, 0 }, // red
|
{ 224, 0, 0 }, // red
|
||||||
{ 0, 224, 0 }, // green
|
{ 0, 224, 0 }, // green
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#define STRFrect "(%d,%d-%d,%d)"
|
#define STRFrect "(%d,%d-%d,%d)"
|
||||||
#define ARGSrect(r) (r).start_row, (r).start_col, (r).end_row, (r).end_col
|
#define ARGSrect(r) (r).start_row, (r).start_col, (r).end_row, (r).end_col
|
||||||
|
|
||||||
// Expand dst to contain src as well
|
/* Expand dst to contain src as well */
|
||||||
static void rect_expand(VTermRect *dst, VTermRect *src)
|
static void rect_expand(VTermRect *dst, VTermRect *src)
|
||||||
{
|
{
|
||||||
if(dst->start_row > src->start_row) dst->start_row = src->start_row;
|
if(dst->start_row > src->start_row) dst->start_row = src->start_row;
|
||||||
@@ -14,19 +14,19 @@ static void rect_expand(VTermRect *dst, VTermRect *src)
|
|||||||
if(dst->end_col < src->end_col) dst->end_col = src->end_col;
|
if(dst->end_col < src->end_col) dst->end_col = src->end_col;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clip the dst to ensure it does not step outside of bounds
|
/* Clip the dst to ensure it does not step outside of bounds */
|
||||||
static void rect_clip(VTermRect *dst, VTermRect *bounds)
|
static void rect_clip(VTermRect *dst, VTermRect *bounds)
|
||||||
{
|
{
|
||||||
if(dst->start_row < bounds->start_row) dst->start_row = bounds->start_row;
|
if(dst->start_row < bounds->start_row) dst->start_row = bounds->start_row;
|
||||||
if(dst->start_col < bounds->start_col) dst->start_col = bounds->start_col;
|
if(dst->start_col < bounds->start_col) dst->start_col = bounds->start_col;
|
||||||
if(dst->end_row > bounds->end_row) dst->end_row = bounds->end_row;
|
if(dst->end_row > bounds->end_row) dst->end_row = bounds->end_row;
|
||||||
if(dst->end_col > bounds->end_col) dst->end_col = bounds->end_col;
|
if(dst->end_col > bounds->end_col) dst->end_col = bounds->end_col;
|
||||||
// Ensure it doesn't end up negatively-sized
|
/* Ensure it doesn't end up negatively-sized */
|
||||||
if(dst->end_row < dst->start_row) dst->end_row = dst->start_row;
|
if(dst->end_row < dst->start_row) dst->end_row = dst->start_row;
|
||||||
if(dst->end_col < dst->start_col) dst->end_col = dst->start_col;
|
if(dst->end_col < dst->start_col) dst->end_col = dst->start_col;
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if the two rectangles are equal
|
/* True if the two rectangles are equal */
|
||||||
static int rect_equal(VTermRect *a, VTermRect *b)
|
static int rect_equal(VTermRect *a, VTermRect *b)
|
||||||
{
|
{
|
||||||
return (a->start_row == b->start_row) &&
|
return (a->start_row == b->start_row) &&
|
||||||
@@ -35,7 +35,7 @@ static int rect_equal(VTermRect *a, VTermRect *b)
|
|||||||
(a->end_col == b->end_col);
|
(a->end_col == b->end_col);
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if small is contained entirely within big
|
/* True if small is contained entirely within big */
|
||||||
static int rect_contains(VTermRect *big, VTermRect *small)
|
static int rect_contains(VTermRect *big, VTermRect *small)
|
||||||
{
|
{
|
||||||
if(small->start_row < big->start_row) return 0;
|
if(small->start_row < big->start_row) return 0;
|
||||||
@@ -45,7 +45,7 @@ static int rect_contains(VTermRect *big, VTermRect *small)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if the rectangles overlap at all
|
/* True if the rectangles overlap at all */
|
||||||
static int rect_intersects(VTermRect *a, VTermRect *b)
|
static int rect_intersects(VTermRect *a, VTermRect *b)
|
||||||
{
|
{
|
||||||
if(a->start_row > b->end_row || b->start_row > a->end_row)
|
if(a->start_row > b->end_row || b->start_row > a->end_row)
|
||||||
|
@@ -10,10 +10,10 @@
|
|||||||
#define UNICODE_SPACE 0x20
|
#define UNICODE_SPACE 0x20
|
||||||
#define UNICODE_LINEFEED 0x0a
|
#define UNICODE_LINEFEED 0x0a
|
||||||
|
|
||||||
// State of the pen at some moment in time, also used in a cell
|
/* State of the pen at some moment in time, also used in a cell */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// After the bitfield
|
/* After the bitfield */
|
||||||
VTermColor fg, bg;
|
VTermColor fg, bg;
|
||||||
|
|
||||||
unsigned int bold : 1;
|
unsigned int bold : 1;
|
||||||
@@ -23,15 +23,15 @@ typedef struct
|
|||||||
unsigned int reverse : 1;
|
unsigned int reverse : 1;
|
||||||
unsigned int conceal : 1;
|
unsigned int conceal : 1;
|
||||||
unsigned int strike : 1;
|
unsigned int strike : 1;
|
||||||
unsigned int font : 4; // 0 to 9
|
unsigned int font : 4; /* 0 to 9 */
|
||||||
|
|
||||||
// Extra state storage that isn't strictly pen-related
|
/* Extra state storage that isn't strictly pen-related */
|
||||||
unsigned int protected_cell : 1;
|
unsigned int protected_cell : 1;
|
||||||
unsigned int dwl : 1; // on a DECDWL or DECDHL line
|
unsigned int dwl : 1; /* on a DECDWL or DECDHL line */
|
||||||
unsigned int dhl : 2; // on a DECDHL line (1=top 2=bottom)
|
unsigned int dhl : 2; /* on a DECDHL line (1=top 2=bottom) */
|
||||||
} ScreenPen;
|
} ScreenPen;
|
||||||
|
|
||||||
// Internal representation of a screen cell
|
/* Internal representation of a screen cell */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
|
uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
|
||||||
@@ -47,7 +47,7 @@ struct VTermScreen
|
|||||||
void *cbdata;
|
void *cbdata;
|
||||||
|
|
||||||
VTermDamageSize damage_merge;
|
VTermDamageSize damage_merge;
|
||||||
// start_row == -1 => no damage
|
/* start_row == -1 => no damage */
|
||||||
VTermRect damaged;
|
VTermRect damaged;
|
||||||
VTermRect pending_scrollrect;
|
VTermRect pending_scrollrect;
|
||||||
int pending_scroll_downward, pending_scroll_rightward;
|
int pending_scroll_downward, pending_scroll_rightward;
|
||||||
@@ -56,13 +56,13 @@ struct VTermScreen
|
|||||||
int cols;
|
int cols;
|
||||||
int global_reverse;
|
int global_reverse;
|
||||||
|
|
||||||
// Primary and Altscreen. buffers[1] is lazily allocated as needed
|
/* Primary and Altscreen. buffers[1] is lazily allocated as needed */
|
||||||
ScreenCell *buffers[2];
|
ScreenCell *buffers[2];
|
||||||
|
|
||||||
// buffer will == buffers[0] or buffers[1], depending on altscreen
|
/* buffer will == buffers[0] or buffers[1], depending on altscreen */
|
||||||
ScreenCell *buffer;
|
ScreenCell *buffer;
|
||||||
|
|
||||||
// buffer for a single screen row used in scrollback storage callbacks
|
/* buffer for a single screen row used in scrollback storage callbacks */
|
||||||
VTermScreenCell *sb_buffer;
|
VTermScreenCell *sb_buffer;
|
||||||
|
|
||||||
ScreenPen pen;
|
ScreenPen pen;
|
||||||
@@ -106,13 +106,13 @@ static void damagerect(VTermScreen *screen, VTermRect rect)
|
|||||||
|
|
||||||
switch(screen->damage_merge) {
|
switch(screen->damage_merge) {
|
||||||
case VTERM_DAMAGE_CELL:
|
case VTERM_DAMAGE_CELL:
|
||||||
// Always emit damage event
|
/* Always emit damage event */
|
||||||
emit = rect;
|
emit = rect;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VTERM_DAMAGE_ROW:
|
case VTERM_DAMAGE_ROW:
|
||||||
// Emit damage longer than one row. Try to merge with existing damage in
|
/* Emit damage longer than one row. Try to merge with existing damage in
|
||||||
// the same row
|
* the same row */
|
||||||
if(rect.end_row > rect.start_row + 1) {
|
if(rect.end_row > rect.start_row + 1) {
|
||||||
// Bigger than 1 line - flush existing, emit this
|
// Bigger than 1 line - flush existing, emit this
|
||||||
vterm_screen_flush_damage(screen);
|
vterm_screen_flush_damage(screen);
|
||||||
@@ -140,7 +140,7 @@ static void damagerect(VTermScreen *screen, VTermRect rect)
|
|||||||
|
|
||||||
case VTERM_DAMAGE_SCREEN:
|
case VTERM_DAMAGE_SCREEN:
|
||||||
case VTERM_DAMAGE_SCROLL:
|
case VTERM_DAMAGE_SCROLL:
|
||||||
// Never emit damage event
|
/* Never emit damage event */
|
||||||
if(screen->damaged.start_row == -1)
|
if(screen->damaged.start_row == -1)
|
||||||
screen->damaged = rect;
|
screen->damaged = rect;
|
||||||
else {
|
else {
|
||||||
@@ -355,14 +355,15 @@ static int scrollrect(VTermRect rect, int downward, int rightward, void *user)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if(rect_contains(&rect, &screen->damaged)) {
|
if(rect_contains(&rect, &screen->damaged)) {
|
||||||
// Scroll region entirely contains the damage; just move it
|
/* Scroll region entirely contains the damage; just move it */
|
||||||
vterm_rect_move(&screen->damaged, -downward, -rightward);
|
vterm_rect_move(&screen->damaged, -downward, -rightward);
|
||||||
rect_clip(&screen->damaged, &rect);
|
rect_clip(&screen->damaged, &rect);
|
||||||
}
|
}
|
||||||
// There are a number of possible cases here, but lets restrict this to only
|
/* There are a number of possible cases here, but lets restrict this to only
|
||||||
// the common case where we might actually gain some performance by
|
* the common case where we might actually gain some performance by
|
||||||
// optimising it. Namely, a vertical scroll that neatly cuts the damage
|
* optimising it. Namely, a vertical scroll that neatly cuts the damage
|
||||||
// region in half.
|
* region in half.
|
||||||
|
*/
|
||||||
else if(rect.start_col <= screen->damaged.start_col &&
|
else if(rect.start_col <= screen->damaged.start_col &&
|
||||||
rect.end_col >= screen->damaged.end_col &&
|
rect.end_col >= screen->damaged.end_col &&
|
||||||
rightward == 0) {
|
rightward == 0) {
|
||||||
@@ -454,8 +455,9 @@ static int settermprop(VTermProp prop, VTermValue *val, void *user)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
screen->buffer = val->boolean ? screen->buffers[BUFIDX_ALTSCREEN] : screen->buffers[BUFIDX_PRIMARY];
|
screen->buffer = val->boolean ? screen->buffers[BUFIDX_ALTSCREEN] : screen->buffers[BUFIDX_PRIMARY];
|
||||||
// only send a damage event on disable; because during enable there's an
|
/* only send a damage event on disable; because during enable there's an
|
||||||
// erase that sends a damage anyway
|
* erase that sends a damage anyway
|
||||||
|
*/
|
||||||
if(!val->boolean)
|
if(!val->boolean)
|
||||||
damagescreen(screen);
|
damagescreen(screen);
|
||||||
break;
|
break;
|
||||||
@@ -464,7 +466,7 @@ static int settermprop(VTermProp prop, VTermValue *val, void *user)
|
|||||||
damagescreen(screen);
|
damagescreen(screen);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
; // ignore
|
; /* ignore */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(screen->callbacks && screen->callbacks->settermprop)
|
if(screen->callbacks && screen->callbacks->settermprop)
|
||||||
@@ -491,7 +493,7 @@ static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new
|
|||||||
ScreenCell *old_buffer = screen->buffers[bufidx];
|
ScreenCell *old_buffer = screen->buffers[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);
|
||||||
|
|
||||||
/* 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;
|
||||||
int new_row = new_rows - 1;
|
int new_row = new_rows - 1;
|
||||||
int col;
|
int col;
|
||||||
@@ -573,11 +575,9 @@ static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int new
|
|||||||
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));
|
||||||
|
|
||||||
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]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
vterm_allocator_free(screen->vt, old_buffer);
|
vterm_allocator_free(screen->vt, old_buffer);
|
||||||
screen->buffers[bufidx] = new_buffer;
|
screen->buffers[bufidx] = new_buffer;
|
||||||
@@ -729,6 +729,7 @@ INTERNAL void vterm_screen_free(VTermScreen *screen)
|
|||||||
vterm_allocator_free(screen->vt, screen->buffers[BUFIDX_ALTSCREEN]);
|
vterm_allocator_free(screen->vt, screen->buffers[BUFIDX_ALTSCREEN]);
|
||||||
|
|
||||||
vterm_allocator_free(screen->vt, screen->sb_buffer);
|
vterm_allocator_free(screen->vt, screen->sb_buffer);
|
||||||
|
|
||||||
vterm_allocator_free(screen->vt, screen);
|
vterm_allocator_free(screen->vt, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,7 +803,7 @@ size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, c
|
|||||||
return _get_chars(screen, 1, str, len, rect);
|
return _get_chars(screen, 1, str, len, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy internal to external representation of a screen cell
|
/* Copy internal to external representation of a screen cell */
|
||||||
int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCell *cell)
|
int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCell *cell)
|
||||||
{
|
{
|
||||||
ScreenCell *intcell = getcell(screen, pos.row, pos.col);
|
ScreenCell *intcell = getcell(screen, pos.row, pos.col);
|
||||||
@@ -860,7 +861,7 @@ int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCe
|
|||||||
|
|
||||||
int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos)
|
int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos)
|
||||||
{
|
{
|
||||||
// This cell is EOL if this and every cell to the right is black
|
/* This cell is EOL if this and every cell to the right is black */
|
||||||
for(; pos.col < screen->cols; pos.col++) {
|
for(; pos.col < screen->cols; pos.col++) {
|
||||||
ScreenCell *cell = getcell(screen, pos.row, pos.col);
|
ScreenCell *cell = getcell(screen, pos.row, pos.col);
|
||||||
if(cell->chars[0] != 0)
|
if(cell->chars[0] != 0)
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
static int on_resize(int rows, int cols, void *user);
|
static int on_resize(int rows, int cols, void *user);
|
||||||
|
|
||||||
// Some convenient wrappers to make callback functions easier
|
/* Some convenient wrappers to make callback functions easier */
|
||||||
|
|
||||||
static void putglyph(VTermState *state, const uint32_t chars[], int width, VTermPos pos)
|
static void putglyph(VTermState *state, const uint32_t chars[], int width, VTermPos pos)
|
||||||
{
|
{
|
||||||
@@ -299,8 +299,9 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
codepoints, &npoints, state->gsingle_set ? 1 : (int)len,
|
codepoints, &npoints, state->gsingle_set ? 1 : (int)len,
|
||||||
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
|
||||||
// for even a single codepoint
|
* for even a single codepoint
|
||||||
|
*/
|
||||||
if(!npoints)
|
if(!npoints)
|
||||||
{
|
{
|
||||||
vterm_allocator_free(state->vt, codepoints);
|
vterm_allocator_free(state->vt, codepoints);
|
||||||
@@ -310,10 +311,10 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
if(state->gsingle_set && npoints)
|
if(state->gsingle_set && npoints)
|
||||||
state->gsingle_set = 0;
|
state->gsingle_set = 0;
|
||||||
|
|
||||||
// This is a combining char. that needs to be merged with the previous
|
/* This is a combining char. that needs to be merged with the previous
|
||||||
// glyph output
|
* glyph output */
|
||||||
if(vterm_unicode_is_combining(codepoints[i])) {
|
if(vterm_unicode_is_combining(codepoints[i])) {
|
||||||
// See if the cursor has moved since
|
/* See if the cursor has moved since */
|
||||||
if(state->pos.row == state->combine_pos.row && state->pos.col == state->combine_pos.col + state->combine_width) {
|
if(state->pos.row == state->combine_pos.row && state->pos.col == state->combine_pos.col + state->combine_width) {
|
||||||
#ifdef DEBUG_GLYPH_COMBINE
|
#ifdef DEBUG_GLYPH_COMBINE
|
||||||
int printpos;
|
int printpos;
|
||||||
@@ -323,12 +324,12 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
printf("} + {");
|
printf("} + {");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Find where we need to append these combining chars
|
/* Find where we need to append these combining chars */
|
||||||
int saved_i = 0;
|
int saved_i = 0;
|
||||||
while(state->combine_chars[saved_i])
|
while(state->combine_chars[saved_i])
|
||||||
saved_i++;
|
saved_i++;
|
||||||
|
|
||||||
// Add extra ones
|
/* Add extra ones */
|
||||||
while(i < npoints && vterm_unicode_is_combining(codepoints[i])) {
|
while(i < npoints && vterm_unicode_is_combining(codepoints[i])) {
|
||||||
if(saved_i >= (int)state->combine_chars_size)
|
if(saved_i >= (int)state->combine_chars_size)
|
||||||
grow_combine_buffer(state);
|
grow_combine_buffer(state);
|
||||||
@@ -344,7 +345,7 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
printf("}\n");
|
printf("}\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Now render it
|
/* Now render it */
|
||||||
putglyph(state, state->combine_chars, state->combine_width, state->combine_pos);
|
putglyph(state, state->combine_chars, state->combine_width, state->combine_pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -418,8 +419,8 @@ static int on_text(const char bytes[], size_t len, void *user)
|
|||||||
putglyph(state, chars, width, state->pos);
|
putglyph(state, chars, width, state->pos);
|
||||||
|
|
||||||
if(i == npoints - 1) {
|
if(i == npoints - 1) {
|
||||||
// End of the buffer. Save the chars in case we have to combine with
|
/* End of the buffer. Save the chars in case we have to combine with
|
||||||
// more on the next call
|
* more on the next call */
|
||||||
int save_i;
|
int save_i;
|
||||||
for(save_i = 0; chars[save_i]; save_i++) {
|
for(save_i = 0; chars[save_i]; save_i++) {
|
||||||
if(save_i >= (int)state->combine_chars_size)
|
if(save_i >= (int)state->combine_chars_size)
|
||||||
@@ -619,8 +620,9 @@ static int on_escape(const char *bytes, size_t len, void *user)
|
|||||||
{
|
{
|
||||||
VTermState *state = user;
|
VTermState *state = user;
|
||||||
|
|
||||||
// Easier to decode this from the first byte, even though the final
|
/* Easier to decode this from the first byte, even though the final
|
||||||
// byte terminates it
|
* byte terminates it
|
||||||
|
*/
|
||||||
switch(bytes[0]) {
|
switch(bytes[0]) {
|
||||||
case ' ':
|
case ' ':
|
||||||
if(len != 2)
|
if(len != 2)
|
||||||
@@ -1338,7 +1340,7 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
|
|||||||
case 2:
|
case 2:
|
||||||
case 4:
|
case 4:
|
||||||
break;
|
break;
|
||||||
// TODO: 1, 2 and 4 aren't meaningful yet without line tab stops
|
/* TODO: 1, 2 and 4 aren't meaningful yet without line tab stops */
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1773,7 +1775,7 @@ static int on_resize(int rows, int cols, void *user)
|
|||||||
if (newtabstops == NULL)
|
if (newtabstops == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// TODO: This can all be done much more efficiently bytewise
|
/* TODO: This can all be done much more efficiently bytewise */
|
||||||
for(col = 0; col < state->cols && col < cols; col++) {
|
for(col = 0; col < state->cols && col < cols; col++) {
|
||||||
unsigned char mask = 1 << (col & 7);
|
unsigned char mask = 1 << (col & 7);
|
||||||
if(state->tabstops[col >> 3] & mask)
|
if(state->tabstops[col >> 3] & mask)
|
||||||
@@ -2012,8 +2014,8 @@ void *vterm_state_get_unrecognised_fbdata(VTermState *state)
|
|||||||
|
|
||||||
int vterm_state_set_termprop(VTermState *state, VTermProp prop, VTermValue *val)
|
int vterm_state_set_termprop(VTermState *state, VTermProp prop, VTermValue *val)
|
||||||
{
|
{
|
||||||
// Only store the new value of the property if usercode said it was happy.
|
/* Only store the new value of the property if usercode said it was happy.
|
||||||
// This is especially important for altscreen switching
|
* This is especially important for altscreen switching */
|
||||||
if(state->callbacks && state->callbacks->settermprop)
|
if(state->callbacks && state->callbacks->settermprop)
|
||||||
if(!(*state->callbacks->settermprop)(prop, val, state->cbdata))
|
if(!(*state->callbacks->settermprop)(prop, val, state->cbdata))
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
#include "vterm_internal.h"
|
#include "vterm_internal.h"
|
||||||
|
|
||||||
/* ### The following from http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
// ### The following from http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||||
* With modifications:
|
// With modifications:
|
||||||
* made functions static
|
// made functions static
|
||||||
* moved 'combining' table to file scope, so other functions can see it
|
// moved 'combining' table to file scope, so other functions can see it
|
||||||
* ###################################################################
|
// ###################################################################
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is an implementation of wcwidth() and wcswidth() (defined in
|
* This is an implementation of wcwidth() and wcswidth() (defined in
|
||||||
@@ -75,8 +74,8 @@ struct interval {
|
|||||||
|
|
||||||
#if !defined(WCWIDTH_FUNCTION) || !defined(IS_COMBINING_FUNCTION)
|
#if !defined(WCWIDTH_FUNCTION) || !defined(IS_COMBINING_FUNCTION)
|
||||||
|
|
||||||
// sorted list of non-overlapping intervals of non-spacing characters
|
/* sorted list of non-overlapping intervals of non-spacing characters */
|
||||||
// generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c"
|
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
|
||||||
// Replaced by the combining table from Vim.
|
// Replaced by the combining table from Vim.
|
||||||
static const struct interval combining[] = {
|
static const struct interval combining[] = {
|
||||||
{0X0300, 0X036F},
|
{0X0300, 0X036F},
|
||||||
@@ -362,7 +361,7 @@ static const struct interval combining[] = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// auxiliary function for binary search in interval table
|
/* auxiliary function for binary search in interval table */
|
||||||
static int bisearch(uint32_t ucs, const struct interval *table, int max) {
|
static int bisearch(uint32_t ucs, const struct interval *table, int max) {
|
||||||
int min = 0;
|
int min = 0;
|
||||||
int mid;
|
int mid;
|
||||||
@@ -382,6 +381,7 @@ static int bisearch(uint32_t ucs, const struct interval *table, int max) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The following two functions define the column width of an ISO 10646
|
/* The following two functions define the column width of an ISO 10646
|
||||||
* character as follows:
|
* character as follows:
|
||||||
*
|
*
|
||||||
@@ -422,30 +422,30 @@ int WCWIDTH_FUNCTION(uint32_t ucs);
|
|||||||
|
|
||||||
static int mk_wcwidth(uint32_t ucs)
|
static int mk_wcwidth(uint32_t ucs)
|
||||||
{
|
{
|
||||||
// test for 8-bit control characters
|
/* test for 8-bit control characters */
|
||||||
if (ucs == 0)
|
if (ucs == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
|
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// binary search in table of non-spacing characters
|
/* binary search in table of non-spacing characters */
|
||||||
if (bisearch(ucs, combining,
|
if (bisearch(ucs, combining,
|
||||||
sizeof(combining) / sizeof(struct interval) - 1))
|
sizeof(combining) / sizeof(struct interval) - 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// if we arrive here, ucs is not a combining or C0/C1 control character
|
/* if we arrive here, ucs is not a combining or C0/C1 control character */
|
||||||
|
|
||||||
return 1 +
|
return 1 +
|
||||||
(ucs >= 0x1100 &&
|
(ucs >= 0x1100 &&
|
||||||
(ucs <= 0x115f || // Hangul Jamo init. consonants
|
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
|
||||||
ucs == 0x2329 || ucs == 0x232a ||
|
ucs == 0x2329 || ucs == 0x232a ||
|
||||||
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
|
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
|
||||||
ucs != 0x303f) || // CJK ... Yi
|
ucs != 0x303f) || /* CJK ... Yi */
|
||||||
(ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables
|
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
|
||||||
(ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compatibility Ideographs
|
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
|
||||||
(ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms
|
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
|
||||||
(ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compatibility Forms
|
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
|
||||||
(ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms
|
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
|
||||||
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
|
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
|
||||||
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
|
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
|
||||||
(ucs >= 0x30000 && ucs <= 0x3fffd)));
|
(ucs >= 0x30000 && ucs <= 0x3fffd)));
|
||||||
@@ -479,8 +479,8 @@ static int mk_wcswidth(const uint32_t *pwcs, size_t n)
|
|||||||
static int mk_wcwidth_cjk(uint32_t ucs)
|
static int mk_wcwidth_cjk(uint32_t ucs)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
// sorted list of non-overlapping intervals of East Asian Ambiguous
|
/* sorted list of non-overlapping intervals of East Asian Ambiguous
|
||||||
// characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c"
|
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
|
||||||
static const struct interval ambiguous[] = {
|
static const struct interval ambiguous[] = {
|
||||||
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
|
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
|
||||||
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
|
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
|
||||||
@@ -537,7 +537,7 @@ static int mk_wcwidth_cjk(uint32_t ucs)
|
|||||||
};
|
};
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
// binary search in table of non-spacing characters
|
/* binary search in table of non-spacing characters */
|
||||||
if (bisearch(ucs, ambiguous,
|
if (bisearch(ucs, ambiguous,
|
||||||
sizeof(ambiguous) / sizeof(struct interval) - 1))
|
sizeof(ambiguous) / sizeof(struct interval) - 1))
|
||||||
return 2;
|
return 2;
|
||||||
@@ -545,6 +545,7 @@ static int mk_wcwidth_cjk(uint32_t ucs)
|
|||||||
return mk_wcwidth(ucs);
|
return mk_wcwidth(ucs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int mk_wcswidth_cjk(const uint32_t *pwcs, size_t n)
|
static int mk_wcswidth_cjk(const uint32_t *pwcs, size_t n)
|
||||||
{
|
{
|
||||||
int w, width = 0;
|
int w, width = 0;
|
||||||
|
@@ -16,7 +16,7 @@ INLINE unsigned int utf8_seqlen(long codepoint)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Does NOT NUL-terminate the buffer
|
/* Does NOT NUL-terminate the buffer */
|
||||||
int fill_utf8(long codepoint, char *str);
|
int fill_utf8(long codepoint, char *str);
|
||||||
|
|
||||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||||
@@ -44,4 +44,4 @@ INLINE int fill_utf8(long codepoint, char *str)
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// end copy
|
/* end copy */
|
||||||
|
@@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
|
||||||
///////////////////
|
/*****************
|
||||||
// API functions //
|
* API functions *
|
||||||
///////////////////
|
*****************/
|
||||||
|
|
||||||
static void *default_malloc(size_t size, void *allocdata UNUSED)
|
static void *default_malloc(size_t size, void *allocdata UNUSED)
|
||||||
{
|
{
|
||||||
@@ -39,7 +39,7 @@ VTerm *vterm_new(int rows, int cols)
|
|||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
// 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 = (*funcs->malloc)(sizeof(VTerm), allocdata);
|
||||||
|
|
||||||
if (vt == NULL)
|
if (vt == NULL)
|
||||||
@@ -269,7 +269,7 @@ VTermValueType vterm_get_attr_type(VTermAttr attr)
|
|||||||
|
|
||||||
case VTERM_N_ATTRS: return 0;
|
case VTERM_N_ATTRS: return 0;
|
||||||
}
|
}
|
||||||
return 0; // UNREACHABLE
|
return 0; /* UNREACHABLE */
|
||||||
}
|
}
|
||||||
|
|
||||||
VTermValueType vterm_get_prop_type(VTermProp prop)
|
VTermValueType vterm_get_prop_type(VTermProp prop)
|
||||||
@@ -287,7 +287,7 @@ VTermValueType vterm_get_prop_type(VTermProp prop)
|
|||||||
|
|
||||||
case VTERM_N_PROPS: return 0;
|
case VTERM_N_PROPS: return 0;
|
||||||
}
|
}
|
||||||
return 0; // UNREACHABLE
|
return 0; /* UNREACHABLE */
|
||||||
}
|
}
|
||||||
|
|
||||||
void vterm_scroll_rect(VTermRect rect,
|
void vterm_scroll_rect(VTermRect rect,
|
||||||
@@ -302,24 +302,26 @@ void vterm_scroll_rect(VTermRect rect,
|
|||||||
|
|
||||||
if(abs(downward) >= rect.end_row - rect.start_row ||
|
if(abs(downward) >= rect.end_row - rect.start_row ||
|
||||||
abs(rightward) >= rect.end_col - rect.start_col) {
|
abs(rightward) >= rect.end_col - rect.start_col) {
|
||||||
// Scroll more than area; just erase the lot
|
/* Scroll more than area; just erase the lot */
|
||||||
(*eraserect)(rect, 0, user);
|
(*eraserect)(rect, 0, user);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rightward >= 0) {
|
if(rightward >= 0) {
|
||||||
// rect: [XXX................]
|
/* rect: [XXX................]
|
||||||
// src: [----------------]
|
* src: [----------------]
|
||||||
// dest: [----------------]
|
* dest: [----------------]
|
||||||
|
*/
|
||||||
dest.start_col = rect.start_col;
|
dest.start_col = rect.start_col;
|
||||||
dest.end_col = rect.end_col - rightward;
|
dest.end_col = rect.end_col - rightward;
|
||||||
src.start_col = rect.start_col + rightward;
|
src.start_col = rect.start_col + rightward;
|
||||||
src.end_col = rect.end_col;
|
src.end_col = rect.end_col;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// rect: [................XXX]
|
/* rect: [................XXX]
|
||||||
// src: [----------------]
|
* src: [----------------]
|
||||||
// dest: [----------------]
|
* dest: [----------------]
|
||||||
|
*/
|
||||||
int leftward = -rightward;
|
int leftward = -rightward;
|
||||||
dest.start_col = rect.start_col + leftward;
|
dest.start_col = rect.start_col + leftward;
|
||||||
dest.end_col = rect.end_col;
|
dest.end_col = rect.end_col;
|
||||||
@@ -375,8 +377,7 @@ void vterm_copy_cells(VTermRect dest,
|
|||||||
test_row = dest.start_row - 1;
|
test_row = dest.start_row - 1;
|
||||||
inc_row = -1;
|
inc_row = -1;
|
||||||
}
|
}
|
||||||
else {
|
else /* downward >= 0 */ {
|
||||||
// downward >= 0
|
|
||||||
init_row = dest.start_row;
|
init_row = dest.start_row;
|
||||||
test_row = dest.end_row;
|
test_row = dest.end_row;
|
||||||
inc_row = +1;
|
inc_row = +1;
|
||||||
@@ -387,8 +388,7 @@ void vterm_copy_cells(VTermRect dest,
|
|||||||
test_col = dest.start_col - 1;
|
test_col = dest.start_col - 1;
|
||||||
inc_col = -1;
|
inc_col = -1;
|
||||||
}
|
}
|
||||||
else {
|
else /* rightward >= 0 */ {
|
||||||
// rightward >= 0
|
|
||||||
init_col = dest.start_col;
|
init_col = dest.start_col;
|
||||||
test_col = dest.end_col;
|
test_col = dest.end_col;
|
||||||
inc_col = +1;
|
inc_col = +1;
|
||||||
|
@@ -55,7 +55,7 @@ struct VTermPen
|
|||||||
unsigned int reverse:1;
|
unsigned int reverse:1;
|
||||||
unsigned int conceal:1;
|
unsigned int conceal:1;
|
||||||
unsigned int strike:1;
|
unsigned int strike:1;
|
||||||
unsigned int font:4; // To store 0-9
|
unsigned int font:4; /* To store 0-9 */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VTermState
|
struct VTermState
|
||||||
@@ -71,20 +71,20 @@ struct VTermState
|
|||||||
int rows;
|
int rows;
|
||||||
int cols;
|
int cols;
|
||||||
|
|
||||||
// Current cursor position
|
/* Current cursor position */
|
||||||
VTermPos pos;
|
VTermPos pos;
|
||||||
|
|
||||||
int at_phantom; // True if we're on the "81st" phantom column to defer a wraparound
|
int at_phantom; /* True if we're on the "81st" phantom column to defer a wraparound */
|
||||||
|
|
||||||
int scrollregion_top;
|
int scrollregion_top;
|
||||||
int scrollregion_bottom; // -1 means unbounded
|
int scrollregion_bottom; /* -1 means unbounded */
|
||||||
#define SCROLLREGION_BOTTOM(state) ((state)->scrollregion_bottom > -1 ? (state)->scrollregion_bottom : (state)->rows)
|
#define SCROLLREGION_BOTTOM(state) ((state)->scrollregion_bottom > -1 ? (state)->scrollregion_bottom : (state)->rows)
|
||||||
int scrollregion_left;
|
int scrollregion_left;
|
||||||
#define SCROLLREGION_LEFT(state) ((state)->mode.leftrightmargin ? (state)->scrollregion_left : 0)
|
#define SCROLLREGION_LEFT(state) ((state)->mode.leftrightmargin ? (state)->scrollregion_left : 0)
|
||||||
int scrollregion_right; // -1 means unbounded
|
int scrollregion_right; /* -1 means unbounded */
|
||||||
#define SCROLLREGION_RIGHT(state) ((state)->mode.leftrightmargin && (state)->scrollregion_right > -1 ? (state)->scrollregion_right : (state)->cols)
|
#define SCROLLREGION_RIGHT(state) ((state)->mode.leftrightmargin && (state)->scrollregion_right > -1 ? (state)->scrollregion_right : (state)->cols)
|
||||||
|
|
||||||
// Bitvector of tab stops
|
/* Bitvector of tab stops */
|
||||||
unsigned char *tabstops;
|
unsigned char *tabstops;
|
||||||
|
|
||||||
/* Primary and Altscreen; lineinfos[1] is lazily allocated as needed */
|
/* Primary and Altscreen; lineinfos[1] is lazily allocated as needed */
|
||||||
@@ -95,14 +95,14 @@ struct VTermState
|
|||||||
#define ROWWIDTH(state,row) ((state)->lineinfo[(row)].doublewidth ? ((state)->cols / 2) : (state)->cols)
|
#define ROWWIDTH(state,row) ((state)->lineinfo[(row)].doublewidth ? ((state)->cols / 2) : (state)->cols)
|
||||||
#define THISROWWIDTH(state) ROWWIDTH(state, (state)->pos.row)
|
#define THISROWWIDTH(state) ROWWIDTH(state, (state)->pos.row)
|
||||||
|
|
||||||
// Mouse state
|
/* Mouse state */
|
||||||
int mouse_col, mouse_row;
|
int mouse_col, mouse_row;
|
||||||
int mouse_buttons;
|
int mouse_buttons;
|
||||||
int mouse_flags;
|
int mouse_flags;
|
||||||
|
|
||||||
enum { MOUSE_X10, MOUSE_UTF8, MOUSE_SGR, MOUSE_RXVT } mouse_protocol;
|
enum { MOUSE_X10, MOUSE_UTF8, MOUSE_SGR, MOUSE_RXVT } mouse_protocol;
|
||||||
|
|
||||||
// Last glyph output, for Unicode recombining purposes
|
/* Last glyph output, for Unicode recombining purposes */
|
||||||
uint32_t *combine_chars;
|
uint32_t *combine_chars;
|
||||||
size_t combine_chars_size; // Number of ELEMENTS in the above
|
size_t combine_chars_size; // Number of ELEMENTS in the above
|
||||||
int combine_width; // The width of the glyph above
|
int combine_width; // The width of the glyph above
|
||||||
@@ -139,7 +139,7 @@ struct VTermState
|
|||||||
|
|
||||||
unsigned int protected_cell : 1;
|
unsigned int protected_cell : 1;
|
||||||
|
|
||||||
// Saved state under DEC mode 1048/1049
|
/* Saved state under DEC mode 1048/1049 */
|
||||||
struct {
|
struct {
|
||||||
VTermPos pos;
|
VTermPos pos;
|
||||||
struct VTermPen pen;
|
struct VTermPen pen;
|
||||||
@@ -211,7 +211,7 @@ struct VTerm
|
|||||||
int string_initial;
|
int string_initial;
|
||||||
} parser;
|
} parser;
|
||||||
|
|
||||||
// len == malloc()ed size; cur == number of valid bytes
|
/* len == malloc()ed size; cur == number of valid bytes */
|
||||||
|
|
||||||
VTermOutputCallback *outfunc;
|
VTermOutputCallback *outfunc;
|
||||||
void *outdata;
|
void *outdata;
|
||||||
|
@@ -746,6 +746,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 */
|
||||||
|
/**/
|
||||||
|
813,
|
||||||
/**/
|
/**/
|
||||||
812,
|
812,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user