/*************************************************************************** ** *A ncurses.c BROWSE package Frank Lübeck ** ** Provide functions from ncurses C-library to GAP. ** We choose a subset of functions, usually the 'w'-variants. ** Panels can also be used. **
*/
#define VERSION "1.8.21"
/* read GAP source header files with a combined header file */
#include"compiled.h"/* GAP headers */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> /* for getenv and co */ #ifdef WIDECHARS #define _XOPEN_SOURCE_EXTENDED #include <locale.h> #include <ncursesw/curses.h> #include <ncursesw/panel.h> #include <ncursesw/term.h> #else #include <ncurses.h> #include <panel.h> #include <term.h> #endif
/* remember attributes at init time XXX static attr_t startattr; static short startcp;
*/
/* We store the living WINDOW and PANEL pointers in two strings. The pointer to window i (zero based counting) is stored in ((WINDOW**)CHARS_STRING(winlist))[i]. If this window is wrapped in a panel then the pointer to this panel is stored in the same position of panellist. For debugging purposes the strings winlist and panellist are available in GAP as record components of the same name in 'NCurses'.
*/ static Obj winlist; static Obj panellist;
/* the functions */
/* get the win or panel from number (return NULL if no valid input) */
WINDOW* winnum(Obj num) { Int n; if (!IS_INTOBJ(num)) return (WINDOW*)0;
n = INT_INTOBJ(num); if (n < 0 || n * sizeof(Obj) >= GET_LEN_STRING(winlist)) return (WINDOW*)0; return ((WINDOW**)CHARS_STRING(winlist))[n];
}
PANEL* pannum(Obj num) { Int n; if (!IS_INTOBJ(num)) return (PANEL*)0;
n = INT_INTOBJ(num); /* no panel for stdscr */ if (n < 1 || n * sizeof(Obj) >= GET_LEN_STRING(panellist)) return (PANEL*)0; return ((PANEL**)CHARS_STRING(panellist))[n];
}
Obj IsStdinATty(Obj self) { if (isatty(0)) returnTrue; else returnFalse;
}
Obj IsStdoutATty(Obj self) { if (isatty(1)) returnTrue; else returnFalse;
}
/* interface to configure some basic behaviour of the ncurses screen */
Obj Cbreak(Obj self) { if (cbreak() != ERR) returnTrue; else returnFalse;
}
Obj Setupterm( Obj self, Obj tnam ) { int i; if (!IS_STRING_REP(tnam)) returnFalse; if (setupterm(CSTR_STRING(tnam), 1, &i) != ERR) returnTrue; else return INTOBJ_INT(i);
}
/* create, delete, move windows */
Obj Newwin( Obj self, Obj nlines, Obj ncols, Obj begin_y, Obj begin_x) { Int nl, nc, by, bx; int num;
WINDOW *win;
if (IS_INTOBJ(nlines))
nl = INT_INTOBJ(nlines); else
nl = 0; if (IS_INTOBJ(ncols))
nc = INT_INTOBJ(ncols); else
nc = 0; if (IS_INTOBJ(begin_y))
by = INT_INTOBJ(begin_y); else
by = 0; if (IS_INTOBJ(begin_x))
bx = INT_INTOBJ(begin_x); else
bx = 0;
win = newwin(nl, nc, by, bx); if (win) {
num = GET_LEN_STRING(winlist)/sizeof(Obj);
GROW_STRING(winlist, (num+1)*sizeof(Obj));
((WINDOW**)(CHARS_STRING(winlist)))[num] = win;
SET_LEN_STRING(winlist, (num+1)*sizeof(Obj));
CHANGED_BAG(winlist); return INTOBJ_INT(num);
} else returnFalse;
}
Obj Delwin( Obj self, Obj num ) {
WINDOW* win; Int i, n;
win = winnum(num); if (win) { if (delwin(win) != ERR) {
n = INT_INTOBJ(num);
((WINDOW**)(CHARS_STRING(winlist)))[n] = 0; if ((n+1)*sizeof(Obj) == GET_LEN_STRING(winlist)) { for (i = GET_LEN_STRING(winlist)/sizeof(Obj);
i > 0 && ((WINDOW**)(CHARS_STRING(winlist)))[i-1] == 0;
i--);
SET_LEN_STRING(winlist, i * sizeof(Obj));
}
CHANGED_BAG(winlist); returnTrue;
} else returnFalse;
} else returnFalse;
}
Obj Mvwin(Obj self, Obj num, Obj y, Obj x) { Int iy, ix;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (IS_INTOBJ(y))
iy = INT_INTOBJ(y); else
iy = 0; if (IS_INTOBJ(x))
ix = INT_INTOBJ(x); else
ix = 0; if (mvwin(win, iy, ix) != ERR) returnTrue; else returnFalse;
}
/* moving curser, writing characters and strings to terminal */
Obj WMove(Obj self, Obj num, Obj y, Obj x) {
WINDOW *win; Int iy, ix;
win = winnum(num); if (!win) returnFalse; if (IS_INTOBJ(y))
iy = INT_INTOBJ(y); else
iy = 0; if (IS_INTOBJ(x))
ix = INT_INTOBJ(x); else
ix = 0; if (wmove(win, iy, ix) != ERR) returnTrue; else returnFalse;
}
/* whole window, or to EOL or to bottom of window */
Obj WClear( Obj self, Obj num ) {
WINDOW* win;
win = winnum(num); if (win) { if (wclear(win) != ERR) returnTrue; else returnFalse;
} else returnFalse;
}
Obj WErase( Obj self, Obj num ) {
WINDOW* win;
win = winnum(num); if (win) { if (werase(win) != ERR) returnTrue; else returnFalse;
} else returnFalse;
}
Obj WClrtoeol( Obj self, Obj num ) {
WINDOW* win;
win = winnum(num); if (win) { if (wclrtoeol(win) != ERR) returnTrue; else returnFalse;
} else returnFalse;
}
Obj WClrtobot( Obj self, Obj num ) {
WINDOW* win;
win = winnum(num); if (win) { if (wclrtobot(win) != ERR) returnTrue; else returnFalse;
} else returnFalse;
}
Obj WAddnstr(Obj self, Obj num, Obj str, Obj n) {
WINDOW *win; Int len;
win = winnum(num); if (!win) returnFalse; if (!IS_STRING_REP(str)) returnFalse; if (!IS_INTOBJ(n))
len = GET_LEN_STRING(str); else
len = INT_INTOBJ(n); if (waddnstr(win, CSTR_STRING(str), len) != ERR) returnTrue; else returnFalse;
}
/* ch can be a GAP character or an INTOBJ (possibly containing
attribute info) */
Obj WAddch(Obj self, Obj num, Obj ch) {
WINDOW *win; Int ich;
win = winnum(num); if (!win) returnFalse; if (TNUM_OBJ(ch) == T_CHAR)
ich = *(UChar*)ADDR_OBJ(ch); elseif (IS_INTOBJ(ch))
ich = INT_INTOBJ(ch); else returnFalse; if (waddch(win, ich) != ERR) returnTrue; else returnFalse;
}
Obj WVline(Obj self, Obj num, Obj ch, Obj n) { Int x, y, ich;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (TNUM_OBJ(ch) == T_CHAR)
ich = *(UChar*)ADDR_OBJ(ch); elseif (IS_INTOBJ(ch))
ich = INT_INTOBJ(ch); else
ich = 0; if (!IS_INTOBJ(n))
getmaxyx(win, y, x); else
y = INT_INTOBJ(n);
x = wvline(win, ich, y); if (x != ERR) return INTOBJ_INT(x); else returnFalse;
}
Obj WHline(Obj self, Obj num, Obj ch, Obj n) { Int x, y, ich;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (TNUM_OBJ(ch) == T_CHAR)
ich = *(UChar*)ADDR_OBJ(ch); elseif (IS_INTOBJ(ch))
ich = INT_INTOBJ(ch); else
ich = 0; if (!IS_INTOBJ(n))
getmaxyx(win, y, x); else
x = INT_INTOBJ(n);
y = whline(win, ich, x); if (y != ERR) return INTOBJ_INT(y); else returnFalse;
}
/* returns integer which can be fed back in waddch */
Obj WInch(Obj self, Obj num) {
WINDOW *win;
win = winnum(num); if (!win) returnFalse; return INTOBJ_INT((Int) winch(win));
}
/* get size of window and cursor position */
Obj Getyx(Obj self, Obj num) {
WINDOW *win; int x, y;
Obj res;
win = winnum(num); if (!win) returnFalse;
res = NEW_PLIST(T_PLIST, 2);
SET_LEN_PLIST(res, 2);
getyx(win, y, x);
SET_ELM_PLIST(res, 1, INTOBJ_INT(y));
SET_ELM_PLIST(res, 2, INTOBJ_INT(x)); return res;
}
Obj Getbegyx(Obj self, Obj num) {
WINDOW *win; int x, y;
Obj res;
win = winnum(num); if (!win) returnFalse;
res = NEW_PLIST(T_PLIST, 2);
SET_LEN_PLIST(res, 2);
getbegyx(win, y, x);
SET_ELM_PLIST(res, 1, INTOBJ_INT(y));
SET_ELM_PLIST(res, 2, INTOBJ_INT(x)); return res;
}
Obj Getmaxyx(Obj self, Obj num) {
WINDOW *win; int x, y;
Obj res;
win = winnum(num); if (!win) returnFalse;
res = NEW_PLIST(T_PLIST, 2);
SET_LEN_PLIST(res, 2);
getmaxyx(win, y, x);
SET_ELM_PLIST(res, 1, INTOBJ_INT(y));
SET_ELM_PLIST(res, 2, INTOBJ_INT(x)); return res;
}
/* the win argument is used for possible echoing */
Obj WGetch(Obj self, Obj num) { int c;
WINDOW *win;
win = winnum(num); if (!win)
win = stdscr;
c = getch(); if (c != ERR) return INTOBJ_INT(c == 127 ? KEY_BACKSPACE : c); else returnFalse;
}
Obj Ungetch(Obj self, Obj ch) { int ich; if (!IS_INTOBJ(ch)) returnFalse;
ich = (int) INT_INTOBJ(ch); if (ungetch(ich) != ERR) returnTrue; else returnFalse;
}
Obj Has_key(Obj self, Obj ch) { int ich; if (!IS_INTOBJ(ch)) returnFalse;
ich = (int) INT_INTOBJ(ch); if (has_key(ich) == TRUE) returnTrue; else returnFalse;
}
/* Keys, we give symbols of standard special keys to GAP */
/* Attributes, we handle colors and standard attributes */
Obj InitAttrs() {
Obj tmp, cp;
UInt4 i, n;
tmp = NEW_PREC(0); if (has_colors()) {
start_color();
use_default_colors();
AssPRec(tmp, RNamName("has_colors"), True); /* initialize color pairs 1..64 */
cp = NEW_PLIST(T_PLIST, 64); for (i = 1; i <= 64 && i < COLOR_PAIRS; i++) { if (i < 64) if (i%8 == i/8) {
init_pair(i, i%8, -1);
} else {
init_pair(i, i % 8, i/8);
} else
init_pair(i, 0, -1);
n = COLOR_PAIR(i);
SET_ELM_PLIST(cp, i, INTOBJ_INT(n));
SET_LEN_PLIST(cp, (UInt)i);
}
AssPRec(tmp, RNamName("ColorPairs"), cp); /* fgcolor with default background */ if (72 < COLOR_PAIRS) {
cp = NEW_PLIST(T_PLIST, 8);
SET_LEN_PLIST(cp, 8); for (i = 0; i <= 7; i++) {
init_pair(65+i, i, -1);
n = COLOR_PAIR(65+i);
SET_ELM_PLIST(cp, i+1, INTOBJ_INT(n));
}
AssPRec(tmp, RNamName("ColorPairsFg"), cp);
} /* bgcolor with default foreground */ if (80 < COLOR_PAIRS) {
cp = NEW_PLIST(T_PLIST, 8);
SET_LEN_PLIST(cp, 8); for (i = 0; i <= 7; i++) {
init_pair(73+i, -1, i);
n = COLOR_PAIR(73+i);
SET_ELM_PLIST(cp, i+1, INTOBJ_INT(n));
}
AssPRec(tmp, RNamName("ColorPairsBg"), cp);
}
} else {
AssPRec(tmp, RNamName("has_colors"), False);
} /* the other attributes */
AssPRec(tmp, RNamName("NORMAL"), INTOBJ_INT(A_NORMAL));
AssPRec(tmp, RNamName("STANDOUT"), INTOBJ_INT(A_STANDOUT));
AssPRec(tmp, RNamName("UNDERLINE"), INTOBJ_INT(A_UNDERLINE));
AssPRec(tmp, RNamName("REVERSE"), INTOBJ_INT(A_REVERSE));
AssPRec(tmp, RNamName("BLINK"), INTOBJ_INT(A_BLINK));
AssPRec(tmp, RNamName("DIM"), INTOBJ_INT(A_DIM));
AssPRec(tmp, RNamName("BOLD"), INTOBJ_INT(A_BOLD));
return tmp;
}
Obj WAttrset(Obj self, Obj num, Obj attrs) { Int i;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (IS_INTOBJ(attrs))
i = INT_INTOBJ(attrs); else
i = 0; if (wattrset(win, i) != ERR) returnTrue; else returnFalse;
}
Obj WAttron(Obj self, Obj num, Obj attrs) { Int i;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (IS_INTOBJ(attrs))
i = INT_INTOBJ(attrs); else
i = 0; if (wattron(win, i) != ERR) returnTrue; else returnFalse;
}
Obj WAttroff(Obj self, Obj num, Obj attrs) { Int i;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (IS_INTOBJ(attrs))
i = INT_INTOBJ(attrs); else
i = 0; if (wattroff(win, i) != ERR) returnTrue; else returnFalse;
}
/* wattr_get is a macro and allows NULL pointers as arguments, this is checked in the code. If we call it with arguments which are obviously never NULL, then gcc >= 4.6 with -Wall or -Waddress issues a warning that a pointer is checked for not being NULL although it is never NULL.
We wrap that macro in a function to avoid the warning. */ int wattr_get_fun(WINDOW *win, attr_t * pa, short *ps, void *opts) { int ret;
ret = wattr_get(win, pa, ps, opts); return ret;
}
Obj WAttrCPGet(Obj self, Obj num) {
WINDOW *win;
attr_t a; short cp;
Obj res;
win = winnum(num); if (!win) returnFalse;
wattr_get_fun(win, &a, &cp, NULL);
res = NEW_PLIST(T_PLIST, 2);
SET_LEN_PLIST(res, 2);
SET_ELM_PLIST(res, 1, INTOBJ_INT((int)a));
SET_ELM_PLIST(res, 2, INTOBJ_INT((int)cp)); return res;
};
Obj WBkgdset(Obj self, Obj num, Obj attrs) { Int i;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (IS_INTOBJ(attrs))
i = INT_INTOBJ(attrs); else
i = 0;
wbkgdset(win, i); returnTrue;
}
Obj WBkgd(Obj self, Obj num, Obj attrs) { Int i;
WINDOW *win;
win = winnum(num); if (!win) returnFalse; if (IS_INTOBJ(attrs))
i = INT_INTOBJ(attrs); else
i = 0;
wbkgd(win, i); returnTrue;
}
/* Panels: create, delete, update, move, stack movements, hide, show */
Obj New_panel(Obj self, Obj num) {
WINDOW *win;
PANEL *pan; int n;
win = winnum(num); if (!win) returnFalse;
n = INT_INTOBJ(num); if (n == 0) /* no panel for stdscr */ returnFalse;
pan = new_panel(win); if (!pan) returnFalse;
GROW_STRING(panellist, (n+1)*sizeof(Obj));
((PANEL**)(CHARS_STRING(panellist)))[n] = pan; if ((n+1)*sizeof(Obj) > GET_LEN_STRING(panellist))
SET_LEN_STRING(panellist, (n+1)*sizeof(Obj));
CHANGED_BAG(panellist); return num;
}
Obj Del_panel(Obj self, Obj pnum) {
PANEL *pan; Int i, n;
pan = pannum(pnum); if (!pan) returnFalse; if (del_panel(pan) != ERR) {
n = INT_INTOBJ(pnum);
((PANEL**)(CHARS_STRING(panellist)))[n] = 0; if ((n+1)*sizeof(Obj) == GET_LEN_STRING(panellist)) { for (i = GET_LEN_STRING(panellist)/sizeof(Obj);
i > 0 && ((PANEL**)(CHARS_STRING(panellist)))[i-1] == 0;
i--);
SET_LEN_STRING(panellist, i * sizeof(Obj));
}
CHANGED_BAG(panellist); returnTrue;
} else returnFalse;
}
/* translate mmask_t to list of integers and vice versa */
Obj IntlistMmask_t(mmask_t mask) {
Obj res; Int l, i;
res = NEW_PLIST(T_PLIST, 1);
SET_LEN_PLIST(res, 0); for (l=1, i=0; i<LENmmaskbits; i++) { if (mask & mmaskbits[i]) {AssPlist(res, l, INTOBJ_INT(i)); l++;}
} return res;
}
mmask_t mmaskIntlist(Obj list) {
mmask_t res = (mmask_t)0; Int l, i, n; while (! IS_PLIST(list)) {
list = ErrorReturnObj(" must be a plain list of integers, not a %s)",
(Int)TNAM_OBJ(list), 0L, "you can replace via 'return ;'" );
}
l = LEN_PLIST(list); for (i = 0; i<l; i++) {
n = INT_INTOBJ(ELM_PLIST(list, i+1)); if (n >= 0 && n < LENmmaskbits) {res += mmaskbits[n];}
} return res;
}
Obj Mousemask(Obj self, Obj list) {
mmask_t new, old;
Obj res; while (! IS_PLIST(list)) {
list = ErrorReturnObj(" must be a plain list of integers, not a %s)",
(Int)TNAM_OBJ(list), 0L, "you can replace via 'return ;'" );
} new = mmaskIntlist(list); new = mousemask(new, &old);
res = NEW_PREC(0);
AssPRec(res, RNamName("new"), IntlistMmask_t(new));
AssPRec(res, RNamName("old"), IntlistMmask_t(old)); return res;
}
static MEVENT mev;
Obj GetMouse(Obj self) { int y, x;
Obj res, mask; if (getmouse(&mev) == ERR) return Fail;
mask = IntlistMmask_t(mev.bstate);
y = mev.y;
x = mev.x; /* find panels/windows from above under mouse event */
res = NEW_PLIST(T_PLIST, 3);
SET_LEN_PLIST(res, 3);
SET_ELM_PLIST(res, 1, INTOBJ_INT(y));
SET_ELM_PLIST(res, 2, INTOBJ_INT(x));
SET_ELM_PLIST(res, 3, mask); return res;
}
Obj Wenclose(Obj self, Obj wnum, Obj iy, Obj ix) {
WINDOW *win; int y, x;
win = winnum(wnum); if (win == NULL) returnFalse; if (! IS_INTOBJ(iy)) returnFalse; else y = INT_INTOBJ(iy); if (! IS_INTOBJ(ix)) returnFalse; else x = INT_INTOBJ(ix); if (wenclose(win, y, x) == TRUE) returnTrue; elsereturnFalse;
}
/* setup and initialize the ncurses package */
winlist = NEW_STRING(sizeof(Obj));
SET_LEN_STRING(winlist, sizeof(Obj));
panellist = NEW_STRING(sizeof(Obj));
SET_LEN_STRING(panellist, sizeof(Obj));
#ifdef WIDECHARS /* set locale from environment */
setlocale(LC_ALL,""); #endif
/* make sure that TERM is set to avoid exit by initscr */
tnam = getenv("TERM"); if (tnam == NULL)
putenv("TERM=dumb"); if (setupterm(tnam, 1, &ierr) == ERR) {
putenv("TERM=xterm-16color");
tnam = getenv("TERM"); if (setupterm(tnam, 1, &ierr) == ERR) {
putenv("TERM=xterm");
tnam = getenv("TERM"); if (setupterm(tnam, 1, &ierr) == ERR) {
putenv("TERM=ansi");
tnam = getenv("TERM"); if (setupterm(tnam, 1, &ierr) == ERR) {
putenv("TERM=dumb");
tnam = getenv("TERM");
}
}
}
}
/* init filters and functions
we assign the functions to components of a record "NCurses" */ /* (re)build kernel part of NCurses */
gvar = GVarName("NCurses");
tmp = VAL_GVAR(gvar); if (!tmp) {
tmp = NEW_PREC(0);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.