diff --git a/python/notcurses/_notcurses.c b/python/notcurses/_notcurses.c deleted file mode 100644 index c07749117..000000000 --- a/python/notcurses/_notcurses.c +++ /dev/null @@ -1,998 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* -Copyright 2020 igo95862 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -#define PY_SSIZE_T_CLEAN -#include -#include -#include -#include "structmember.h" - -typedef struct -{ - PyObject_HEAD - uint64_t ncchannels_ptr; -} NcChannelsObject; - -static PyMethodDef NcChannels_methods[] = { - {NULL, NULL, 0, NULL}, -}; - -static PyTypeObject NcChannelsType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "notcurses._notcurses._NcChannels", - .tp_doc = "Notcurses Channels", - .tp_basicsize = sizeof(NcChannelsObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = PyType_GenericNew, - .tp_init = NULL, - .tp_methods = NcChannels_methods, -}; - -typedef struct -{ - PyObject_HEAD - struct ncplane *ncplane_ptr; -} NcPlaneObject; - -static PyMethodDef NcPlane_methods[] = { - {NULL, NULL, 0, NULL}, -}; - -static PyTypeObject NcPlaneType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "notcurses._notcurses._NcPlane", - .tp_doc = "Notcurses Plane", - .tp_basicsize = sizeof(NcPlaneObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = PyType_GenericNew, - .tp_init = NULL, - .tp_methods = NcPlane_methods, -}; - -typedef struct -{ - PyObject_HEAD - struct notcurses_options options; - struct notcurses *notcurses_context_ptr; -} NotcursesContextObject; - -static PyMethodDef NotcursesContext_methods[] = { - {NULL, NULL, 0, NULL}, -}; - -static PyTypeObject NotcursesContextType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "notcurses._notcurses._NotcursesContext", - .tp_doc = "Notcurses Context", - .tp_basicsize = sizeof(NotcursesContextObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = PyType_GenericNew, - .tp_methods = NotcursesContext_methods, -}; - -typedef struct -{ - PyObject_HEAD - struct ncdirect *ncdirect_ptr; -} NcDirectObject; - -static PyMethodDef NcDirect_methods[] = { - {NULL, NULL, 0, NULL}, -}; - -static PyTypeObject NcDirectType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "notcurses._notcurses._NcDirect", - .tp_doc = "Notcurses Direct", - .tp_basicsize = sizeof(NcDirectObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = PyType_GenericNew, - .tp_methods = NcDirect_methods, -}; - -typedef struct -{ - PyObject_HEAD - long codepoint; - int y_pos; - int x_pos; - bool is_alt; - bool is_shift; - bool is_ctrl; - uint64_t seqnum; -} NcInputObject; - -static PyMemberDef NcInput_members[] = { - {"codepoint", T_LONG, offsetof(NcInputObject, codepoint), READONLY, "Codepoint"}, - {"y_pos", T_INT, offsetof(NcInputObject, y_pos), READONLY, "Y axis positions"}, - {"x_pos", T_INT, offsetof(NcInputObject, x_pos), READONLY, "X axis positions"}, - {"is_alt", T_BOOL, offsetof(NcInputObject, is_alt), READONLY, "Is alt pressed"}, - {"is_shift", T_BOOL, offsetof(NcInputObject, is_shift), READONLY, "Is shift pressed"}, - {"is_ctrl", T_BOOL, offsetof(NcInputObject, is_ctrl), READONLY, "Is ctrl pressed"}, - {"seqnum", T_ULONGLONG, offsetof(NcInputObject, seqnum), READONLY, "Sequence number"}, - {NULL}}; - -static PyMethodDef NcInput_methods[] = { - {NULL, NULL, 0, NULL}, -}; - -static PyTypeObject NcInputType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "notcurses._notcurses._NcInput", - .tp_doc = "Notcurses Input", - .tp_basicsize = sizeof(NcInputObject), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = PyType_GenericNew, - .tp_members = NcInput_members, - .tp_methods = NcInput_methods, -}; - -// Functions - -/* Prototype - -static PyObject * -_ncdirect_init(PyObject *self, PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcDirectType, &ncdirect_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_init arguments"); - return NULL; - } - struct ncdirect *ncdirect_ptr = ncdirect_init(NULL, NULL, 0); - if (ncdirect_ptr != NULL) - { - ncdirect_ref->ncdirect_ptr = ncdirect_ptr; - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse NcDirect_init arguments"); - return NULL; - } -} - -*/ -// NcDirect -static PyObject * -_nc_direct_init(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcDirectType, &ncdirect_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_init arguments"); - return NULL; - } - struct ncdirect *ncdirect_ptr = ncdirect_init(NULL, NULL, 0); - if (ncdirect_ptr != NULL) - { - ncdirect_ref->ncdirect_ptr = ncdirect_ptr; - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcDirectObject"); - return NULL; - } -} - -static PyObject * -_nc_direct_stop(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcDirectType, &ncdirect_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_init arguments"); - return NULL; - } - int return_code = ncdirect_stop(ncdirect_ref->ncdirect_ptr); - if (return_code == 0) - { - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to stop NcDirectObject"); - return NULL; - } -} - -static PyObject * -_nc_direct_putstr(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - const char *string = NULL; - const NcChannelsObject *channels_object = NULL; - if (!PyArg_ParseTuple(args, "O!s|O", - &NcDirectType, &ncdirect_ref, - &string, - &channels_object)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_putstr arguments"); - return NULL; - } - uint64_t channels = 0; - if (PyObject_IsInstance((PyObject *)channels_object, (PyObject *)&NcChannelsType)) - { - channels = channels_object->ncchannels_ptr; - } - else if ((PyObject *)channels_object == (PyObject *)Py_None) - { - channels = 0; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Unknown _NcChannels type"); - return NULL; - } - - int return_code = ncdirect_putstr(ncdirect_ref->ncdirect_ptr, channels, string); - if (return_code >= 0) - { - return PyLong_FromLong(return_code); - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed put string on NcDirect"); - return NULL; - } -} - -static PyObject * -_nc_direct_get_dim_x(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcDirectType, &ncdirect_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_get_dim_x arguments"); - return NULL; - } - if (ncdirect_ref != NULL) - { - return PyLong_FromLong(ncdirect_dim_x(ncdirect_ref->ncdirect_ptr)); - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcDirectObject"); - return NULL; - } -} - -static PyObject * -_nc_direct_get_dim_y(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcDirectType, &ncdirect_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_get_dim_y arguments"); - return NULL; - } - if (ncdirect_ref != NULL) - { - return PyLong_FromLong(ncdirect_dim_y(ncdirect_ref->ncdirect_ptr)); - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcDirectObject"); - return NULL; - } -} - -static PyObject * -_nc_direct_disable_cursor(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcDirectType, &ncdirect_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_disable_cursor arguments"); - return NULL; - } - if (ncdirect_ref != NULL) - { - ncdirect_cursor_disable(ncdirect_ref->ncdirect_ptr); - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcDirectObject"); - return NULL; - } -} - -static PyObject * -_nc_direct_enable_cursor(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcDirectObject *ncdirect_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcDirectType, &ncdirect_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncdirect_enable_cursor arguments"); - return NULL; - } - if (ncdirect_ref != NULL) - { - ncdirect_cursor_enable(ncdirect_ref->ncdirect_ptr); - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcDirectObject"); - return NULL; - } -} -// NcChannels - -static PyObject * -_nc_channels_set_background_rgb(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcChannelsObject *nchannels_ref = NULL; - int red = 0; - int green = 0; - int blue = 0; - if (!PyArg_ParseTuple(args, "O!iii", - &NcChannelsType, &nchannels_ref, - &red, &green, &blue)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncchannels_set_background_rgb arguments"); - return NULL; - } - - if (nchannels_ref == NULL) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcChannelsObject"); - return NULL; - } - - int return_code = channels_set_bg_rgb8(&(nchannels_ref->ncchannels_ptr), red, green, blue); - if (return_code != 0) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to set channel background colors"); - return NULL; - } - Py_RETURN_NONE; -} - -static PyObject * -_nc_channels_set_foreground_rgb(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcChannelsObject *nchannels_ref = NULL; - int red = 0; - int green = 0; - int blue = 0; - if (!PyArg_ParseTuple(args, "O!iii", - &NcChannelsType, &nchannels_ref, - &red, &green, &blue)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _ncchannels_set_foreground_rgb arguments"); - return NULL; - } - - if (nchannels_ref == NULL) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcChannelsObject"); - return NULL; - } - - int return_code = channels_set_fg_rgb8(&(nchannels_ref->ncchannels_ptr), red, green, blue); - if (return_code != 0) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to set channel foreground colors"); - return NULL; - } - Py_RETURN_NONE; -} - -// NotcursesContext - -static PyObject * -_notcurses_context_init(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_init arguments"); - return NULL; - } - struct notcurses *notcurses_context_ptr = notcurses_init(NULL, NULL); - if (notcurses_context_ptr != NULL) - { - notcurses_context_ref->notcurses_context_ptr = notcurses_context_ptr; - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed initialize Notcurses"); - return NULL; - } -} - -static PyObject * -_notcurses_context_stop(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_stop arguments"); - return NULL; - } - int return_code = notcurses_stop(notcurses_context_ref->notcurses_context_ptr); - if (return_code == 0) - { - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to stop notcurses context"); - return NULL; - } -} - -static PyObject * -_notcurses_context_render(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_render arguments"); - return NULL; - } - int return_code = notcurses_render(notcurses_context_ref->notcurses_context_ptr); - if (return_code == 0) - { - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to render"); - return NULL; - } -} - -static PyObject * -_notcurses_context_mouse_disable(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_mouse_disable arguments"); - return NULL; - } - int return_code = notcurses_mouse_disable(notcurses_context_ref->notcurses_context_ptr); - if (return_code == 0) - { - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to disable mouse"); - return NULL; - } -} - -static PyObject * -_notcurses_context_mouse_enable(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_mouse_enable arguments"); - return NULL; - } - int return_code = notcurses_mouse_enable(notcurses_context_ref->notcurses_context_ptr); - if (return_code == 0) - { - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to enable mouse"); - return NULL; - } -} - -static PyObject * -_notcurses_context_cursor_disable(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_cursor_disable arguments"); - return NULL; - } - int return_code = notcurses_cursor_disable(notcurses_context_ref->notcurses_context_ptr); - if (return_code == 0) - { - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to disable cursor"); - return NULL; - } -} - -static PyObject * -_notcurses_context_cursor_enable(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - int y = 0; - int x = 0; - if (!PyArg_ParseTuple(args, "O!|ii", &NotcursesContextType, ¬curses_context_ref, - &y, &x)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_cursor_enable arguments"); - return NULL; - } - int return_code = notcurses_cursor_enable(notcurses_context_ref->notcurses_context_ptr, y, x); - if (return_code == 0) - { - Py_RETURN_NONE; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to enable cursor"); - return NULL; - } -} - -static NcPlaneObject * -_notcurses_context_get_std_plane(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_cursor_enable arguments"); - return NULL; - } - struct ncplane *std_plane = notcurses_stdplane(notcurses_context_ref->notcurses_context_ptr); - NcPlaneObject *ncplane_ref = PyObject_NEW(NcPlaneObject, &NcPlaneType); - - if (ncplane_ref != NULL && std_plane != NULL) - { - ncplane_ref->ncplane_ptr = std_plane; - return ncplane_ref; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to get std plane"); - return NULL; - } -} - -static NcInputObject * -_notcurses_context_get_input_blocking(PyObject *Py_UNUSED(self), PyObject *args) -{ - NotcursesContextObject *notcurses_context_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NotcursesContextType, ¬curses_context_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _notcurses_context_get_input_blocking arguments"); - return NULL; - } - struct ncinput nc_input_ptr = {0}; - char32_t code_point = notcurses_getc_blocking(notcurses_context_ref->notcurses_context_ptr, &nc_input_ptr); - NcInputObject *nc_input_ref = PyObject_NEW(NcInputObject, &NcInputType); - PyObject_INIT(nc_input_ref, &NcInputType); - if (code_point != (char32_t)-1) - { - - nc_input_ref->codepoint = (long)nc_input_ptr.id; - nc_input_ref->y_pos = nc_input_ptr.y; - nc_input_ref->x_pos = nc_input_ptr.x; - nc_input_ref->is_alt = nc_input_ptr.alt; - nc_input_ref->is_shift = nc_input_ptr.shift; - nc_input_ref->is_ctrl = nc_input_ptr.ctrl; - nc_input_ref->seqnum = nc_input_ptr.seqnum; - - return nc_input_ref; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to get input"); - return NULL; - } -} - -// NcPlane - -static PyObject * -_nc_plane_set_background_rgb(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_ref = NULL; - int red = 0; - int green = 0; - int blue = 0; - if (!PyArg_ParseTuple(args, "O!iii", - &NcPlaneType, &nc_plane_ref, - &red, &green, &blue)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_set_background_rgb arguments"); - return NULL; - } - - if (nc_plane_ref == NULL) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcPlaneObject"); - return NULL; - } - - int return_code = ncplane_set_bg_rgb8(nc_plane_ref->ncplane_ptr, red, green, blue); - if (return_code != 0) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to set plane background colors"); - return NULL; - } - Py_RETURN_NONE; -} - -static PyObject * -_nc_plane_set_foreground_rgb(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_ref = NULL; - int red = 0; - int green = 0; - int blue = 0; - if (!PyArg_ParseTuple(args, "O!iii", - &NcPlaneType, &nc_plane_ref, - &red, &green, &blue)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_set_foreground_rgb arguments"); - return NULL; - } - - if (nc_plane_ref == NULL) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcPlaneObject"); - return NULL; - } - - int return_code = ncplane_set_fg_rgb8(nc_plane_ref->ncplane_ptr, red, green, blue); - if (return_code != 0) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to set plane foreground colors"); - return NULL; - } - Py_RETURN_NONE; -} - -static PyObject * -_nc_plane_putstr(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_ref = NULL; - int y_pos = -1; - int x_pos = -1; - const char *string = NULL; - if (!PyArg_ParseTuple(args, "O!sii", - &NcPlaneType, &nc_plane_ref, - &string, - &y_pos, &x_pos)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_putstr arguments"); - return NULL; - } - - if (nc_plane_ref == NULL) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcPlaneObject"); - return NULL; - } - - int return_code = ncplane_putstr_yx(nc_plane_ref->ncplane_ptr, y_pos, x_pos, string); - return PyLong_FromLong(return_code); -} - -static PyObject * -_nc_plane_putstr_aligned(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_ref = NULL; - int y_pos = -1; - ncalign_e align = NCALIGN_UNALIGNED; - const char *string = NULL; - if (!PyArg_ParseTuple(args, "O!sii", - &NcPlaneType, &nc_plane_ref, - &string, - &y_pos, &align)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_putstr_aligned arguments"); - return NULL; - } - - int return_code = ncplane_putstr_aligned(nc_plane_ref->ncplane_ptr, y_pos, align, string); - return PyLong_FromLong(return_code); -} - -static PyObject * -_nc_plane_dimensions_yx(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_ref = NULL; - int y_dim = 0; - int x_dim = 0; - if (!PyArg_ParseTuple(args, "O!", - &NcPlaneType, &nc_plane_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_set_foreground_rgb arguments"); - return NULL; - } - - if (nc_plane_ref == NULL) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to acquire NcPlaneObject"); - return NULL; - } - - ncplane_dim_yx(nc_plane_ref->ncplane_ptr, &y_dim, &x_dim); - return PyTuple_Pack(2, PyLong_FromLong(y_dim), PyLong_FromLong(x_dim)); -} - -static PyObject * -_nc_plane_polyfill_yx(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_ref = NULL; - int y_dim = -1; - int x_dim = -1; - const char *cell_str = NULL; - if (!PyArg_ParseTuple(args, "O!iis", - &NcPlaneType, &nc_plane_ref, - &y_dim, &x_dim, - &cell_str)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_polyfill_yx arguments"); - return NULL; - } - cell cell_to_fill_with = CELL_CHAR_INITIALIZER(*cell_str); - int return_code = ncplane_polyfill_yx(nc_plane_ref->ncplane_ptr, y_dim, x_dim, &cell_to_fill_with); - if (return_code != -1) - { - return PyLong_FromLong((long)return_code); - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to polyfill"); - return NULL; - } -} - -static PyObject * -_nc_plane_erase(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_ref = NULL; - if (!PyArg_ParseTuple(args, "O!", &NcPlaneType, &nc_plane_ref)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_erase arguments"); - return NULL; - } - ncplane_erase(nc_plane_ref->ncplane_ptr); - Py_RETURN_NONE; -} - -static NcPlaneObject * -_nc_plane_create(PyObject *Py_UNUSED(self), PyObject *args) -{ - NcPlaneObject *nc_plane_parent = NULL; - int y_pos, x_pos, rows_num, cols_num; - if (!PyArg_ParseTuple(args, "O!iiii", - &NcPlaneType, &nc_plane_parent, - &y_pos, &x_pos, - &rows_num, &cols_num)) - { - PyErr_SetString(PyExc_RuntimeError, "Failed to parse _nc_plane_create arguments"); - return NULL; - } - ncplane_options create_options = { - .y = y_pos, - .x = x_pos, - .rows = rows_num, - .cols = cols_num, - }; - struct ncplane *new_nc_plane = ncplane_create(nc_plane_parent->ncplane_ptr, &create_options); - if (new_nc_plane != NULL) - { - NcPlaneObject *ncplane_ref = PyObject_NEW(NcPlaneObject, &NcPlaneType); - - ncplane_ref->ncplane_ptr = new_nc_plane; - return ncplane_ref; - } - else - { - PyErr_SetString(PyExc_RuntimeError, "Failed to create NcPlane"); - return NULL; - } -} - -static PyObject * -get_notcurses_version_str(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) -{ - const char *verstion_str = notcurses_version(); - return PyUnicode_FromString(verstion_str); -} - -// Copy pasta -// {"_nc_direct_init", (PyCFunction)_ncdirect_init, METH_VARARGS, NULL}, -static PyMethodDef NotcursesMethods[] = { - {"_nc_direct_init", (PyCFunction)_nc_direct_init, METH_VARARGS, NULL}, - {"_nc_direct_stop", (PyCFunction)_nc_direct_stop, METH_VARARGS, NULL}, - {"_nc_direct_putstr", (PyCFunction)_nc_direct_putstr, METH_VARARGS, NULL}, - {"_nc_direct_get_dim_x", (PyCFunction)_nc_direct_get_dim_x, METH_VARARGS, NULL}, - {"_nc_direct_get_dim_y", (PyCFunction)_nc_direct_get_dim_y, METH_VARARGS, NULL}, - {"_nc_direct_disable_cursor", (PyCFunction)_nc_direct_disable_cursor, METH_VARARGS, NULL}, - {"_nc_direct_enable_cursor", (PyCFunction)_nc_direct_enable_cursor, METH_VARARGS, NULL}, - {"_nc_channels_set_background_rgb", (PyCFunction)_nc_channels_set_background_rgb, METH_VARARGS, NULL}, - {"_nc_channels_set_foreground_rgb", (PyCFunction)_nc_channels_set_foreground_rgb, METH_VARARGS, NULL}, - {"_notcurses_context_init", (PyCFunction)_notcurses_context_init, METH_VARARGS, NULL}, - {"_notcurses_context_stop", (PyCFunction)_notcurses_context_stop, METH_VARARGS, NULL}, - {"_notcurses_context_render", (PyCFunction)_notcurses_context_render, METH_VARARGS, NULL}, - {"_notcurses_context_mouse_disable", (PyCFunction)_notcurses_context_mouse_disable, METH_VARARGS, NULL}, - {"_notcurses_context_mouse_enable", (PyCFunction)_notcurses_context_mouse_enable, METH_VARARGS, NULL}, - {"_notcurses_context_cursor_disable", (PyCFunction)_notcurses_context_cursor_disable, METH_VARARGS, NULL}, - {"_notcurses_context_cursor_enable", (PyCFunction)_notcurses_context_cursor_enable, METH_VARARGS, NULL}, - {"_notcurses_context_get_std_plane", (PyCFunction)_notcurses_context_get_std_plane, METH_VARARGS, NULL}, - {"_nc_plane_set_background_rgb", (PyCFunction)_nc_plane_set_background_rgb, METH_VARARGS, NULL}, - {"_nc_plane_set_foreground_rgb", (PyCFunction)_nc_plane_set_foreground_rgb, METH_VARARGS, NULL}, - {"_nc_plane_putstr", (PyCFunction)_nc_plane_putstr, METH_VARARGS, NULL}, - {"_nc_plane_putstr_aligned", (PyCFunction)_nc_plane_putstr_aligned, METH_VARARGS, NULL}, - {"_nc_plane_dimensions_yx", (PyCFunction)_nc_plane_dimensions_yx, METH_VARARGS, NULL}, - {"_nc_plane_polyfill_yx", (PyCFunction)_nc_plane_polyfill_yx, METH_VARARGS, NULL}, - {"_nc_plane_erase", (PyCFunction)_nc_plane_erase, METH_VARARGS, NULL}, - {"_nc_plane_create", (PyCFunction)_nc_plane_create, METH_VARARGS, NULL}, - {"_notcurses_context_get_input_blocking", (PyCFunction)_notcurses_context_get_input_blocking, METH_VARARGS, NULL}, - {"get_notcurses_version", (PyCFunction)get_notcurses_version_str, METH_NOARGS, NULL}, - {NULL, NULL, 0, NULL}, -}; - -static struct PyModuleDef NotcursesModule = { - PyModuleDef_HEAD_INIT, - .m_name = "Notcurses", /* name of module */ - .m_doc = "Notcurses.", /* module documentation, may be NULL */ - .m_size = -1, /* size of per-interpreter state of the module, - or -1 if the module keeps state in global variables. */ - NotcursesMethods, -}; - -PyMODINIT_FUNC -PyInit__notcurses(void) -{ - PyObject *py_module; // create the module - if (PyType_Ready(&NotcursesContextType) < 0) - return NULL; - - if (PyType_Ready(&NcPlaneType) < 0) - return NULL; - - if (PyType_Ready(&NcDirectType) < 0) - return NULL; - - if (PyType_Ready(&NcChannelsType) < 0) - return NULL; - - if (PyType_Ready(&NcInputType) < 0) - return NULL; - - py_module = PyModule_Create(&NotcursesModule); - if (py_module == NULL) - return NULL; - - Py_INCREF(&NotcursesContextType); - if (PyModule_AddObject(py_module, "_NotcursesContext", (PyObject *)&NotcursesContextType) < 0) - { - Py_DECREF(&NotcursesContextType); - Py_DECREF(py_module); - return NULL; - } - - Py_INCREF(&NcPlaneType); - if (PyModule_AddObject(py_module, "_NcPlane", (PyObject *)&NcPlaneType) < 0) - { - Py_DECREF(&NcPlaneType); - Py_DECREF(py_module); - return NULL; - } - - Py_INCREF(&NcDirectType); - if (PyModule_AddObject(py_module, "_NcDirect", (PyObject *)&NcDirectType) < 0) - { - Py_DECREF(&NcDirectType); - Py_DECREF(py_module); - return NULL; - } - - Py_INCREF(&NcChannelsType); - if (PyModule_AddObject(py_module, "_NcChannels", (PyObject *)&NcChannelsType) < 0) - { - Py_DECREF(&NcChannelsType); - Py_DECREF(py_module); - return NULL; - } - - Py_INCREF(&NcInputType); - if (PyModule_AddObject(py_module, "_NcInput", (PyObject *)&NcInputType) < 0) - { - Py_DECREF(&NcInputType); - Py_DECREF(py_module); - return NULL; - } - - // Constants PyModule_AddIntMacro(py_module, ); - int constants_control_value = 0; - // Inputs - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_INVALID); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_RESIZE); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_UP); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_RIGHT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_DOWN); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_LEFT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_INS); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_DEL); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_BACKSPACE); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_PGDOWN); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_PGUP); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_HOME); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_END); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F00); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F01); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F02); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F03); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F04); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F05); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F06); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F07); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F08); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F09); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F10); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F11); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_F12); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_ENTER); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_CLS); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_DLEFT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_DRIGHT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_ULEFT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_URIGHT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_CENTER); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_BEGIN); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_CANCEL); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_CLOSE); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_COMMAND); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_COPY); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_EXIT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_PRINT); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_REFRESH); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_BUTTON1); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_BUTTON2); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_BUTTON3); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_SCROLL_UP); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_SCROLL_DOWN); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_BUTTON6); - constants_control_value |= PyModule_AddIntMacro(py_module, NCKEY_RELEASE); - // Nc Align - constants_control_value |= PyModule_AddIntConstant(py_module, "NCALIGN_UNALIGNED", NCALIGN_UNALIGNED); - constants_control_value |= PyModule_AddIntConstant(py_module, "NCALIGN_LEFT", NCALIGN_LEFT); - constants_control_value |= PyModule_AddIntConstant(py_module, "NCALIGN_CENTER", NCALIGN_CENTER); - constants_control_value |= PyModule_AddIntConstant(py_module, "NCALIGN_RIGHT", NCALIGN_RIGHT); - // Scale - constants_control_value |= PyModule_AddIntConstant(py_module, "NCSCALE_NONE", NCSCALE_NONE); - constants_control_value |= PyModule_AddIntConstant(py_module, "NCSCALE_SCALE", NCSCALE_SCALE); - constants_control_value |= PyModule_AddIntConstant(py_module, "NCSCALE_STRETCH", NCSCALE_STRETCH); - if (constants_control_value < 0) - { - Py_DECREF(py_module); - return NULL; - } - - return py_module; -} diff --git a/python/notcurses/_notcurses.py b/python/notcurses/_notcurses.py deleted file mode 100644 index 874dba11d..000000000 --- a/python/notcurses/_notcurses.py +++ /dev/null @@ -1,255 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -# Copyright 2020 igo95862 - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import annotations - -from typing import Optional, Tuple - - -class _NcChannels: - ... - - -class _NcPlane: - ... - - -class _NotcursesContext: - ... - - -class _NcDirect: - ... - - -class _NcInput: - @property - def codepoint(self) -> int: - ... - - @property - def y_pos(self) -> int: - ... - - @property - def x_pos(self) -> int: - ... - - @property - def is_alt(self) -> bool: - ... - - @property - def is_shift(self) -> bool: - ... - - @property - def is_ctrl(self) -> bool: - ... - - @property - def seqnum(self) -> int: - ... - - -def _nc_direct_init(ncdirect: _NcDirect, /) -> None: - ... - - -def _nc_direct_stop(ncdirect: _NcDirect, /) -> None: - ... - - -def _nc_direct_putstr(nc_direct: _NcDirect, - string: str, - nc_channels: Optional[_NcChannels], /) -> int: - ... - - -def _nc_direct_get_dim_x(nc_direct: _NcDirect, /) -> int: - ... - - -def _nc_direct_get_dim_y(nc_direct: _NcDirect, /) -> int: - ... - - -def _nc_direct_disable_cursor(nc_direct: _NcDirect, /) -> None: - ... - - -def _nc_direct_enable_cursor(nc_direct: _NcDirect, /) -> None: - ... - - -def _nc_channels_set_background_rgb( - nc_channels: _NcChannels, - red: int, green: int, blue: int, /) -> None: - ... - - -def _nc_channels_set_foreground_rgb( - nc_channels: _NcChannels, - red: int, green: int, blue: int, /) -> None: - ... - - -def _notcurses_context_init(nc_context: _NotcursesContext, /) -> None: - ... - - -def _notcurses_context_stop(nc_context: _NotcursesContext, /) -> None: - ... - - -def _notcurses_context_render(nc_context: _NotcursesContext, /) -> None: - ... - - -def _notcurses_context_mouse_disable(nc_context: _NotcursesContext, /) -> None: - ... - - -def _notcurses_context_mouse_enable(nc_context: _NotcursesContext, /) -> None: - ... - - -def _notcurses_context_cursor_disable( - nc_context: _NotcursesContext, /) -> None: - ... - - -def _notcurses_context_cursor_enable( - nc_context: _NotcursesContext, - y_pos: int, x_pos: int, /) -> None: - ... - - -def _notcurses_context_get_std_plane( - nc_context: _NotcursesContext, /) -> _NcPlane: - ... - - -def _notcurses_context_get_input_blocking( - nc_context: _NotcursesContext, /) -> _NcInput: - ... - - -def _nc_plane_set_background_rgb( - nc_plane: _NcPlane, - red: int, green: int, blue: int, /) -> None: - ... - - -def _nc_plane_set_foreground_rgb( - nc_plane: _NcPlane, - red: int, green: int, blue: int, /) -> None: - ... - - -def _nc_plane_putstr( - nc_plane: _NcPlane, string: str, - y_pos: int, x_pos: int, /) -> int: - ... - - -def _nc_plane_putstr_aligned( - nc_plane: _NcPlane, string: str, - y_pos: int, align: int, /) -> int: - ... - - -def _nc_plane_dimensions_yx(nc_plane: _NcPlane, /) -> Tuple[int, int]: - ... - - -def _nc_plane_polyfill_yx( - nc_plane: _NcPlane, - y_pos: int, x_pos: int, cell_str: str, /) -> int: - ... - - -def _nc_plane_erase(nc_plane: _NcPlane, /) -> None: - ... - - -def _nc_plane_create( - nc_plane: _NcPlane, - y_pos: int, x_pos: int, - rows_num: int, cols_num: int, /) -> _NcPlane: - ... - - -def get_notcurses_version() -> str: - """Returns notcurses version from library""" - ... - - -# Assign 0 to make this stub file importable -NCKEY_INVALID: int = 0 -NCKEY_UP: int = 0 -NCKEY_RESIZE: int = 0 -NCKEY_RIGHT: int = 0 -NCKEY_DOWN: int = 0 -NCKEY_LEFT: int = 0 -NCKEY_INS: int = 0 -NCKEY_DEL: int = 0 -NCKEY_BACKSPACE: int = 0 -NCKEY_PGDOWN: int = 0 -NCKEY_PGUP: int = 0 -NCKEY_HOME: int = 0 -NCKEY_END: int = 0 -NCKEY_F00: int = 0 -NCKEY_F01: int = 0 -NCKEY_F02: int = 0 -NCKEY_F03: int = 0 -NCKEY_F04: int = 0 -NCKEY_F05: int = 0 -NCKEY_F06: int = 0 -NCKEY_F07: int = 0 -NCKEY_F08: int = 0 -NCKEY_F09: int = 0 -NCKEY_F10: int = 0 -NCKEY_F11: int = 0 -NCKEY_F12: int = 0 -NCKEY_ENTER: int = 0 -NCKEY_CLS: int = 0 -NCKEY_DLEFT: int = 0 -NCKEY_DRIGHT: int = 0 -NCKEY_ULEFT: int = 0 -NCKEY_URIGHT: int = 0 -NCKEY_CENTER: int = 0 -NCKEY_BEGIN: int = 0 -NCKEY_CANCEL: int = 0 -NCKEY_CLOSE: int = 0 -NCKEY_COMMAND: int = 0 -NCKEY_COPY: int = 0 -NCKEY_EXIT: int = 0 -NCKEY_PRINT: int = 0 -NCKEY_REFRESH: int = 0 -NCKEY_BUTTON1: int = 0 -NCKEY_BUTTON2: int = 0 -NCKEY_BUTTON3: int = 0 -NCKEY_SCROLL_UP: int = 0 -NCKEY_SCROLL_DOWN: int = 0 -NCKEY_BUTTON6: int = 0 -NCKEY_RELEASE: int = 0 -NCALIGN_UNALIGNED: int = 0 -NCALIGN_LEFT: int = 0 -NCALIGN_CENTER: int = 0 -NCALIGN_RIGHT: int = 0 -NCSCALE_NONE: int = 0 -NCSCALE_SCALE: int = 0 -NCSCALE_STRETCH: int = 0 diff --git a/python/notcurses/notcurses.py b/python/notcurses/notcurses.py deleted file mode 100644 index e69e13598..000000000 --- a/python/notcurses/notcurses.py +++ /dev/null @@ -1,634 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -# Copyright 2020 igo95862 - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Notcurses python module -""" -from __future__ import annotations - -from enum import IntEnum -from typing import Dict, Iterable, Optional, Tuple, Union - -from . import _notcurses -from ._notcurses import (_nc_channels_set_background_rgb, - _nc_channels_set_foreground_rgb, - _nc_direct_disable_cursor, _nc_direct_enable_cursor, - _nc_direct_get_dim_x, _nc_direct_get_dim_y, - _nc_direct_init, _nc_direct_putstr, _nc_direct_stop, - _nc_plane_create, _nc_plane_dimensions_yx, - _nc_plane_erase, _nc_plane_putstr, - _nc_plane_putstr_aligned, - _nc_plane_set_background_rgb, - _nc_plane_set_foreground_rgb, _NcChannels, _NcDirect, - _NcInput, _NcPlane, _notcurses_context_cursor_disable, - _notcurses_context_cursor_enable, - _notcurses_context_get_input_blocking, - _notcurses_context_get_std_plane, - _notcurses_context_init, - _notcurses_context_mouse_disable, - _notcurses_context_mouse_enable, - _notcurses_context_render, _notcurses_context_stop, - _NotcursesContext) - - -class NcAlign(IntEnum): - """ - Enum containing alignment types - - :cvar UNALIGNED: No alignment - :cvar LEFT: Left alignment - :cvar CENTER: Center alignment - :cvar RIGHT: Right alignment - """ - UNALIGNED = _notcurses.NCALIGN_UNALIGNED - LEFT = _notcurses.NCALIGN_LEFT - CENTER = _notcurses.NCALIGN_CENTER - RIGHT = _notcurses.NCALIGN_RIGHT - - -class NotcursesContext: - """ - Notcurses Context - - This class controls the attached terminal and should only be - initialized once per terminal. - - Using :py:func:`get_std_plane` is recommended in most cases instead - of directly initializing the context. - """ - - def __init__(self, - start_immediately: bool = True): - """ - Create the context - - :param bool start_immediately: Whether or not to acquire the terminal - """ - self._nc_context = _NotcursesContext() - self._has_started = False - if start_immediately: - self.start() - - def render(self) -> None: - """ - Updates the terminal window with the actual content - This should be called after the you have filled the - plane with such function as :py:meth:`NcPlane.put_lines` - - .. warning:: - This method is not thread safe. - """ - _notcurses_context_render(self._nc_context) - - def start(self) -> None: - """Notcurses acquires the terminal.""" - _notcurses_context_init(self._nc_context) - self._has_started = True - - def stop(self) -> None: - """ - Notcurses releases the terminal. - - This will be automatically called with the context object - gets garbage collected. - """ - _notcurses_context_stop(self._nc_context) - self._has_started = False - - def get_input_blocking(self) -> NcInput: - """ - Waits synchronously for an :py:class:`NcInput` event. - """ - return NcInput( - _notcurses_context_get_input_blocking(self._nc_context) - ) - - def enable_mouse(self) -> None: - """Enables mouse on the terminal""" - _notcurses_context_mouse_enable(self._nc_context) - - def disable_mouse(self) -> None: - """Disables mouse on the terminal""" - _notcurses_context_mouse_disable(self._nc_context) - - def enable_cursor(self) -> None: - """Enables cursor on the terminal""" - _notcurses_context_cursor_enable(self._nc_context, 0, 0) - - def disable_cursor(self) -> None: - """Disables cursor on the terminal""" - _notcurses_context_cursor_disable(self._nc_context) - - def __del__(self) -> None: - if self._has_started: - self.stop() - - -class NcInput: - """Represents an input event""" - - def __init__(self, nc_input: _NcInput): - self._nc_input = nc_input - - @property - def code(self) -> Union[str, NcInputCodes]: - """ - Either a single character or an enum of :py:class:`NcInputCodes` - - For example, `q` represents a button Q on keyboard. - `NcInputCodes.MOUSE_LEFT_BUTTON` represents left mouse button click. - - The keys references can be found in :py:class:`NcInputCodes` - - :rtype: Union[str, NcInputCodes] - """ - try: - return NC_INPUT_CODES[self._nc_input.codepoint] - except KeyError: - return chr(self._nc_input.codepoint) - - @property - def y_pos(self) -> int: - """ - Y position of event - - :rtype: int - """ - return self._nc_input.y_pos - - @property - def x_pos(self) -> int: - """ - X position of event - - :rtype: int - """ - return self._nc_input.x_pos - - @property - def is_alt(self) -> bool: - """ - Was Alt key pressed during event? - - :rtype: bool - """ - return self._nc_input.is_alt - - @property - def is_shift(self) -> bool: - """ - Was Shift key pressed during event? - - :rtype: bool - """ - return self._nc_input.is_shift - - @property - def is_ctrl(self) -> bool: - """ - Was Ctrl key pressed during event? - - :rtype: bool - """ - return self._nc_input.is_ctrl - - @property - def seqnum(self) -> int: - """ - Sequence number - - :rtype: int - """ - return self._nc_input.seqnum - - -class NcPlane: - """Class representing a drawing surface""" - - def __init__(self, plane: _NcPlane, context: NotcursesContext) -> None: - """ - NcPlane should not be initialized directly by user. - Use :py:meth:`NcPlane.create_sub_plane` to create sub planes from the - standard plane - """ - self._nc_plane = plane - self.context = context - - @property - def dimensions_yx(self) -> Tuple[int, int]: - """ - Returns Y and X dimensions of the plane - - :rtype: Tuple[int, int] - """ - return _nc_plane_dimensions_yx(self._nc_plane) - - def putstr( - self, - string: str, - y_pos: int = -1, x_pos: int = -1) -> int: - """ - Puts a string on the plane - - :param str string: String to put - :param int y_pos: Y position to put string. - By default is the cursor position. - :param int x_pos: X position to put string. - By default is the cursor position. - :returns: Number of characters written. - Negative if some characters could not be written. - :rtype: int - """ - return _nc_plane_putstr( - self._nc_plane, - string, - y_pos, - x_pos, - ) - - def putstr_aligned(self, - string: str, - y_pos: int = -1, - align: NcAlign = NcAlign.UNALIGNED) -> int: - """ - Puts a string on the plane with specified alignment - instead of X coordinate - - :param str string: String to put - :param int y_pos: Y position to put string. - By default is the cursor position. - :param NcAlign align: Use specific alignment. - :returns: Number of characters written. - Negative if some characters could not be written. - :rtype: int - """ - return _nc_plane_putstr_aligned( - self._nc_plane, - string, - y_pos, - align, - ) - - def put_lines( - self, lines_iter: Iterable[str], wrap_lines: bool = False - ) -> None: - """ - Puts string from the iterator on the plane. - Each string is put on a new line. - - :param iter[str] lines_iter: Iterator of lines to put on the plane - :param bool wrap_lines: If line is longer that the surface - should it be continued on the next line? Default false. - """ - y_pos = 0 - - for line in lines_iter: - # TODO: needs to stop if we are outside the plane - chars_put = self.putstr(line, y_pos, 0) - y_pos += 1 - - if not wrap_lines: - continue - - while chars_put < 0: - line = line[abs(chars_put):] - chars_put = self.putstr(line, y_pos, 0) - y_pos += 1 - - def erase(self) -> None: - """Remove all symbols from plane""" - return _nc_plane_erase(self._nc_plane) - - def set_background_rgb( - self, red: int, green: int, blue: int) -> None: - """ - Sets the background color - - :param int red: Red color component given as integer from 0 to 255 - :param int green: Green color component given as integer from 0 to 255 - :param int blue: Blue color component given as integer from 0 to 255 - """ - _nc_plane_set_background_rgb(self._nc_plane, red, green, blue) - - def set_foreground_rgb( - self, red: int, green: int, blue: int) -> None: - """ - Sets the foreground color - - :param int red: Red color component given as integer from 0 to 255 - :param int green: Green color component given as integer from 0 to 255 - :param int blue: Blue color component given as integer from 0 to 255 - """ - _nc_plane_set_foreground_rgb(self._nc_plane, red, green, blue) - - def create_sub_plane( - self, - y_pos: int = 0, - x_pos: int = 0, - rows_num: Optional[int] = None, - cols_num: Optional[int] = None - ) -> NcPlane: - """ - Creates a new plane within this plane - - :param int y_pos: top left corner Y coordinate - relative to top left corner of parent - - :param int x_pos: top left corner X coordinate - relative to top left corner of parent - - :param int rows_num: Number of rows (i.e. Y size) - :param int cols_num: Number of columns (i.e. X size) - :returns: New plane - :rtype: NcPlane - """ - - if cols_num is None: - y_dim, _ = self.dimensions_yx - cols_num = y_dim // 2 - - if rows_num is None: - _, x_dim = self.dimensions_yx - rows_num = x_dim - - new_plane = _nc_plane_create( - self._nc_plane, - y_pos, x_pos, rows_num, cols_num - ) - - return NcPlane(new_plane, self.context) - - -_default_context: Optional[NotcursesContext] = None - - -def get_std_plane() -> NcPlane: - """ - Initializes context and returns the standard plane. - - .. warning:: - The terminal will be acquired by notcurses and uncontrollable until - the standard plane will be dereferenced. - - :return: Standard plane of the terminal - :rtype: NcPlane - """ - global _default_context - if _default_context is None: - _default_context = NotcursesContext() - - std_plane_ref = _notcurses_context_get_std_plane( - _default_context._nc_context) - return NcPlane(std_plane_ref, _default_context) - - -class NcChannels: - """ - Class that hold the colors and transparency values - - Can be used in some functions instead of directly specifying colors. - """ - - def __init__(self) -> None: - self._nc_channels = _NcChannels() - - def set_background_rgb(self, red: int, green: int, blue: int) -> None: - """ - Sets the background color - - :param int red: Red color component given as integer from 0 to 255 - :param int green: Green color component given as integer from 0 to 255 - :param int blue: Blue color component given as integer from 0 to 255 - """ - _nc_channels_set_background_rgb( - self._nc_channels, - red, green, blue, - ) - - def set_foreground_rgb(self, red: int, green: int, blue: int) -> None: - """ - Sets the foreground color - - :param int red: Red color component given as integer from 0 to 255 - :param int green: Green color component given as integer from 0 to 255 - :param int blue: Blue color component given as integer from 0 to 255 - """ - _nc_channels_set_foreground_rgb( - self._nc_channels, - red, green, blue, - ) - - -class NcDirect: - """ - NcDirect is a subset of Notcurses. - It does not clear entire terminal but instead draws on to normal - terminal surface. That means the output is preserved after the application - has exited and can be scrolled back. - - NcDirect has only one main plane. - """ - - def __init__(self, - start_immediately: bool = True): - """ - Create the main direct plane. - - :param bool start_immediately: Whether or not to start NcDirect on - initialization. - """ - self._nc_direct = _NcDirect() - self._is_cursor_enabled: Optional[bool] = None - self._has_started = False - if start_immediately: - self.start() - - def __del__(self) -> None: - if self._has_started: - self.stop() - - def start(self) -> None: - """ - Start NcDirect. - """ - _nc_direct_init(self._nc_direct) - self._has_started = True - - def stop(self) -> None: - """ - Stop NcDirect - - Will be automatically called if NcDirect object gets garbage collected - """ - _nc_direct_stop(self._nc_direct) - - def putstr( - self, string: str, - nc_channels: Optional[NcChannels] = None) -> int: - """ - Puts a string on the plane. - This will immediately take effect. There is not `render` function for - NcDirect. - - :param Optional[NcChannels] nc_channels: The colors string will use - :returns: Number of characters written. - Negative if some characters could not be written. - :rtype: int - """ - - return _nc_direct_putstr( - self._nc_direct, - string, - nc_channels._nc_channels - if nc_channels is not None else nc_channels, - ) - - @property - def dimensions_yx(self) -> Tuple[int, int]: - """ - Returns Y and X dimensions of the plane - - :rtype: Tuple[int, int] - """ - return (_nc_direct_get_dim_y(self._nc_direct), - _nc_direct_get_dim_x(self._nc_direct)) - - @property - def cursor_enabled(self) -> Optional[bool]: - """ - Is the cursor enabled? - - Assign boolean to enable or disable cursor. - - :type: bool - :rtype: bool - """ - return self._is_cursor_enabled - - @cursor_enabled.setter - def cursor_enabled(self, set_to_what: Optional[bool]) -> None: - self._is_cursor_enabled = set_to_what - if set_to_what: - _nc_direct_enable_cursor(self._nc_direct) - else: - _nc_direct_disable_cursor(self._nc_direct) - - -class NcInputCodes(IntEnum): - """ - Enum containing special keys mapping - - :cvar INVALID: - :cvar UP: - :cvar RESIZE: - :cvar RIGHT: - :cvar DOWN: - :cvar LEFT: - :cvar INSERT: - :cvar DELETE: - :cvar BACKSPACE: - :cvar PAGE_DOWN: - :cvar PAGE_UP: - :cvar HOME: - :cvar EBD: - :cvar F0: - :cvar F1: - :cvar F2: - :cvar F3: - :cvar F4: - :cvar F5: - :cvar F6: - :cvar F7: - :cvar F8: - :cvar F9: - :cvar F10: - :cvar F11: - :cvar F12: - :cvar ENTER: - :cvar CAPS_LOCL: - :cvar DOWN_LEFT: - :cvar DOWN_RIGHT: - :cvar UP_LEFT: - :cvar UP_RIGHT: - :cvar CENTER: - :cvar BEGIN: - :cvar CANCEL: - :cvar CLOSE: - :cvar COMMAND: - :cvar COPY: - :cvar EXIT: - :cvar PRINT: - :cvar REFRESH: - :cvar MOUSE_LEFT_BUTTON: - :cvar MOUSE_MIDDLE_BUTTON: - :cvar MOUSE_RIGHT_BUTTON: - :cvar MOUSE_SCROLL_UP: - :cvar MOUSE_SCROLL_DOWN: - :cvar MOUSE_6: - :cvar MOUSE_RELEASE: - """ - INVALID = _notcurses.NCKEY_INVALID - UP = _notcurses.NCKEY_UP - RESIZE = _notcurses.NCKEY_RESIZE - RIGHT = _notcurses.NCKEY_RIGHT - DOWN = _notcurses.NCKEY_DOWN - LEFT = _notcurses.NCKEY_LEFT - INSERT = _notcurses.NCKEY_INS - DELETE = _notcurses.NCKEY_DEL - BACKSPACE = _notcurses.NCKEY_BACKSPACE - PAGE_DOWN = _notcurses.NCKEY_PGDOWN - PAGE_UP = _notcurses.NCKEY_PGUP - HOME = _notcurses.NCKEY_HOME - EBD = _notcurses.NCKEY_END - F0 = _notcurses.NCKEY_F00 - F1 = _notcurses.NCKEY_F01 - F2 = _notcurses.NCKEY_F02 - F3 = _notcurses.NCKEY_F03 - F4 = _notcurses.NCKEY_F04 - F5 = _notcurses.NCKEY_F05 - F6 = _notcurses.NCKEY_F06 - F7 = _notcurses.NCKEY_F07 - F8 = _notcurses.NCKEY_F08 - F9 = _notcurses.NCKEY_F09 - F10 = _notcurses.NCKEY_F10 - F11 = _notcurses.NCKEY_F11 - F12 = _notcurses.NCKEY_F12 - ENTER = _notcurses.NCKEY_ENTER - CAPS_LOCL = _notcurses.NCKEY_CLS - DOWN_LEFT = _notcurses.NCKEY_DLEFT - DOWN_RIGHT = _notcurses.NCKEY_DRIGHT - UP_LEFT = _notcurses.NCKEY_ULEFT - UP_RIGHT = _notcurses.NCKEY_URIGHT - CENTER = _notcurses.NCKEY_CENTER - BEGIN = _notcurses.NCKEY_BEGIN - CANCEL = _notcurses.NCKEY_CANCEL - CLOSE = _notcurses.NCKEY_CLOSE - COMMAND = _notcurses.NCKEY_COMMAND - COPY = _notcurses.NCKEY_COPY - EXIT = _notcurses.NCKEY_EXIT - PRINT = _notcurses.NCKEY_PRINT - REFRESH = _notcurses.NCKEY_REFRESH - MOUSE_LEFT_BUTTON = _notcurses.NCKEY_BUTTON1 - MOUSE_MIDDLE_BUTTON = _notcurses.NCKEY_BUTTON2 - MOUSE_RIGHT_BUTTON = _notcurses.NCKEY_BUTTON3 - MOUSE_SCROLL_UP = _notcurses.NCKEY_SCROLL_UP - MOUSE_SCROLL_DOWN = _notcurses.NCKEY_SCROLL_DOWN - MOUSE_6 = _notcurses.NCKEY_BUTTON6 - MOUSE_RELEASE = _notcurses.NCKEY_RELEASE - - -NC_INPUT_CODES: Dict[int, NcInputCodes] = { - element.value: element for element in NcInputCodes -}