// PyToaster - PixelToaster powered by Python // Copyright (C) 2005 Bram de Greve // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include "PixelToaster.h" #include #ifndef Py_RETURN_NONE # define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif #ifndef Py_RETURN_TRUE # define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True #endif #ifndef Py_RETURN_FALSE # define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False #endif #ifdef NDEBUG # define PY_TOASTER_COUT(x) #else # include # define PY_TOASTER_COUT(x) do { std::cout << x; } while (false) #endif #define PY_TOASTER_DEFINE_TYPE(type, methods, members, maker, doc) \ { \ PyObject_HEAD_INIT(NULL) \ 0, /*ob_size*/ \ "PyToaster." #type, /*tp_name*/ \ sizeof(type), /*tp_basicsize*/ \ 0, /*tp_itemsize*/ \ (destructor)type::dealloc, /*tp_dealloc*/ \ 0, /*tp_print*/ \ 0, /*tp_getattr*/ \ 0, /*tp_setattr*/ \ 0, /*tp_compare*/ \ 0, /*tp_repr*/ \ 0, /*tp_as_number*/ \ 0, /*tp_as_sequence*/ \ 0, /*tp_as_mapping*/ \ 0, /*tp_hash */ \ 0, /*tp_call*/ \ 0, /*tp_str*/ \ 0, /*tp_getattro*/ \ 0, /*tp_setattro*/ \ 0, /*tp_as_buffer*/ \ Py_TPFLAGS_DEFAULT, /*tp_flags*/ \ doc, /* tp_doc */ \ 0, /* tp_traverse */ \ 0, /* tp_clear */ \ 0, /* tp_richcompare */ \ 0, /* tp_weaklistoffset */ \ 0, /* tp_iter */ \ 0, /* tp_iternext */ \ methods, /* tp_methods */ \ members, /* tp_members */ \ 0, /* tp_getset */ \ 0, /* tp_base */ \ 0, /* tp_dict */ \ 0, /* tp_descr_get */ \ 0, /* tp_descr_set */ \ 0, /* tp_dictoffset */ \ 0, /* tp_init */ \ 0, /* tp_alloc */ \ maker, /* tp_new */ \ } \ /**/ namespace PyToaster { void injectPyObjectType(PyObject* module, PyTypeObject& type, char* name) { type.ob_type = &PyType_Type; if (PyType_Ready(&type) >= 0) { Py_INCREF(&type); PyModule_AddObject(module, name, (PyObject*)&type); } } // --- MOUSE ----------------------------------------------------------------------------------- struct Mouse: public PyObject { static void dealloc(void* object); Mouse(PixelToaster::Mouse mouse); int left; int middle; int right; float x; float y; }; void Mouse::dealloc(void* object) { delete static_cast(object); } Mouse::Mouse(PixelToaster::Mouse mouse): left(mouse.buttons.left), middle(mouse.buttons.middle), right(mouse.buttons.right), x(mouse.x), y(mouse.y) { } static Mouse dummyMouse = Mouse(PixelToaster::Mouse()); #define MOUSE_OFFSET_OF(member) \ (reinterpret_cast(&(dummyMouse.member)) \ - reinterpret_cast(&dummyMouse)) static PyMemberDef MouseMembers[] = { {"left", T_INT, MOUSE_OFFSET_OF(left), READONLY, "true if left button is pressed."}, {"middle", T_INT, MOUSE_OFFSET_OF(middle), READONLY , "true if middle button is pressed."}, {"right", T_INT, MOUSE_OFFSET_OF(right), READONLY, "true if right button is pressed."}, {"x", T_FLOAT, MOUSE_OFFSET_OF(x), READONLY , "current mouse cursor x position. ranges from 0 to display width - 1, from left to right."}, {"y", T_FLOAT, MOUSE_OFFSET_OF(y), READONLY, "current mouse cursor y position. ranges from 0 to display height - 1, from top to bottom."}, {NULL} /* Sentinel */ }; static PyTypeObject MouseType = PY_TOASTER_DEFINE_TYPE(Mouse, 0, MouseMembers, 0, "Mouse class."); // --- LISTENER -------------------------------------------------------------------------------- class ListenerProxy: public PixelToaster::Listener { public: ListenerProxy(); ~ListenerProxy(); void listener(PyObject* x); PyObject* listener() const; void onKeyDown(PixelToaster::Key key); void onKeyPressed(PixelToaster::Key key); void onKeyUp(PixelToaster::Key key); void onMouseButtonDown(PixelToaster::Mouse mouse); void onMouseButtonUp(PixelToaster::Mouse mouse); void onMouseMove(PixelToaster::Mouse mouse); void onActivate(bool active); void onClose(); private: PyObject* listener_; }; ListenerProxy::ListenerProxy(): listener_(Py_None) { Py_INCREF(listener_); } ListenerProxy::~ListenerProxy() { Py_DECREF(listener_); } void ListenerProxy::listener(PyObject* x) { Py_INCREF(x); Py_DECREF(listener_); listener_ = x; } PyObject* ListenerProxy::listener() const { Py_INCREF(listener_); return listener_; } void ListenerProxy::onKeyDown(PixelToaster::Key key) { PY_TOASTER_COUT("onKeyDown: " << key << std::endl); if (listener_ != Py_None) { Py_XDECREF(PyObject_CallMethod( listener_, "onKeyDown", "(i)", static_cast(key))); } } void ListenerProxy::onKeyPressed(PixelToaster::Key key) { PY_TOASTER_COUT("onKeyPressed: " << key << std::endl); if (listener_ != Py_None) { Py_XDECREF(PyObject_CallMethod( listener_, "onKeyPressed", "(i)", static_cast(key))); } } void ListenerProxy::onKeyUp(PixelToaster::Key key) { PY_TOASTER_COUT("onKeyUp: " << key << std::endl); if (listener_ != Py_None) { Py_XDECREF(PyObject_CallMethod( listener_, "onKeyUp", "(i)", static_cast(key))); } } void ListenerProxy::onMouseButtonDown(PixelToaster::Mouse mouse) { PY_TOASTER_COUT("onKeyUp: " << mouse.buttons.left << " " << mouse.buttons.middle << " " << mouse.buttons.right << " " << mouse.x << " " << mouse.y << std::endl); if (listener_ != Py_None) { PyObject* pyMouse = new Mouse(mouse); Py_XDECREF(PyObject_CallMethod(listener_, "onMouseButtonDown", "(o)", pyMouse)); Py_XDECREF(pyMouse); } } void ListenerProxy::onMouseButtonUp(PixelToaster::Mouse mouse) { PY_TOASTER_COUT("onKeyUp: " << mouse.buttons.left << " " << mouse.buttons.middle << " " << mouse.buttons.right << " " << mouse.x << " " << mouse.y << std::endl); if (listener_ != Py_None) { PyObject* pyMouse = new Mouse(mouse); Py_XDECREF(PyObject_CallMethod(listener_, "onMouseButtonUp", "(o)", pyMouse)); Py_XDECREF(pyMouse); } } void ListenerProxy::onMouseMove(PixelToaster::Mouse mouse) { PY_TOASTER_COUT("onKeyUp: " << mouse.buttons.left << " " << mouse.buttons.middle << " " << mouse.buttons.right << " " << mouse.x << " " << mouse.y << std::endl); if (listener_ != Py_None) { PyObject* pyMouse = new Mouse(mouse); Py_XDECREF(PyObject_CallMethod(listener_, "onMouseMove", "(o)", pyMouse)); Py_XDECREF(pyMouse); } } void ListenerProxy::onActivate(bool active) { PY_TOASTER_COUT("onActivate: " << active << std::endl); if (listener_ != Py_None) { Py_XDECREF(PyObject_CallMethod(listener_, "onActivate", "(i)", static_cast(active))); } } void ListenerProxy::onClose() { PY_TOASTER_COUT("onClose" << std::endl); if (listener_ != Py_None) { Py_XDECREF(PyObject_CallMethod(listener_, "onClose", 0)); } } // --- DISPLAY --------------------------------------------------------------------------------- class Display: public PyObject { public: static PyObject* make(PyTypeObject *subType, PyObject *args, PyObject *kwds); static void dealloc(Display* object); static PyObject* open(Display* self, PyObject* args); static PyObject* close(Display* self); static PyObject* listener(Display* self, PyObject* args); static PyObject* update(PyObject* self, PyObject* args); static PyObject* title(PyObject* self); static PyObject* width(PyObject* self); static PyObject* height(PyObject* self); private: Display(); Display(const char* title, int width, int height, PixelToaster::Output output, PixelToaster::Mode mode); ListenerProxy listenerProxy_; PixelToaster::Display display_; std::vector buffer_; }; static PyMethodDef DisplayMethods[] = { {"open", (PyCFunction)Display::open, METH_VARARGS, "open([title, width, height [, mode [, output]]])"}, {"close", (PyCFunction)Display::close, METH_NOARGS, "close()"}, {"listener", (PyCFunction)Display::listener, METH_VARARGS, "listener([listener])"}, {"update", (PyCFunction)Display::update, METH_VARARGS, "update(pixels)"}, {"title", (PyCFunction)Display::title, METH_NOARGS, "title()"}, {"width", (PyCFunction)Display::width, METH_NOARGS, "width()"}, {"height", (PyCFunction)Display::height, METH_NOARGS, "height()"}, {NULL} }; static PyTypeObject DisplayType = PY_TOASTER_DEFINE_TYPE(Display, DisplayMethods, 0, Display::make, "Display class."); PyObject* Display::make(PyTypeObject *subType, PyObject *args, PyObject *kwds) { if (kwds != 0 && PyDict_Size(kwds) > 0) { PyErr_Format(PyExc_TypeError, "PyToaster.Display constructor takes no keyword arguments"); return 0; } try { if (args == 0 || PyTuple_Size(args) == 0) { return new Display; } const char* title = 0; int width = 0; int height = 0; int output = PixelToaster::Output::Windowed; int mode = PixelToaster::Mode::TrueColor; if (!PyArg_ParseTuple(args, "sii|ii:constructor", &title, &width, &height, &output, &mode)) { return 0; } return new Display(title, width, height, static_cast(output), static_cast(mode)); } catch (std::bad_alloc) { return PyErr_NoMemory(); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "unknown error"); return 0; } } void Display::dealloc(Display* self) { delete self; } PyObject* Display::open(Display* self, PyObject* args) { if (args == 0 || PyTuple_Size(args) == 0) { if (self->display_.open()) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } const char* title = 0; int width = 0; int height = 0; int output = PixelToaster::Output::Windowed; int mode = PixelToaster::Mode::TrueColor; if (!PyArg_ParseTuple(args, "sii|ii", &title, &width, &height, &output, &mode)) { return 0; } try { if (self->display_.open(title, width, height, static_cast(output), static_cast(mode))) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } catch(...) { Py_RETURN_FALSE; } } PyObject* Display::close(Display* self) { self->display_.close(); Py_RETURN_NONE; } PyObject* Display::listener(Display* self, PyObject* args) { PyObject* pyListener = 0; if (!PyArg_ParseTuple(args, "|O", &pyListener)) { return 0; } if (pyListener) { // called with new listener as argument if (pyListener == Py_None) { self->listenerProxy_.listener(0); self->display_.listener(0); } else { self->listenerProxy_.listener(pyListener); self->display_.listener(&self->listenerProxy_); } Py_RETURN_NONE; } else { // called without arguments, return listener. return static_cast(self)->listenerProxy_.listener(); } } PyObject* Display::update(PyObject* self, PyObject* args) { PyObject* pyBuffer; if (!PyArg_ParseTuple(args, "O", &pyBuffer)) { return 0; } PyBufferProcs* bufferProcs = pyBuffer->ob_type->tp_as_buffer; if (!bufferProcs) { PyErr_SetString(PyExc_TypeError, "argument has no buffer interface"); return 0; } getreadbufferproc getreadbuffer = bufferProcs->bf_getreadbuffer; if (!getreadbuffer) { PyErr_SetString(PyExc_TypeError, "argument is not a readable buffer"); return 0; } PixelToaster::Display& display = static_cast(self)->display_; const int displaySize = display.width() * display.height(); int bufferLength = 0; const int numberOfSegments = bufferProcs->bf_getsegcount(pyBuffer, &bufferLength); if (bufferLength != 4 * displaySize) { PyErr_SetString(PyExc_TypeError, "buffer has incorrect size"); return 0; } std::vector& buffer = static_cast(self)->buffer_; buffer.resize(static_cast(bufferLength)); char* dest = &buffer[0]; for (int i = 0; i < numberOfSegments; ++i) { void* segment; const int segmentLength = getreadbuffer(pyBuffer, i, &segment); if (segmentLength == -1) { return 0; } ::memcpy(dest, segment, segmentLength); } if (display.update(reinterpret_cast(&buffer[0]))) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } PyObject* Display::title(PyObject* self) { return Py_BuildValue("s", static_cast(self)->display_.title()); } PyObject* Display::width(PyObject* self) { return Py_BuildValue("i", static_cast(self)->display_.width()); } PyObject* Display::height(PyObject* self) { return Py_BuildValue("i", static_cast(self)->display_.height()); } Display::Display() { this->ob_type = &DisplayType; _Py_NewReference( this ); //display_.listener(&listenerProxy_); //PY_TOASTER_COUT(display_.listener() << "\n"); } Display::Display(const char* title, int width, int height, PixelToaster::Output output, PixelToaster::Mode mode): display_(title, width, height, output, mode) { this->ob_type = &DisplayType; _Py_NewReference( this ); //display_.listener(&listenerProxy_); //PY_TOASTER_COUT(display_.listener() << "\n"); } // --- TIMER ----------------------------------------------------------------------------------- class Timer: public PyObject { public: static PyObject* make(PyTypeObject *subType, PyObject *args, PyObject *kwds); static void dealloc(void* object); static PyObject* reset(PyObject* self); static PyObject* time(PyObject* self); static PyObject* delta(PyObject* self); static PyObject* resolution(PyObject* self); static PyObject* wait(PyObject* self, PyObject* args); private: Timer(); PixelToaster::Timer timer_; }; static PyMethodDef TimerMethods[] = { {"reset", (PyCFunction)Timer::reset, METH_NOARGS, "reset()"}, {"time", (PyCFunction)Timer::time, METH_NOARGS, "time()"}, {"delta", (PyCFunction)Timer::delta, METH_NOARGS, "delta()"}, {"resolution", (PyCFunction)Timer::resolution, METH_NOARGS, "resolution()"}, {"wait", (PyCFunction)Timer::wait, METH_VARARGS, "wait(seconds)"}, {NULL} }; static PyTypeObject TimerType = PY_TOASTER_DEFINE_TYPE(Timer, TimerMethods, 0, Timer::make, "Display class."); PyObject* Timer::make(PyTypeObject *subType, PyObject *args, PyObject *kwds) { return new Timer; } void Timer::dealloc(void* object) { delete static_cast(object); } PyObject* Timer::reset(PyObject* self) { static_cast(self)->timer_.reset(); Py_RETURN_NONE; } PyObject* Timer::time(PyObject* self) { return Py_BuildValue("d", static_cast(self)->timer_.time()); } PyObject* Timer::delta(PyObject* self) { return Py_BuildValue("d", static_cast(self)->timer_.delta()); } PyObject* Timer::resolution(PyObject* self) { return Py_BuildValue("d", static_cast(self)->timer_.resolution()); } PyObject* Timer::wait(PyObject* self, PyObject* args) { double seconds; if (!PyArg_ParseTuple(args, "d", &seconds)) { return 0; } static_cast(self)->timer_.wait(seconds); Py_RETURN_NONE; } Timer::Timer() { this->ob_type = &TimerType; _Py_NewReference( this ); } } // --- MODULE -------------------------------------------------------------------------------------- extern "C" { PyMODINIT_FUNC initPyToaster(void) { using namespace PyToaster; PyObject* module = Py_InitModule("PyToaster", 0); injectPyObjectType(module, MouseType, "Mouse"); injectPyObjectType(module, DisplayType, "Display"); injectPyObjectType(module, TimerType, "Timer"); PyModule_AddIntConstant(module, "MODE_TRUE_COLOR", PixelToaster::Mode::TrueColor); PyModule_AddIntConstant(module, "MODE_FLOATING_POINT", PixelToaster::Mode::FloatingPoint); PyModule_AddIntConstant(module, "OUTPUT_DEFAULT", PixelToaster::Output::Default); PyModule_AddIntConstant(module, "OUTPUT_WINDOWED", PixelToaster::Output::Windowed); PyModule_AddIntConstant(module, "OUTPUT_FULLSCREEN", PixelToaster::Output::Fullscreen); PyModule_AddIntConstant(module, "KEY_ENTER", '\n'); PyModule_AddIntConstant(module, "KEY_BACK_SPACE", '\b'); PyModule_AddIntConstant(module, "KEY_TAB", '\t'); PyModule_AddIntConstant(module, "KEY_CANCEL", 0x03); PyModule_AddIntConstant(module, "KEY_CLEAR", 0x0C); PyModule_AddIntConstant(module, "KEY_SHIFT", 0x10); PyModule_AddIntConstant(module, "KEY_CONTROL", 0x11); PyModule_AddIntConstant(module, "KEY_ALT", 0x12); PyModule_AddIntConstant(module, "KEY_PAUSE", 0x13); PyModule_AddIntConstant(module, "KEY_CAPS_LOCK", 0x14); PyModule_AddIntConstant(module, "KEY_ESCAPE", 0x1B); PyModule_AddIntConstant(module, "KEY_SPACE", 0x20); PyModule_AddIntConstant(module, "KEY_PAGE_UP", 0x21); PyModule_AddIntConstant(module, "KEY_PAGE_DOWN", 0x22); PyModule_AddIntConstant(module, "KEY_END", 0x23); PyModule_AddIntConstant(module, "KEY_HOME", 0x24); PyModule_AddIntConstant(module, "KEY_LEFT", 0x25); PyModule_AddIntConstant(module, "KEY_UP", 0x26); PyModule_AddIntConstant(module, "KEY_RIGHT", 0x27); PyModule_AddIntConstant(module, "KEY_DOWN", 0x28); PyModule_AddIntConstant(module, "KEY_COMMA", 0x2C); PyModule_AddIntConstant(module, "KEY_PERIOD", 0x2E); PyModule_AddIntConstant(module, "KEY_SLASH", 0x2F); PyModule_AddIntConstant(module, "KEY_ZERO", 0x30); PyModule_AddIntConstant(module, "KEY_ONE", 0x31); PyModule_AddIntConstant(module, "KEY_TWO", 0x32); PyModule_AddIntConstant(module, "KEY_THREE", 0x33); PyModule_AddIntConstant(module, "KEY_FOUR", 0x34); PyModule_AddIntConstant(module, "KEY_FIVE", 0x35); PyModule_AddIntConstant(module, "KEY_SIX", 0x36); PyModule_AddIntConstant(module, "KEY_SEVEN", 0x37); PyModule_AddIntConstant(module, "KEY_EIGHT", 0x38); PyModule_AddIntConstant(module, "KEY_NINE", 0x39); PyModule_AddIntConstant(module, "KEY_SEMI_COLON", 0x3B); PyModule_AddIntConstant(module, "KEY_EQUALS", 0x3D); PyModule_AddIntConstant(module, "KEY_A", 0x41); PyModule_AddIntConstant(module, "KEY_B", 0x42); PyModule_AddIntConstant(module, "KEY_C", 0x43); PyModule_AddIntConstant(module, "KEY_D", 0x44); PyModule_AddIntConstant(module, "KEY_E", 0x45); PyModule_AddIntConstant(module, "KEY_F", 0x46); PyModule_AddIntConstant(module, "KEY_G", 0x47); PyModule_AddIntConstant(module, "KEY_H", 0x48); PyModule_AddIntConstant(module, "KEY_I", 0x49); PyModule_AddIntConstant(module, "KEY_J", 0x4A); PyModule_AddIntConstant(module, "KEY_K", 0x4B); PyModule_AddIntConstant(module, "KEY_L", 0x4C); PyModule_AddIntConstant(module, "KEY_M", 0x4D); PyModule_AddIntConstant(module, "KEY_N", 0x4E); PyModule_AddIntConstant(module, "KEY_O", 0x4F); PyModule_AddIntConstant(module, "KEY_P", 0x50); PyModule_AddIntConstant(module, "KEY_Q", 0x51); PyModule_AddIntConstant(module, "KEY_R", 0x52); PyModule_AddIntConstant(module, "KEY_S", 0x53); PyModule_AddIntConstant(module, "KEY_T", 0x54); PyModule_AddIntConstant(module, "KEY_U", 0x55); PyModule_AddIntConstant(module, "KEY_V", 0x56); PyModule_AddIntConstant(module, "KEY_W", 0x57); PyModule_AddIntConstant(module, "KEY_X", 0x58); PyModule_AddIntConstant(module, "KEY_Y", 0x59); PyModule_AddIntConstant(module, "KEY_Z", 0x5A); PyModule_AddIntConstant(module, "KEY_OPEN_BRACKET", 0x5B); PyModule_AddIntConstant(module, "KEY_BACK_SLASH", 0x5C); PyModule_AddIntConstant(module, "KEY_CLOSE_BRACKET", 0x5D); PyModule_AddIntConstant(module, "KEY_NUM_PAD0", 0x60); PyModule_AddIntConstant(module, "KEY_NUM_PAD1", 0x61); PyModule_AddIntConstant(module, "KEY_NUM_PAD2", 0x62); PyModule_AddIntConstant(module, "KEY_NUM_PAD3", 0x63); PyModule_AddIntConstant(module, "KEY_NUM_PAD4", 0x64); PyModule_AddIntConstant(module, "KEY_NUM_PAD5", 0x65); PyModule_AddIntConstant(module, "KEY_NUM_PAD6", 0x66); PyModule_AddIntConstant(module, "KEY_NUM_PAD7", 0x67); PyModule_AddIntConstant(module, "KEY_NUM_PAD8", 0x68); PyModule_AddIntConstant(module, "KEY_NUM_PAD9", 0x69); PyModule_AddIntConstant(module, "KEY_MULTIPLY", 0x6A); PyModule_AddIntConstant(module, "KEY_ADD", 0x6B); PyModule_AddIntConstant(module, "KEY_SEPARATOR", 0x6C); PyModule_AddIntConstant(module, "KEY_SUBTRACT", 0x6D); PyModule_AddIntConstant(module, "KEY_DECIMAL", 0x6E); PyModule_AddIntConstant(module, "KEY_DIVIDE", 0x6F); PyModule_AddIntConstant(module, "KEY_F1", 0x70); PyModule_AddIntConstant(module, "KEY_F2", 0x71); PyModule_AddIntConstant(module, "KEY_F3", 0x72); PyModule_AddIntConstant(module, "KEY_F4", 0x73); PyModule_AddIntConstant(module, "KEY_F5", 0x74); PyModule_AddIntConstant(module, "KEY_F6", 0x75); PyModule_AddIntConstant(module, "KEY_F7", 0x76); PyModule_AddIntConstant(module, "KEY_F8", 0x77); PyModule_AddIntConstant(module, "KEY_F9", 0x78); PyModule_AddIntConstant(module, "KEY_F10", 0x79); PyModule_AddIntConstant(module, "KEY_F11", 0x7A); PyModule_AddIntConstant(module, "KEY_F12", 0x7B); PyModule_AddIntConstant(module, "KEY_DELETE", 0x7F); PyModule_AddIntConstant(module, "KEY_NUM_LOCK", 0x90); PyModule_AddIntConstant(module, "KEY_SCROLL_LOCK", 0x91); PyModule_AddIntConstant(module, "KEY_PRINT_SCREEN", 0x9A); PyModule_AddIntConstant(module, "KEY_INSERT", 0x9B); PyModule_AddIntConstant(module, "KEY_HELP", 0x9C); PyModule_AddIntConstant(module, "KEY_META", 0x9D); PyModule_AddIntConstant(module, "KEY_BACK_QUOTE", 0xC0); PyModule_AddIntConstant(module, "KEY_QUOTE", 0xDE); PyModule_AddIntConstant(module, "KEY_FINAL", 0x18); PyModule_AddIntConstant(module, "KEY_CONVERT", 0x1C); PyModule_AddIntConstant(module, "KEY_NON_CONVERT", 0x1D); PyModule_AddIntConstant(module, "KEY_ACCEPT", 0x1E); PyModule_AddIntConstant(module, "KEY_MODE_CHANGE", 0x1F); PyModule_AddIntConstant(module, "KEY_KANA", 0x15); PyModule_AddIntConstant(module, "KEY_KANJI", 0x19); PyModule_AddIntConstant(module, "KEY_UNDEFINED", 0x0); } } // EOF