0
0
mirror of https://github.com/python/cpython.git synced 2024-11-24 17:47:13 +01:00
cpython/Modules/stdwinmodule.c
Guido van Rossum 01769f083f Change set/getcutbuffer to use the new stdwin interface.
This makes it possible to cut/paste strings wuth embedded null bytes.
1990-10-30 13:39:00 +00:00

1525 lines
29 KiB
C

/* Stdwin module */
/* Stdwin itself is a module, not a separate object type.
Object types defined here:
wp: a window
dp: a drawing structure (only one can exist at a time)
mp: a menu
tp: a textedit block
*/
/* Rules for translating C stdwin function calls into Python stwin:
- All names drop their initial letter 'w'
- Functions with a window as first parameter are methods of window objects
- There is no equivalent for wclose(); just delete the window object
(all references to it!) (XXX maybe this is a bad idea)
- w.begindrawing() returns a drawing object
- There is no equivalent for wenddrawing(win); just delete the drawing
object (all references to it!) (XXX maybe this is a bad idea)
- Functions that may only be used inside wbegindrawing / wendddrawing
are methods of the drawing object; this includes the text measurement
functions (which however have doubles as module functions).
- Methods of the drawing object drop an initial 'draw' from their name
if they have it, e.g., wdrawline() --> d.line()
- The obvious type conversions: int --> intobject; string --> stringobject
- A text parameter followed by a length parameter is only a text (string)
parameter in Python
- A point or other pair of horizontal and vertical coordinates is always
a pair of integers in Python
- Two points forming a rectangle or endpoints of a line segment are a
pair of points in Python
- The arguments to d.elarc() are three points.
- The functions wgetclip() and wsetclip() are translated into
stdwin.getcutbuffer() and stdwin.setcutbuffer(); 'clip' is really
a bad word for what these functions do (clipping has a different
meaning in the drawing world), while cutbuffer is standard X jargon.
XXX This must change again in the light of changes to stdwin!
- For textedit, similar rules hold, but they are less strict.
XXX more?
*/
#include <stdio.h>
#include "stdwin.h"
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "dictobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "objimpl.h"
#include "import.h"
#include "modsupport.h"
#include "errors.h"
/* Window and menu object types declared here because of forward references */
typedef struct {
OB_HEAD
object *w_title;
WINDOW *w_win;
object *w_attr; /* Attributes dictionary */
} windowobject;
extern typeobject Windowtype; /* Really static, forward */
#define is_windowobject(wp) ((wp)->ob_type == &Windowtype)
typedef struct {
OB_HEAD
MENU *m_menu;
int m_id;
object *m_attr; /* Attributes dictionary */
} menuobject;
extern typeobject Menutype; /* Really static, forward */
#define is_menuobject(mp) ((mp)->ob_type == &Menutype)
/* Strongly stdwin-specific argument handlers */
static int
getmousedetail(v, ep)
object *v;
EVENT *ep;
{
if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 4)
return err_badarg();
return getintintarg(gettupleitem(v, 0),
&ep->u.where.h, &ep->u.where.v) &&
getintarg(gettupleitem(v, 1), &ep->u.where.clicks) &&
getintarg(gettupleitem(v, 2), &ep->u.where.button) &&
getintarg(gettupleitem(v, 3), &ep->u.where.mask);
}
static int
getmenudetail(v, ep)
object *v;
EVENT *ep;
{
object *mp;
if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2)
return err_badarg();
mp = gettupleitem(v, 0);
if (mp == NULL || !is_menuobject(mp))
return err_badarg();
ep->u.m.id = ((menuobject *)mp) -> m_id;
return getintarg(gettupleitem(v, 1), &ep->u.m.item);
}
static int
geteventarg(v, ep)
object *v;
EVENT *ep;
{
object *wp, *detail;
int a[4];
if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 3)
return err_badarg();
if (!getintarg(gettupleitem(v, 0), &ep->type))
return 0;
wp = gettupleitem(v, 1);
if (wp == None)
ep->window = NULL;
else if (wp == NULL || !is_windowobject(wp))
return err_badarg();
else
ep->window = ((windowobject *)wp) -> w_win;
detail = gettupleitem(v, 2);
switch (ep->type) {
case WE_CHAR:
if (!is_stringobject(detail) || getstringsize(detail) != 1)
return err_badarg();
ep->u.character = getstringvalue(detail)[0];
return 1;
case WE_COMMAND:
return getintarg(detail, &ep->u.command);
case WE_DRAW:
if (!getrectarg(detail, a))
return 0;
ep->u.area.left = a[0];
ep->u.area.top = a[1];
ep->u.area.right = a[2];
ep->u.area.bottom = a[3];
return 1;
case WE_MOUSE_DOWN:
case WE_MOUSE_UP:
case WE_MOUSE_MOVE:
return getmousedetail(detail, ep);
case WE_MENU:
return getmenudetail(detail, ep);
default:
return 1;
}
}
/* Return construction tools */
static object *
makepoint(a, b)
int a, b;
{
object *v;
object *w;
if ((v = newtupleobject(2)) == NULL)
return NULL;
if ((w = newintobject((long)a)) == NULL ||
settupleitem(v, 0, w) != 0 ||
(w = newintobject((long)b)) == NULL ||
settupleitem(v, 1, w) != 0) {
DECREF(v);
return NULL;
}
return v;
}
static object *
makerect(a, b, c, d)
int a, b, c, d;
{
object *v;
object *w;
if ((v = newtupleobject(2)) == NULL)
return NULL;
if ((w = makepoint(a, b)) == NULL ||
settupleitem(v, 0, w) != 0 ||
(w = makepoint(c, d)) == NULL ||
settupleitem(v, 1, w) != 0) {
DECREF(v);
return NULL;
}
return v;
}
static object *
makemouse(hor, ver, clicks, button, mask)
int hor, ver, clicks, button, mask;
{
object *v;
object *w;
if ((v = newtupleobject(4)) == NULL)
return NULL;
if ((w = makepoint(hor, ver)) == NULL ||
settupleitem(v, 0, w) != 0 ||
(w = newintobject((long)clicks)) == NULL ||
settupleitem(v, 1, w) != 0 ||
(w = newintobject((long)button)) == NULL ||
settupleitem(v, 2, w) != 0 ||
(w = newintobject((long)mask)) == NULL ||
settupleitem(v, 3, w) != 0) {
DECREF(v);
return NULL;
}
return v;
}
static object *
makemenu(mp, item)
object *mp;
int item;
{
object *v;
object *w;
if ((v = newtupleobject(2)) == NULL)
return NULL;
INCREF(mp);
if (settupleitem(v, 0, mp) != 0 ||
(w = newintobject((long)item)) == NULL ||
settupleitem(v, 1, w) != 0) {
DECREF(v);
return NULL;
}
return v;
}
/* Drawing objects */
typedef struct {
OB_HEAD
windowobject *d_ref;
} drawingobject;
static drawingobject *Drawing; /* Set to current drawing object, or NULL */
/* Drawing methods */
static void
drawing_dealloc(dp)
drawingobject *dp;
{
wenddrawing(dp->d_ref->w_win);
Drawing = NULL;
DECREF(dp->d_ref);
free((char *)dp);
}
static object *
drawing_generic(dp, args, func)
drawingobject *dp;
object *args;
void (*func) FPROTO((int, int, int, int));
{
int a[4];
if (!getrectarg(args, a))
return NULL;
(*func)(a[0], a[1], a[2], a[3]);
INCREF(None);
return None;
}
static object *
drawing_line(dp, args)
drawingobject *dp;
object *args;
{
drawing_generic(dp, args, wdrawline);
}
static object *
drawing_xorline(dp, args)
drawingobject *dp;
object *args;
{
drawing_generic(dp, args, wxorline);
}
static object *
drawing_circle(dp, args)
drawingobject *dp;
object *args;
{
int a[3];
if (!getpointintarg(args, a))
return NULL;
wdrawcircle(a[0], a[1], a[2]);
INCREF(None);
return None;
}
static object *
drawing_elarc(dp, args)
drawingobject *dp;
object *args;
{
int a[6];
if (!get3pointarg(args, a))
return NULL;
wdrawelarc(a[0], a[1], a[2], a[3], a[4], a[5]);
INCREF(None);
return None;
}
static object *
drawing_box(dp, args)
drawingobject *dp;
object *args;
{
drawing_generic(dp, args, wdrawbox);
}
static object *
drawing_erase(dp, args)
drawingobject *dp;
object *args;
{
drawing_generic(dp, args, werase);
}
static object *
drawing_paint(dp, args)
drawingobject *dp;
object *args;
{
drawing_generic(dp, args, wpaint);
}
static object *
drawing_invert(dp, args)
drawingobject *dp;
object *args;
{
drawing_generic(dp, args, winvert);
}
static object *
drawing_cliprect(dp, args)
drawingobject *dp;
object *args;
{
drawing_generic(dp, args, wcliprect);
}
static object *
drawing_noclip(dp, args)
drawingobject *dp;
object *args;
{
if (!getnoarg(args))
return NULL;
wnoclip();
INCREF(None);
return None;
}
static object *
drawing_shade(dp, args)
drawingobject *dp;
object *args;
{
int a[5];
if (!getrectintarg(args, a))
return NULL;
wshade(a[0], a[1], a[2], a[3], a[4]);
INCREF(None);
return None;
}
static object *
drawing_text(dp, args)
drawingobject *dp;
object *args;
{
int a[2];
object *s;
if (!getpointstrarg(args, a, &s))
return NULL;
wdrawtext(a[0], a[1], getstringvalue(s), (int)getstringsize(s));
INCREF(None);
return None;
}
/* The following four are also used as stdwin functions */
static object *
drawing_lineheight(dp, args)
drawingobject *dp;
object *args;
{
if (!getnoarg(args))
return NULL;
return newintobject((long)wlineheight());
}
static object *
drawing_baseline(dp, args)
drawingobject *dp;
object *args;
{
if (!getnoarg(args))
return NULL;
return newintobject((long)wbaseline());
}
static object *
drawing_textwidth(dp, args)
drawingobject *dp;
object *args;
{
object *s;
if (!getstrarg(args, &s))
return NULL;
return newintobject(
(long)wtextwidth(getstringvalue(s), (int)getstringsize(s)));
}
static object *
drawing_textbreak(dp, args)
drawingobject *dp;
object *args;
{
object *s;
int a;
if (!getstrintarg(args, &s, &a))
return NULL;
return newintobject(
(long)wtextbreak(getstringvalue(s), (int)getstringsize(s), a));
}
static struct methodlist drawing_methods[] = {
{"box", drawing_box},
{"circle", drawing_circle},
{"cliprect", drawing_cliprect},
{"elarc", drawing_elarc},
{"erase", drawing_erase},
{"invert", drawing_invert},
{"line", drawing_line},
{"noclip", drawing_noclip},
{"paint", drawing_paint},
{"shade", drawing_shade},
{"text", drawing_text},
{"xorline", drawing_xorline},
/* Text measuring methods: */
{"baseline", drawing_baseline},
{"lineheight", drawing_lineheight},
{"textbreak", drawing_textbreak},
{"textwidth", drawing_textwidth},
{NULL, NULL} /* sentinel */
};
static object *
drawing_getattr(wp, name)
drawingobject *wp;
char *name;
{
return findmethod(drawing_methods, (object *)wp, name);
}
static typeobject Drawingtype = {
OB_HEAD_INIT(&Typetype)
0, /*ob_size*/
"drawing", /*tp_name*/
sizeof(drawingobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
drawing_dealloc, /*tp_dealloc*/
0, /*tp_print*/
drawing_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
};
/* Text(edit) objects */
typedef struct {
OB_HEAD
TEXTEDIT *t_text;
windowobject *t_ref;
object *t_attr; /* Attributes dictionary */
} textobject;
extern typeobject Texttype; /* Really static, forward */
static textobject *
newtextobject(wp, left, top, right, bottom)
windowobject *wp;
int left, top, right, bottom;
{
textobject *tp;
tp = NEWOBJ(textobject, &Texttype);
if (tp == NULL)
return NULL;
tp->t_attr = NULL;
INCREF(wp);
tp->t_ref = wp;
tp->t_text = tecreate(wp->w_win, left, top, right, bottom);
if (tp->t_text == NULL) {
DECREF(tp);
return (textobject *) err_nomem();
}
return tp;
}
/* Text(edit) methods */
static void
text_dealloc(tp)
textobject *tp;
{
if (tp->t_text != NULL)
tefree(tp->t_text);
if (tp->t_attr != NULL)
DECREF(tp->t_attr);
DECREF(tp->t_ref);
DEL(tp);
}
static object *
text_arrow(self, args)
textobject *self;
object *args;
{
int code;
if (!getintarg(args, &code))
return NULL;
tearrow(self->t_text, code);
INCREF(None);
return None;
}
static object *
text_draw(self, args)
textobject *self;
object *args;
{
register TEXTEDIT *tp = self->t_text;
int a[4];
int left, top, right, bottom;
if (!getrectarg(args, a))
return NULL;
if (Drawing != NULL) {
err_setstr(RuntimeError, "not drawing");
return NULL;
}
/* Clip to text area and ignore if area is empty */
left = tegetleft(tp);
top = tegettop(tp);
right = tegetright(tp);
bottom = tegetbottom(tp);
if (a[0] < left) a[0] = left;
if (a[1] < top) a[1] = top;
if (a[2] > right) a[2] = right;
if (a[3] > bottom) a[3] = bottom;
if (a[0] < a[2] && a[1] < a[3]) {
/* Hide/show focus around draw call; these are undocumented,
but required here to get the highlighting correct.
The call to werase is also required for this reason.
Finally, this forces us to require (above) that we are NOT
already drawing. */
tehidefocus(tp);
wbegindrawing(self->t_ref->w_win);
werase(a[0], a[1], a[2], a[3]);
tedrawnew(tp, a[0], a[1], a[2], a[3]);
wenddrawing(self->t_ref->w_win);
teshowfocus(tp);
}
INCREF(None);
return None;
}
static object *
text_event(self, args)
textobject *self;
object *args;
{
register TEXTEDIT *tp = self->t_text;
EVENT e;
if (!geteventarg(args, &e))
return NULL;
if (e.type == WE_MOUSE_DOWN) {
/* Cheat at the left margin */
if (e.u.where.h < 0 && tegetleft(tp) == 0)
e.u.where.h = 0;
/* XXX should also check right margin and bottom,
but we have no wgetdocsize() yet */
}
return newintobject((long) teevent(tp, &e));
}
static object *
text_getfocus(self, args)
textobject *self;
object *args;
{
if (!getnoarg(args))
return NULL;
return makepoint(tegetfoc1(self->t_text), tegetfoc2(self->t_text));
}
static object *
text_getfocustext(self, args)
textobject *self;
object *args;
{
int f1, f2;
char *text;
if (!getnoarg(args))
return NULL;
f1 = tegetfoc1(self->t_text);
f2 = tegetfoc2(self->t_text);
text = tegettext(self->t_text);
return newsizedstringobject(text + f1, f2-f1);
}
static object *
text_getrect(self, args)
textobject *self;
object *args;
{
if (!getnoarg(args))
return NULL;
return makerect(tegetleft(self->t_text),
tegettop(self->t_text),
tegetright(self->t_text),
tegetbottom(self->t_text));
}
static object *
text_gettext(self, args)
textobject *self;
object *args;
{
if (!getnoarg(args))
return NULL;
return newsizedstringobject(tegettext(self->t_text),
tegetlen(self->t_text));
}
static object *
text_move(self, args)
textobject *self;
object *args;
{
int a[4];
if (!getrectarg(args, a))
return NULL;
temovenew(self->t_text, a[0], a[1], a[2], a[3]);
INCREF(None);
return None;
}
static object *
text_setfocus(self, args)
textobject *self;
object *args;
{
int a[2];
if (!getpointarg(args, a))
return NULL;
tesetfocus(self->t_text, a[0], a[1]);
INCREF(None);
return None;
}
static object *
text_replace(self, args)
textobject *self;
object *args;
{
object *text;
if (!getstrarg(args, &text))
return NULL;
tereplace(self->t_text, getstringvalue(text));
INCREF(None);
return None;
}
static struct methodlist text_methods[] = {
"arrow", text_arrow,
"draw", text_draw,
"event", text_event,
"getfocus", text_getfocus,
"getfocustext", text_getfocustext,
"getrect", text_getrect,
"gettext", text_gettext,
"move", text_move,
"replace", text_replace,
"setfocus", text_setfocus,
{NULL, NULL} /* sentinel */
};
static object *
text_getattr(tp, name)
textobject *tp;
char *name;
{
if (tp->t_attr != NULL) {
object *v = dictlookup(tp->t_attr, name);
if (v != NULL) {
INCREF(v);
return v;
}
}
return findmethod(text_methods, (object *)tp, name);
}
static int
text_setattr(tp, name, v)
textobject *tp;
char *name;
object *v;
{
if (tp->t_attr == NULL) {
tp->t_attr = newdictobject();
if (tp->t_attr == NULL)
return -1;
}
if (v == NULL)
return dictremove(tp->t_attr, name);
else
return dictinsert(tp->t_attr, name, v);
}
static typeobject Texttype = {
OB_HEAD_INIT(&Typetype)
0, /*ob_size*/
"textedit", /*tp_name*/
sizeof(textobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
text_dealloc, /*tp_dealloc*/
0, /*tp_print*/
text_getattr, /*tp_getattr*/
text_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
};
/* Menu objects */
#define MAXNMENU 50
static menuobject *menulist[MAXNMENU]; /* Slot 0 unused */
static menuobject *
newmenuobject(title)
object *title;
{
int id;
MENU *menu;
menuobject *mp;
for (id = 1; id < MAXNMENU; id++) {
if (menulist[id] == NULL)
break;
}
if (id >= MAXNMENU)
return (menuobject *) err_nomem();
menu = wmenucreate(id, getstringvalue(title));
if (menu == NULL)
return (menuobject *) err_nomem();
mp = NEWOBJ(menuobject, &Menutype);
if (mp != NULL) {
mp->m_menu = menu;
mp->m_id = id;
mp->m_attr = NULL;
menulist[id] = mp;
}
else
wmenudelete(menu);
return mp;
}
/* Menu methods */
static void
menu_dealloc(mp)
menuobject *mp;
{
int id = mp->m_id;
if (id >= 0 && id < MAXNMENU) {
menulist[id] = NULL;
}
wmenudelete(mp->m_menu);
if (mp->m_attr != NULL)
DECREF(mp->m_attr);
DEL(mp);
}
static object *
menu_additem(self, args)
menuobject *self;
object *args;
{
object *text;
int shortcut;
if (is_tupleobject(args)) {
object *v;
if (!getstrstrarg(args, &text, &v))
return NULL;
if (getstringsize(v) != 1) {
err_badarg();
return NULL;
}
shortcut = *getstringvalue(v) & 0xff;
}
else {
if (!getstrarg(args, &text))
return NULL;
shortcut = -1;
}
wmenuadditem(self->m_menu, getstringvalue(text), shortcut);
INCREF(None);
return None;
}
static object *
menu_setitem(self, args)
menuobject *self;
object *args;
{
int index;
object *text;
if (!getintstrarg(args, &index, &text))
return NULL;
wmenusetitem(self->m_menu, index, getstringvalue(text));
INCREF(None);
return None;
}
static object *
menu_enable(self, args)
menuobject *self;
object *args;
{
int index;
int flag;
if (!getintintarg(args, &index, &flag))
return NULL;
wmenuenable(self->m_menu, index, flag);
INCREF(None);
return None;
}
static object *
menu_check(self, args)
menuobject *self;
object *args;
{
int index;
int flag;
if (!getintintarg(args, &index, &flag))
return NULL;
wmenucheck(self->m_menu, index, flag);
INCREF(None);
return None;
}
static struct methodlist menu_methods[] = {
"additem", menu_additem,
"setitem", menu_setitem,
"enable", menu_enable,
"check", menu_check,
{NULL, NULL} /* sentinel */
};
static object *
menu_getattr(mp, name)
menuobject *mp;
char *name;
{
if (mp->m_attr != NULL) {
object *v = dictlookup(mp->m_attr, name);
if (v != NULL) {
INCREF(v);
return v;
}
}
return findmethod(menu_methods, (object *)mp, name);
}
static int
menu_setattr(mp, name, v)
menuobject *mp;
char *name;
object *v;
{
if (mp->m_attr == NULL) {
mp->m_attr = newdictobject();
if (mp->m_attr == NULL)
return -1;
}
if (v == NULL)
return dictremove(mp->m_attr, name);
else
return dictinsert(mp->m_attr, name, v);
}
static typeobject Menutype = {
OB_HEAD_INIT(&Typetype)
0, /*ob_size*/
"menu", /*tp_name*/
sizeof(menuobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
menu_dealloc, /*tp_dealloc*/
0, /*tp_print*/
menu_getattr, /*tp_getattr*/
menu_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
};
/* Windows */
#define MAXNWIN 50
static windowobject *windowlist[MAXNWIN];
/* Window methods */
static void
window_dealloc(wp)
windowobject *wp;
{
if (wp->w_win != NULL) {
int tag = wgettag(wp->w_win);
if (tag >= 0 && tag < MAXNWIN)
windowlist[tag] = NULL;
else
fprintf(stderr, "XXX help! tag %d in window_dealloc\n",
tag);
wclose(wp->w_win);
}
DECREF(wp->w_title);
if (wp->w_attr != NULL)
DECREF(wp->w_attr);
free((char *)wp);
}
static void
window_print(wp, fp, flags)
windowobject *wp;
FILE *fp;
int flags;
{
fprintf(fp, "<window titled '%s'>", getstringvalue(wp->w_title));
}
static object *
window_begindrawing(wp, args)
windowobject *wp;
object *args;
{
drawingobject *dp;
if (!getnoarg(args))
return NULL;
if (Drawing != NULL) {
err_setstr(RuntimeError, "already drawing");
return NULL;
}
dp = NEWOBJ(drawingobject, &Drawingtype);
if (dp == NULL)
return NULL;
Drawing = dp;
INCREF(wp);
dp->d_ref = wp;
wbegindrawing(wp->w_win);
return (object *)dp;
}
static object *
window_change(wp, args)
windowobject *wp;
object *args;
{
int a[4];
if (!getrectarg(args, a))
return NULL;
wchange(wp->w_win, a[0], a[1], a[2], a[3]);
INCREF(None);
return None;
}
static object *
window_gettitle(wp, args)
windowobject *wp;
object *args;
{
if (!getnoarg(args))
return NULL;
INCREF(wp->w_title);
return wp->w_title;
}
static object *
window_getwinsize(wp, args)
windowobject *wp;
object *args;
{
int width, height;
if (!getnoarg(args))
return NULL;
wgetwinsize(wp->w_win, &width, &height);
return makepoint(width, height);
}
static object *
window_getdocsize(wp, args)
windowobject *wp;
object *args;
{
int width, height;
if (!getnoarg(args))
return NULL;
wgetdocsize(wp->w_win, &width, &height);
return makepoint(width, height);
}
static object *
window_getorigin(wp, args)
windowobject *wp;
object *args;
{
int width, height;
if (!getnoarg(args))
return NULL;
wgetorigin(wp->w_win, &width, &height);
return makepoint(width, height);
}
static object *
window_scroll(wp, args)
windowobject *wp;
object *args;
{
int a[6];
if (!getrectpointarg(args, a))
return NULL;
wscroll(wp->w_win, a[0], a[1], a[2], a[3], a[4], a[5]);
INCREF(None);
return None;
}
static object *
window_setdocsize(wp, args)
windowobject *wp;
object *args;
{
int a[2];
if (!getpointarg(args, a))
return NULL;
wsetdocsize(wp->w_win, a[0], a[1]);
INCREF(None);
return None;
}
static object *
window_setorigin(wp, args)
windowobject *wp;
object *args;
{
int a[2];
if (!getpointarg(args, a))
return NULL;
wsetorigin(wp->w_win, a[0], a[1]);
INCREF(None);
return None;
}
static object *
window_settitle(wp, args)
windowobject *wp;
object *args;
{
object *title;
if (!getstrarg(args, &title))
return NULL;
DECREF(wp->w_title);
INCREF(title);
wp->w_title = title;
wsettitle(wp->w_win, getstringvalue(title));
INCREF(None);
return None;
}
static object *
window_show(wp, args)
windowobject *wp;
object *args;
{
int a[4];
if (!getrectarg(args, a))
return NULL;
wshow(wp->w_win, a[0], a[1], a[2], a[3]);
INCREF(None);
return None;
}
static object *
window_settimer(wp, args)
windowobject *wp;
object *args;
{
int a;
if (!getintarg(args, &a))
return NULL;
wsettimer(wp->w_win, a);
INCREF(None);
return None;
}
static object *
window_menucreate(self, args)
windowobject *self;
object *args;
{
menuobject *mp;
object *title;
if (!getstrarg(args, &title))
return NULL;
wmenusetdeflocal(1);
mp = newmenuobject(title);
if (mp == NULL)
return NULL;
wmenuattach(self->w_win, mp->m_menu);
return (object *)mp;
}
static object *
window_textcreate(self, args)
windowobject *self;
object *args;
{
textobject *tp;
int a[4];
if (!getrectarg(args, a))
return NULL;
return (object *)
newtextobject(self, a[0], a[1], a[2], a[3]);
}
static struct methodlist window_methods[] = {
{"begindrawing",window_begindrawing},
{"change", window_change},
{"getdocsize", window_getdocsize},
{"getorigin", window_getorigin},
{"gettitle", window_gettitle},
{"getwinsize", window_getwinsize},
{"menucreate", window_menucreate},
{"scroll", window_scroll},
{"setdocsize", window_setdocsize},
{"setorigin", window_setorigin},
{"settimer", window_settimer},
{"settitle", window_settitle},
{"show", window_show},
{"textcreate", window_textcreate},
{NULL, NULL} /* sentinel */
};
static object *
window_getattr(wp, name)
windowobject *wp;
char *name;
{
if (wp->w_attr != NULL) {
object *v = dictlookup(wp->w_attr, name);
if (v != NULL) {
INCREF(v);
return v;
}
}
return findmethod(window_methods, (object *)wp, name);
}
static int
window_setattr(wp, name, v)
windowobject *wp;
char *name;
object *v;
{
if (wp->w_attr == NULL) {
wp->w_attr = newdictobject();
if (wp->w_attr == NULL)
return -1;
}
if (v == NULL)
return dictremove(wp->w_attr, name);
else
return dictinsert(wp->w_attr, name, v);
}
static typeobject Windowtype = {
OB_HEAD_INIT(&Typetype)
0, /*ob_size*/
"window", /*tp_name*/
sizeof(windowobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
window_dealloc, /*tp_dealloc*/
window_print, /*tp_print*/
window_getattr, /*tp_getattr*/
window_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
};
/* Stdwin methods */
static object *
stdwin_open(sw, args)
object *sw;
object *args;
{
int tag;
object *title;
windowobject *wp;
if (!getstrarg(args, &title))
return NULL;
for (tag = 0; tag < MAXNWIN; tag++) {
if (windowlist[tag] == NULL)
break;
}
if (tag >= MAXNWIN)
return err_nomem();
wp = NEWOBJ(windowobject, &Windowtype);
if (wp == NULL)
return NULL;
INCREF(title);
wp->w_title = title;
wp->w_win = wopen(getstringvalue(title), (void (*)()) NULL);
wp->w_attr = NULL;
if (wp->w_win == NULL) {
DECREF(wp);
return NULL;
}
windowlist[tag] = wp;
wsettag(wp->w_win, tag);
return (object *)wp;
}
static object *
stdwin_getevent(sw, args)
object *sw;
object *args;
{
EVENT e;
object *v, *w;
if (!getnoarg(args))
return NULL;
if (Drawing != NULL) {
err_setstr(RuntimeError, "cannot getevent() while drawing");
return NULL;
}
again:
wgetevent(&e);
if (e.type == WE_COMMAND && e.u.command == WC_CANCEL) {
/* Turn keyboard interrupts into exceptions */
err_set(KeyboardInterrupt);
return NULL;
}
if (e.window == NULL && (e.type == WE_COMMAND || e.type == WE_CHAR))
goto again;
v = newtupleobject(3);
if (v == NULL)
return NULL;
if ((w = newintobject((long)e.type)) == NULL) {
DECREF(v);
return NULL;
}
settupleitem(v, 0, w);
if (e.window == NULL)
w = None;
else {
int tag = wgettag(e.window);
if (tag < 0 || tag >= MAXNWIN || windowlist[tag] == NULL)
w = None;
else
w = (object *)windowlist[tag];
}
if ((long)w == (long)0x80000001) {
err_setstr(SystemError, "bad pointer in stdwin.getevent()");
return NULL;
}
INCREF(w);
settupleitem(v, 1, w);
switch (e.type) {
case WE_CHAR:
{
char c[1];
c[0] = e.u.character;
w = newsizedstringobject(c, 1);
}
break;
case WE_COMMAND:
w = newintobject((long)e.u.command);
break;
case WE_DRAW:
w = makerect(e.u.area.left, e.u.area.top,
e.u.area.right, e.u.area.bottom);
break;
case WE_MOUSE_DOWN:
case WE_MOUSE_MOVE:
case WE_MOUSE_UP:
w = makemouse(e.u.where.h, e.u.where.v,
e.u.where.clicks,
e.u.where.button,
e.u.where.mask);
break;
case WE_MENU:
if (e.u.m.id >= 0 && e.u.m.id < MAXNMENU &&
menulist[e.u.m.id] != NULL)
w = (object *)menulist[e.u.m.id];
else
w = None;
w = makemenu(w, e.u.m.item);
break;
default:
w = None;
INCREF(w);
break;
}
if (w == NULL) {
DECREF(v);
return NULL;
}
settupleitem(v, 2, w);
return v;
}
static object *
stdwin_setdefwinpos(sw, args)
object *sw;
object *args;
{
int a[2];
if (!getpointarg(args, a))
return NULL;
wsetdefwinpos(a[0], a[1]);
INCREF(None);
return None;
}
static object *
stdwin_setdefwinsize(sw, args)
object *sw;
object *args;
{
int a[2];
if (!getpointarg(args, a))
return NULL;
wsetdefwinsize(a[0], a[1]);
INCREF(None);
return None;
}
static object *
stdwin_menucreate(self, args)
object *self;
object *args;
{
object *title;
if (!getstrarg(args, &title))
return NULL;
wmenusetdeflocal(0);
return (object *)newmenuobject(title);
}
static object *
stdwin_askfile(self, args)
object *self;
object *args;
{
object *prompt, *dflt;
int new, ret;
char buf[256];
if (!getstrstrintarg(args, &prompt, &dflt, &new))
return NULL;
strncpy(buf, getstringvalue(dflt), sizeof buf);
buf[sizeof buf - 1] = '\0';
ret = waskfile(getstringvalue(prompt), buf, sizeof buf, new);
if (!ret) {
err_set(KeyboardInterrupt);
return NULL;
}
return newstringobject(buf);
}
static object *
stdwin_askync(self, args)
object *self;
object *args;
{
object *prompt;
int new, ret;
if (!getstrintarg(args, &prompt, &new))
return NULL;
ret = waskync(getstringvalue(prompt), new);
if (ret < 0) {
err_set(KeyboardInterrupt);
return NULL;
}
return newintobject((long)ret);
}
static object *
stdwin_askstr(self, args)
object *self;
object *args;
{
object *prompt, *dflt;
int ret;
char buf[256];
if (!getstrstrarg(args, &prompt, &dflt))
return NULL;
strncpy(buf, getstringvalue(dflt), sizeof buf);
buf[sizeof buf - 1] = '\0';
ret = waskstr(getstringvalue(prompt), buf, sizeof buf);
if (!ret) {
err_set(KeyboardInterrupt);
return NULL;
}
return newstringobject(buf);
}
static object *
stdwin_message(self, args)
object *self;
object *args;
{
object *msg;
if (!getstrarg(args, &msg))
return NULL;
wmessage(getstringvalue(msg));
INCREF(None);
return None;
}
static object *
stdwin_fleep(self, args)
object *self;
object *args;
{
if (!getnoarg(args))
return NULL;
wfleep();
INCREF(None);
return None;
}
static object *
stdwin_setcutbuffer(self, args)
object *self;
object *args;
{
object *str;
if (!getstrarg(args, &str))
return NULL;
wsetcutbuffer(0, getstringvalue(str), getstringsize(str));
INCREF(None);
return None;
}
static object *
stdwin_getcutbuffer(self, args)
object *self;
object *args;
{
char *str;
int len;
if (!getnoarg(args))
return NULL;
str = wgetcutbuffer(0, &len);
if (str == NULL) {
str = "";
len = 0;
}
return newsizedstringobject(str, len);
}
static struct methodlist stdwin_methods[] = {
{"askfile", stdwin_askfile},
{"askstr", stdwin_askstr},
{"askync", stdwin_askync},
{"fleep", stdwin_fleep},
{"getcutbuffer", stdwin_getcutbuffer},
{"getevent", stdwin_getevent},
{"menucreate", stdwin_menucreate},
{"message", stdwin_message},
{"open", stdwin_open},
{"setcutbuffer", stdwin_setcutbuffer},
{"setdefwinpos", stdwin_setdefwinpos},
{"setdefwinsize", stdwin_setdefwinsize},
/* Text measuring methods borrow code from drawing objects: */
{"baseline", drawing_baseline},
{"lineheight", drawing_lineheight},
{"textbreak", drawing_textbreak},
{"textwidth", drawing_textwidth},
{NULL, NULL} /* sentinel */
};
void
initstdwin()
{
initmodule("stdwin", stdwin_methods);
}