You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1076 lines
30 KiB

"""Reimplementation of the standard extension module '_curses' using cffi."""
import sys
from functools import wraps
from _curses_cffi import ffi, lib
def _copy_to_globals(name):
globals()[name] = getattr(lib, name)
def _setup():
for name in ['ERR', 'OK', 'KEY_MIN', 'KEY_MAX',
'A_ATTRIBUTES', 'A_NORMAL', 'A_STANDOUT', 'A_UNDERLINE',
'A_REVERSE', 'A_BLINK', 'A_DIM', 'A_BOLD', 'A_ALTCHARSET',
'A_PROTECT', 'A_CHARTEXT', 'A_COLOR',
'COLOR_BLACK', 'COLOR_RED', 'COLOR_GREEN', 'COLOR_YELLOW',
'COLOR_BLUE', 'COLOR_MAGENTA', 'COLOR_CYAN', 'COLOR_WHITE',
]:
_copy_to_globals(name)
if not lib._m_NetBSD:
_copy_to_globals('A_INVIS')
for name in ['A_HORIZONTAL', 'A_LEFT', 'A_LOW', 'A_RIGHT', 'A_TOP',
'A_VERTICAL',
]:
if hasattr(lib, name):
_copy_to_globals(name)
if lib._m_NCURSES_MOUSE_VERSION:
for name in ["BUTTON1_PRESSED", "BUTTON1_RELEASED", "BUTTON1_CLICKED",
"BUTTON1_DOUBLE_CLICKED", "BUTTON1_TRIPLE_CLICKED",
"BUTTON2_PRESSED", "BUTTON2_RELEASED", "BUTTON2_CLICKED",
"BUTTON2_DOUBLE_CLICKED", "BUTTON2_TRIPLE_CLICKED",
"BUTTON3_PRESSED", "BUTTON3_RELEASED", "BUTTON3_CLICKED",
"BUTTON3_DOUBLE_CLICKED", "BUTTON3_TRIPLE_CLICKED",
"BUTTON4_PRESSED", "BUTTON4_RELEASED", "BUTTON4_CLICKED",
"BUTTON4_DOUBLE_CLICKED", "BUTTON4_TRIPLE_CLICKED",
"BUTTON_SHIFT", "BUTTON_CTRL", "BUTTON_ALT",
"ALL_MOUSE_EVENTS", "REPORT_MOUSE_POSITION",
]:
_copy_to_globals(name)
if not lib._m_NetBSD:
for key in range(lib.KEY_MIN, lib.KEY_MAX):
key_n = lib.keyname(key)
if key_n == ffi.NULL:
continue
key_n = ffi.string(key_n)
if key_n == b"UNKNOWN KEY":
continue
if not isinstance(key_n, str): # python 3
key_n = key_n.decode()
key_n = key_n.replace('(', '').replace(')', '')
globals()[key_n] = key
_setup()
# Do we want this?
# version = "2.2"
# __version__ = "2.2"
# ____________________________________________________________
_initialised_setupterm = False
_initialised = False
_initialised_color = False
def _ensure_initialised_setupterm():
if not _initialised_setupterm:
raise error("must call (at least) setupterm() first")
def _ensure_initialised():
if not _initialised:
raise error("must call initscr() first")
def _ensure_initialised_color():
if not _initialised and _initialised_color:
raise error("must call start_color() first")
def _check_ERR(code, fname):
if code != lib.ERR:
return None
elif fname is None:
raise error("curses function returned ERR")
else:
raise error("%s() returned ERR" % (fname,))
def _check_NULL(rval):
if rval == ffi.NULL:
raise error("curses function returned NULL")
return rval
def _call_lib(method_name, *args):
return getattr(lib, method_name)(*args)
def _call_lib_check_ERR(method_name, *args):
return _check_ERR(_call_lib(method_name, *args), method_name)
def _mk_no_return(method_name):
def _execute():
_ensure_initialised()
return _call_lib_check_ERR(method_name)
_execute.__name__ = method_name
return _execute
def _mk_flag_func(method_name):
# This is in the CPython implementation, but not documented anywhere.
# We have to support it, though, even if it make me sad.
def _execute(flag=True):
_ensure_initialised()
if flag:
return _call_lib_check_ERR(method_name)
else:
return _call_lib_check_ERR('no' + method_name)
_execute.__name__ = method_name
return _execute
def _mk_return_val(method_name):
def _execute():
return _call_lib(method_name)
_execute.__name__ = method_name
return _execute
def _mk_w_getyx(method_name):
def _execute(self):
y = _call_lib(method_name + 'y', self._win)
x = _call_lib(method_name + 'x', self._win)
return (y, x)
_execute.__name__ = method_name
return _execute
def _mk_w_no_return(method_name):
def _execute(self, *args):
return _call_lib_check_ERR(method_name, self._win, *args)
_execute.__name__ = method_name
return _execute
def _mk_w_return_val(method_name):
def _execute(self, *args):
return _call_lib(method_name, self._win, *args)
_execute.__name__ = method_name
return _execute
def _chtype(ch):
return int(ffi.cast("chtype", ch))
def _texttype(text):
if isinstance(text, str):
return text
elif isinstance(text, unicode):
return str(text) # default encoding
else:
raise TypeError("str or unicode expected, got a '%s' object"
% (type(text).__name__,))
def _extract_yx(args):
if len(args) >= 2:
return (args[0], args[1], args[2:])
return (None, None, args)
def _process_args(funcname, args, count, optcount, frontopt=0):
outargs = []
if frontopt:
if len(args) > count + optcount:
# We have the front optional args here.
outargs.extend(args[:frontopt])
args = args[frontopt:]
else:
# No front optional args, so make them None.
outargs.extend([None] * frontopt)
if (len(args) < count) or (len(args) > count + optcount):
raise error("%s requires %s to %s arguments" % (
funcname, count, count + optcount + frontopt))
outargs.extend(args)
return outargs
def _argspec(count, optcount=0, frontopt=0):
def _argspec_deco(func):
@wraps(func)
def _wrapped(self, *args):
outargs = _process_args(
func.__name__, args, count, optcount, frontopt)
return func(self, *outargs)
return _wrapped
return _argspec_deco
# ____________________________________________________________
class error(Exception):
pass
class Window(object):
def __init__(self, window):
self._win = window
def __del__(self):
if self._win != lib.stdscr:
lib.delwin(self._win)
untouchwin = _mk_w_no_return("untouchwin")
touchwin = _mk_w_no_return("touchwin")
redrawwin = _mk_w_no_return("redrawwin")
insertln = _mk_w_no_return("winsertln")
erase = _mk_w_no_return("werase")
deleteln = _mk_w_no_return("wdeleteln")
is_wintouched = _mk_w_return_val("is_wintouched")
syncdown = _mk_w_return_val("wsyncdown")
syncup = _mk_w_return_val("wsyncup")
standend = _mk_w_return_val("wstandend")
standout = _mk_w_return_val("wstandout")
cursyncup = _mk_w_return_val("wcursyncup")
clrtoeol = _mk_w_return_val("wclrtoeol")
clrtobot = _mk_w_return_val("wclrtobot")
clear = _mk_w_return_val("wclear")
idcok = _mk_w_no_return("idcok")
immedok = _mk_w_no_return("immedok")
timeout = _mk_w_no_return("wtimeout")
getyx = _mk_w_getyx("getcur")
getbegyx = _mk_w_getyx("getbeg")
getmaxyx = _mk_w_getyx("getmax")
getparyx = _mk_w_getyx("getpar")
clearok = _mk_w_no_return("clearok")
idlok = _mk_w_no_return("idlok")
leaveok = _mk_w_no_return("leaveok")
notimeout = _mk_w_no_return("notimeout")
scrollok = _mk_w_no_return("scrollok")
insdelln = _mk_w_no_return("winsdelln")
syncok = _mk_w_no_return("syncok")
mvwin = _mk_w_no_return("mvwin")
mvderwin = _mk_w_no_return("mvderwin")
move = _mk_w_no_return("wmove")
if not lib._m_STRICT_SYSV_CURSES:
resize = _mk_w_no_return("wresize")
if lib._m_NetBSD:
keypad = _mk_w_return_val("keypad")
nodelay = _mk_w_return_val("nodelay")
else:
keypad = _mk_w_no_return("keypad")
nodelay = _mk_w_no_return("nodelay")
@_argspec(1, 1, 2)
def addch(self, y, x, ch, attr=None):
if attr is None:
attr = lib.A_NORMAL
ch = _chtype(ch)
if y is not None:
code = lib.mvwaddch(self._win, y, x, ch | attr)
else:
code = lib.waddch(self._win, ch | attr)
return _check_ERR(code, "addch")
@_argspec(1, 1, 2)
def addstr(self, y, x, text, attr=None):
text = _texttype(text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
if y is not None:
code = lib.mvwaddstr(self._win, y, x, text)
else:
code = lib.waddstr(self._win, text)
if attr is not None:
lib.wattrset(self._win, attr_old)
return _check_ERR(code, "addstr")
@_argspec(2, 1, 2)
def addnstr(self, y, x, text, n, attr=None):
text = _texttype(text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
if y is not None:
code = lib.mvwaddnstr(self._win, y, x, text, n)
else:
code = lib.waddnstr(self._win, text, n)
if attr is not None:
lib.wattrset(self._win, attr_old)
return _check_ERR(code, "addnstr")
def bkgd(self, ch, attr=None):
if attr is None:
attr = lib.A_NORMAL
return _check_ERR(lib.wbkgd(self._win, _chtype(ch) | attr), "bkgd")
attroff = _mk_w_no_return("wattroff")
attron = _mk_w_no_return("wattron")
attrset = _mk_w_no_return("wattrset")
def bkgdset(self, ch, attr=None):
if attr is None:
attr = lib.A_NORMAL
lib.wbkgdset(self._win, _chtype(ch) | attr)
return None
def border(self, ls=0, rs=0, ts=0, bs=0, tl=0, tr=0, bl=0, br=0):
lib.wborder(self._win,
_chtype(ls), _chtype(rs), _chtype(ts), _chtype(bs),
_chtype(tl), _chtype(tr), _chtype(bl), _chtype(br))
return None
def box(self, vertint=0, horint=0):
lib.box(self._win, vertint, horint)
return None
@_argspec(1, 1, 2)
def chgat(self, y, x, num, attr=None):
# These optional args are in a weird order.
if attr is None:
attr = num
num = -1
color = ((attr >> 8) & 0xff)
attr = attr - (color << 8)
if y is not None:
code = lib.mvwchgat(self._win, y, x, num, attr, color, ffi.NULL)
lib.touchline(self._win, y, 1)
else:
yy, _ = self.getyx()
code = lib.wchgat(self._win, num, attr, color, ffi.NULL)
lib.touchline(self._win, yy, 1)
return _check_ERR(code, "chgat")
def delch(self, *args):
if len(args) == 0:
code = lib.wdelch(self._win)
elif len(args) == 2:
code = lib.mvwdelch(self._win, *args)
else:
raise error("delch requires 0 or 2 arguments")
return _check_ERR(code, "[mv]wdelch")
def derwin(self, *args):
nlines = 0
ncols = 0
if len(args) == 2:
begin_y, begin_x = args
elif len(args) == 4:
nlines, ncols, begin_y, begin_x = args
else:
raise error("derwin requires 2 or 4 arguments")
win = lib.derwin(self._win, nlines, ncols, begin_y, begin_x)
return Window(_check_NULL(win))
def echochar(self, ch, attr=None):
if attr is None:
attr = lib.A_NORMAL
ch = _chtype(ch)
if lib._m_ispad(self._win):
code = lib.pechochar(self._win, ch | attr)
else:
code = lib.wechochar(self._win, ch | attr)
return _check_ERR(code, "echochar")
if lib._m_NCURSES_MOUSE_VERSION:
enclose = _mk_w_return_val("wenclose")
getbkgd = _mk_w_return_val("getbkgd")
def getch(self, *args):
if len(args) == 0:
val = lib.wgetch(self._win)
elif len(args) == 2:
val = lib.mvwgetch(self._win, *args)
else:
raise error("getch requires 0 or 2 arguments")
return val
def getkey(self, *args):
if len(args) == 0:
val = lib.wgetch(self._win)
elif len(args) == 2:
val = lib.mvwgetch(self._win, *args)
else:
raise error("getkey requires 0 or 2 arguments")
if val == lib.ERR:
raise error("no input")
elif val <= 255:
return chr(val)
else:
# XXX: The following line is different if `__NetBSD__` is defined.
val = lib.keyname(val)
if val == ffi.NULL:
return ""
return ffi.string(val)
@_argspec(0, 1, 2)
def getstr(self, y, x, n=1023):
n = min(n, 1023)
buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */
if y is None:
val = lib.wgetnstr(self._win, buf, n)
else:
val = lib.mvwgetnstr(self._win, y, x, buf, n)
if val == lib.ERR:
return ""
return ffi.string(buf)
@_argspec(2, 1, 2)
def hline(self, y, x, ch, n, attr=None):
ch = _chtype(ch)
if attr is None:
attr = lib.A_NORMAL
if y is not None:
_check_ERR(lib.wmove(self._win, y, x), "wmove")
return _check_ERR(lib.whline(self._win, ch | attr, n), "hline")
@_argspec(1, 1, 2)
def insch(self, y, x, ch, attr=None):
ch = _chtype(ch)
if attr is None:
attr = lib.A_NORMAL
if y is not None:
code = lib.mvwinsch(self._win, y, x, ch | attr)
else:
code = lib.winsch(self._win, ch | attr)
return _check_ERR(code, "insch")
def inch(self, *args):
if len(args) == 0:
return lib.winch(self._win)
elif len(args) == 2:
return lib.mvwinch(self._win, *args)
else:
raise error("inch requires 0 or 2 arguments")
@_argspec(0, 1, 2)
def instr(self, y, x, n=1023):
n = min(n, 1023)
buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */
if y is None:
code = lib.winnstr(self._win, buf, n)
else:
code = lib.mvwinnstr(self._win, y, x, buf, n)
if code == lib.ERR:
return ""
return ffi.string(buf)
@_argspec(1, 1, 2)
def insstr(self, y, x, text, attr=None):
text = _texttype(text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
if y is not None:
code = lib.mvwinsstr(self._win, y, x, text)
else:
code = lib.winsstr(self._win, text)
if attr is not None:
lib.wattrset(self._win, attr_old)
return _check_ERR(code, "insstr")
@_argspec(2, 1, 2)
def insnstr(self, y, x, text, n, attr=None):
text = _texttype(text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
if y is not None:
code = lib.mvwinsnstr(self._win, y, x, text, n)
else:
code = lib.winsnstr(self._win, text, n)
if attr is not None:
lib.wattrset(self._win, attr_old)
return _check_ERR(code, "insnstr")
def is_linetouched(self, line):
code = lib.is_linetouched(self._win, line)
if code == lib.ERR:
raise error("is_linetouched: line number outside of boundaries")
if code == lib.FALSE:
return False
return True
def noutrefresh(self, *args):
if lib._m_ispad(self._win):
if len(args) != 6:
raise error(
"noutrefresh() called for a pad requires 6 arguments")
return _check_ERR(lib.pnoutrefresh(self._win, *args),
"pnoutrefresh")
else:
# XXX: Better args check here? We need zero args.
return _check_ERR(lib.wnoutrefresh(self._win, *args),
"wnoutrefresh")
nooutrefresh = noutrefresh # "to be removed in 2.3", but in 2.7, 3.x.
def _copywin(self, dstwin, overlay,
sminr, sminc, dminr, dminc, dmaxr, dmaxc):
return _check_ERR(lib.copywin(self._win, dstwin._win,
sminr, sminc, dminr, dminc, dmaxr, dmaxc,
overlay), "copywin")
def overlay(self, dstwin, *args):
if len(args) == 6:
return self._copywin(dstwin, True, *args)
elif len(args) == 0:
return _check_ERR(lib.overlay(self._win, dstwin._win), "overlay")
else:
raise error("overlay requires one or seven arguments")
def overwrite(self, dstwin, *args):
if len(args) == 6:
return self._copywin(dstwin, False, *args)
elif len(args) == 0:
return _check_ERR(lib.overwrite(self._win, dstwin._win),
"overwrite")
else:
raise error("overwrite requires one or seven arguments")
def putwin(self, filep):
# filestar = ffi.new("FILE *", filep)
return _check_ERR(lib.putwin(self._win, filep), "putwin")
def redrawln(self, beg, num):
return _check_ERR(lib.wredrawln(self._win, beg, num), "redrawln")
def refresh(self, *args):
if lib._m_ispad(self._win):
if len(args) != 6:
raise error(
"noutrefresh() called for a pad requires 6 arguments")
return _check_ERR(lib.prefresh(self._win, *args), "prefresh")
else:
# XXX: Better args check here? We need zero args.
return _check_ERR(lib.wrefresh(self._win, *args), "wrefresh")
def setscrreg(self, y, x):
return _check_ERR(lib.wsetscrreg(self._win, y, x), "wsetscrreg")
def subwin(self, *args):
nlines = 0
ncols = 0
if len(args) == 2:
begin_y, begin_x = args
elif len(args) == 4:
nlines, ncols, begin_y, begin_x = args
else:
raise error("subwin requires 2 or 4 arguments")
if lib._m_ispad(self._win):
win = lib.subpad(self._win, nlines, ncols, begin_y, begin_x)
else:
win = lib.subwin(self._win, nlines, ncols, begin_y, begin_x)
return Window(_check_NULL(win))
def scroll(self, nlines=None):
if nlines is None:
return _check_ERR(lib.scroll(self._win), "scroll")
else:
return _check_ERR(lib.wscrl(self._win, nlines), "scroll")
def touchline(self, st, cnt, val=None):
if val is None:
return _check_ERR(lib.touchline(self._win, st, cnt), "touchline")
else:
return _check_ERR(lib.wtouchln(self._win, st, cnt, val),
"touchline")
@_argspec(2, 1, 2)
def vline(self, y, x, ch, n, attr=None):
ch = _chtype(ch)
if attr is None:
attr = lib.A_NORMAL
if y is not None:
_check_ERR(lib.wmove(self._win, y, x), "wmove")
return _check_ERR(lib.wvline(self._win, ch | attr, n), "vline")
beep = _mk_no_return("beep")
def_prog_mode = _mk_no_return("def_prog_mode")
def_shell_mode = _mk_no_return("def_shell_mode")
doupdate = _mk_no_return("doupdate")
endwin = _mk_no_return("endwin")
flash = _mk_no_return("flash")
nocbreak = _mk_no_return("nocbreak")
noecho = _mk_no_return("noecho")
nonl = _mk_no_return("nonl")
noraw = _mk_no_return("noraw")
reset_prog_mode = _mk_no_return("reset_prog_mode")
reset_shell_mode = _mk_no_return("reset_shell_mode")
resetty = _mk_no_return("resetty")
savetty = _mk_no_return("savetty")
cbreak = _mk_flag_func("cbreak")
echo = _mk_flag_func("echo")
nl = _mk_flag_func("nl")
raw = _mk_flag_func("raw")
baudrate = _mk_return_val("baudrate")
termattrs = _mk_return_val("termattrs")
termname = _mk_return_val("termname")
longname = _mk_return_val("longname")
can_change_color = _mk_return_val("can_change_color")
has_colors = _mk_return_val("has_colors")
has_ic = _mk_return_val("has_ic")
has_il = _mk_return_val("has_il")
isendwin = _mk_return_val("isendwin")
flushinp = _mk_return_val("flushinp")
noqiflush = _mk_return_val("noqiflush")
def filter():
lib.filter()
return None
def color_content(color):
_ensure_initialised_color()
r, g, b = ffi.new("short *"), ffi.new("short *"), ffi.new("short *")
if lib.color_content(color, r, g, b) == lib.ERR:
raise error("Argument 1 was out of range. Check value of COLORS.")
return (r[0], g[0], b[0])
def color_pair(n):
_ensure_initialised_color()
return (n << 8)
def curs_set(vis):
_ensure_initialised()
val = lib.curs_set(vis)
_check_ERR(val, "curs_set")
return val
def delay_output(ms):
_ensure_initialised()
return _check_ERR(lib.delay_output(ms), "delay_output")
def erasechar():
_ensure_initialised()
return lib.erasechar()
def getsyx():
_ensure_initialised()
yx = ffi.new("int[2]")
lib._m_getsyx(yx)
return (yx[0], yx[1])
if lib._m_NCURSES_MOUSE_VERSION:
def getmouse():
_ensure_initialised()
mevent = ffi.new("MEVENT *")
_check_ERR(lib.getmouse(mevent), "getmouse")
return (mevent.id, mevent.x, mevent.y, mevent.z, mevent.bstate)
def ungetmouse(id, x, y, z, bstate):
_ensure_initialised()
mevent = ffi.new("MEVENT *")
mevent.id, mevent.x, mevent.y, mevent.z, mevent.bstate = (
id, x, y, z, bstate)
return _check_ERR(lib.ungetmouse(mevent), "ungetmouse")
def getwin(filep):
return Window(_check_NULL(lib.getwin(filep)))
def halfdelay(tenths):
_ensure_initialised()
return _check_ERR(lib.halfdelay(tenths), "halfdelay")
if not lib._m_STRICT_SYSV_CURSES:
def has_key(ch):
_ensure_initialised()
return lib.has_key(ch)
def init_color(color, r, g, b):
_ensure_initialised_color()
return _check_ERR(lib.init_color(color, r, g, b), "init_color")
def init_pair(pair, f, b):
_ensure_initialised_color()
return _check_ERR(lib.init_pair(pair, f, b), "init_pair")
def _mk_acs(name, ichar):
if len(ichar) == 1:
globals()[name] = lib.acs_map[ord(ichar)]
else:
globals()[name] = globals()[ichar]
def _map_acs():
_mk_acs("ACS_ULCORNER", 'l')
_mk_acs("ACS_LLCORNER", 'm')
_mk_acs("ACS_URCORNER", 'k')
_mk_acs("ACS_LRCORNER", 'j')
_mk_acs("ACS_LTEE", 't')
_mk_acs("ACS_RTEE", 'u')
_mk_acs("ACS_BTEE", 'v')
_mk_acs("ACS_TTEE", 'w')
_mk_acs("ACS_HLINE", 'q')
_mk_acs("ACS_VLINE", 'x')
_mk_acs("ACS_PLUS", 'n')
_mk_acs("ACS_S1", 'o')
_mk_acs("ACS_S9", 's')
_mk_acs("ACS_DIAMOND", '`')
_mk_acs("ACS_CKBOARD", 'a')
_mk_acs("ACS_DEGREE", 'f')
_mk_acs("ACS_PLMINUS", 'g')
_mk_acs("ACS_BULLET", '~')
_mk_acs("ACS_LARROW", ',')
_mk_acs("ACS_RARROW", '+')
_mk_acs("ACS_DARROW", '.')
_mk_acs("ACS_UARROW", '-')
_mk_acs("ACS_BOARD", 'h')
_mk_acs("ACS_LANTERN", 'i')
_mk_acs("ACS_BLOCK", '0')
_mk_acs("ACS_S3", 'p')
_mk_acs("ACS_S7", 'r')
_mk_acs("ACS_LEQUAL", 'y')
_mk_acs("ACS_GEQUAL", 'z')
_mk_acs("ACS_PI", '{')
_mk_acs("ACS_NEQUAL", '|')
_mk_acs("ACS_STERLING", '}')
_mk_acs("ACS_BSSB", "ACS_ULCORNER")
_mk_acs("ACS_SSBB", "ACS_LLCORNER")
_mk_acs("ACS_BBSS", "ACS_URCORNER")
_mk_acs("ACS_SBBS", "ACS_LRCORNER")
_mk_acs("ACS_SBSS", "ACS_RTEE")
_mk_acs("ACS_SSSB", "ACS_LTEE")
_mk_acs("ACS_SSBS", "ACS_BTEE")
_mk_acs("ACS_BSSS", "ACS_TTEE")
_mk_acs("ACS_BSBS", "ACS_HLINE")
_mk_acs("ACS_SBSB", "ACS_VLINE")
_mk_acs("ACS_SSSS", "ACS_PLUS")
def initscr():
if _initialised:
lib.wrefresh(lib.stdscr)
return Window(lib.stdscr)
win = _check_NULL(lib.initscr())
globals()['_initialised_setupterm'] = True
globals()['_initialised'] = True
_map_acs()
globals()["LINES"] = lib.LINES
globals()["COLS"] = lib.COLS
return Window(win)
def setupterm(term=None, fd=-1):
if fd == -1:
# XXX: Check for missing stdout here?
fd = sys.stdout.fileno()
if _initialised_setupterm:
return None
if term is None:
term = ffi.NULL
err = ffi.new("int *")
if lib.setupterm(term, fd, err) == lib.ERR:
err = err[0]
if err == 0:
raise error("setupterm: could not find terminal")
elif err == -1:
raise error("setupterm: could not find terminfo database")
else:
raise error("setupterm: unknown error")
globals()["_initialised_setupterm"] = True
return None
def intrflush(ch):
_ensure_initialised()
return _check_ERR(lib.intrflush(ffi.NULL, ch), "intrflush")
# XXX: #ifdef HAVE_CURSES_IS_TERM_RESIZED
def is_term_resized(lines, columns):
_ensure_initialised()
return lib.is_term_resized(lines, columns)
if not lib._m_NetBSD:
def keyname(ch):
_ensure_initialised()
if ch < 0:
raise error("invalid key number")
knp = lib.keyname(ch)
if knp == ffi.NULL:
return ""
return ffi.string(knp)
def killchar():
return lib.killchar()
def meta(ch):
return _check_ERR(lib.meta(lib.stdscr, ch), "meta")
if lib._m_NCURSES_MOUSE_VERSION:
def mouseinterval(interval):
_ensure_initialised()
return _check_ERR(lib.mouseinterval(interval), "mouseinterval")
def mousemask(newmask):
_ensure_initialised()
oldmask = ffi.new("mmask_t *")
availmask = lib.mousemask(newmask, oldmask)
return (availmask, oldmask)
def napms(ms):
_ensure_initialised()
return lib.napms(ms)
def newpad(nlines, ncols):
_ensure_initialised()
return Window(_check_NULL(lib.newpad(nlines, ncols)))
def newwin(nlines, ncols, begin_y=None, begin_x=None):
_ensure_initialised()
if begin_x is None:
if begin_y is not None:
raise error("newwin requires 2 or 4 arguments")
begin_y = begin_x = 0
return Window(_check_NULL(lib.newwin(nlines, ncols, begin_y, begin_x)))
def pair_content(pair):
_ensure_initialised_color()
f = ffi.new("short *")
b = ffi.new("short *")
if lib.pair_content(pair, f, b) == lib.ERR:
raise error("Argument 1 was out of range. (1..COLOR_PAIRS-1)")
return (f, b)
def pair_number(pairvalue):
_ensure_initialised_color()
return (pairvalue & lib.A_COLOR) >> 8
def putp(text):
text = _texttype(text)
return _check_ERR(lib.putp(text), "putp")
def qiflush(flag=True):
_ensure_initialised()
if flag:
lib.qiflush()
else:
lib.noqiflush()
return None
# XXX: Do something about the following?
# /* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES
# * and _curses.COLS */
# #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)
# static int
# update_lines_cols(void)
# {
# PyObject *o;
# PyObject *m = PyImport_ImportModuleNoBlock("curses");
# if (!m)
# return 0;
# o = PyInt_FromLong(LINES);
# if (!o) {
# Py_DECREF(m);
# return 0;
# }
# if (PyObject_SetAttrString(m, "LINES", o)) {
# Py_DECREF(m);
# Py_DECREF(o);
# return 0;
# }
# if (PyDict_SetItemString(ModDict, "LINES", o)) {
# Py_DECREF(m);
# Py_DECREF(o);
# return 0;
# }
# Py_DECREF(o);
# o = PyInt_FromLong(COLS);
# if (!o) {
# Py_DECREF(m);
# return 0;
# }
# if (PyObject_SetAttrString(m, "COLS", o)) {
# Py_DECREF(m);
# Py_DECREF(o);
# return 0;
# }
# if (PyDict_SetItemString(ModDict, "COLS", o)) {
# Py_DECREF(m);
# Py_DECREF(o);
# return 0;
# }
# Py_DECREF(o);
# Py_DECREF(m);
# return 1;
# }
# #endif
# #ifdef HAVE_CURSES_RESIZETERM
# static PyObject *
# PyCurses_ResizeTerm(PyObject *self, PyObject *args)
# {
# int lines;
# int columns;
# PyObject *result;
# PyCursesInitialised;
# if (!PyArg_ParseTuple(args,"ii:resizeterm", &lines, &columns))
# return NULL;
# result = PyCursesCheckERR(resizeterm(lines, columns), "resizeterm");
# if (!result)
# return NULL;
# if (!update_lines_cols())
# return NULL;
# return result;
# }
# #endif
# #ifdef HAVE_CURSES_RESIZE_TERM
# static PyObject *
# PyCurses_Resize_Term(PyObject *self, PyObject *args)
# {
# int lines;
# int columns;
# PyObject *result;
# PyCursesInitialised;
# if (!PyArg_ParseTuple(args,"ii:resize_term", &lines, &columns))
# return NULL;
# result = PyCursesCheckERR(resize_term(lines, columns), "resize_term");
# if (!result)
# return NULL;
# if (!update_lines_cols())
# return NULL;
# return result;
# }
# #endif /* HAVE_CURSES_RESIZE_TERM */
def setsyx(y, x):
_ensure_initialised()
lib.setsyx(y, x)
return None
def start_color():
_check_ERR(lib.start_color(), "start_color")
globals()["COLORS"] = lib.COLORS
globals()["COLOR_PAIRS"] = lib.COLOR_PAIRS
globals()["_initialised_color"] = True
return None
def tigetflag(capname):
_ensure_initialised_setupterm()
return lib.tigetflag(capname)
def tigetnum(capname):
_ensure_initialised_setupterm()
return lib.tigetnum(capname)
def tigetstr(capname):
_ensure_initialised_setupterm()
val = lib.tigetstr(capname)
if int(ffi.cast("intptr_t", val)) in (0, -1):
return None
return ffi.string(val)
def tparm(fmt, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
args = [ffi.cast("int", i) for i in (i1, i2, i3, i4, i5, i6, i7, i8, i9)]
result = lib.tparm(fmt, *args)
if result == ffi.NULL:
raise error("tparm() returned NULL")
return ffi.string(result)
def typeahead(fd):
_ensure_initialised()
return _check_ERR(lib.typeahead(fd), "typeahead")
def unctrl(ch):
_ensure_initialised()
return lib.unctrl(_chtype(ch))
def ungetch(ch):
_ensure_initialised()
return _check_ERR(lib.ungetch(_chtype(ch)), "ungetch")
def use_env(flag):
lib.use_env(flag)
return None
if not lib._m_STRICT_SYSV_CURSES:
def use_default_colors():
_ensure_initialised_color()
return _check_ERR(lib.use_default_colors(), "use_default_colors")