From 85076d30121291a8d56fa68b29c21a47f0e59e2d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 1 Nov 2016 19:04:38 +0530 Subject: [PATCH] Implement add combining char --- kitty/data-types.h | 2 ++ kitty/line.c | 24 +++++++++++++++++++++--- kitty_tests/datatypes.py | 11 ++++++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/kitty/data-types.h b/kitty/data-types.h index 8f3b1c88a..d5c0211ac 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -36,6 +36,8 @@ typedef unsigned int index_type; #define COL_MASK 0xFFFFFFFF #define COL_SHIFT 32 #define HAS_BG_MASK (0xFF << COL_SHIFT) +#define CC_MASK 0xFFFF +#define CC_SHIFT 16 typedef struct { PyObject_HEAD diff --git a/kitty/line.c b/kitty/line.c index 9b462cdfa..03fda0e73 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -35,7 +35,7 @@ text_at(Line* self, PyObject *x) { if (ans == NULL) return PyErr_NoMemory(); PyUnicode_WriteChar(ans, 0, ch); } else { - Py_UCS4 cc1 = cc & 0xFFFF, cc2 = cc >> 16; + Py_UCS4 cc1 = cc & CC_MASK, cc2 = cc >> 16; Py_UCS4 maxc = (ch > cc1) ? MAX(ch, cc2) : MAX(cc1, cc2); ans = PyUnicode_New(cc2 ? 3 : 2, maxc); if (ans == NULL) return PyErr_NoMemory(); @@ -59,7 +59,7 @@ as_unicode(Line* self) { char_type ch = self->chars[i] & CHAR_MASK; char_type cc = self->combining_chars[i]; buf[n++] = ch & CHAR_MASK; - Py_UCS4 cc1 = cc & 0xFFFF, cc2; + Py_UCS4 cc1 = cc & CC_MASK, cc2; if (cc1) { buf[n++] = cc1; cc2 = cc >> 16; @@ -71,10 +71,28 @@ as_unicode(Line* self) { return ans; } +static PyObject* +add_combining_char(Line* self, PyObject *args) { + int new_char; + unsigned int x; + if (!PyArg_ParseTuple(args, "IC", &x, &new_char)) return NULL; + if (x >= self->xnum) { + 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; + Py_RETURN_NONE; +} + // Boilerplate {{{ static PyMethodDef methods[] = { {"text_at", (PyCFunction)text_at, METH_O, - "Return the text in the specified cell" + "text_at(x) -> Return the text in the specified cell" + }, + {"add_combining_char", (PyCFunction)add_combining_char, METH_VARARGS, + "add_combining_char(x, ch) -> Add the specified character as a combining char to the specified cell." }, {NULL} /* Sentinel */ }; diff --git a/kitty_tests/datatypes.py b/kitty_tests/datatypes.py index 16e278e1e..babddb045 100644 --- a/kitty_tests/datatypes.py +++ b/kitty_tests/datatypes.py @@ -13,7 +13,7 @@ from kitty.fast_data_types import LineBuf class TestDataTypes(BaseTest): - def test_line_buf(self): + def test_line(self): lb = LineBuf(2, 3) for y in range(2): line = lb.line(y) @@ -24,6 +24,15 @@ class TestDataTypes(BaseTest): lb.line(5) with self.assertRaises(ValueError): lb.line(0).text_at(5) + l = lb.line(0) + l.add_combining_char(0, '1') + self.ae(l.text_at(0), ' 1') + l.add_combining_char(0, '2') + self.ae(l.text_at(0), ' 12') + l.add_combining_char(0, '3') + self.ae(l.text_at(0), ' 13') + self.ae(l.text_at(1), ' ') + self.ae(str(l), ' 13 ') def test_line_ops(self): t = 'Testing with simple text'