📄 _cursesmodule.c
字号:
/*
* This is a curses module for Python.
*
* Based on prior work by Lance Ellinghaus and Oliver Andrich
* Version 1.2 of this module: Copyright 1994 by Lance Ellinghouse,
* Cathedral City, California Republic, United States of America.
*
* Version 1.5b1, heavily extended for ncurses by Oliver Andrich:
* Copyright 1996,1997 by Oliver Andrich, Koblenz, Germany.
*
* Tidied for Python 1.6, and currently maintained by
* <akuchlin@mems-exchange.org>.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this source file to use, copy, modify, merge, or publish it
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or in any new file that contains a substantial portion of
* this file.
*
* THE AUTHOR MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF
* THE SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
* EXPRESS OR IMPLIED WARRANTY. THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, STRICT LIABILITY OR
* ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* CVS: $Id: _cursesmodule.c,v 2.61.6.3 2002/09/30 16:16:13 loewis Exp $ */
/*
A number of SysV or ncurses functions don't have wrappers yet; if you need
a given function, add it and send a patch. Here's a list of currently
unsupported functions:
addchnstr addchstr chgat color_set define_key
del_curterm delscreen dupwin inchnstr inchstr innstr keyok
mcprint mvaddchnstr mvaddchstr mvchgat mvcur mvinchnstr
mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr mvwchgat
mvwgetnstr mvwinchnstr mvwinchstr mvwinnstr newterm
resizeterm restartterm ripoffline scr_dump
scr_init scr_restore scr_set scrl set_curterm set_term setterm
tgetent tgetflag tgetnum tgetstr tgoto timeout tputs
use_default_colors vidattr vidputs waddchnstr waddchstr wchgat
wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl
Low-priority:
slk_attr slk_attr_off slk_attr_on slk_attr_set slk_attroff
slk_attron slk_attrset slk_clear slk_color slk_init slk_label
slk_noutrefresh slk_refresh slk_restore slk_set slk_touch
Menu extension (ncurses and probably SYSV):
current_item free_item free_menu item_count item_description
item_index item_init item_name item_opts item_opts_off
item_opts_on item_term item_userptr item_value item_visible
menu_back menu_driver menu_fore menu_format menu_grey
menu_init menu_items menu_mark menu_opts menu_opts_off
menu_opts_on menu_pad menu_pattern menu_request_by_name
menu_request_name menu_spacing menu_sub menu_term menu_userptr
menu_win new_item new_menu pos_menu_cursor post_menu
scale_menu set_current_item set_item_init set_item_opts
set_item_term set_item_userptr set_item_value set_menu_back
set_menu_fore set_menu_format set_menu_grey set_menu_init
set_menu_items set_menu_mark set_menu_opts set_menu_pad
set_menu_pattern set_menu_spacing set_menu_sub set_menu_term
set_menu_userptr set_menu_win set_top_row top_row unpost_menu
Form extension (ncurses and probably SYSV):
current_field data_ahead data_behind dup_field
dynamic_fieldinfo field_arg field_back field_buffer
field_count field_fore field_index field_info field_init
field_just field_opts field_opts_off field_opts_on field_pad
field_status field_term field_type field_userptr form_driver
form_fields form_init form_opts form_opts_off form_opts_on
form_page form_request_by_name form_request_name form_sub
form_term form_userptr form_win free_field free_form
link_field link_fieldtype move_field new_field new_form
new_page pos_form_cursor post_form scale_form
set_current_field set_field_back set_field_buffer
set_field_fore set_field_init set_field_just set_field_opts
set_field_pad set_field_status set_field_term set_field_type
set_field_userptr set_fieldtype_arg set_fieldtype_choice
set_form_fields set_form_init set_form_opts set_form_page
set_form_sub set_form_term set_form_userptr set_form_win
set_max_field set_new_page unpost_form
*/
/* Release Number */
char *PyCursesVersion = "2.2";
/* Includes */
#include "Python.h"
#ifdef __osf__
#define _XOPEN_SOURCE_EXTENDED /* Define macro for OSF/1 */
#define STRICT_SYSV_CURSES /* Don't use ncurses extensions */
#endif
#ifdef __hpux
#define _XOPEN_SOURCE_EXTENDED
#define STRICT_SYSV_CURSES
#endif
#define CURSES_MODULE
#include "py_curses.h"
/* These prototypes are in <term.h>, but including this header
#defines many common symbols (such as "lines") which breaks the
curses module in other ways. So the code will just specify
explicit prototypes here. */
extern int setupterm(char *,int,int *);
#ifdef __sgi
#include <term.h>
#endif
#if !defined(HAVE_NCURSES_H) && (defined(sgi) || defined(__sun) || defined(SCO5))
#define STRICT_SYSV_CURSES /* Don't use ncurses extensions */
typedef chtype attr_t; /* No attr_t type is available */
#endif
#if defined(_AIX)
#define STRICT_SYSV_CURSES
#endif
/* Definition of exception curses.error */
static PyObject *PyCursesError;
/* Tells whether setupterm() has been called to initialise terminfo. */
static int initialised_setupterm = FALSE;
/* Tells whether initscr() has been called to initialise curses. */
static int initialised = FALSE;
/* Tells whether start_color() has been called to initialise color usage. */
static int initialisedcolors = FALSE;
/* Utility Macros */
#define PyCursesSetupTermCalled \
if (initialised_setupterm != TRUE) { \
PyErr_SetString(PyCursesError, \
"must call (at least) setupterm() first"); \
return 0; }
#define PyCursesInitialised \
if (initialised != TRUE) { \
PyErr_SetString(PyCursesError, \
"must call initscr() first"); \
return 0; }
#define PyCursesInitialisedColor \
if (initialisedcolors != TRUE) { \
PyErr_SetString(PyCursesError, \
"must call start_color() first"); \
return 0; }
/* Utility Functions */
/*
* Check the return code from a curses function and return None
* or raise an exception as appropriate. These are exported using the
* CObject API.
*/
static PyObject *
PyCursesCheckERR(int code, char *fname)
{
if (code != ERR) {
Py_INCREF(Py_None);
return Py_None;
} else {
if (fname == NULL) {
PyErr_SetString(PyCursesError, catchall_ERR);
} else {
PyErr_Format(PyCursesError, "%s() returned ERR", fname);
}
return NULL;
}
}
static int
PyCurses_ConvertToChtype(PyObject *obj, chtype *ch)
{
if (PyInt_Check(obj)) {
*ch = (chtype) PyInt_AsLong(obj);
} else if(PyString_Check(obj)
&& (PyString_Size(obj) == 1)) {
*ch = (chtype) *PyString_AsString(obj);
} else {
return 0;
}
return 1;
}
/* Function versions of the 3 functions for tested whether curses has been
initialised or not. */
static int func_PyCursesSetupTermCalled(void)
{
PyCursesSetupTermCalled;
return 1;
}
static int func_PyCursesInitialised(void)
{
PyCursesInitialised;
return 1;
}
static int func_PyCursesInitialisedColor(void)
{
PyCursesInitialisedColor;
return 1;
}
/*****************************************************************************
The Window Object
******************************************************************************/
/* Definition of the window type */
PyTypeObject PyCursesWindow_Type;
/* Function prototype macros for Window object
X - function name
TYPE - parameter Type
ERGSTR - format string for construction of the return value
PARSESTR - format string for argument parsing
*/
#define Window_NoArgNoReturnFunction(X) \
static PyObject *PyCursesWindow_ ## X (PyCursesWindowObject *self, PyObject *args) \
{ if (!PyArg_NoArgs(args)) return NULL; \
return PyCursesCheckERR(X(self->win), # X); }
#define Window_NoArgTrueFalseFunction(X) \
static PyObject * PyCursesWindow_ ## X (PyCursesWindowObject *self, PyObject *args) \
{ \
if (!PyArg_NoArgs(args)) return NULL; \
if (X (self->win) == FALSE) { Py_INCREF(Py_False); return Py_False; } \
else { Py_INCREF(Py_True); return Py_True; } }
#define Window_NoArgNoReturnVoidFunction(X) \
static PyObject * PyCursesWindow_ ## X (PyCursesWindowObject *self, PyObject *args) \
{ \
if (!PyArg_NoArgs(args)) return NULL; \
X(self->win); Py_INCREF(Py_None); return Py_None; }
#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \
static PyObject * PyCursesWindow_ ## X (PyCursesWindowObject *self, PyObject *args) \
{ \
TYPE arg1, arg2; \
if (!PyArg_NoArgs(args)) return NULL; \
X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); }
#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \
static PyObject * PyCursesWindow_ ## X (PyCursesWindowObject *self, PyObject *args) \
{ \
TYPE arg1; \
if (!PyArg_Parse(args, PARSESTR, &arg1)) return NULL; \
X(self->win,arg1); Py_INCREF(Py_None); return Py_None; }
#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \
static PyObject * PyCursesWindow_ ## X (PyCursesWindowObject *self, PyObject *args) \
{ \
TYPE arg1; \
if (!PyArg_Parse(args,PARSESTR, &arg1)) return NULL; \
return PyCursesCheckERR(X(self->win, arg1), # X); }
#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \
static PyObject * PyCursesWindow_ ## X (PyCursesWindowObject *self, PyObject *args) \
{ \
TYPE arg1, arg2; \
if (!PyArg_Parse(args,PARSESTR, &arg1, &arg2)) return NULL; \
return PyCursesCheckERR(X(self->win, arg1, arg2), # X); }
/* ------------- WINDOW routines --------------- */
Window_NoArgNoReturnFunction(untouchwin)
Window_NoArgNoReturnFunction(touchwin)
Window_NoArgNoReturnFunction(redrawwin)
Window_NoArgNoReturnFunction(winsertln)
Window_NoArgNoReturnFunction(werase)
Window_NoArgNoReturnFunction(wdeleteln)
Window_NoArgTrueFalseFunction(is_wintouched)
Window_NoArgNoReturnVoidFunction(wsyncup)
Window_NoArgNoReturnVoidFunction(wsyncdown)
Window_NoArgNoReturnVoidFunction(wstandend)
Window_NoArgNoReturnVoidFunction(wstandout)
Window_NoArgNoReturnVoidFunction(wcursyncup)
Window_NoArgNoReturnVoidFunction(wclrtoeol)
Window_NoArgNoReturnVoidFunction(wclrtobot)
Window_NoArgNoReturnVoidFunction(wclear)
Window_OneArgNoReturnVoidFunction(idcok, int, "i;True(1) or False(0)")
Window_OneArgNoReturnVoidFunction(immedok, int, "i;True(1) or False(0)")
Window_OneArgNoReturnVoidFunction(wtimeout, int, "i;delay")
Window_NoArg2TupleReturnFunction(getyx, int, "(ii)")
Window_NoArg2TupleReturnFunction(getbegyx, int, "(ii)")
Window_NoArg2TupleReturnFunction(getmaxyx, int, "(ii)")
Window_NoArg2TupleReturnFunction(getparyx, int, "(ii)")
Window_OneArgNoReturnFunction(wattron, attr_t, "l;attr")
Window_OneArgNoReturnFunction(wattroff, attr_t, "l;attr")
Window_OneArgNoReturnFunction(wattrset, attr_t, "l;attr")
Window_OneArgNoReturnFunction(clearok, int, "i;True(1) or False(0)")
Window_OneArgNoReturnFunction(idlok, int, "i;True(1) or False(0)")
#if defined(__NetBSD__)
Window_OneArgNoReturnVoidFunction(keypad, int, "i;True(1) or False(0)")
#else
Window_OneArgNoReturnFunction(keypad, int, "i;True(1) or False(0)")
#endif
Window_OneArgNoReturnFunction(leaveok, int, "i;True(1) or False(0)")
#if defined(__NetBSD__)
Window_OneArgNoReturnVoidFunction(nodelay, int, "i;True(1) or False(0)")
#else
Window_OneArgNoReturnFunction(nodelay, int, "i;True(1) or False(0)")
#endif
Window_OneArgNoReturnFunction(notimeout, int, "i;True(1) or False(0)")
Window_OneArgNoReturnFunction(scrollok, int, "i;True(1) or False(0)")
Window_OneArgNoReturnFunction(winsdelln, int, "i;nlines")
Window_OneArgNoReturnFunction(syncok, int, "i;True(1) or False(0)")
Window_TwoArgNoReturnFunction(mvwin, int, "(ii);y,x")
Window_TwoArgNoReturnFunction(mvderwin, int, "(ii);y,x")
Window_TwoArgNoReturnFunction(wmove, int, "(ii);y,x")
#ifndef STRICT_SYSV_CURSES
Window_TwoArgNoReturnFunction(wresize, int, "(ii);lines,columns")
#endif
/* Allocation and deallocation of Window Objects */
static PyObject *
PyCursesWindow_New(WINDOW *win)
{
PyCursesWindowObject *wo;
wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type);
if (wo == NULL) return NULL;
wo->win = win;
return (PyObject *)wo;
}
static void
PyCursesWindow_Dealloc(PyCursesWindowObject *wo)
{
if (wo->win != stdscr) delwin(wo->win);
PyObject_DEL(wo);
}
/* Addch, Addstr, Addnstr */
static PyObject *
PyCursesWindow_AddCh(PyCursesWindowObject *self, PyObject *args)
{
int rtn, x, y, use_xy = FALSE;
PyObject *temp;
chtype ch = 0;
attr_t attr = A_NORMAL;
switch (ARG_COUNT(args)) {
case 1:
if (!PyArg_Parse(args, "O;ch or int", &temp))
return NULL;
break;
case 2:
if (!PyArg_Parse(args, "(Ol);ch or int,attr", &temp, &attr))
return NULL;
break;
case 3:
if (!PyArg_Parse(args,"(iiO);y,x,ch or int", &y, &x, &temp))
return NULL;
use_xy = TRUE;
break;
case 4:
if (!PyArg_Parse(args,"(iiOl);y,x,ch or int, attr",
&y, &x, &temp, &attr))
return NULL;
use_xy = TRUE;
break;
default:
PyErr_SetString(PyExc_TypeError, "addch requires 1 to 4 arguments");
return NULL;
}
if (!PyCurses_ConvertToChtype(temp, &ch)) {
PyErr_SetString(PyExc_TypeError, "argument 1 or 3 must be a ch or an int");
return NULL;
}
if (use_xy == TRUE)
rtn = mvwaddch(self->win,y,x, ch | attr);
else {
rtn = waddch(self->win, ch | attr);
}
return PyCursesCheckERR(rtn, "addch");
}
static PyObject *
PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args)
{
int rtn;
int x, y;
char *str;
attr_t attr = A_NORMAL , attr_old = A_NORMAL;
int use_xy = FALSE, use_attr = FALSE;
switch (ARG_COUNT(args)) {
case 1:
if (!PyArg_Parse(args,"s;str", &str))
return NULL;
break;
case 2:
if (!PyArg_Parse(args,"(sl);str,attr", &str, &attr))
return NULL;
use_attr = TRUE;
break;
case 3:
if (!PyArg_Parse(args,"(iis);int,int,str", &y, &x, &str))
return NULL;
use_xy = TRUE;
break;
case 4:
if (!PyArg_Parse(args,"(iisl);int,int,str,attr", &y, &x, &str, &attr))
return NULL;
use_xy = use_attr = TRUE;
break;
default:
PyErr_SetString(PyExc_TypeError, "addstr requires 1 to 4 arguments");
return NULL;
}
if (use_attr == TRUE) {
attr_old = getattrs(self->win);
wattrset(self->win,attr);
}
if (use_xy == TRUE)
rtn = mvwaddstr(self->win,y,x,str);
else
rtn = waddstr(self->win,str);
if (use_attr == TRUE)
wattrset(self->win,attr_old);
return PyCursesCheckERR(rtn, "addstr");
}
static PyObject *
PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args)
{
int rtn, x, y, n;
char *str;
attr_t attr = A_NORMAL , attr_old = A_NORMAL;
int use_xy = FALSE, use_attr = FALSE;
switch (ARG_COUNT(args)) {
case 2:
if (!PyArg_Parse(args,"(si);str,n", &str, &n))
return NULL;
break;
case 3:
if (!PyArg_Parse(args,"(sil);str,n,attr", &str, &n, &attr))
return NULL;
use_attr = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -