| """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") |