Use a null to represent a blank rather than a space
This has performance benefits when clearing (can use a single memset). Also allows detecting trailing whitespace on lines correctly.
This commit is contained in:
parent
382daacb73
commit
bc97cfa024
@ -38,7 +38,7 @@ typedef uint16_t sprite_index;
|
|||||||
#define SGR_PROTOCOL 2
|
#define SGR_PROTOCOL 2
|
||||||
#define URXVT_PROTOCOL 3
|
#define URXVT_PROTOCOL 3
|
||||||
|
|
||||||
#define BLANK_CHAR 32
|
#define BLANK_CHAR 0
|
||||||
#define CHAR_MASK 0xFFFFFF
|
#define CHAR_MASK 0xFFFFFF
|
||||||
#define ATTRS_SHIFT 24
|
#define ATTRS_SHIFT 24
|
||||||
#define ATTRS_MASK_WITHOUT_WIDTH 0xFC000000
|
#define ATTRS_MASK_WITHOUT_WIDTH 0xFC000000
|
||||||
|
|||||||
@ -19,12 +19,13 @@ clear_chars_to(LineBuf* linebuf, index_type y, char_type ch) {
|
|||||||
clear_chars_in_line(lineptr(linebuf, y), linebuf->xnum, ch);
|
clear_chars_in_line(lineptr(linebuf, y), linebuf->xnum, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void linebuf_clear(LineBuf *self, char_type ch) {
|
void
|
||||||
|
linebuf_clear(LineBuf *self, char_type ch) {
|
||||||
memset(self->buf, 0, self->xnum * self->ynum * sizeof(Cell));
|
memset(self->buf, 0, self->xnum * self->ynum * sizeof(Cell));
|
||||||
memset(self->continued_map, 0, self->ynum * sizeof(bool));
|
memset(self->continued_map, 0, self->ynum * sizeof(bool));
|
||||||
for (index_type i = 0; i < self->ynum; i++) {
|
for (index_type i = 0; i < self->ynum; i++) self->line_map[i] = i;
|
||||||
clear_chars_to(self, i, ch);
|
if (ch != 0) {
|
||||||
self->line_map[i] = i;
|
for (index_type i = 0; i < self->ynum; i++) clear_chars_to(self, i, ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
|||||||
self->line->xnum = xnum;
|
self->line->xnum = xnum;
|
||||||
for(index_type i = 0; i < ynum; i++) {
|
for(index_type i = 0; i < ynum; i++) {
|
||||||
self->line_map[i] = i;
|
self->line_map[i] = i;
|
||||||
clear_chars_to(self, i, BLANK_CHAR);
|
if (BLANK_CHAR != 0) clear_chars_to(self, i, BLANK_CHAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,7 +152,7 @@ allocate_line_storage(Line *line, bool initialize) {
|
|||||||
if (initialize) {
|
if (initialize) {
|
||||||
line->cells = PyMem_Calloc(line->xnum, sizeof(Cell));
|
line->cells = PyMem_Calloc(line->xnum, sizeof(Cell));
|
||||||
if (line->cells == NULL) { PyErr_NoMemory(); return false; }
|
if (line->cells == NULL) { PyErr_NoMemory(); return false; }
|
||||||
clear_chars_in_line(line->cells, line->xnum, BLANK_CHAR);
|
if (BLANK_CHAR != 0) clear_chars_in_line(line->cells, line->xnum, BLANK_CHAR);
|
||||||
} else {
|
} else {
|
||||||
line->cells = PyMem_Malloc(line->xnum * sizeof(Cell));
|
line->cells = PyMem_Malloc(line->xnum * sizeof(Cell));
|
||||||
if (line->cells == NULL) { PyErr_NoMemory(); return false; }
|
if (line->cells == NULL) { PyErr_NoMemory(); return false; }
|
||||||
@ -199,7 +200,7 @@ copy_line_to(LineBuf *self, PyObject *args) {
|
|||||||
static inline void
|
static inline void
|
||||||
clear_line_(Line *l, index_type xnum) {
|
clear_line_(Line *l, index_type xnum) {
|
||||||
memset(l->cells, 0, xnum * sizeof(Cell));
|
memset(l->cells, 0, xnum * sizeof(Cell));
|
||||||
clear_chars_in_line(l->cells, xnum, BLANK_CHAR);
|
if (BLANK_CHAR != 0) clear_chars_in_line(l->cells, xnum, BLANK_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void linebuf_clear_line(LineBuf *self, index_type y) {
|
void linebuf_clear_line(LineBuf *self, index_type y) {
|
||||||
|
|||||||
38
kitty/line.c
38
kitty/line.c
@ -62,14 +62,22 @@ static PyObject *
|
|||||||
as_unicode(Line* self) {
|
as_unicode(Line* self) {
|
||||||
Py_ssize_t n = 0;
|
Py_ssize_t n = 0;
|
||||||
Py_UCS4 *buf = PyMem_Malloc(3 * self->xnum * sizeof(Py_UCS4));
|
Py_UCS4 *buf = PyMem_Malloc(3 * self->xnum * sizeof(Py_UCS4));
|
||||||
if (buf == NULL) {
|
if (buf == NULL) return PyErr_NoMemory();
|
||||||
PyErr_NoMemory();
|
index_type xlimit = self->xnum;
|
||||||
return NULL;
|
if (BLANK_CHAR == 0) {
|
||||||
|
while (xlimit != 0) {
|
||||||
|
if ((self->cells[xlimit - 1].ch & CHAR_MASK) != BLANK_CHAR) break;
|
||||||
|
xlimit--;
|
||||||
}
|
}
|
||||||
for(index_type i = 0; i < self->xnum; i++) {
|
}
|
||||||
char_type attrs = self->cells[i].ch >> ATTRS_SHIFT;
|
char_type previous_width = 0;
|
||||||
if ((attrs & WIDTH_MASK) < 1) continue;
|
for(index_type i = 0; i < xlimit; i++) {
|
||||||
buf[n++] = self->cells[i].ch & CHAR_MASK;
|
char_type ch = self->cells[i].ch & CHAR_MASK;
|
||||||
|
if (ch == 0) {
|
||||||
|
if (previous_width == 2) { previous_width = 0; continue; };
|
||||||
|
ch = ' ';
|
||||||
|
}
|
||||||
|
buf[n++] = ch;
|
||||||
char_type cc = self->cells[i].cc;
|
char_type cc = self->cells[i].cc;
|
||||||
Py_UCS4 cc1 = cc & CC_MASK, cc2;
|
Py_UCS4 cc1 = cc & CC_MASK, cc2;
|
||||||
if (cc1) {
|
if (cc1) {
|
||||||
@ -77,6 +85,7 @@ as_unicode(Line* self) {
|
|||||||
cc2 = cc >> 16;
|
cc2 = cc >> 16;
|
||||||
if (cc2) buf[n++] = cc2;
|
if (cc2) buf[n++] = cc2;
|
||||||
}
|
}
|
||||||
|
previous_width = (self->cells[i].ch >> ATTRS_SHIFT) & WIDTH_MASK;
|
||||||
}
|
}
|
||||||
PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, n);
|
PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, n);
|
||||||
PyMem_Free(buf);
|
PyMem_Free(buf);
|
||||||
@ -136,7 +145,7 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
|
|||||||
|
|
||||||
index_type limit = self->xnum, i=0;
|
index_type limit = self->xnum, i=0;
|
||||||
int r;
|
int r;
|
||||||
if (!self->continued) { // Trim trailing spaces
|
if (!self->continued) { // Trim trailing blanks
|
||||||
for(r = self->xnum - 1; r >= 0; r--) {
|
for(r = self->xnum - 1; r >= 0; r--) {
|
||||||
if ((self->cells[r].ch & CHAR_MASK) != BLANK_CHAR) break;
|
if ((self->cells[r].ch & CHAR_MASK) != BLANK_CHAR) break;
|
||||||
}
|
}
|
||||||
@ -144,11 +153,15 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
|
|||||||
}
|
}
|
||||||
bool bold = false, italic = false, reverse = false, strike = false;
|
bool bold = false, italic = false, reverse = false, strike = false;
|
||||||
uint32_t fg = 0, bg = 0, decoration_fg = 0, decoration = 0;
|
uint32_t fg = 0, bg = 0, decoration_fg = 0, decoration = 0;
|
||||||
|
char_type previous_width = 0;
|
||||||
|
|
||||||
WRITE_SGR(0);
|
WRITE_SGR(0);
|
||||||
for (index_type pos=0; pos < limit; pos++) {
|
for (index_type pos=0; pos < limit; pos++) {
|
||||||
char_type attrs = self->cells[pos].ch >> ATTRS_SHIFT, ch = self->cells[pos].ch & CHAR_MASK;
|
char_type attrs = self->cells[pos].ch >> ATTRS_SHIFT, ch = self->cells[pos].ch & CHAR_MASK;
|
||||||
if (ch == 0 || (attrs & WIDTH_MASK) < 1) continue;
|
if (ch == 0) {
|
||||||
|
if (previous_width == 2) { previous_width = 0; continue; }
|
||||||
|
ch = ' ';
|
||||||
|
}
|
||||||
CHECK_BOOL(bold, BOLD_SHIFT, 1, 22);
|
CHECK_BOOL(bold, BOLD_SHIFT, 1, 22);
|
||||||
CHECK_BOOL(italic, ITALIC_SHIFT, 3, 23);
|
CHECK_BOOL(italic, ITALIC_SHIFT, 3, 23);
|
||||||
CHECK_BOOL(reverse, REVERSE_SHIFT, 7, 27);
|
CHECK_BOOL(reverse, REVERSE_SHIFT, 7, 27);
|
||||||
@ -175,6 +188,7 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
|
|||||||
cc1 = cc >> 16;
|
cc1 = cc >> 16;
|
||||||
if (cc1) { WRITE_CH(cc1); }
|
if (cc1) { WRITE_CH(cc1); }
|
||||||
}
|
}
|
||||||
|
previous_width = attrs & WIDTH_MASK;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
#undef CHECK_BOOL
|
#undef CHECK_BOOL
|
||||||
@ -305,7 +319,7 @@ cursor_from(Line* self, PyObject *args) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
line_clear_text(Line *self, unsigned int at, unsigned int num, int ch) {
|
line_clear_text(Line *self, unsigned int at, unsigned int num, int ch) {
|
||||||
const char_type repl = ((char_type)ch & CHAR_MASK) | (1 << ATTRS_SHIFT);
|
const char_type repl = ((char_type)ch & CHAR_MASK) | ( (ch ? 1 : 0) << ATTRS_SHIFT);
|
||||||
#define PREFIX \
|
#define PREFIX \
|
||||||
for (index_type i = at; i < MIN(self->xnum, at + num); i++) { \
|
for (index_type i = at; i < MIN(self->xnum, at + num); i++) { \
|
||||||
self->cells[i].ch = (self->cells[i].ch & ATTRS_MASK_WITHOUT_WIDTH) | repl; \
|
self->cells[i].ch = (self->cells[i].ch & ATTRS_MASK_WITHOUT_WIDTH) | repl; \
|
||||||
@ -321,7 +335,7 @@ line_clear_text(Line *self, unsigned int at, unsigned int num, int ch) {
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
clear_text(Line* self, PyObject *args) {
|
clear_text(Line* self, PyObject *args) {
|
||||||
#define clear_text_doc "clear_text(at, num, ch=' ') -> Clear characters in the specified range, preserving formatting."
|
#define clear_text_doc "clear_text(at, num, ch=BLANK_CHAR) -> Clear characters in the specified range, preserving formatting."
|
||||||
unsigned int at, num;
|
unsigned int at, num;
|
||||||
int ch = BLANK_CHAR;
|
int ch = BLANK_CHAR;
|
||||||
if (!PyArg_ParseTuple(args, "II|C", &at, &num, &ch)) return NULL;
|
if (!PyArg_ParseTuple(args, "II|C", &at, &num, &ch)) return NULL;
|
||||||
@ -369,7 +383,7 @@ void line_right_shift(Line *self, unsigned int at, unsigned int num) {
|
|||||||
// Check if a wide character was split at the right edge
|
// Check if a wide character was split at the right edge
|
||||||
char_type w = (self->cells[self->xnum - 1].ch >> ATTRS_SHIFT) & WIDTH_MASK;
|
char_type w = (self->cells[self->xnum - 1].ch >> ATTRS_SHIFT) & WIDTH_MASK;
|
||||||
if (w != 1) {
|
if (w != 1) {
|
||||||
self->cells[self->xnum - 1].ch = (1 << ATTRS_SHIFT) | BLANK_CHAR;
|
self->cells[self->xnum - 1].ch = ((BLANK_CHAR ? 1 : 0) << ATTRS_SHIFT) | BLANK_CHAR;
|
||||||
clear_sprite_position(self->cells[self->xnum - 1]);
|
clear_sprite_position(self->cells[self->xnum - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@ rewrap_inner(BufType *src, BufType *dest, const index_type src_limit, HistoryBuf
|
|||||||
src_line_is_continued = is_src_line_continued(src_y);
|
src_line_is_continued = is_src_line_continued(src_y);
|
||||||
src_x_limit = src->xnum;
|
src_x_limit = src->xnum;
|
||||||
if (!src_line_is_continued) {
|
if (!src_line_is_continued) {
|
||||||
// Trim trailing white-space since there is a hard line break at the end of this line
|
// Trim trailing blanks since there is a hard line break at the end of this line
|
||||||
while(src_x_limit && (src->line->cells[src_x_limit - 1].ch & CHAR_MASK) == BLANK_CHAR) src_x_limit--;
|
while(src_x_limit && (src->line->cells[src_x_limit - 1].ch & CHAR_MASK) == BLANK_CHAR) src_x_limit--;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ class TestDataTypes(BaseTest):
|
|||||||
new.copy_old(old)
|
new.copy_old(old)
|
||||||
self.ae(new.line(0), old.line(1))
|
self.ae(new.line(0), old.line(1))
|
||||||
new.clear()
|
new.clear()
|
||||||
self.ae(str(new.line(0)), ' ' * new.xnum)
|
self.ae(str(new.line(0)), '')
|
||||||
old.set_attribute(REVERSE, False)
|
old.set_attribute(REVERSE, False)
|
||||||
for y in range(old.ynum):
|
for y in range(old.ynum):
|
||||||
for x in range(old.xnum):
|
for x in range(old.xnum):
|
||||||
@ -140,22 +140,23 @@ class TestDataTypes(BaseTest):
|
|||||||
lb = LineBuf(2, 3)
|
lb = LineBuf(2, 3)
|
||||||
for y in range(lb.ynum):
|
for y in range(lb.ynum):
|
||||||
line = lb.line(y)
|
line = lb.line(y)
|
||||||
self.ae(str(line), ' ' * lb.xnum)
|
self.ae(str(line), '')
|
||||||
for x in range(lb.xnum):
|
for x in range(lb.xnum):
|
||||||
self.ae(line[x], ' ')
|
self.ae(line[x], '\0')
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
lb.line(lb.ynum)
|
lb.line(lb.ynum)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
lb.line(0)[lb.xnum]
|
lb.line(0)[lb.xnum]
|
||||||
l = lb.line(0)
|
l = lb.line(0)
|
||||||
|
l.set_text(' ', 0, len(' '), C())
|
||||||
l.add_combining_char(0, '1')
|
l.add_combining_char(0, '1')
|
||||||
self.ae(l[0], ' 1')
|
self.ae(l[0], ' 1')
|
||||||
l.add_combining_char(0, '2')
|
l.add_combining_char(0, '2')
|
||||||
self.ae(l[0], ' 12')
|
self.ae(l[0], ' 12')
|
||||||
l.add_combining_char(0, '3')
|
l.add_combining_char(0, '3')
|
||||||
self.ae(l[0], ' 13')
|
self.ae(l[0], ' 13')
|
||||||
self.ae(l[1], ' ')
|
self.ae(l[1], '\0')
|
||||||
self.ae(str(l), ' 13 ')
|
self.ae(str(l), ' 13')
|
||||||
t = 'Testing with simple text'
|
t = 'Testing with simple text'
|
||||||
lb = LineBuf(2, len(t))
|
lb = LineBuf(2, len(t))
|
||||||
l = lb.line(0)
|
l = lb.line(0)
|
||||||
@ -257,18 +258,21 @@ class TestDataTypes(BaseTest):
|
|||||||
def test_rewrap_wider(self):
|
def test_rewrap_wider(self):
|
||||||
' New buffer wider '
|
' New buffer wider '
|
||||||
lb = create_lbuf('0123 ', '56789')
|
lb = create_lbuf('0123 ', '56789')
|
||||||
lb2 = self.line_comparison_rewrap(lb, '0123 5', '6789 ', ' ' * 6)
|
lb2 = self.line_comparison_rewrap(lb, '0123 5', '6789', '')
|
||||||
self.assertContinued(lb2, False, True)
|
self.assertContinued(lb2, False, True)
|
||||||
|
|
||||||
lb = create_lbuf('12', 'abc')
|
lb = create_lbuf('12', 'abc')
|
||||||
lb2 = self.line_comparison_rewrap(lb, '12 ', 'abc ')
|
lb2 = self.line_comparison_rewrap(lb, '12', 'abc')
|
||||||
self.assertContinued(lb2, False, False)
|
self.assertContinued(lb2, False, False)
|
||||||
|
|
||||||
def test_rewrap_narrower(self):
|
def test_rewrap_narrower(self):
|
||||||
' New buffer narrower '
|
' New buffer narrower '
|
||||||
lb = create_lbuf('123 ', 'abcde')
|
lb = create_lbuf('123', 'abcde')
|
||||||
lb2 = self.line_comparison_rewrap(lb, '123', 'abc', 'de ')
|
lb2 = self.line_comparison_rewrap(lb, '123', 'abc', 'de')
|
||||||
self.assertContinued(lb2, False, False, True)
|
self.assertContinued(lb2, False, False, True)
|
||||||
|
lb = create_lbuf('123 ', 'abcde')
|
||||||
|
lb2 = self.line_comparison_rewrap(lb, '123', ' a', 'bcd', 'e')
|
||||||
|
self.assertContinued(lb2, False, True, True, True)
|
||||||
|
|
||||||
@skipIf('ANCIENT_WCWIDTH' in os.environ, 'wcwidth() is too old')
|
@skipIf('ANCIENT_WCWIDTH' in os.environ, 'wcwidth() is too old')
|
||||||
def test_utils(self):
|
def test_utils(self):
|
||||||
|
|||||||
@ -45,15 +45,15 @@ class TestParser(BaseTest):
|
|||||||
pb = partial(self.parse_bytes_dump, s)
|
pb = partial(self.parse_bytes_dump, s)
|
||||||
|
|
||||||
pb('12', '12')
|
pb('12', '12')
|
||||||
self.ae(str(s.line(0)), '12 ')
|
self.ae(str(s.line(0)), '12')
|
||||||
self.ae(s.cursor.x, 2)
|
self.ae(s.cursor.x, 2)
|
||||||
pb('3456', '3456')
|
pb('3456', '3456')
|
||||||
self.ae(str(s.line(0)), '12345')
|
self.ae(str(s.line(0)), '12345')
|
||||||
self.ae(str(s.line(1)), '6 ')
|
self.ae(str(s.line(1)), '6')
|
||||||
pb(b'\n123\n\r45', ('screen_linefeed',), '123', ('screen_linefeed',), ('screen_carriage_return',), '45')
|
pb(b'\n123\n\r45', ('screen_linefeed',), '123', ('screen_linefeed',), ('screen_carriage_return',), '45')
|
||||||
self.ae(str(s.line(1)), '6 ')
|
self.ae(str(s.line(1)), '6')
|
||||||
self.ae(str(s.line(2)), ' 123 ')
|
self.ae(str(s.line(2)), ' 123')
|
||||||
self.ae(str(s.line(3)), '45 ')
|
self.ae(str(s.line(3)), '45')
|
||||||
parse_bytes(s, b'\rabcde')
|
parse_bytes(s, b'\rabcde')
|
||||||
self.ae(str(s.line(3)), 'abcde')
|
self.ae(str(s.line(3)), 'abcde')
|
||||||
pb('\rßxyz1', ('screen_carriage_return',), 'ßxyz1')
|
pb('\rßxyz1', ('screen_carriage_return',), 'ßxyz1')
|
||||||
@ -65,11 +65,11 @@ class TestParser(BaseTest):
|
|||||||
s = self.create_screen()
|
s = self.create_screen()
|
||||||
pb = partial(self.parse_bytes_dump, s)
|
pb = partial(self.parse_bytes_dump, s)
|
||||||
pb('12\033Da', '12', ('screen_index',), 'a')
|
pb('12\033Da', '12', ('screen_index',), 'a')
|
||||||
self.ae(str(s.line(0)), '12 ')
|
self.ae(str(s.line(0)), '12')
|
||||||
self.ae(str(s.line(1)), ' a ')
|
self.ae(str(s.line(1)), ' a')
|
||||||
pb('\033x', ('Unknown char after ESC: 0x%x' % ord('x'),))
|
pb('\033x', ('Unknown char after ESC: 0x%x' % ord('x'),))
|
||||||
pb('\033c123', ('screen_reset', ), '123')
|
pb('\033c123', ('screen_reset', ), '123')
|
||||||
self.ae(str(s.line(0)), '123 ')
|
self.ae(str(s.line(0)), '123')
|
||||||
|
|
||||||
def test_charsets(self):
|
def test_charsets(self):
|
||||||
s = self.create_screen()
|
s = self.create_screen()
|
||||||
@ -79,14 +79,14 @@ class TestParser(BaseTest):
|
|||||||
s = self.create_screen()
|
s = self.create_screen()
|
||||||
pb = partial(self.parse_bytes_dump, s)
|
pb = partial(self.parse_bytes_dump, s)
|
||||||
pb('\033)0\x0e/_', ('screen_designate_charset', 1, ord('0')), ('screen_change_charset', 1), '/_')
|
pb('\033)0\x0e/_', ('screen_designate_charset', 1, ord('0')), ('screen_change_charset', 1), '/_')
|
||||||
self.ae(str(s.line(0)), '/\xa0 ')
|
self.ae(str(s.line(0)), '/\xa0')
|
||||||
self.assertTrue(s.callbacks.iutf8)
|
self.assertTrue(s.callbacks.iutf8)
|
||||||
pb('\033%@_', ('screen_use_latin1', 1), '_')
|
pb('\033%@_', ('screen_use_latin1', 1), '_')
|
||||||
self.assertFalse(s.callbacks.iutf8)
|
self.assertFalse(s.callbacks.iutf8)
|
||||||
s = self.create_screen()
|
s = self.create_screen()
|
||||||
pb = partial(self.parse_bytes_dump, s)
|
pb = partial(self.parse_bytes_dump, s)
|
||||||
pb('\033(0/_', ('screen_designate_charset', 0, ord('0')), '/_')
|
pb('\033(0/_', ('screen_designate_charset', 0, ord('0')), '/_')
|
||||||
self.ae(str(s.line(0)), '/\xa0 ')
|
self.ae(str(s.line(0)), '/\xa0')
|
||||||
|
|
||||||
def test_csi_codes(self):
|
def test_csi_codes(self):
|
||||||
s = self.create_screen()
|
s = self.create_screen()
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class TestScreen(BaseTest):
|
|||||||
self.assertTrue(s.linebuf.is_continued(2))
|
self.assertTrue(s.linebuf.is_continued(2))
|
||||||
self.ae(str(s.line(0)), 'a' * 5)
|
self.ae(str(s.line(0)), 'a' * 5)
|
||||||
self.ae(str(s.line(1)), 'b' * 5)
|
self.ae(str(s.line(1)), 'b' * 5)
|
||||||
self.ae(str(s.line(2)), 'b' * 2 + ' ' * 3)
|
self.ae(str(s.line(2)), 'b' * 2)
|
||||||
self.ae(s.cursor.x, 2), self.ae(s.cursor.y, 2)
|
self.ae(s.cursor.x, 2), self.ae(s.cursor.y, 2)
|
||||||
s.draw('c' * 15)
|
s.draw('c' * 15)
|
||||||
self.ae(str(s.line(0)), 'b' * 5)
|
self.ae(str(s.line(0)), 'b' * 5)
|
||||||
@ -60,17 +60,17 @@ class TestScreen(BaseTest):
|
|||||||
self.ae(s.cursor.x, 5), self.ae(s.cursor.y, 0)
|
self.ae(s.cursor.x, 5), self.ae(s.cursor.y, 0)
|
||||||
s.draw('ニチハ')
|
s.draw('ニチハ')
|
||||||
self.ae(str(s.line(0)), 'ココx')
|
self.ae(str(s.line(0)), 'ココx')
|
||||||
self.ae(str(s.line(1)), 'ニチ ')
|
self.ae(str(s.line(1)), 'ニチ')
|
||||||
self.ae(str(s.line(2)), 'ハ ')
|
self.ae(str(s.line(2)), 'ハ')
|
||||||
self.ae(s.cursor.x, 2), self.ae(s.cursor.y, 2)
|
self.ae(s.cursor.x, 2), self.ae(s.cursor.y, 2)
|
||||||
s.draw('Ƶ̧\u0308')
|
s.draw('Ƶ̧\u0308')
|
||||||
self.ae(str(s.line(2)), 'ハƵ̧\u0308 ')
|
self.ae(str(s.line(2)), 'ハƵ̧\u0308')
|
||||||
self.ae(s.cursor.x, 3), self.ae(s.cursor.y, 2)
|
self.ae(s.cursor.x, 3), self.ae(s.cursor.y, 2)
|
||||||
s.draw('xy'), s.draw('\u0306')
|
s.draw('xy'), s.draw('\u0306')
|
||||||
self.ae(str(s.line(2)), 'ハƵ̧\u0308xy\u0306')
|
self.ae(str(s.line(2)), 'ハƵ̧\u0308xy\u0306')
|
||||||
self.ae(s.cursor.x, 5), self.ae(s.cursor.y, 2)
|
self.ae(s.cursor.x, 5), self.ae(s.cursor.y, 2)
|
||||||
s.draw('c' * 15)
|
s.draw('c' * 15)
|
||||||
self.ae(str(s.line(0)), 'ニチ ')
|
self.ae(str(s.line(0)), 'ニチ')
|
||||||
|
|
||||||
# Now test without line-wrap
|
# Now test without line-wrap
|
||||||
s.reset(), s.reset_dirty()
|
s.reset(), s.reset_dirty()
|
||||||
@ -111,12 +111,12 @@ class TestScreen(BaseTest):
|
|||||||
self.assertTrue(s.line(0).cursor_from(1).bold)
|
self.assertTrue(s.line(0).cursor_from(1).bold)
|
||||||
s.cursor_back(1)
|
s.cursor_back(1)
|
||||||
s.insert_characters(20)
|
s.insert_characters(20)
|
||||||
self.ae(str(s.line(0)), ' ')
|
self.ae(str(s.line(0)), '')
|
||||||
s.draw('xココ')
|
s.draw('xココ')
|
||||||
s.cursor_back(5)
|
s.cursor_back(5)
|
||||||
s.reset_dirty()
|
s.reset_dirty()
|
||||||
s.insert_characters(1)
|
s.insert_characters(1)
|
||||||
self.ae(str(s.line(0)), ' xコ ')
|
self.ae(str(s.line(0)), ' xコ')
|
||||||
c = Cursor()
|
c = Cursor()
|
||||||
c.italic = True
|
c.italic = True
|
||||||
s.line(0).apply_cursor(c, 0, 5)
|
s.line(0).apply_cursor(c, 0, 5)
|
||||||
@ -126,7 +126,7 @@ class TestScreen(BaseTest):
|
|||||||
|
|
||||||
init()
|
init()
|
||||||
s.delete_characters(2)
|
s.delete_characters(2)
|
||||||
self.ae(str(s.line(0)), 'ade ')
|
self.ae(str(s.line(0)), 'ade')
|
||||||
self.assertTrue(s.line(0).cursor_from(4).bold)
|
self.assertTrue(s.line(0).cursor_from(4).bold)
|
||||||
self.assertFalse(s.line(0).cursor_from(2).bold)
|
self.assertFalse(s.line(0).cursor_from(2).bold)
|
||||||
|
|
||||||
@ -136,11 +136,11 @@ class TestScreen(BaseTest):
|
|||||||
self.assertTrue(s.line(0).cursor_from(1).bold)
|
self.assertTrue(s.line(0).cursor_from(1).bold)
|
||||||
self.assertFalse(s.line(0).cursor_from(4).bold)
|
self.assertFalse(s.line(0).cursor_from(4).bold)
|
||||||
s.erase_characters(20)
|
s.erase_characters(20)
|
||||||
self.ae(str(s.line(0)), 'a ')
|
self.ae(str(s.line(0)), 'a')
|
||||||
|
|
||||||
init()
|
init()
|
||||||
s.erase_in_line()
|
s.erase_in_line()
|
||||||
self.ae(str(s.line(0)), 'a ')
|
self.ae(str(s.line(0)), 'a')
|
||||||
self.assertTrue(s.line(0).cursor_from(1).bold)
|
self.assertTrue(s.line(0).cursor_from(1).bold)
|
||||||
self.assertFalse(s.line(0).cursor_from(0).bold)
|
self.assertFalse(s.line(0).cursor_from(0).bold)
|
||||||
init()
|
init()
|
||||||
@ -148,7 +148,7 @@ class TestScreen(BaseTest):
|
|||||||
self.ae(str(s.line(0)), ' cde')
|
self.ae(str(s.line(0)), ' cde')
|
||||||
init()
|
init()
|
||||||
s.erase_in_line(2)
|
s.erase_in_line(2)
|
||||||
self.ae(str(s.line(0)), ' ')
|
self.ae(str(s.line(0)), '')
|
||||||
init()
|
init()
|
||||||
s.erase_in_line(2, True)
|
s.erase_in_line(2, True)
|
||||||
self.ae((False, False, False, False, False), tuple(map(lambda i: s.line(0).cursor_from(i).bold, range(5))))
|
self.ae((False, False, False, False, False), tuple(map(lambda i: s.line(0).cursor_from(i).bold, range(5))))
|
||||||
@ -168,19 +168,19 @@ class TestScreen(BaseTest):
|
|||||||
|
|
||||||
init()
|
init()
|
||||||
s.erase_in_display()
|
s.erase_in_display()
|
||||||
self.ae(all_lines(s), ('12345', '12 ', ' ', ' ', ' '))
|
self.ae(all_lines(s), ('12345', '12', '', '', ''))
|
||||||
|
|
||||||
init()
|
init()
|
||||||
s.erase_in_display(1)
|
s.erase_in_display(1)
|
||||||
self.ae(all_lines(s), (' ', ' 45', '12345', '12345', '12345'))
|
self.ae(all_lines(s), ('', ' 45', '12345', '12345', '12345'))
|
||||||
|
|
||||||
init()
|
init()
|
||||||
s.erase_in_display(2)
|
s.erase_in_display(2)
|
||||||
self.ae(all_lines(s), (' ', ' ', ' ', ' ', ' '))
|
self.ae(all_lines(s), ('', '', '', '', ''))
|
||||||
self.assertTrue(s.line(0).cursor_from(1).bold)
|
self.assertTrue(s.line(0).cursor_from(1).bold)
|
||||||
init()
|
init()
|
||||||
s.erase_in_display(2, True)
|
s.erase_in_display(2, True)
|
||||||
self.ae(all_lines(s), (' ', ' ', ' ', ' ', ' '))
|
self.ae(all_lines(s), ('', '', '', '', ''))
|
||||||
self.assertFalse(s.line(0).cursor_from(1).bold)
|
self.assertFalse(s.line(0).cursor_from(1).bold)
|
||||||
|
|
||||||
def test_cursor_movement(self):
|
def test_cursor_movement(self):
|
||||||
@ -203,13 +203,13 @@ class TestScreen(BaseTest):
|
|||||||
s = self.create_screen()
|
s = self.create_screen()
|
||||||
s.draw('12345' * 5)
|
s.draw('12345' * 5)
|
||||||
s.index()
|
s.index()
|
||||||
self.ae(str(s.line(4)), ' ' * 5)
|
self.ae(str(s.line(4)), '')
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
self.ae(str(s.line(i)), '12345')
|
self.ae(str(s.line(i)), '12345')
|
||||||
s.draw('12345' * 5)
|
s.draw('12345' * 5)
|
||||||
s.cursor_up(5)
|
s.cursor_up(5)
|
||||||
s.reverse_index()
|
s.reverse_index()
|
||||||
self.ae(str(s.line(0)), ' ' * 5)
|
self.ae(str(s.line(0)), '')
|
||||||
for i in range(1, 5):
|
for i in range(1, 5):
|
||||||
self.ae(str(s.line(i)), '12345')
|
self.ae(str(s.line(i)), '12345')
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ class TestScreen(BaseTest):
|
|||||||
s.resize(3, 10)
|
s.resize(3, 10)
|
||||||
self.ae(str(s.line(0)), '0'*5 + '1'*5)
|
self.ae(str(s.line(0)), '0'*5 + '1'*5)
|
||||||
self.ae(str(s.line(1)), '2'*5 + '3'*5)
|
self.ae(str(s.line(1)), '2'*5 + '3'*5)
|
||||||
self.ae(str(s.line(2)), '4'*5 + ' '*5)
|
self.ae(str(s.line(2)), '4'*5)
|
||||||
s.resize(5, 1)
|
s.resize(5, 1)
|
||||||
self.ae(str(s.line(0)), '4')
|
self.ae(str(s.line(0)), '4')
|
||||||
hb = s.historybuf
|
hb = s.historybuf
|
||||||
@ -229,8 +229,8 @@ class TestScreen(BaseTest):
|
|||||||
s.draw(''.join([str(i) * s.columns for i in range(s.lines*2)]))
|
s.draw(''.join([str(i) * s.columns for i in range(s.lines*2)]))
|
||||||
self.ae(str(s.line(4)), '9'*5)
|
self.ae(str(s.line(4)), '9'*5)
|
||||||
s.resize(5, 2)
|
s.resize(5, 2)
|
||||||
self.ae(str(s.line(3)), '9 ')
|
self.ae(str(s.line(3)), '9')
|
||||||
self.ae(str(s.line(4)), ' ')
|
self.ae(str(s.line(4)), '')
|
||||||
|
|
||||||
def test_tab_stops(self):
|
def test_tab_stops(self):
|
||||||
# Taken from vttest/main.c
|
# Taken from vttest/main.c
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user