summaryrefslogtreecommitdiff
path: root/demo/_curses.py
diff options
context:
space:
mode:
Diffstat (limited to 'demo/_curses.py')
-rw-r--r--demo/_curses.py1075
1 files changed, 1075 insertions, 0 deletions
diff --git a/demo/_curses.py b/demo/_curses.py
new file mode 100644
index 0000000..46443c2
--- /dev/null
+++ b/demo/_curses.py
@@ -0,0 +1,1075 @@
+"""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")