You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
999 lines
33 KiB
C
999 lines
33 KiB
C
// 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 <Python.h>
|
|
#include <notcurses/notcurses.h>
|
|
#include <notcurses/direct.h>
|
|
#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;
|
|
}
|