From fab2213c25dba337d2196ae6cbbb55d9358b2a4c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 13 Nov 2016 10:21:54 +0530 Subject: [PATCH] More work on native streams --- generate-unicode-data.py | 57 +++++++ kitty/boss.py | 6 +- kitty/char_grid.py | 9 +- kitty/charsets.c | 30 ++++ kitty/colors.c | 2 +- kitty/config.py | 13 +- kitty/cursor.c | 75 +++++---- kitty/data-types.c | 13 +- kitty/data-types.h | 78 ++++++++- kitty/line-buf.c | 23 ++- kitty/line.c | 73 ++++----- kitty/modes.h | 2 +- kitty/parser.c | 12 -- kitty/savepoints.c | 47 ++++++ kitty/screen.c | 334 ++++++++++++++++++++++++++++++++++++--- kitty/screen.py | 7 +- kitty/sprites.c | 4 - kitty/tracker.c | 7 +- kitty/unicode-data.h | 11 ++ kitty_tests/__init__.py | 10 +- 20 files changed, 652 insertions(+), 161 deletions(-) create mode 100644 generate-unicode-data.py create mode 100644 kitty/savepoints.c create mode 100644 kitty/unicode-data.h diff --git a/generate-unicode-data.py b/generate-unicode-data.py new file mode 100644 index 000000000..7c3233109 --- /dev/null +++ b/generate-unicode-data.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2016, Kovid Goyal + +import unicodedata +import itertools +import sys + +IGNORED_CATEGORIES = ('Cc', 'Cf', 'Cn', 'Cs') + + +def ranges(i): + for a, b in itertools.groupby(enumerate(i), lambda r: r[1] - r[0]): + b = list(b) + yield b[0][1], b[-1][1] + + +def generate_data(chars): + points, cranges = [], [] + for l, r in ranges(chars): + if l == r: + points.append(l) + else: + cranges.append((l, r)) + return points, cranges + + +def generate_predicate(name, chars): + points, ranges = generate_data(chars) + ranges = ['(0x%s %s ch && ch <= 0x%s)' % (l, '<' if l == 0 else '<=', r) for l, r in ranges] + points = ['(ch == 0x%x)' % p for p in points] + return ''' +static inline bool %s(uint32_t ch) { + return %s || %s; +} + ''' % (name, '||'.join(ranges), '||'.join(points)) + + +def main(): + combining_chars = [] + igchars = [] + for c in map(chr, range(sys.maxunicode + 1)): + if unicodedata.category(c) in IGNORED_CATEGORIES: + igchars.append(ord(c)) + if unicodedata.combining(c): + combining_chars.append(ord(c)) + + cc = generate_predicate('is_combining_char', combining_chars) + ig = generate_predicate('is_ignored_char', igchars) + with open('kitty/unicode-data.h', 'w') as f: + print('#pragma once', file=f) + print(cc, file=f) + print(ig, file=f) + +if __name__ == '__main__': + main() + # TODO: delete kitty/unicode.py alongwith kitty/screen.py diff --git a/kitty/boss.py b/kitty/boss.py index c2cb81526..e4fd8994e 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -97,10 +97,10 @@ class Boss(Thread): def on_focus(self, window, focused): if focused: - if self.screen.enable_focus_tracking: + if self.screen.enable_focus_tracking(): self.write_to_child(b'\x1b[I') else: - if self.screen.enable_focus_tracking: + if self.screen.enable_focus_tracking(): self.write_to_child(b'\x1b[O') def on_mouse_button(self, window, button, action, mods): @@ -110,7 +110,7 @@ class Boss(Thread): # text = glfw.glfwGetClipboardString(window) text = subprocess.check_output(['xsel']) if text: - if self.screen.in_bracketed_paste_mode: + if self.screen.in_bracketed_paste_mode(): text = BRACKETED_PASTE_START.encode('ascii') + text + BRACKETED_PASTE_END.encode('ascii') self.write_to_child(text) diff --git a/kitty/char_grid.py b/kitty/char_grid.py index 56a511b91..26af008bb 100644 --- a/kitty/char_grid.py +++ b/kitty/char_grid.py @@ -16,7 +16,8 @@ from .fast_data_types import ( glBlendFunc, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, glClear, GL_COLOR_BUFFER_BIT, glClearColor, glViewport, glUniform2ui, glUniform4f, glUniform1i, glUniform2f, glDrawArraysInstanced, GL_TRIANGLE_FAN, - glEnable, glDisable, GL_BLEND, glDrawArrays, ColorProfile, REVERSE + glEnable, glDisable, GL_BLEND, glDrawArrays, ColorProfile, REVERSE, + CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE ) Size = namedtuple('Size', 'width height') @@ -303,11 +304,11 @@ class CharGrid: col = cursor.color or self.default_cursor.color shape = cursor.shape or self.default_cursor.shape alpha = self.opts.cursor_opacity - if alpha < 1.0 and shape == 'block': + if alpha < 1.0 and shape == CURSOR_BLOCK: glEnable(GL_BLEND) - right = left + (width(1.5) if shape == 'beam' else sg.dx) + right = left + (width(1.5) if shape == CURSOR_BEAM else sg.dx) bottom = top - sg.dy - if shape == 'underline': + if shape == CURSOR_UNDERLINE: top = bottom + width(vert=False) glUniform4f(ul('color'), col[0], col[1], col[2], alpha) glUniform2f(ul('xpos'), left, right) diff --git a/kitty/charsets.c b/kitty/charsets.c index e7846513e..eca4419f3 100644 --- a/kitty/charsets.c +++ b/kitty/charsets.c @@ -166,3 +166,33 @@ uint16_t* translation_table(char which) { } return charset_translations[0]; } + +// UTF-8 decode taken from: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + +static const uint8_t utf8_data[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df + 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef + 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff + 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 + 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 + 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 + 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 +}; + +uint32_t decode_utf8(uint32_t* state, uint32_t* codep, uint8_t byte) { + uint32_t type = utf8_data[byte]; + + *codep = (*state != UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8_data[256 + *state*16 + type]; + return *state; +} diff --git a/kitty/colors.c b/kitty/colors.c index e4b8ea09d..0b209e3b1 100644 --- a/kitty/colors.c +++ b/kitty/colors.c @@ -63,7 +63,7 @@ new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) { } static void -dealloc(Cursor* self) { +dealloc(ColorProfile* self) { Py_TYPE(self)->tp_free((PyObject*)self); } diff --git a/kitty/config.py b/kitty/config.py index ec393d4b8..50bef68c1 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -6,6 +6,7 @@ import re from collections import namedtuple from itertools import repeat +from .fast_data_types import CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE key_pat = re.compile(r'([a-zA-Z][a-zA-Z0-9_-]*)\s+(.+)$') # Color definitions {{{ @@ -186,12 +187,14 @@ def to_font_size(x): return max(6, float(x)) +cshapes = {'block': CURSOR_BLOCK, 'beam': CURSOR_BEAM, 'underline': CURSOR_UNDERLINE} + + def to_cursor_shape(x): - shapes = 'block underline beam' - x = x.lower() - if x not in shapes.split(): - raise ValueError('Invalid cursor shape: {} allowed values are {}'.format(x, shapes)) - return x + try: + return cshapes[x.lower()] + except KeyError: + raise ValueError('Invalid cursor shape: {} allowed values are {}'.format(x, ', '.join(cshapes))) def to_bool(x): diff --git a/kitty/cursor.c b/kitty/cursor.c index 88219e512..a25950f3f 100644 --- a/kitty/cursor.c +++ b/kitty/cursor.c @@ -9,50 +9,30 @@ #include -#define INIT_NONE(x) Py_INCREF(Py_None); x = Py_None; - static PyObject * new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) { Cursor *self; self = (Cursor *)type->tp_alloc(type, 0); - if (self != NULL) { - self->x = PyLong_FromLong(0); - if (self->x == NULL) { Py_CLEAR(self); return NULL; } - self->y = self->x; Py_INCREF(self->y); - INIT_NONE(self->shape); - INIT_NONE(self->blink); - INIT_NONE(self->color); - self->hidden = Py_False; Py_INCREF(Py_False); - self->bold = 0; self->italic = 0; self->reverse = 0; self->strikethrough = 0; self->decoration = 0; - self->fg = 0; self->bg = 0; self->decoration_fg = 0; - } return (PyObject*) self; } static void dealloc(Cursor* self) { - Py_CLEAR(self->shape); - Py_CLEAR(self->blink); - Py_CLEAR(self->color); - Py_CLEAR(self->hidden); - Py_CLEAR(self->x); - Py_CLEAR(self->y); Py_TYPE(self)->tp_free((PyObject*)self); } #define EQ(x) (a->x == b->x) -#define PEQ(x) (PyObject_RichCompareBool(a->x, b->x, Py_EQ) == 1) static int __eq__(Cursor *a, Cursor *b) { - return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && PEQ(x) && PEQ(y) && PEQ(shape) && PEQ(blink) && PEQ(color) && PEQ(hidden); + return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(blink) && EQ(color) && EQ(hidden); } #define BOOL(x) ((x) ? Py_True : Py_False) static PyObject * repr(Cursor *self) { return PyUnicode_FromFormat( - "Cursor(x=%R, y=%R, shape=%R, blink=%R, hidden=%R, color=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, decoration=%d, decoration_fg=#%08x)", - self->x, self->y, self->shape, self->blink, self->hidden, self->color, self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), self->decoration, self->decoration_fg + "Cursor(x=%u, y=%u, shape=%d, blink=%R, hidden=%R, color=#%08x, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, decoration=%d, decoration_fg=#%08x)", + self->x, self->y, self->shape, BOOL(self->blink), BOOL(self->hidden), self->color, self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), self->decoration, self->decoration_fg ); } @@ -64,29 +44,39 @@ reset_display_attrs(Cursor *self) { Py_RETURN_NONE; } +void cursor_reset(Cursor *self) { + self->x = 0; self->y = 0; + self->shape = 0; self->blink = false; + self->color = 0; self->hidden = false; +} + static PyObject* -copy(Cursor *self, PyObject *args); +copy(Cursor *self); #define copy_doc "Create a clone of this cursor" +static PyObject* color_get(Cursor *self, void UNUSED *closure) { + if (!(self->color & 0xFF)) { Py_RETURN_NONE; } + return Py_BuildValue("BBB", (self->color >> 24) & 0xFF, (self->color >> 16) & 0xFF, (self->color >> 8) & 0xFF); +} + // Boilerplate {{{ BOOL_GETSET(Cursor, bold) BOOL_GETSET(Cursor, italic) BOOL_GETSET(Cursor, reverse) BOOL_GETSET(Cursor, strikethrough) +BOOL_GETSET(Cursor, hidden) +BOOL_GETSET(Cursor, blink) static PyMemberDef members[] = { - {"x", T_OBJECT_EX, offsetof(Cursor, x), 0, "x"}, - {"y", T_OBJECT_EX, offsetof(Cursor, y), 0, "y"}, - {"shape", T_OBJECT_EX, offsetof(Cursor, shape), 0, "shape"}, - {"blink", T_OBJECT_EX, offsetof(Cursor, blink), 0, "blink"}, - {"color", T_OBJECT_EX, offsetof(Cursor, color), 0, "color"}, - {"hidden", T_OBJECT_EX, offsetof(Cursor, hidden), 0, "hidden"}, - + {"x", T_INT, offsetof(Cursor, x), 0, "x"}, + {"y", T_INT, offsetof(Cursor, y), 0, "y"}, + {"shape", T_UBYTE, offsetof(Cursor, shape), 0, "shape"}, + {"color", T_ULONG, offsetof(Cursor, color), 0, "color"}, {"decoration", T_UBYTE, offsetof(Cursor, decoration), 0, "decoration"}, - {"fg", T_UINT, offsetof(Cursor, fg), 0, "fg"}, - {"bg", T_UINT, offsetof(Cursor, bg), 0, "bg"}, - {"decoration_fg", T_UINT, offsetof(Cursor, decoration_fg), 0, "decoration_fg"}, + {"fg", T_ULONG, offsetof(Cursor, fg), 0, "fg"}, + {"bg", T_ULONG, offsetof(Cursor, bg), 0, "bg"}, + {"decoration_fg", T_ULONG, offsetof(Cursor, decoration_fg), 0, "decoration_fg"}, {NULL} /* Sentinel */ }; @@ -95,6 +85,9 @@ static PyGetSetDef getseters[] = { GETSET(italic) GETSET(reverse) GETSET(strikethrough) + GETSET(hidden) + GETSET(blink) + {"color", (getter) color_get, NULL, "color", NULL}, {NULL} /* Sentinel */ }; @@ -127,16 +120,20 @@ RICHCMP(Cursor) // }}} -static PyObject* -copy(Cursor *self, PyObject UNUSED *args) { -#define CPY(x) ans->x = self->x; Py_XINCREF(self->x); +Cursor* +cursor_copy(Cursor *self) { #define CCY(x) ans->x = self->x; Cursor* ans; ans = alloc_cursor(); if (ans == NULL) { PyErr_NoMemory(); return NULL; } - CPY(x); CPY(y); CPY(shape); CPY(blink); CPY(color); CPY(hidden); + CCY(x); CCY(y); CCY(shape); CCY(blink); CCY(color); CCY(hidden); CCY(bold); CCY(italic); CCY(strikethrough); CCY(reverse); CCY(decoration); CCY(fg); CCY(bg); CCY(decoration_fg); - return (PyObject*)ans; + return ans; +} + +static PyObject* +copy(Cursor *self) { + return (PyObject*)cursor_copy(self); } Cursor *alloc_cursor() { diff --git a/kitty/data-types.c b/kitty/data-types.c index b7d1ad06c..271c100e8 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -6,16 +6,6 @@ */ #include "data-types.h" -extern int init_LineBuf(PyObject *); -extern int init_Cursor(PyObject *); -extern int init_Line(PyObject *); -extern int init_ColorProfile(PyObject *); -extern int init_SpriteMap(PyObject *); -extern int init_ChangeTracker(PyObject *); -extern int init_Screen(PyObject *); -extern PyObject* create_256_color_table(); -extern PyObject* parse_bytes_dump(PyObject UNUSED *self, PyObject *val); -extern PyObject* parse_bytes(PyObject UNUSED *self, PyObject *val); #include "gl.h" #include "modes.h" @@ -58,6 +48,9 @@ PyInit_fast_data_types(void) { PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT); PyModule_AddStringMacro(m, BRACKETED_PASTE_START); PyModule_AddStringMacro(m, BRACKETED_PASTE_END); + PyModule_AddIntMacro(m, CURSOR_BLOCK); + PyModule_AddIntMacro(m, CURSOR_BEAM); + PyModule_AddIntMacro(m, CURSOR_UNDERLINE); } return m; diff --git a/kitty/data-types.h b/kitty/data-types.h index edf831e18..4f2d1b08c 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -37,6 +37,12 @@ typedef unsigned int index_type; #define HAS_BG_MASK (0xFF << COL_SHIFT) #define CC_MASK 0xFFFF #define CC_SHIFT 16 +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 1 + +#define CURSOR_BLOCK 1 +#define CURSOR_BEAM 2 +#define CURSOR_UNDERLINE 3 #define CURSOR_TO_ATTRS(c, w) \ ((w) | (((c->decoration & 3) << DECORATION_SHIFT) | ((c->bold & 1) << BOLD_SHIFT) | \ @@ -119,6 +125,7 @@ typedef struct { bool continued; bool needs_free; } Line; +PyTypeObject Line_Type; typedef struct { @@ -136,17 +143,19 @@ typedef struct { decoration_type *decoration_fg; combining_type *combining_chars; } LineBuf; +PyTypeObject LineBuf_Type; typedef struct { PyObject_HEAD - PyObject *x, *y, *shape, *blink, *hidden, *color; - bool bold, italic, reverse, strikethrough; - uint8_t decoration; - uint32_t fg, bg, decoration_fg; + bool bold, italic, reverse, strikethrough, blink, hidden; + int x, y; + uint8_t decoration, shape; + unsigned long fg, bg, decoration_fg, color; } Cursor; +PyTypeObject Cursor_Type; typedef struct { @@ -156,6 +165,7 @@ typedef struct { uint32_t ansi_color_table[120]; } ColorProfile; +PyTypeObject ColorProfile_Type; typedef struct SpritePosition SpritePosition; struct SpritePosition { @@ -167,6 +177,7 @@ struct SpritePosition { bool filled; bool rendered; }; +PyTypeObject SpritePosition_Type; typedef struct { PyObject_HEAD @@ -177,6 +188,7 @@ typedef struct { bool dirty; } SpriteMap; +PyTypeObject SpriteMap_Type; typedef struct { PyObject_HEAD @@ -190,12 +202,26 @@ typedef struct { bool *changed_cells; unsigned int history_line_added_count; } ChangeTracker; +PyTypeObject ChangeTracker_Type; typedef struct { - bool LNM, IRM, DECTEM, DECSCNM, DECOM, DECAWM, DECCOLM; + bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mBRACKETED_PASTE, mFOCUS_TRACKING; } ScreenModes; +PyTypeObject ScreenModes_Type; +typedef struct { + PyObject_HEAD + + unsigned int current_charset; + uint16_t *g0_charset, *g1_charset; + uint32_t utf8_state; + Cursor *cursor; + bool mDECOM; + bool mDECAWM; + +} Savepoint; +PyTypeObject Savepoint_Type; typedef struct { PyObject_HEAD @@ -215,14 +241,56 @@ typedef struct { bool parser_has_pending_text; } Screen; +PyTypeObject Screen_Type; Line* alloc_line(); Cursor* alloc_cursor(); LineBuf* alloc_linebuf(); ChangeTracker* alloc_change_tracker(); +Savepoint* alloc_savepoint(); #define left_shift_line(line, at, num) \ for(index_type __i__ = (at); __i__ < (line)->xnum - (num); __i__++) { \ COPY_CELL(line, __i__ + (num), line, __i__) \ } \ if ((((line)->chars[(at)] >> ATTRS_SHIFT) & WIDTH_MASK) != 1) (line)->chars[(at)] = (1 << ATTRS_SHIFT) | 32; + + +// Global functions +int init_LineBuf(PyObject *); +int init_Cursor(PyObject *); +int init_Line(PyObject *); +int init_ColorProfile(PyObject *); +int init_SpriteMap(PyObject *); +int init_ChangeTracker(PyObject *); +int init_Screen(PyObject *); +PyObject* create_256_color_table(); +PyObject* parse_bytes_dump(PyObject UNUSED *, PyObject *); +PyObject* parse_bytes(PyObject UNUSED *, PyObject *); +uint16_t* translation_table(char); +uint32_t decode_utf8(uint32_t*, uint32_t*, uint8_t byte); +void linebuf_init_line(LineBuf *, index_type); +void line_set_char(Line *, unsigned int , uint32_t , unsigned int , Cursor *); +void line_right_shift(Line *, unsigned int , unsigned int ); +void line_add_combining_char(Line *, uint32_t , unsigned int ); +void cursor_reset(Cursor*); +void linebuf_set_attribute(LineBuf *, unsigned int , unsigned int ); +Cursor* cursor_copy(Cursor*); +void linebuf_clear(LineBuf *); +bool screen_restore_cursor(Screen *); +bool screen_save_cursor(Screen *); +bool screen_cursor_position(Screen*, unsigned int, unsigned int); +bool screen_erase_in_display(Screen *, unsigned int, bool); +bool screen_draw(Screen *screen, uint8_t *buf, unsigned int buflen); +bool update_cell_range_data(SpriteMap *, Line *, unsigned int, unsigned int, ColorProfile *, const uint32_t, const uint32_t, unsigned int *); +uint32_t to_color(ColorProfile *, uint32_t, uint32_t); +PyObject* line_text_at(char_type, combining_type); +void linebuf_init_line(LineBuf *, index_type); +#define DECLARE_CH_SCREEN_HANDLER(name) bool screen_##name(Screen *screen, uint8_t ch); +DECLARE_CH_SCREEN_HANDLER(bell) +DECLARE_CH_SCREEN_HANDLER(backspace) +DECLARE_CH_SCREEN_HANDLER(tab) +DECLARE_CH_SCREEN_HANDLER(linefeed) +DECLARE_CH_SCREEN_HANDLER(carriage_return) +DECLARE_CH_SCREEN_HANDLER(shift_out) +DECLARE_CH_SCREEN_HANDLER(shift_in) diff --git a/kitty/line-buf.c b/kitty/line-buf.c index b351c2185..b7dd0e36f 100644 --- a/kitty/line-buf.c +++ b/kitty/line-buf.c @@ -7,7 +7,6 @@ #include "data-types.h" #include -extern PyTypeObject Line_Type; static inline void clear_chars_to_space(LineBuf* linebuf, index_type y) { @@ -15,15 +14,19 @@ clear_chars_to_space(LineBuf* linebuf, index_type y) { for (index_type i = 0; i < linebuf->xnum; i++) chars[i] = (1 << ATTRS_SHIFT) | 32; } -static PyObject* -clear(LineBuf *self) { -#define clear_doc "Clear all lines in this LineBuf" +void linebuf_clear(LineBuf *self) { memset(self->buf, 0, self->block_size * CELL_SIZE); memset(self->continued_map, 0, self->ynum * sizeof(bool)); for (index_type i = 0; i < self->ynum; i++) { clear_chars_to_space(self, i); self->line_map[i] = i; } +} + +static PyObject* +clear(LineBuf *self) { +#define clear_doc "Clear all lines in this LineBuf" + linebuf_clear(self); Py_RETURN_NONE; } @@ -110,16 +113,20 @@ line(LineBuf *self, PyObject *y) { return (PyObject*)self->line; } +void linebuf_set_attribute(LineBuf *self, unsigned int shift, unsigned int val) { + char_type mask; + for (index_type y = 0; y < self->ynum; y++) { + SET_ATTRIBUTE(self->chars + y * self->xnum, shift, val); + } +} + static PyObject* set_attribute(LineBuf *self, PyObject *args) { #define set_attribute_doc "set_attribute(which, val) -> Set the attribute on all cells in the line." unsigned int shift, val; - char_type mask; if (!PyArg_ParseTuple(args, "II", &shift, &val)) return NULL; if (shift < DECORATION_SHIFT || shift > STRIKE_SHIFT) { PyErr_SetString(PyExc_ValueError, "Unknown attribute"); return NULL; } - for (index_type y = 0; y < self->ynum; y++) { - SET_ATTRIBUTE(self->chars + y * self->xnum, shift, val); - } + linebuf_set_attribute(self, shift, val); Py_RETURN_NONE; } diff --git a/kitty/line.c b/kitty/line.c index 65db254f5..94be0007b 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -6,7 +6,6 @@ */ #include "data-types.h" -extern PyTypeObject Cursor_Type; static PyObject * new(PyTypeObject UNUSED *type, PyObject UNUSED *args, PyObject UNUSED *kwds) { @@ -108,6 +107,12 @@ basic_cell_data(Line *self, PyObject *val) { return Py_BuildValue("IBK", (unsigned int)(ch & CHAR_MASK), (unsigned char)(ch >> ATTRS_SHIFT), (unsigned long long)self->colors[x]); } +void line_add_combining_char(Line *self, uint32_t ch, unsigned int x) { + combining_type c = self->combining_chars[x]; + if (c & CC_MASK) self->combining_chars[x] = (c & CC_MASK) | ( (ch & CC_MASK) << CC_SHIFT ); + else self->combining_chars[x] = ch & CC_MASK; +} + static PyObject* add_combining_char(Line* self, PyObject *args) { #define add_combining_char_doc "add_combining_char(x, ch) -> Add the specified character as a combining char to the specified cell." @@ -118,9 +123,7 @@ add_combining_char(Line* self, PyObject *args) { PyErr_SetString(PyExc_ValueError, "Column index out of bounds"); return NULL; } - combining_type c = self->combining_chars[x]; - if (c & CC_MASK) self->combining_chars[x] = (c & CC_MASK) | ( (new_char & CC_MASK) << CC_SHIFT ); - else self->combining_chars[x] = new_char & CC_MASK; + line_add_combining_char(self, new_char, x); Py_RETURN_NONE; } @@ -134,7 +137,6 @@ set_text(Line* self, PyObject *args) { Cursor *cursor; int kind; void *buf; - unsigned long x; if (!PyArg_ParseTuple(args, "UnnO!", &src, &offset, &sz, &Cursor_Type, &cursor)) return NULL; if (PyUnicode_READY(src) != 0) { @@ -148,12 +150,11 @@ set_text(Line* self, PyObject *args) { PyErr_SetString(PyExc_ValueError, "Out of bounds offset/sz"); return NULL; } - x = PyLong_AsUnsignedLong(cursor->x); attrs = CURSOR_TO_ATTRS(cursor, 1); color_type col = (cursor->fg & COL_MASK) | ((color_type)(cursor->bg & COL_MASK) << COL_SHIFT); decoration_type dfg = cursor->decoration_fg & COL_MASK; - for (index_type i = x; offset < limit && i < self->xnum; i++, offset++) { + for (index_type i = cursor->x; offset < limit && i < self->xnum; i++, offset++) { self->chars[i] = (PyUnicode_READ(kind, buf, offset) & CHAR_MASK) | attrs; self->colors[i] = col; self->decoration_fg[i] = dfg; @@ -166,23 +167,16 @@ set_text(Line* self, PyObject *args) { static PyObject* cursor_from(Line* self, PyObject *args) { #define cursor_from_doc "cursor_from(x, y=0) -> Create a cursor object based on the formatting attributes at the specified x position. The y value of the cursor is set as specified." - unsigned long x, y = 0; - PyObject *xo, *yo; + unsigned int x, y = 0; Cursor* ans; - if (!PyArg_ParseTuple(args, "k|k", &x, &y)) return NULL; + if (!PyArg_ParseTuple(args, "I|I", &x, &y)) return NULL; if (x >= self->xnum) { PyErr_SetString(PyExc_ValueError, "Out of bounds x"); return NULL; } ans = alloc_cursor(); if (ans == NULL) { PyErr_NoMemory(); return NULL; } - xo = PyLong_FromUnsignedLong(x); yo = PyLong_FromUnsignedLong(y); - if (xo == NULL || yo == NULL) { - Py_CLEAR(ans); Py_CLEAR(xo); Py_CLEAR(yo); - PyErr_NoMemory(); return NULL; - } - Py_CLEAR(ans->x); Py_CLEAR(ans->y); - ans->x = xo; ans->y = yo; + ans->x = x; ans->y = y; char_type attrs = self->chars[x] >> ATTRS_SHIFT; ATTRS_TO_CURSOR(attrs, ans); COLORS_TO_CURSOR(self->colors[x], ans); @@ -228,6 +222,15 @@ apply_cursor(Line* self, PyObject *args) { Py_RETURN_NONE; } +void line_right_shift(Line *self, unsigned int at, unsigned int num) { + for(index_type i = self->xnum - 1; i >= at + num; i--) { + COPY_SELF_CELL(i - num, i) + } + // Check if a wide character was split at the right edge + char_type w = (self->chars[self->xnum - 1] >> ATTRS_SHIFT) & 3; + if (w != 1) self->chars[self->xnum - 1] = (1 << ATTRS_SHIFT) | 32; +} + static PyObject* right_shift(Line *self, PyObject *args) { #define right_shift_doc "right_shift(at, num) -> ..." @@ -238,12 +241,7 @@ right_shift(Line *self, PyObject *args) { return NULL; } if (num > 0) { - for(index_type i = self->xnum - 1; i >= at + num; i--) { - COPY_SELF_CELL(i - num, i) - } - // Check if a wide character was split at the right edge - char_type w = (self->chars[self->xnum - 1] >> ATTRS_SHIFT) & 3; - if (w != 1) self->chars[self->xnum - 1] = (1 << ATTRS_SHIFT) | 32; + line_right_shift(self, at, num); } Py_RETURN_NONE; } @@ -261,20 +259,8 @@ left_shift(Line *self, PyObject *args) { Py_RETURN_NONE; } -static PyObject* -set_char(Line *self, PyObject *args) { -#define set_char_doc "set_char(at, ch, width=1, cursor=None) -> Set the character at the specified cell. If cursor is not None, also set attributes from that cursor." - unsigned int at, width=1; - int ch; - Cursor *cursor = NULL; +void line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Cursor *cursor) { char_type attrs; - - if (!PyArg_ParseTuple(args, "IC|IO!", &at, &ch, &width, &Cursor_Type, &cursor)) return NULL; - if (at >= self->xnum) { - PyErr_SetString(PyExc_ValueError, "Out of bounds"); - return NULL; - } - if (cursor == NULL) { attrs = (((self->chars[at] >> ATTRS_SHIFT) & ~3) | (width & 3)) << ATTRS_SHIFT; } else { @@ -284,6 +270,21 @@ set_char(Line *self, PyObject *args) { } self->chars[at] = (ch & CHAR_MASK) | attrs; self->combining_chars[at] = 0; +} + +static PyObject* +set_char(Line *self, PyObject *args) { +#define set_char_doc "set_char(at, ch, width=1, cursor=None) -> Set the character at the specified cell. If cursor is not None, also set attributes from that cursor." + unsigned int at, width=1; + int ch; + Cursor *cursor = NULL; + + if (!PyArg_ParseTuple(args, "IC|IO!", &at, &ch, &width, &Cursor_Type, &cursor)) return NULL; + if (at >= self->xnum) { + PyErr_SetString(PyExc_ValueError, "Out of bounds"); + return NULL; + } + line_set_char(self, at, ch, width, cursor); Py_RETURN_NONE; } diff --git a/kitty/modes.h b/kitty/modes.h index 4b2b04530..d54813afe 100644 --- a/kitty/modes.h +++ b/kitty/modes.h @@ -18,7 +18,7 @@ right margin are lost. Otherwise, new display characters replace old display characters at the cursor position. */ -#define IRM +#define IRM 4 // Private modes. diff --git a/kitty/parser.c b/kitty/parser.c index fdd268aed..fd3209f84 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -8,24 +8,12 @@ #include "data-types.h" #include "control-codes.h" -extern PyTypeObject Screen_Type; - #define NORMAL_STATE 0 #define ESC_STATE 1 #define CSI_STATE 2 #define OSC_STATE 3 #define DCS_STATE 4 -#define DECLARE_CH_SCREEN_HANDLER(name) extern bool screen_##name(Screen *screen, uint8_t ch); -DECLARE_CH_SCREEN_HANDLER(bell) -DECLARE_CH_SCREEN_HANDLER(backspace) -DECLARE_CH_SCREEN_HANDLER(tab) -DECLARE_CH_SCREEN_HANDLER(linefeed) -DECLARE_CH_SCREEN_HANDLER(carriage_return) -DECLARE_CH_SCREEN_HANDLER(shift_out) -DECLARE_CH_SCREEN_HANDLER(shift_in) -extern bool screen_draw(Screen *screen, uint8_t *buf, unsigned int buflen); - // Parse text {{{ static inline bool read_text(Screen *screen, uint8_t *buf, unsigned int buflen, unsigned int *pos) { diff --git a/kitty/savepoints.c b/kitty/savepoints.c new file mode 100644 index 000000000..e5182e578 --- /dev/null +++ b/kitty/savepoints.c @@ -0,0 +1,47 @@ +/* + * savepoints.c + * Copyright (C) 2016 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#include "data-types.h" + +static PyObject * +new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) { + Savepoint *self; + self = (Savepoint *)type->tp_alloc(type, 0); + return (PyObject*) self; +} + +static void +dealloc(Savepoint* self) { + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +// Boilerplate {{{ + +static PyMethodDef methods[] = { + {NULL} /* Sentinel */ +}; + + +PyTypeObject Savepoint_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "fast_data_types.Savepoint", + .tp_basicsize = sizeof(Savepoint), + .tp_dealloc = (destructor)dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "Savepoint", + .tp_methods = methods, + .tp_new = new, +}; + +INIT_TYPE(Savepoint) + +Savepoint *alloc_savepoint() { + return (Savepoint*)new(&Savepoint_Type, NULL, NULL); +} + +// }}} diff --git a/kitty/screen.c b/kitty/screen.c index d35835832..812229be7 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -6,19 +6,27 @@ */ #include "data-types.h" +#include +#include "unicode-data.h" +#include "tracker.h" +#include "modes.h" -static const ScreenModes empty_modes = {0}; +static const ScreenModes empty_modes = {0, .mDECAWM=true, .mDECTCEM=true}; +// Constructor/destructor {{{ static PyObject* new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { Screen *self; PyObject *callbacks = Py_None; - if (!PyArg_ParseTuple(args, "|O", &callbacks)) return NULL; + unsigned int columns, lines; + if (!PyArg_ParseTuple(args, "|OII", &callbacks, &lines, &columns)) return NULL; self = (Screen *)type->tp_alloc(type, 0); if (self != NULL) { self->current_charset = 2; - self->columns = 80; self->lines=24; + self->g0_charset = translation_table('B'); + self->g1_charset = translation_table('0'); + self->columns = columns; self->lines = lines; self->modes = empty_modes; self->utf8_state = 0; self->margin_top = 0; self->margin_bottom = self->lines - 1; @@ -42,60 +50,349 @@ dealloc(Screen* self) { Py_CLEAR(self->cursor); Py_CLEAR(self->main_linebuf); Py_CLEAR(self->alt_linebuf); Py_CLEAR(self->main_savepoints); Py_CLEAR(self->alt_savepoints); Py_CLEAR(self->change_tracker); Py_TYPE(self)->tp_free((PyObject*)self); -} +} // }}} -bool screen_bell(Screen UNUSED *scr, uint8_t ch) { +bool screen_bell(Screen UNUSED *self, uint8_t ch) { // {{{ FILE *f = fopen("/dev/tty", "w"); if (f != NULL) { fwrite(&ch, 1, 1, f); fclose(f); } return true; -} +} // }}} -bool screen_draw(Screen UNUSED *scr, uint8_t UNUSED ch) { + +bool screen_linefeed(Screen UNUSED *self, uint8_t UNUSED ch) { // TODO: Implement this return true; } -bool screen_backspace(Screen UNUSED *scr, uint8_t UNUSED ch) { - // TODO: Implement this - return true; -} - -bool screen_tab(Screen UNUSED *scr, uint8_t UNUSED ch) { +bool screen_carriage_return(Screen UNUSED *self, uint8_t UNUSED ch) { // TODO: Implement this return true; } -bool screen_linefeed(Screen UNUSED *scr, uint8_t UNUSED ch) { +// Draw text {{{ + +static inline int safe_wcwidth(uint32_t ch) { + int ans = wcwidth(ch); + if (ans < 0) ans = 1; + return MIN(2, ans); +} + +static inline bool +draw_codepoint(Screen UNUSED *self, uint32_t ch) { + if (is_ignored_char(ch)) return true; + int char_width = safe_wcwidth(ch); + int space_left_in_line = self->columns - self->cursor->x; + if (space_left_in_line < char_width) { + if (self->modes.mDECAWM) { + if (!screen_carriage_return(self, 13)) return false; + if (!screen_linefeed(self, 10)) return false; + self->linebuf->continued_map[self->cursor->y] = true; + } else { + self->cursor->x = self->columns - char_width; + } + } + if (char_width > 0) { + unsigned int cx = self->cursor->x; + linebuf_init_line(self->linebuf, self->cursor->y); + if (self->modes.mIRM) { + line_right_shift(self->linebuf->line, self->cursor->x, char_width); + } + line_set_char(self->linebuf->line, self->cursor->x, ch, char_width, self->cursor); + self->cursor->x++; + if (char_width == 2) { + line_set_char(self->linebuf->line, self->cursor->x, 0, 0, self->cursor); + self->cursor->x++; + } + unsigned int right = self->modes.mIRM ? self->columns - 1 : MIN((unsigned int)(MAX(self->cursor->x, 1) - 1), self->columns - 1); + tracker_update_cell_range(self->change_tracker, self->cursor->y, cx, right); + } else if (is_combining_char(ch)) { + if (self->cursor->x > 0) { + linebuf_init_line(self->linebuf, self->cursor->y); + line_add_combining_char(self->linebuf->line, ch, self->cursor->x - 1); + tracker_update_cell_range(self->change_tracker, self->cursor->y, self->cursor->x - 1, self->cursor->x - 1); + } else if (self->cursor->y > 0) { + linebuf_init_line(self->linebuf, self->cursor->y - 1); + line_add_combining_char(self->linebuf->line, ch, self->columns - 1); + tracker_update_cell_range(self->change_tracker, self->cursor->y - 1, self->columns - 1, self->columns - 1); + } + } + return true; +} + +static inline bool +screen_draw_utf8(Screen *self, uint8_t *buf, unsigned int buflen) { + uint32_t prev = UTF8_ACCEPT, codepoint = 0; + for (unsigned int i = 0; i < buflen; i++, prev = self->utf8_state) { + switch (decode_utf8(&self->utf8_state, &codepoint, buf[i])) { + case UTF8_ACCEPT: + if (!draw_codepoint(self, codepoint)) return false; + break; + case UTF8_REJECT: + self->utf8_state = UTF8_ACCEPT; + if (prev != UTF8_ACCEPT) i--; + break; + } + } + return true; +} + +static inline bool +screen_draw_charset(Screen *self, unsigned short *table, uint8_t *buf, unsigned int buflen) { + for (unsigned int i = 0; i < buflen; i++) { + if (!draw_codepoint(self, table[buf[i]])) return false; + } + return true; +} + +bool screen_draw(Screen *self, uint8_t *buf, unsigned int buflen) { + switch(self->current_charset) { + case 0: + return screen_draw_charset(self, self->g0_charset, buf, buflen); + break; + case 1: + return screen_draw_charset(self, self->g1_charset, buf, buflen); + break; + default: + return screen_draw_utf8(self, buf, buflen); break; + } +} +// }}} + +bool screen_backspace(Screen UNUSED *self, uint8_t UNUSED ch) { // TODO: Implement this return true; } -bool screen_carriage_return(Screen UNUSED *scr, uint8_t UNUSED ch) { +bool screen_tab(Screen UNUSED *self, uint8_t UNUSED ch) { // TODO: Implement this return true; } -bool screen_shift_out(Screen UNUSED *scr, uint8_t UNUSED ch) { +bool screen_shift_out(Screen UNUSED *self, uint8_t UNUSED ch) { // TODO: Implement this return true; } -bool screen_shift_in(Screen UNUSED *scr, uint8_t UNUSED ch) { +bool screen_shift_in(Screen UNUSED *self, uint8_t UNUSED ch) { // TODO: Implement this return true; } +bool screen_toggle_screen_buffer(Screen *self) { + if (!screen_save_cursor(self)) return false; + if (self->linebuf == self->main_linebuf) { + self->linebuf = self->alt_linebuf; + self->savepoints = self->alt_savepoints; + } else { + self->linebuf = self->main_linebuf; + self->savepoints = self->main_savepoints; + } + screen_restore_cursor(self); + tracker_update_screen(self->change_tracker); + return true; +} + + +// Modes {{{ + +static inline void set_mode_from_const(Screen *self, int mode, bool val) { + switch(mode) { + case LNM: + self->modes.mLNM = val; break; + case IRM: + self->modes.mIRM = val; break; + case DECTCEM: + self->modes.mDECTCEM = val; break; + case DECSCNM: + self->modes.mDECSCNM = val; break; + case DECOM: + self->modes.mDECOM = val; break; + case DECAWM: + self->modes.mDECAWM = val; break; + case DECCOLM: + self->modes.mDECCOLM = val; break; + case BRACKETED_PASTE: + self->modes.mBRACKETED_PASTE = val; break; + case FOCUS_TRACKING: + self->modes.mFOCUS_TRACKING = val; break; + } +} + +bool screen_set_mode(Screen *self, int mode) { + if (mode == DECCOLM) { + // When DECCOLM mode is set, the screen is erased and the cursor + // moves to the home position. + if (!screen_erase_in_display(self, 2, false)) return false; + if (!screen_cursor_position(self, 1, 1)) return false; + } + // According to `vttest`, DECOM should also home the cursor, see + // vttest/main.c:303. + if (mode == DECOM) { if (!screen_cursor_position(self, 1, 1)) return false; } + + if (mode == DECSCNM) { + // Mark all displayed characters as reverse. + linebuf_set_attribute(self->linebuf, REVERSE_SHIFT, 1); + tracker_update_screen(self->change_tracker); + self->cursor->reverse = true; + tracker_cursor_changed(self->change_tracker); + } + + if (mode == DECTCEM && self->cursor->hidden) { + self->cursor->hidden = false; + tracker_cursor_changed(self->change_tracker); + } + + if (mode == ALTERNATE_SCREEN && self->linebuf == self->main_linebuf) { + if (!screen_toggle_screen_buffer(self)) return false; + } + set_mode_from_const(self, mode, true); + return true; +} + +static PyObject* +in_bracketed_paste_mode(Screen *self) { +#define in_bracketed_paste_mode_doc "" + PyObject *ans = self->modes.mBRACKETED_PASTE ? Py_True : Py_False; + Py_INCREF(ans); + return ans; +} + +static PyObject* +enable_focus_tracking(Screen *self) { +#define enable_focus_tracking_doc "" + PyObject *ans = self->modes.mFOCUS_TRACKING ? Py_True : Py_False; + Py_INCREF(ans); + return ans; +} + +bool screen_reset_mode(Screen *self, int mode) { + if (mode == DECCOLM) { + // When DECCOLM mode is set, the screen is erased and the cursor + // moves to the home position. + if (!screen_erase_in_display(self, 2, false)) return false; + if (!screen_cursor_position(self, 1, 1)) return false; + } + // According to `vttest`, DECOM should also home the cursor, see + // vttest/main.c:303. + if (mode == DECOM) { if (!screen_cursor_position(self, 1, 1)) return false; } + + if (mode == DECSCNM) { + // Mark all displayed characters as reverse. + linebuf_set_attribute(self->linebuf, REVERSE_SHIFT, 0); + tracker_update_screen(self->change_tracker); + self->cursor->reverse = false; + tracker_cursor_changed(self->change_tracker); + } + + if (mode == DECTCEM && !self->cursor->hidden) { + self->cursor->hidden = true; + tracker_cursor_changed(self->change_tracker); + } + + if (mode == ALTERNATE_SCREEN && self->linebuf != self->main_linebuf) { + if (!screen_toggle_screen_buffer(self)) return false; + } + + set_mode_from_const(self, mode, false); + return true; +} +// }}} + +// Cursor {{{ +bool screen_save_cursor(Screen *self) { + Savepoint *sp = alloc_savepoint(); + if (sp == NULL) return false; + sp->cursor = cursor_copy(self->cursor); + if (sp->cursor == NULL) { Py_CLEAR(sp); return NULL; } + sp->g0_charset = self->g0_charset; + sp->g1_charset = self->g1_charset; + sp->current_charset = self->current_charset; + sp->mDECOM = self->modes.mDECOM; + sp->mDECAWM = self->modes.mDECAWM; + sp->utf8_state = self->utf8_state; + bool ret = PyList_Append(self->savepoints, (PyObject*)sp) == 0; + Py_CLEAR(sp); + return ret; +} + +bool screen_restore_cursor(Screen *self) { + Py_ssize_t sz = PyList_GET_SIZE(self->savepoints); + if (sz > 0) { + Savepoint *sp = (Savepoint*)PyList_GET_ITEM(self->savepoints, sz - 1); + self->g0_charset = sp->g0_charset; + self->g1_charset = sp->g1_charset; + self->current_charset = sp->current_charset; + self->utf8_state = sp->utf8_state; + if (sp->mDECOM) screen_set_mode(self, DECOM); + if (sp->mDECAWM) screen_set_mode(self, DECAWM); + PyList_SetSlice(self->savepoints, sz-1, sz, NULL); + } else { + screen_cursor_position(self, 1, 1); + tracker_cursor_changed(self->change_tracker); + screen_reset_mode(self, DECOM); + } + return true; +} + +bool screen_cursor_position(Screen UNUSED *self, unsigned int UNUSED line, unsigned int UNUSED column) { + return true; // TODO: Implement this +} + +// }}} + +// Editing {{{ +bool screen_erase_in_display(Screen UNUSED *self, unsigned int UNUSED how, bool UNUSED private) { + return true; // TODO: Implement this +} +// }}} + +bool screen_reset(Screen *self) { + if (self->linebuf == self->alt_linebuf) {if (!screen_toggle_screen_buffer(self)) return false; } + linebuf_clear(self->linebuf); + // TODO: Implement this + return true; +} + +static PyObject* +line(Screen *self, PyObject *val) { +#define line_doc "" + unsigned long y = PyLong_AsUnsignedLong(val); + if (y >= self->lines) { PyErr_SetString(PyExc_IndexError, "Out of bounds"); return NULL; } + linebuf_init_line(self->linebuf, y); + Py_INCREF(self->linebuf->line); + return (PyObject*) self->linebuf->line; +} + +static PyObject* +draw(Screen *self, PyObject *args) { +#define draw_doc "" + Py_buffer pybuf; + if(!PyArg_ParseTuple(args, "y*", &pybuf)) return NULL; + if (!screen_draw(self, pybuf.buf, pybuf.len)) return NULL; + Py_RETURN_NONE; +} + // Boilerplate {{{ static PyMethodDef methods[] = { + METHOD(line, METH_O) + METHOD(draw, METH_VARARGS) + METHOD(enable_focus_tracking, METH_NOARGS) + METHOD(in_bracketed_paste_mode, METH_NOARGS) + {NULL} /* Sentinel */ }; - +static PyMemberDef members[] = { + {"cursor", T_OBJECT_EX, offsetof(Screen, cursor), 0, "cursor"}, + {"linebuf", T_OBJECT_EX, offsetof(Screen, linebuf), 0, "linebuf"}, + {NULL} +}; + PyTypeObject Screen_Type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "fast_data_types.Screen", @@ -104,6 +401,7 @@ PyTypeObject Screen_Type = { .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "Screen", .tp_methods = methods, + .tp_members = members, .tp_new = new, }; diff --git a/kitty/screen.py b/kitty/screen.py index c4615195e..6f87f2925 100644 --- a/kitty/screen.py +++ b/kitty/screen.py @@ -11,7 +11,7 @@ from typing import Sequence from pyte import charsets as cs, graphics as g, modes as mo from .utils import wcwidth, is_simple_string, sanitize_title from .unicode import ignore_pat -from .fast_data_types import LineBuf, REVERSE, Cursor, ChangeTracker +from .fast_data_types import LineBuf, REVERSE, Cursor, ChangeTracker, CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE #: A container for screen's scroll margins. @@ -251,11 +251,9 @@ class Screen: if mo.ALTERNATE_SCREEN in self.mode and self.linebuf is self.main_linebuf: self.toggle_screen_buffer() - @property def in_bracketed_paste_mode(self): return mo.BRACKETED_PASTE in self.mode - @property def enable_focus_tracking(self): return mo.FOCUS_TRACKING in self.mode @@ -302,7 +300,6 @@ class Screen: from ``b"B0UK"``, otherwise ignored. :param str mode: if ``"("`` ``G0`` charset is defined, if ``")"`` -- we operate on ``G1``. - .. warning:: User-defined charsets are currently not supported. """ if code in cs.MAPS: @@ -984,7 +981,7 @@ class Screen: shape = blink = None if mode > 0: blink = bool(mode % 2) - shape = 'block' if mode < 3 else 'underline' if mode < 5 else 'beam' if mode < 7 else None + shape = CURSOR_BLOCK if mode < 3 else CURSOR_UNDERLINE if mode < 5 else CURSOR_BEAM if mode < 7 else None if shape != self.cursor.shape or blink != self.cursor.blink: self.cursor.shape, self.cursor.blink = shape, blink self.cursor_changed() diff --git a/kitty/sprites.c b/kitty/sprites.c index 477a491eb..3e658219e 100644 --- a/kitty/sprites.c +++ b/kitty/sprites.c @@ -7,10 +7,6 @@ #include "data-types.h" #include -extern PyTypeObject Line_Type; -extern PyTypeObject ColorProfile_Type; -extern uint32_t to_color(ColorProfile *, uint32_t, uint32_t); -extern PyObject* line_text_at(char_type, combining_type); static PyObject* new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { diff --git a/kitty/tracker.c b/kitty/tracker.c index 0986e00d0..b4338c21a 100644 --- a/kitty/tracker.c +++ b/kitty/tracker.c @@ -7,11 +7,6 @@ #include "data-types.h" #include "tracker.h" -extern PyTypeObject SpriteMap_Type; -extern PyTypeObject ColorProfile_Type; -extern PyTypeObject LineBuf_Type; -extern bool update_cell_range_data(SpriteMap *, Line *, unsigned int, unsigned int, ColorProfile *, const uint32_t, const uint32_t, unsigned int *); -extern void linebuf_init_line(LineBuf *, index_type); #define RESET_STATE_VARS(self) \ self->screen_changed = false; self->cursor_changed = false; self->dirty = false; self->history_line_added_count = 0; @@ -273,7 +268,7 @@ static PyMethodDef methods[] = { }; -static PyTypeObject ChangeTracker_Type = { +PyTypeObject ChangeTracker_Type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "fast_data_types.ChangeTracker", .tp_basicsize = sizeof(ChangeTracker), diff --git a/kitty/unicode-data.h b/kitty/unicode-data.h new file mode 100644 index 000000000..3deab3a95 --- /dev/null +++ b/kitty/unicode-data.h @@ -0,0 +1,11 @@ +#pragma once + +static inline bool is_combining_char(uint32_t ch) { + return (0x768 <= ch && ch <= 0x846)||(0x848 <= ch && ch <= 0x879)||(0x1155 <= ch && ch <= 0x1159)||(0x1425 <= ch && ch <= 0x1469)||(0x1473 <= ch && ch <= 0x1474)||(0x1476 <= ch && ch <= 0x1477)||(0x1552 <= ch && ch <= 0x1562)||(0x1611 <= ch && ch <= 0x1631)||(0x1750 <= ch && ch <= 0x1756)||(0x1759 <= ch && ch <= 0x1764)||(0x1767 <= ch && ch <= 0x1768)||(0x1770 <= ch && ch <= 0x1773)||(0x1840 <= ch && ch <= 0x1866)||(0x2027 <= ch && ch <= 0x2035)||(0x2070 <= ch && ch <= 0x2073)||(0x2075 <= ch && ch <= 0x2083)||(0x2085 <= ch && ch <= 0x2087)||(0x2089 <= ch && ch <= 0x2093)||(0x2137 <= ch && ch <= 0x2139)||(0x2275 <= ch && ch <= 0x2303)||(0x2385 <= ch && ch <= 0x2388)||(0x3157 <= ch && ch <= 0x3158)||(0x3640 <= ch && ch <= 0x3642)||(0x3656 <= ch && ch <= 0x3659)||(0x3768 <= ch && ch <= 0x3769)||(0x3784 <= ch && ch <= 0x3787)||(0x3864 <= ch && ch <= 0x3865)||(0x3953 <= ch && ch <= 0x3954)||(0x3962 <= ch && ch <= 0x3965)||(0x3970 <= ch && ch <= 0x3972)||(0x3974 <= ch && ch <= 0x3975)||(0x4153 <= ch && ch <= 0x4154)||(0x4957 <= ch && ch <= 0x4959)||(0x6457 <= ch && ch <= 0x6459)||(0x6679 <= ch && ch <= 0x6680)||(0x6773 <= ch && ch <= 0x6780)||(0x6832 <= ch && ch <= 0x6845)||(0x7019 <= ch && ch <= 0x7027)||(0x7082 <= ch && ch <= 0x7083)||(0x7154 <= ch && ch <= 0x7155)||(0x7376 <= ch && ch <= 0x7378)||(0x7380 <= ch && ch <= 0x7392)||(0x7394 <= ch && ch <= 0x7400)||(0x7416 <= ch && ch <= 0x7417)||(0x7616 <= ch && ch <= 0x7669)||(0x7676 <= ch && ch <= 0x7679)||(0x8400 <= ch && ch <= 0x8412)||(0x8421 <= ch && ch <= 0x8432)||(0x11503 <= ch && ch <= 0x11505)||(0x11744 <= ch && ch <= 0x11775)||(0x12330 <= ch && ch <= 0x12335)||(0x12441 <= ch && ch <= 0x12442)||(0x42612 <= ch && ch <= 0x42621)||(0x42654 <= ch && ch <= 0x42655)||(0x42736 <= ch && ch <= 0x42737)||(0x43232 <= ch && ch <= 0x43249)||(0x43307 <= ch && ch <= 0x43309)||(0x43698 <= ch && ch <= 0x43700)||(0x43703 <= ch && ch <= 0x43704)||(0x43710 <= ch && ch <= 0x43711)||(0x65056 <= ch && ch <= 0x65071)||(0x66422 <= ch && ch <= 0x66426)||(0x68152 <= ch && ch <= 0x68154)||(0x68325 <= ch && ch <= 0x68326)||(0x69817 <= ch && ch <= 0x69818)||(0x69888 <= ch && ch <= 0x69890)||(0x69939 <= ch && ch <= 0x69940)||(0x70197 <= ch && ch <= 0x70198)||(0x70377 <= ch && ch <= 0x70378)||(0x70502 <= ch && ch <= 0x70508)||(0x70512 <= ch && ch <= 0x70516)||(0x70850 <= ch && ch <= 0x70851)||(0x71103 <= ch && ch <= 0x71104)||(0x71350 <= ch && ch <= 0x71351)||(0x92912 <= ch && ch <= 0x92916)||(0x92976 <= ch && ch <= 0x92982)||(0x119141 <= ch && ch <= 0x119145)||(0x119149 <= ch && ch <= 0x119154)||(0x119163 <= ch && ch <= 0x119170)||(0x119173 <= ch && ch <= 0x119179)||(0x119210 <= ch && ch <= 0x119213)||(0x119362 <= ch && ch <= 0x119364)||(0x125136 <= ch && ch <= 0x125142) || (ch == 0x5bf)||(ch == 0x5c7)||(ch == 0x670)||(ch == 0x711)||(ch == 0x93c)||(ch == 0x94d)||(ch == 0x9bc)||(ch == 0x9cd)||(ch == 0xa3c)||(ch == 0xa4d)||(ch == 0xabc)||(ch == 0xacd)||(ch == 0xb3c)||(ch == 0xb4d)||(ch == 0xbcd)||(ch == 0xc4d)||(ch == 0xcbc)||(ch == 0xccd)||(ch == 0xd4d)||(ch == 0xdca)||(ch == 0xf35)||(ch == 0xf37)||(ch == 0xf39)||(ch == 0xf74)||(ch == 0xf80)||(ch == 0xfc6)||(ch == 0x1037)||(ch == 0x108d)||(ch == 0x1714)||(ch == 0x1734)||(ch == 0x17d2)||(ch == 0x17dd)||(ch == 0x18a9)||(ch == 0x1a60)||(ch == 0x1a7f)||(ch == 0x1b34)||(ch == 0x1b44)||(ch == 0x1be6)||(ch == 0x1c37)||(ch == 0x1ced)||(ch == 0x1cf4)||(ch == 0x20e1)||(ch == 0x2d7f)||(ch == 0xa66f)||(ch == 0xa806)||(ch == 0xa8c4)||(ch == 0xa953)||(ch == 0xa9b3)||(ch == 0xa9c0)||(ch == 0xaab0)||(ch == 0xaac1)||(ch == 0xaaf6)||(ch == 0xabed)||(ch == 0xfb1e)||(ch == 0x101fd)||(ch == 0x102e0)||(ch == 0x10a0d)||(ch == 0x10a0f)||(ch == 0x10a3f)||(ch == 0x11046)||(ch == 0x1107f)||(ch == 0x11173)||(ch == 0x111c0)||(ch == 0x111ca)||(ch == 0x1133c)||(ch == 0x1134d)||(ch == 0x1163f)||(ch == 0x1172b)||(ch == 0x1bc9e); +} + + +static inline bool is_ignored_char(uint32_t ch) { + return (0x0 < ch && ch <= 0x31)||(0x127 <= ch && ch <= 0x159)||(0x888 <= ch && ch <= 0x889)||(0x896 <= ch && ch <= 0x899)||(0x1367 <= ch && ch <= 0x1368)||(0x1419 <= ch && ch <= 0x1420)||(0x1480 <= ch && ch <= 0x1487)||(0x1515 <= ch && ch <= 0x1519)||(0x1525 <= ch && ch <= 0x1541)||(0x1564 <= ch && ch <= 0x1565)||(0x1806 <= ch && ch <= 0x1807)||(0x1867 <= ch && ch <= 0x1868)||(0x1970 <= ch && ch <= 0x1983)||(0x2043 <= ch && ch <= 0x2047)||(0x2094 <= ch && ch <= 0x2095)||(0x2140 <= ch && ch <= 0x2141)||(0x2143 <= ch && ch <= 0x2207)||(0x2229 <= ch && ch <= 0x2274)||(0x2445 <= ch && ch <= 0x2446)||(0x2449 <= ch && ch <= 0x2450)||(0x2483 <= ch && ch <= 0x2485)||(0x2490 <= ch && ch <= 0x2491)||(0x2501 <= ch && ch <= 0x2502)||(0x2505 <= ch && ch <= 0x2506)||(0x2511 <= ch && ch <= 0x2518)||(0x2520 <= ch && ch <= 0x2523)||(0x2532 <= ch && ch <= 0x2533)||(0x2556 <= ch && ch <= 0x2560)||(0x2571 <= ch && ch <= 0x2574)||(0x2577 <= ch && ch <= 0x2578)||(0x2618 <= ch && ch <= 0x2619)||(0x2627 <= ch && ch <= 0x2630)||(0x2633 <= ch && ch <= 0x2634)||(0x2638 <= ch && ch <= 0x2640)||(0x2642 <= ch && ch <= 0x2648)||(0x2655 <= ch && ch <= 0x2661)||(0x2678 <= ch && ch <= 0x2688)||(0x2746 <= ch && ch <= 0x2747)||(0x2766 <= ch && ch <= 0x2767)||(0x2769 <= ch && ch <= 0x2783)||(0x2788 <= ch && ch <= 0x2789)||(0x2802 <= ch && ch <= 0x2808)||(0x2810 <= ch && ch <= 0x2816)||(0x2829 <= ch && ch <= 0x2830)||(0x2833 <= ch && ch <= 0x2834)||(0x2874 <= ch && ch <= 0x2875)||(0x2885 <= ch && ch <= 0x2886)||(0x2889 <= ch && ch <= 0x2890)||(0x2894 <= ch && ch <= 0x2901)||(0x2904 <= ch && ch <= 0x2907)||(0x2916 <= ch && ch <= 0x2917)||(0x2936 <= ch && ch <= 0x2945)||(0x2955 <= ch && ch <= 0x2957)||(0x2966 <= ch && ch <= 0x2968)||(0x2976 <= ch && ch <= 0x2978)||(0x2981 <= ch && ch <= 0x2983)||(0x2987 <= ch && ch <= 0x2989)||(0x3002 <= ch && ch <= 0x3005)||(0x3011 <= ch && ch <= 0x3013)||(0x3022 <= ch && ch <= 0x3023)||(0x3025 <= ch && ch <= 0x3030)||(0x3032 <= ch && ch <= 0x3045)||(0x3067 <= ch && ch <= 0x3071)||(0x3130 <= ch && ch <= 0x3132)||(0x3150 <= ch && ch <= 0x3156)||(0x3163 <= ch && ch <= 0x3167)||(0x3172 <= ch && ch <= 0x3173)||(0x3184 <= ch && ch <= 0x3191)||(0x3258 <= ch && ch <= 0x3259)||(0x3278 <= ch && ch <= 0x3284)||(0x3287 <= ch && ch <= 0x3293)||(0x3300 <= ch && ch <= 0x3301)||(0x3315 <= ch && ch <= 0x3328)||(0x3387 <= ch && ch <= 0x3388)||(0x3407 <= ch && ch <= 0x3414)||(0x3416 <= ch && ch <= 0x3422)||(0x3428 <= ch && ch <= 0x3429)||(0x3446 <= ch && ch <= 0x3448)||(0x3456 <= ch && ch <= 0x3457)||(0x3479 <= ch && ch <= 0x3481)||(0x3518 <= ch && ch <= 0x3519)||(0x3527 <= ch && ch <= 0x3529)||(0x3531 <= ch && ch <= 0x3534)||(0x3552 <= ch && ch <= 0x3557)||(0x3568 <= ch && ch <= 0x3569)||(0x3573 <= ch && ch <= 0x3584)||(0x3643 <= ch && ch <= 0x3646)||(0x3676 <= ch && ch <= 0x3712)||(0x3717 <= ch && ch <= 0x3718)||(0x3723 <= ch && ch <= 0x3724)||(0x3726 <= ch && ch <= 0x3731)||(0x3752 <= ch && ch <= 0x3753)||(0x3774 <= ch && ch <= 0x3775)||(0x3790 <= ch && ch <= 0x3791)||(0x3802 <= ch && ch <= 0x3803)||(0x3808 <= ch && ch <= 0x3839)||(0x3949 <= ch && ch <= 0x3952)||(0x4059 <= ch && ch <= 0x4095)||(0x4296 <= ch && ch <= 0x4300)||(0x4302 <= ch && ch <= 0x4303)||(0x4686 <= ch && ch <= 0x4687)||(0x4702 <= ch && ch <= 0x4703)||(0x4750 <= ch && ch <= 0x4751)||(0x4790 <= ch && ch <= 0x4791)||(0x4806 <= ch && ch <= 0x4807)||(0x4886 <= ch && ch <= 0x4887)||(0x4955 <= ch && ch <= 0x4956)||(0x4989 <= ch && ch <= 0x4991)||(0x5018 <= ch && ch <= 0x5023)||(0x5110 <= ch && ch <= 0x5111)||(0x5118 <= ch && ch <= 0x5119)||(0x5789 <= ch && ch <= 0x5791)||(0x5881 <= ch && ch <= 0x5887)||(0x5909 <= ch && ch <= 0x5919)||(0x5943 <= ch && ch <= 0x5951)||(0x5972 <= ch && ch <= 0x5983)||(0x6004 <= ch && ch <= 0x6015)||(0x6110 <= ch && ch <= 0x6111)||(0x6122 <= ch && ch <= 0x6127)||(0x6138 <= ch && ch <= 0x6143)||(0x6158 <= ch && ch <= 0x6159)||(0x6170 <= ch && ch <= 0x6175)||(0x6264 <= ch && ch <= 0x6271)||(0x6315 <= ch && ch <= 0x6319)||(0x6390 <= ch && ch <= 0x6399)||(0x6444 <= ch && ch <= 0x6447)||(0x6460 <= ch && ch <= 0x6463)||(0x6465 <= ch && ch <= 0x6467)||(0x6510 <= ch && ch <= 0x6511)||(0x6517 <= ch && ch <= 0x6527)||(0x6572 <= ch && ch <= 0x6575)||(0x6602 <= ch && ch <= 0x6607)||(0x6619 <= ch && ch <= 0x6621)||(0x6684 <= ch && ch <= 0x6685)||(0x6781 <= ch && ch <= 0x6782)||(0x6794 <= ch && ch <= 0x6799)||(0x6810 <= ch && ch <= 0x6815)||(0x6830 <= ch && ch <= 0x6831)||(0x6847 <= ch && ch <= 0x6911)||(0x6988 <= ch && ch <= 0x6991)||(0x7037 <= ch && ch <= 0x7039)||(0x7156 <= ch && ch <= 0x7163)||(0x7224 <= ch && ch <= 0x7226)||(0x7242 <= ch && ch <= 0x7244)||(0x7296 <= ch && ch <= 0x7359)||(0x7368 <= ch && ch <= 0x7375)||(0x7418 <= ch && ch <= 0x7423)||(0x7670 <= ch && ch <= 0x7675)||(0x7958 <= ch && ch <= 0x7959)||(0x7966 <= ch && ch <= 0x7967)||(0x8006 <= ch && ch <= 0x8007)||(0x8014 <= ch && ch <= 0x8015)||(0x8062 <= ch && ch <= 0x8063)||(0x8148 <= ch && ch <= 0x8149)||(0x8176 <= ch && ch <= 0x8177)||(0x8203 <= ch && ch <= 0x8207)||(0x8234 <= ch && ch <= 0x8238)||(0x8288 <= ch && ch <= 0x8303)||(0x8306 <= ch && ch <= 0x8307)||(0x8349 <= ch && ch <= 0x8351)||(0x8383 <= ch && ch <= 0x8399)||(0x8433 <= ch && ch <= 0x8447)||(0x8588 <= ch && ch <= 0x8591)||(0x9211 <= ch && ch <= 0x9215)||(0x9255 <= ch && ch <= 0x9279)||(0x9291 <= ch && ch <= 0x9311)||(0x11124 <= ch && ch <= 0x11125)||(0x11158 <= ch && ch <= 0x11159)||(0x11194 <= ch && ch <= 0x11196)||(0x11218 <= ch && ch <= 0x11243)||(0x11248 <= ch && ch <= 0x11263)||(0x11508 <= ch && ch <= 0x11512)||(0x11560 <= ch && ch <= 0x11564)||(0x11566 <= ch && ch <= 0x11567)||(0x11624 <= ch && ch <= 0x11630)||(0x11633 <= ch && ch <= 0x11646)||(0x11671 <= ch && ch <= 0x11679)||(0x11843 <= ch && ch <= 0x11903)||(0x12020 <= ch && ch <= 0x12031)||(0x12246 <= ch && ch <= 0x12271)||(0x12284 <= ch && ch <= 0x12287)||(0x12439 <= ch && ch <= 0x12440)||(0x12544 <= ch && ch <= 0x12548)||(0x12590 <= ch && ch <= 0x12592)||(0x12731 <= ch && ch <= 0x12735)||(0x12772 <= ch && ch <= 0x12783)||(0x19894 <= ch && ch <= 0x19903)||(0x40918 <= ch && ch <= 0x40959)||(0x42125 <= ch && ch <= 0x42127)||(0x42183 <= ch && ch <= 0x42191)||(0x42540 <= ch && ch <= 0x42559)||(0x42744 <= ch && ch <= 0x42751)||(0x42926 <= ch && ch <= 0x42927)||(0x42936 <= ch && ch <= 0x42998)||(0x43052 <= ch && ch <= 0x43055)||(0x43066 <= ch && ch <= 0x43071)||(0x43128 <= ch && ch <= 0x43135)||(0x43205 <= ch && ch <= 0x43213)||(0x43226 <= ch && ch <= 0x43231)||(0x43262 <= ch && ch <= 0x43263)||(0x43348 <= ch && ch <= 0x43358)||(0x43389 <= ch && ch <= 0x43391)||(0x43482 <= ch && ch <= 0x43485)||(0x43575 <= ch && ch <= 0x43583)||(0x43598 <= ch && ch <= 0x43599)||(0x43610 <= ch && ch <= 0x43611)||(0x43715 <= ch && ch <= 0x43738)||(0x43767 <= ch && ch <= 0x43776)||(0x43783 <= ch && ch <= 0x43784)||(0x43791 <= ch && ch <= 0x43792)||(0x43799 <= ch && ch <= 0x43807)||(0x43878 <= ch && ch <= 0x43887)||(0x44014 <= ch && ch <= 0x44015)||(0x44026 <= ch && ch <= 0x44031)||(0x55204 <= ch && ch <= 0x55215)||(0x55239 <= ch && ch <= 0x55242)||(0x55292 <= ch && ch <= 0x57343)||(0x64110 <= ch && ch <= 0x64111)||(0x64218 <= ch && ch <= 0x64255)||(0x64263 <= ch && ch <= 0x64274)||(0x64280 <= ch && ch <= 0x64284)||(0x64450 <= ch && ch <= 0x64466)||(0x64832 <= ch && ch <= 0x64847)||(0x64912 <= ch && ch <= 0x64913)||(0x64968 <= ch && ch <= 0x65007)||(0x65022 <= ch && ch <= 0x65023)||(0x65050 <= ch && ch <= 0x65055)||(0x65132 <= ch && ch <= 0x65135)||(0x65277 <= ch && ch <= 0x65280)||(0x65471 <= ch && ch <= 0x65473)||(0x65480 <= ch && ch <= 0x65481)||(0x65488 <= ch && ch <= 0x65489)||(0x65496 <= ch && ch <= 0x65497)||(0x65501 <= ch && ch <= 0x65503)||(0x65519 <= ch && ch <= 0x65531)||(0x65534 <= ch && ch <= 0x65535)||(0x65614 <= ch && ch <= 0x65615)||(0x65630 <= ch && ch <= 0x65663)||(0x65787 <= ch && ch <= 0x65791)||(0x65795 <= ch && ch <= 0x65798)||(0x65844 <= ch && ch <= 0x65846)||(0x65933 <= ch && ch <= 0x65935)||(0x65948 <= ch && ch <= 0x65951)||(0x65953 <= ch && ch <= 0x65999)||(0x66046 <= ch && ch <= 0x66175)||(0x66205 <= ch && ch <= 0x66207)||(0x66257 <= ch && ch <= 0x66271)||(0x66300 <= ch && ch <= 0x66303)||(0x66340 <= ch && ch <= 0x66351)||(0x66379 <= ch && ch <= 0x66383)||(0x66427 <= ch && ch <= 0x66431)||(0x66500 <= ch && ch <= 0x66503)||(0x66518 <= ch && ch <= 0x66559)||(0x66718 <= ch && ch <= 0x66719)||(0x66730 <= ch && ch <= 0x66815)||(0x66856 <= ch && ch <= 0x66863)||(0x66916 <= ch && ch <= 0x66926)||(0x66928 <= ch && ch <= 0x67071)||(0x67383 <= ch && ch <= 0x67391)||(0x67414 <= ch && ch <= 0x67423)||(0x67432 <= ch && ch <= 0x67583)||(0x67590 <= ch && ch <= 0x67591)||(0x67641 <= ch && ch <= 0x67643)||(0x67645 <= ch && ch <= 0x67646)||(0x67743 <= ch && ch <= 0x67750)||(0x67760 <= ch && ch <= 0x67807)||(0x67830 <= ch && ch <= 0x67834)||(0x67868 <= ch && ch <= 0x67870)||(0x67898 <= ch && ch <= 0x67902)||(0x67904 <= ch && ch <= 0x67967)||(0x68024 <= ch && ch <= 0x68027)||(0x68048 <= ch && ch <= 0x68049)||(0x68103 <= ch && ch <= 0x68107)||(0x68148 <= ch && ch <= 0x68151)||(0x68155 <= ch && ch <= 0x68158)||(0x68168 <= ch && ch <= 0x68175)||(0x68185 <= ch && ch <= 0x68191)||(0x68256 <= ch && ch <= 0x68287)||(0x68327 <= ch && ch <= 0x68330)||(0x68343 <= ch && ch <= 0x68351)||(0x68406 <= ch && ch <= 0x68408)||(0x68438 <= ch && ch <= 0x68439)||(0x68467 <= ch && ch <= 0x68471)||(0x68498 <= ch && ch <= 0x68504)||(0x68509 <= ch && ch <= 0x68520)||(0x68528 <= ch && ch <= 0x68607)||(0x68681 <= ch && ch <= 0x68735)||(0x68787 <= ch && ch <= 0x68799)||(0x68851 <= ch && ch <= 0x68857)||(0x68864 <= ch && ch <= 0x69215)||(0x69247 <= ch && ch <= 0x69631)||(0x69710 <= ch && ch <= 0x69713)||(0x69744 <= ch && ch <= 0x69758)||(0x69826 <= ch && ch <= 0x69839)||(0x69865 <= ch && ch <= 0x69871)||(0x69882 <= ch && ch <= 0x69887)||(0x69956 <= ch && ch <= 0x69967)||(0x70007 <= ch && ch <= 0x70015)||(0x70094 <= ch && ch <= 0x70095)||(0x70133 <= ch && ch <= 0x70143)||(0x70206 <= ch && ch <= 0x70271)||(0x70314 <= ch && ch <= 0x70319)||(0x70379 <= ch && ch <= 0x70383)||(0x70394 <= ch && ch <= 0x70399)||(0x70413 <= ch && ch <= 0x70414)||(0x70417 <= ch && ch <= 0x70418)||(0x70458 <= ch && ch <= 0x70459)||(0x70469 <= ch && ch <= 0x70470)||(0x70473 <= ch && ch <= 0x70474)||(0x70478 <= ch && ch <= 0x70479)||(0x70481 <= ch && ch <= 0x70486)||(0x70488 <= ch && ch <= 0x70492)||(0x70500 <= ch && ch <= 0x70501)||(0x70509 <= ch && ch <= 0x70511)||(0x70517 <= ch && ch <= 0x70783)||(0x70856 <= ch && ch <= 0x70863)||(0x70874 <= ch && ch <= 0x71039)||(0x71094 <= ch && ch <= 0x71095)||(0x71134 <= ch && ch <= 0x71167)||(0x71237 <= ch && ch <= 0x71247)||(0x71258 <= ch && ch <= 0x71295)||(0x71352 <= ch && ch <= 0x71359)||(0x71370 <= ch && ch <= 0x71423)||(0x71450 <= ch && ch <= 0x71452)||(0x71468 <= ch && ch <= 0x71471)||(0x71488 <= ch && ch <= 0x71839)||(0x71923 <= ch && ch <= 0x71934)||(0x71936 <= ch && ch <= 0x72383)||(0x72441 <= ch && ch <= 0x73727)||(0x74650 <= ch && ch <= 0x74751)||(0x74869 <= ch && ch <= 0x74879)||(0x75076 <= ch && ch <= 0x77823)||(0x78895 <= ch && ch <= 0x82943)||(0x83527 <= ch && ch <= 0x92159)||(0x92729 <= ch && ch <= 0x92735)||(0x92778 <= ch && ch <= 0x92781)||(0x92784 <= ch && ch <= 0x92879)||(0x92910 <= ch && ch <= 0x92911)||(0x92918 <= ch && ch <= 0x92927)||(0x92998 <= ch && ch <= 0x93007)||(0x93048 <= ch && ch <= 0x93052)||(0x93072 <= ch && ch <= 0x93951)||(0x94021 <= ch && ch <= 0x94031)||(0x94079 <= ch && ch <= 0x94094)||(0x94112 <= ch && ch <= 0x110591)||(0x110594 <= ch && ch <= 0x113663)||(0x113771 <= ch && ch <= 0x113775)||(0x113789 <= ch && ch <= 0x113791)||(0x113801 <= ch && ch <= 0x113807)||(0x113818 <= ch && ch <= 0x113819)||(0x113824 <= ch && ch <= 0x118783)||(0x119030 <= ch && ch <= 0x119039)||(0x119079 <= ch && ch <= 0x119080)||(0x119155 <= ch && ch <= 0x119162)||(0x119273 <= ch && ch <= 0x119295)||(0x119366 <= ch && ch <= 0x119551)||(0x119639 <= ch && ch <= 0x119647)||(0x119666 <= ch && ch <= 0x119807)||(0x119968 <= ch && ch <= 0x119969)||(0x119971 <= ch && ch <= 0x119972)||(0x119975 <= ch && ch <= 0x119976)||(0x120075 <= ch && ch <= 0x120076)||(0x120135 <= ch && ch <= 0x120137)||(0x120486 <= ch && ch <= 0x120487)||(0x120780 <= ch && ch <= 0x120781)||(0x121484 <= ch && ch <= 0x121498)||(0x121520 <= ch && ch <= 0x124927)||(0x125125 <= ch && ch <= 0x125126)||(0x125143 <= ch && ch <= 0x126463)||(0x126501 <= ch && ch <= 0x126502)||(0x126524 <= ch && ch <= 0x126529)||(0x126531 <= ch && ch <= 0x126534)||(0x126549 <= ch && ch <= 0x126550)||(0x126565 <= ch && ch <= 0x126566)||(0x126620 <= ch && ch <= 0x126624)||(0x126652 <= ch && ch <= 0x126703)||(0x126706 <= ch && ch <= 0x126975)||(0x127020 <= ch && ch <= 0x127023)||(0x127124 <= ch && ch <= 0x127135)||(0x127151 <= ch && ch <= 0x127152)||(0x127222 <= ch && ch <= 0x127231)||(0x127245 <= ch && ch <= 0x127247)||(0x127340 <= ch && ch <= 0x127343)||(0x127387 <= ch && ch <= 0x127461)||(0x127491 <= ch && ch <= 0x127503)||(0x127547 <= ch && ch <= 0x127551)||(0x127561 <= ch && ch <= 0x127567)||(0x127570 <= ch && ch <= 0x127743)||(0x128721 <= ch && ch <= 0x128735)||(0x128749 <= ch && ch <= 0x128751)||(0x128756 <= ch && ch <= 0x128767)||(0x128884 <= ch && ch <= 0x128895)||(0x128981 <= ch && ch <= 0x129023)||(0x129036 <= ch && ch <= 0x129039)||(0x129096 <= ch && ch <= 0x129103)||(0x129114 <= ch && ch <= 0x129119)||(0x129160 <= ch && ch <= 0x129167)||(0x129198 <= ch && ch <= 0x129295)||(0x129305 <= ch && ch <= 0x129407)||(0x129413 <= ch && ch <= 0x129471)||(0x129473 <= ch && ch <= 0x131071)||(0x173783 <= ch && ch <= 0x173823)||(0x177973 <= ch && ch <= 0x177983)||(0x178206 <= ch && ch <= 0x178207)||(0x183970 <= ch && ch <= 0x194559)||(0x195102 <= ch && ch <= 0x917759)||(0x918000 <= ch && ch <= 0x983039)||(0x1048574 <= ch && ch <= 0x1048575)||(0x1114110 <= ch && ch <= 0x1114111) || (ch == 0xad)||(ch == 0x38b)||(ch == 0x38d)||(ch == 0x3a2)||(ch == 0x530)||(ch == 0x560)||(ch == 0x588)||(ch == 0x590)||(ch == 0x6dd)||(ch == 0x83f)||(ch == 0x984)||(ch == 0x9a9)||(ch == 0x9b1)||(ch == 0x9de)||(ch == 0xa04)||(ch == 0xa29)||(ch == 0xa31)||(ch == 0xa34)||(ch == 0xa37)||(ch == 0xa3d)||(ch == 0xa5d)||(ch == 0xa84)||(ch == 0xa8e)||(ch == 0xa92)||(ch == 0xaa9)||(ch == 0xab1)||(ch == 0xab4)||(ch == 0xac6)||(ch == 0xaca)||(ch == 0xb04)||(ch == 0xb29)||(ch == 0xb31)||(ch == 0xb34)||(ch == 0xb5e)||(ch == 0xb84)||(ch == 0xb91)||(ch == 0xb9b)||(ch == 0xb9d)||(ch == 0xbc9)||(ch == 0xc04)||(ch == 0xc0d)||(ch == 0xc11)||(ch == 0xc29)||(ch == 0xc45)||(ch == 0xc49)||(ch == 0xc57)||(ch == 0xc80)||(ch == 0xc84)||(ch == 0xc8d)||(ch == 0xc91)||(ch == 0xca9)||(ch == 0xcb4)||(ch == 0xcc5)||(ch == 0xcc9)||(ch == 0xcdf)||(ch == 0xcf0)||(ch == 0xd04)||(ch == 0xd0d)||(ch == 0xd11)||(ch == 0xd45)||(ch == 0xd49)||(ch == 0xd84)||(ch == 0xdb2)||(ch == 0xdbc)||(ch == 0xdd5)||(ch == 0xdd7)||(ch == 0xe83)||(ch == 0xe89)||(ch == 0xe98)||(ch == 0xea0)||(ch == 0xea4)||(ch == 0xea6)||(ch == 0xeac)||(ch == 0xeba)||(ch == 0xec5)||(ch == 0xec7)||(ch == 0xf48)||(ch == 0xf98)||(ch == 0xfbd)||(ch == 0xfcd)||(ch == 0x10c6)||(ch == 0x1249)||(ch == 0x1257)||(ch == 0x1259)||(ch == 0x1289)||(ch == 0x12b1)||(ch == 0x12bf)||(ch == 0x12c1)||(ch == 0x12d7)||(ch == 0x1311)||(ch == 0x170d)||(ch == 0x176d)||(ch == 0x1771)||(ch == 0x191f)||(ch == 0x1a5f)||(ch == 0x1cf7)||(ch == 0x1f58)||(ch == 0x1f5a)||(ch == 0x1f5c)||(ch == 0x1f5e)||(ch == 0x1fb5)||(ch == 0x1fc5)||(ch == 0x1fdc)||(ch == 0x1ff5)||(ch == 0x1fff)||(ch == 0x208f)||(ch == 0x2bc9)||(ch == 0x2c2f)||(ch == 0x2c5f)||(ch == 0x2d26)||(ch == 0x2da7)||(ch == 0x2daf)||(ch == 0x2db7)||(ch == 0x2dbf)||(ch == 0x2dc7)||(ch == 0x2dcf)||(ch == 0x2dd7)||(ch == 0x2ddf)||(ch == 0x2e9a)||(ch == 0x3040)||(ch == 0x318f)||(ch == 0x321f)||(ch == 0x32ff)||(ch == 0xa9ce)||(ch == 0xa9ff)||(ch == 0xab27)||(ch == 0xab2f)||(ch == 0xfb37)||(ch == 0xfb3d)||(ch == 0xfb3f)||(ch == 0xfb42)||(ch == 0xfb45)||(ch == 0xfe53)||(ch == 0xfe67)||(ch == 0xfe75)||(ch == 0xffe7)||(ch == 0x1000c)||(ch == 0x10027)||(ch == 0x1003b)||(ch == 0x1003e)||(ch == 0x1039e)||(ch == 0x10809)||(ch == 0x10836)||(ch == 0x10856)||(ch == 0x108f3)||(ch == 0x10a04)||(ch == 0x10a14)||(ch == 0x10a18)||(ch == 0x110bd)||(ch == 0x11135)||(ch == 0x111e0)||(ch == 0x11212)||(ch == 0x11287)||(ch == 0x11289)||(ch == 0x1128e)||(ch == 0x1129e)||(ch == 0x11304)||(ch == 0x11329)||(ch == 0x11331)||(ch == 0x11334)||(ch == 0x1246f)||(ch == 0x16a5f)||(ch == 0x16b5a)||(ch == 0x16b62)||(ch == 0x1d455)||(ch == 0x1d49d)||(ch == 0x1d4ad)||(ch == 0x1d4ba)||(ch == 0x1d4bc)||(ch == 0x1d4c4)||(ch == 0x1d506)||(ch == 0x1d515)||(ch == 0x1d51d)||(ch == 0x1d53a)||(ch == 0x1d53f)||(ch == 0x1d545)||(ch == 0x1d551)||(ch == 0x1daa0)||(ch == 0x1ee04)||(ch == 0x1ee20)||(ch == 0x1ee23)||(ch == 0x1ee28)||(ch == 0x1ee33)||(ch == 0x1ee38)||(ch == 0x1ee3a)||(ch == 0x1ee48)||(ch == 0x1ee4a)||(ch == 0x1ee4c)||(ch == 0x1ee50)||(ch == 0x1ee53)||(ch == 0x1ee58)||(ch == 0x1ee5a)||(ch == 0x1ee5c)||(ch == 0x1ee5e)||(ch == 0x1ee60)||(ch == 0x1ee63)||(ch == 0x1ee6b)||(ch == 0x1ee73)||(ch == 0x1ee78)||(ch == 0x1ee7d)||(ch == 0x1ee7f)||(ch == 0x1ee8a)||(ch == 0x1eea4)||(ch == 0x1eeaa)||(ch == 0x1f0c0)||(ch == 0x1f0d0)||(ch == 0x1f12f)||(ch == 0x1f57a)||(ch == 0x1f5a4); +} + diff --git a/kitty_tests/__init__.py b/kitty_tests/__init__.py index e1949d568..64ebda3d7 100644 --- a/kitty_tests/__init__.py +++ b/kitty_tests/__init__.py @@ -4,8 +4,8 @@ from unittest import TestCase -from kitty.screen import Screen -from kitty.fast_data_types import LineBuf, Cursor +from kitty.screen import Screen as S +from kitty.fast_data_types import LineBuf, Cursor, Screen def filled_line_buf(ynum=5, xnum=5, cursor=Cursor()): @@ -31,8 +31,10 @@ class BaseTest(TestCase): ae = TestCase.assertEqual def create_screen(self, cols=5, lines=5, history_size=5): - s = Screen(history_size, columns=cols, lines=lines) - return s + return S(history_size, columns=cols, lines=lines) + + def create_screen2(self, cols=5, lines=5, history_size=5): + return Screen(history_size, None, lines, cols) def assertEqualAttributes(self, c1, c2): x1, y1, c1.x, c1.y = c1.x, c1.y, 0, 0