From a7c699adf2d43db1709478334103183b40a65f88 Mon Sep 17 00:00:00 2001 From: ellson <devnull@localhost> Date: Thu, 6 Jan 2005 15:01:44 +0000 Subject: [PATCH] add lefty, dotty, lneato to graphviz2 tree --- cmd/lefty/ws/mswin32/garray.c | 350 +++++ cmd/lefty/ws/mswin32/gbutton.c | 168 +++ cmd/lefty/ws/mswin32/gcanvas.c | 1389 +++++++++++++++++++ cmd/lefty/ws/mswin32/gcommon.c | 762 +++++++++++ cmd/lefty/ws/mswin32/gcommon.h | 179 +++ cmd/lefty/ws/mswin32/glabel.c | 174 +++ cmd/lefty/ws/mswin32/gmenu.c | 121 ++ cmd/lefty/ws/mswin32/gpcanvas.c | 1226 +++++++++++++++++ cmd/lefty/ws/mswin32/gquery.c | 262 ++++ cmd/lefty/ws/mswin32/gscroll.c | 210 +++ cmd/lefty/ws/mswin32/gtext.c | 219 +++ cmd/lefty/ws/mswin32/gview.c | 180 +++ cmd/lefty/ws/mswin32/lefty.rc | 94 ++ cmd/lefty/ws/mswin32/resource.h | 44 + cmd/lefty/ws/none/garray.c | 62 + cmd/lefty/ws/none/gbutton.c | 43 + cmd/lefty/ws/none/gcanvas.c | 137 ++ cmd/lefty/ws/none/gcommon.c | 54 + cmd/lefty/ws/none/gcommon.h | 138 ++ cmd/lefty/ws/none/glabel.c | 42 + cmd/lefty/ws/none/gmenu.c | 52 + cmd/lefty/ws/none/gpcanvas.c | 128 ++ cmd/lefty/ws/none/gquery.c | 48 + cmd/lefty/ws/none/gscroll.c | 42 + cmd/lefty/ws/none/gtext.c | 43 + cmd/lefty/ws/none/gview.c | 42 + cmd/lefty/ws/x11/.cvsignore | 6 + cmd/lefty/ws/x11/Makefile.am | 17 + cmd/lefty/ws/x11/garray.c | 562 ++++++++ cmd/lefty/ws/x11/gbutton.c | 223 +++ cmd/lefty/ws/x11/gcanvas.c | 1664 +++++++++++++++++++++++ cmd/lefty/ws/x11/gcommon.c | 319 +++++ cmd/lefty/ws/x11/gcommon.h | 212 +++ cmd/lefty/ws/x11/glabel.c | 259 ++++ cmd/lefty/ws/x11/gmenu.c | 151 ++ cmd/lefty/ws/x11/gpcanvas.c | 777 +++++++++++ cmd/lefty/ws/x11/gquery.c | 335 +++++ cmd/lefty/ws/x11/gscroll.c | 293 ++++ cmd/lefty/ws/x11/gtext.c | 322 +++++ cmd/lefty/ws/x11/gview.c | 250 ++++ cmd/lefty/ws/x11/libfilereq/.cvsignore | 6 + cmd/lefty/ws/x11/libfilereq/Dir.c | 206 +++ cmd/lefty/ws/x11/libfilereq/Draw.c | 858 ++++++++++++ cmd/lefty/ws/x11/libfilereq/Makefile.am | 14 + cmd/lefty/ws/x11/libfilereq/Path.c | 893 ++++++++++++ 45 files changed, 13576 insertions(+) create mode 100644 cmd/lefty/ws/mswin32/garray.c create mode 100644 cmd/lefty/ws/mswin32/gbutton.c create mode 100644 cmd/lefty/ws/mswin32/gcanvas.c create mode 100644 cmd/lefty/ws/mswin32/gcommon.c create mode 100644 cmd/lefty/ws/mswin32/gcommon.h create mode 100644 cmd/lefty/ws/mswin32/glabel.c create mode 100644 cmd/lefty/ws/mswin32/gmenu.c create mode 100644 cmd/lefty/ws/mswin32/gpcanvas.c create mode 100644 cmd/lefty/ws/mswin32/gquery.c create mode 100644 cmd/lefty/ws/mswin32/gscroll.c create mode 100644 cmd/lefty/ws/mswin32/gtext.c create mode 100644 cmd/lefty/ws/mswin32/gview.c create mode 100644 cmd/lefty/ws/mswin32/lefty.rc create mode 100644 cmd/lefty/ws/mswin32/resource.h create mode 100644 cmd/lefty/ws/none/garray.c create mode 100644 cmd/lefty/ws/none/gbutton.c create mode 100644 cmd/lefty/ws/none/gcanvas.c create mode 100644 cmd/lefty/ws/none/gcommon.c create mode 100644 cmd/lefty/ws/none/gcommon.h create mode 100644 cmd/lefty/ws/none/glabel.c create mode 100644 cmd/lefty/ws/none/gmenu.c create mode 100644 cmd/lefty/ws/none/gpcanvas.c create mode 100644 cmd/lefty/ws/none/gquery.c create mode 100644 cmd/lefty/ws/none/gscroll.c create mode 100644 cmd/lefty/ws/none/gtext.c create mode 100644 cmd/lefty/ws/none/gview.c create mode 100644 cmd/lefty/ws/x11/.cvsignore create mode 100644 cmd/lefty/ws/x11/Makefile.am create mode 100644 cmd/lefty/ws/x11/garray.c create mode 100644 cmd/lefty/ws/x11/gbutton.c create mode 100644 cmd/lefty/ws/x11/gcanvas.c create mode 100644 cmd/lefty/ws/x11/gcommon.c create mode 100644 cmd/lefty/ws/x11/gcommon.h create mode 100644 cmd/lefty/ws/x11/glabel.c create mode 100644 cmd/lefty/ws/x11/gmenu.c create mode 100644 cmd/lefty/ws/x11/gpcanvas.c create mode 100644 cmd/lefty/ws/x11/gquery.c create mode 100644 cmd/lefty/ws/x11/gscroll.c create mode 100644 cmd/lefty/ws/x11/gtext.c create mode 100644 cmd/lefty/ws/x11/gview.c create mode 100644 cmd/lefty/ws/x11/libfilereq/.cvsignore create mode 100644 cmd/lefty/ws/x11/libfilereq/Dir.c create mode 100644 cmd/lefty/ws/x11/libfilereq/Draw.c create mode 100644 cmd/lefty/ws/x11/libfilereq/Makefile.am create mode 100644 cmd/lefty/ws/x11/libfilereq/Path.c diff --git a/cmd/lefty/ws/mswin32/garray.c b/cmd/lefty/ws/mswin32/garray.c new file mode 100644 index 000000000..1b797e35a --- /dev/null +++ b/cmd/lefty/ws/mswin32/garray.c @@ -0,0 +1,350 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WAU widget->u.a + +int GAcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + DWORD wflags; + int mode, ai; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + wflags = WS_CHILDWINDOW; + mode = G_AWVARRAY; + WAU->func = NULL; + ps.x = ps.y = MINAWSIZE; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINAWSIZE); + break; + case G_ATTRBORDERWIDTH: + wflags |= WS_BORDER; + break; + case G_ATTRMODE: + if (Strcmp("horizontal", attrp[ai].u.t) == 0) + mode = G_AWHARRAY; + else if (Strcmp("vertical", attrp[ai].u.t) == 0) + mode = G_AWVARRAY; + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRLAYOUT: + if (Strcmp("on", attrp[ai].u.t) == 0) { + Gawsetmode(widget, FALSE); + WAU->mode = G_AWHARRAY; + } else if (Strcmp("off", attrp[ai].u.t) == 0) { + Gawsetmode(widget, TRUE); + WAU->mode = G_AWHARRAY; + } else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRRESIZECB: + WAU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + Gawinitialize(widget, mode); + Gadjustwrect(parent, &ps); + if (! + (widget->w = + CreateWindow("ArrayClass", "array", wflags, 0, 0, ps.x, ps.y, + parent->w, (HMENU) (widget - &Gwidgets[0]), + hinstance, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + ShowWindow(widget->w, SW_SHOW); + UpdateWindow(widget->w); + if (parent && parent->type == G_ARRAYWIDGET) + Gawinsertchild(parent, widget); + return 0; +} + +int GAsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Gwidget_t *parent; + PIXsize_t ps; + DWORD wflags1; + int ai; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINAWSIZE); +/* Gadjustwrect (parent, &ps);*/ + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, + wflags1); + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTSETATTR2, "borderwidth"); + return -1; + case G_ATTRMODE: + Gerr(POS, G_ERRCANNOTSETATTR2, "mode"); + return -1; + case G_ATTRLAYOUT: + if (Strcmp("on", attrp[ai].u.t) == 0) + Gawsetmode(widget, FALSE); + else if (Strcmp("off", attrp[ai].u.t) == 0) + Gawsetmode(widget, TRUE); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRRESIZECB: + WAU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GAgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + RECT r; + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GetWindowRect(widget->w, &r); + attrp[ai].u.s.x = r.right - r.left; + attrp[ai].u.s.y = r.bottom - r.top; + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTGETATTR, "borderwidth"); + return -1; + case G_ATTRMODE: + attrp[ai].u.t = (WAU->mode == G_AWHARRAY) ? + "horizontal" : "vertical"; + break; + case G_ATTRLAYOUT: + attrp[ai].u.t = (Gawgetmode(widget)) ? "off" : "on"; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", widget->w); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRRESIZECB: + attrp[ai].u.func = WAU->func; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GAdestroywidget(Gwidget_t * widget) +{ + Gwidget_t *parent; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + if (parent && parent->type == G_ARRAYWIDGET) + Gawdeletechild(parent, widget); + Gawdestroy(widget); + DestroyWindow(widget->w); + return 0; +} + +/* the rest of this file contains the implementation of the array widget */ + +static void dolayout(Gwidget_t *, int); + +int Gaworder(Gwidget_t * widget, void *data, Gawordercb func) +{ + (*func) (data, &WAU->data); + dolayout(widget, TRUE); + return 0; +} + +int Gawsetmode(Gwidget_t * widget, int mode) +{ + WAU->data.batchmode = mode; + dolayout(widget, TRUE); + return 0; +} + +int Gawgetmode(Gwidget_t * widget) +{ + return WAU->data.batchmode; +} + +void Gawdefcoordscb(int wi, Gawdata_t * dp) +{ + Gawcarray_t *cp; + int sx, sy, csx, csy, ci; + + sx = dp->sx, sy = dp->sy; + csx = csy = 0; + for (ci = 0; ci < dp->cj; ci++) { + cp = &dp->carray[ci]; + if (!cp->flag) + continue; + cp->ox = csx, cp->oy = csy; + if (dp->type == G_AWVARRAY) + cp->sx = sx - 2 * cp->bs, csy += cp->sy + 2 * cp->bs; + else + cp->sy = sy - 2 * cp->bs, csx += cp->sx + 2 * cp->bs; + } + if (dp->type == G_AWVARRAY) + dp->sy = csy; + else + dp->sx = csx; +} + +void Gawinitialize(Gwidget_t * widget, int mode) +{ + WAU->data.type = mode; + if (! + (WAU->data.carray = + Marrayalloc((long) AWCARRAYINCR * AWCARRAYSIZE))) + panic(POS, "Gawinitialize", "cannot allocate carray"); + WAU->data.cn = AWCARRAYINCR; + WAU->data.cj = 0; + WAU->data.batchmode = FALSE; + WAU->data.working = FALSE; +} + +void Gawdestroy(Gwidget_t * widget) +{ + Marrayfree(WAU->data.carray); + WAU->data.cn = WAU->data.cj = 0; +} + +void Gawresize(Gwidget_t * widget) +{ + dolayout(widget, FALSE); +} + +void Gawinsertchild(Gwidget_t * parent, Gwidget_t * child) +{ + if (parent->u.a->data.cj == parent->u.a->data.cn) { + parent->u.a->data.carray = Marraygrow(parent->u.a->data.carray, + (long) (parent->u.a->data. + cn + + AWCARRAYINCR) * + AWCARRAYSIZE); + parent->u.a->data.cn += AWCARRAYINCR; + } + parent->u.a->data.carray[parent->u.a->data.cj++].w = child->w; + dolayout(parent, TRUE); +} + +void Gawdeletechild(Gwidget_t * parent, Gwidget_t * child) +{ + int ci; + + for (ci = 0; ci < parent->u.a->data.cj; ci++) + if (parent->u.a->data.carray[ci].w == child->w) + break; + if (ci < parent->u.a->data.cj) { + for (; ci + 1 < parent->u.a->data.cj; ci++) + parent->u.a->data.carray[ci].w = + parent->u.a->data.carray[ci + 1].w; + parent->u.a->data.cj--; + dolayout(parent, TRUE); + } +} + +static void dolayout(Gwidget_t * widget, int flag) +{ + Gawdata_t *dp; + Gawcarray_t *cp; + RECT r; + int sx, sy, ci; + + if (WAU->data.batchmode || WAU->data.working) + return; + WAU->data.working = TRUE; + dp = &WAU->data; + for (ci = 0; ci < dp->cj; ci++) { + cp = &dp->carray[ci]; + GetWindowRect(cp->w, &r); + cp->flag = 1; + cp->ox = 0; + cp->oy = 0; + cp->sx = r.right - r.left; + cp->sy = r.bottom - r.top; + cp->bs = 0; + } + GetClientRect(widget->w, &r); + dp->sx = r.right - r.left, dp->sy = r.bottom - r.top; + if (WAU->func) + (*WAU->func) (widget - &Gwidgets[0], dp); + else + Gawdefcoordscb(widget - &Gwidgets[0], dp); + if ((sx = dp->sx) < MINAWSIZE) + sx = MINAWSIZE; + if ((sy = dp->sy) < MINAWSIZE) + sy = MINAWSIZE; + if (flag && (r.right - r.left != sx || r.bottom - r.top != sy)) { + sx -= (r.right - r.left); + sy -= (r.bottom - r.top); + GetWindowRect(widget->w, &r); + sx += (r.right - r.left); + sy += (r.bottom - r.top); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, sx, sy, + SWP_NOMOVE | SWP_NOZORDER); + } + for (ci = 0; ci < dp->cj; ci++) { + cp = &dp->carray[ci]; + SetWindowPos(cp->w, (HWND) NULL, cp->ox, cp->oy, cp->sx, cp->sy, + SWP_NOZORDER); + } + WAU->data.working = FALSE; +} diff --git a/cmd/lefty/ws/mswin32/gbutton.c b/cmd/lefty/ws/mswin32/gbutton.c new file mode 100644 index 000000000..79760e456 --- /dev/null +++ b/cmd/lefty/ws/mswin32/gbutton.c @@ -0,0 +1,168 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WBU widget->u.b + +int GBcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + DWORD wflags; + char *s; + int ai; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + wflags = WS_CHILDWINDOW | BS_PUSHBUTTON; + WBU->func = NULL; + ps.x = ps.y = MINBWSIZE; + s = "button"; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINBWSIZE); + break; + case G_ATTRBORDERWIDTH: + wflags |= WS_BORDER; + break; + case G_ATTRTEXT: + s = attrp[ai].u.t; + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRBUTTONCB: + WBU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + Gadjustwrect(parent, &ps); + if (!(widget->w = CreateWindow("BUTTON", s, wflags, 0, 0, ps.x, ps.y, + parent->w, + (HMENU) (widget - &Gwidgets[0]), + hinstance, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + ShowWindow(widget->w, SW_SHOW); + UpdateWindow(widget->w); + if (parent && parent->type == G_ARRAYWIDGET) + Gawinsertchild(parent, widget); + return 0; +} + +int GBsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Gwidget_t *parent; + PIXsize_t ps; + DWORD wflags1; + int ai; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINBWSIZE); + Gadjustwrect(parent, &ps); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, + wflags1); + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTSETATTR2, "borderwidth"); + return -1; + case G_ATTRTEXT: + SetWindowText(widget->w, attrp[ai].u.t); + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRBUTTONCB: + WBU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GBgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + RECT r; + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GetWindowRect(widget->w, &r); + attrp[ai].u.s.x = r.right - r.left; + attrp[ai].u.s.y = r.bottom - r.top; + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTGETATTR, "borderwidth"); + return -1; + case G_ATTRTEXT: + GetWindowText(widget->w, &Gbufp[0], Gbufn); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", widget->w); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRBUTTONCB: + attrp[ai].u.func = WBU->func; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GBdestroywidget(Gwidget_t * widget) +{ + Gwidget_t *parent; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + if (parent && parent->type == G_ARRAYWIDGET) + Gawdeletechild(parent, widget); + DestroyWindow(widget->w); + return 0; +} diff --git a/cmd/lefty/ws/mswin32/gcanvas.c b/cmd/lefty/ws/mswin32/gcanvas.c new file mode 100644 index 000000000..e925119e9 --- /dev/null +++ b/cmd/lefty/ws/mswin32/gcanvas.c @@ -0,0 +1,1389 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WCU widget->u.c +#define WINDOW widget->u.c->window +#define GC widget->u.c->gc +#define ISVISIBLE(r) ( \ + (r.o.x <= WCU->clip.c.x) && (r.c.x >= WCU->clip.o.x) && \ + (r.o.y <= WCU->clip.c.y) && (r.c.y >= WCU->clip.o.y) \ +) + +#define max(a, b) (((a) >= (b)) ? (a) : (b)) +#define min(a, b) (((a) <= (b)) ? (a) : (b)) + +static long gstyles[5] = { + /* G_SOLID */ PS_SOLID, + /* G_DASHED */ PS_DASH, + /* G_DOTTED */ PS_DOT, + /* G_LONGDASHED */ PS_DASH, + /* G_SHORTDASHED */ PS_DASH, +}; + +static char grays[][4] = { + {0x00, 0x00, 0x00, 0x00,}, + {0x08, 0x00, 0x00, 0x00,}, + {0x08, 0x00, 0x02, 0x00,}, + {0x0A, 0x00, 0x02, 0x00,}, + {0x0A, 0x00, 0x0A, 0x00,}, + {0x0A, 0x04, 0x0A, 0x00,}, + {0x0A, 0x04, 0x0A, 0x01,}, + {0x0A, 0x05, 0x0A, 0x01,}, + {0x0A, 0x05, 0x0A, 0x05,}, + {0x0E, 0x05, 0x0A, 0x05,}, + {0x0E, 0x05, 0x0B, 0x05,}, + {0x0F, 0x05, 0x0B, 0x05,}, + {0x0F, 0x05, 0x0F, 0x05,}, + {0x0F, 0x0D, 0x0F, 0x05,}, + {0x0F, 0x0D, 0x0F, 0x07,}, + {0x0F, 0x0F, 0x0F, 0x07,}, + {0x0F, 0x0F, 0x0F, 0x0F,}, +}; + +static int curcursori = -1; + +static void bezier(PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t); +static HFONT findfont(char *, int); +static int scalebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t, int, int); +static void setgattr(Gwidget_t *, Ggattr_t *); + +static PIXrect_t rdrawtopix(Gwidget_t *, Grect_t); +static PIXpoint_t pdrawtopix(Gwidget_t *, Gpoint_t); +static PIXsize_t sdrawtopix(Gwidget_t *, Gsize_t); +static Gsize_t spixtodraw(Gwidget_t *, PIXsize_t); +static Grect_t rpixtodraw(Gwidget_t *, PIXrect_t); +static PIXrect_t rdrawtobpix(Gbitmap_t *, Grect_t); +static PIXpoint_t pdrawtobpix(Gbitmap_t *, Gpoint_t); + +int GCcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + LOGPALETTE pal[2]; /* the 2 here is to provide enough space + for palPalEntry[0] and [1] */ + HBRUSH brush; + HPEN pen; + HBITMAP bmap; + HCURSOR cursor; + DWORD wflags; + int color, ai, i; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + wflags = WS_CHILDWINDOW; + WCU->func = NULL; + WCU->needredraw = FALSE; + WCU->buttonsdown = 0; + WCU->bstate[0] = WCU->bstate[1] = WCU->bstate[2] = 0; + ps.x = ps.y = MINCWSIZE; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINCWSIZE); + break; + case G_ATTRBORDERWIDTH: + wflags |= WS_BORDER; + break; + case G_ATTRCURSOR: + /* will do it after the widget is created */ + break; + case G_ATTRCOLOR: + /* will do it after the widget is created */ + break; + case G_ATTRVIEWPORT: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOW: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTREVENTCB: + WCU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + Gadjustwrect(parent, &ps); + WCU->wrect.o.x = 0.0, WCU->wrect.o.y = 0.0; + WCU->wrect.c.x = 1.0, WCU->wrect.c.y = 1.0; + WCU->vsize.x = ps.x, WCU->vsize.y = ps.y; + if (!(widget->w = CreateWindow("CanvasClass", "canvas", wflags, 0, 0, + ps.x, ps.y, parent->w, + (HMENU) (widget - &Gwidgets[0]), + hinstance, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + ShowWindow(widget->w, SW_SHOW); + UpdateWindow(widget->w); + SetCursor(LoadCursor((HINSTANCE) NULL, IDC_ARROW)); + GC = GetDC(widget->w); + WCU->ncolor = 2; + pal[0].palVersion = 0x300; /* HA HA HA */ + pal[0].palNumEntries = 2; + pal[0].palPalEntry[0].peRed = 255; + pal[0].palPalEntry[0].peGreen = 255; + pal[0].palPalEntry[0].peBlue = 255; + pal[0].palPalEntry[0].peFlags = 0; + pal[0].palPalEntry[1].peRed = 0; + pal[0].palPalEntry[1].peGreen = 0; + pal[0].palPalEntry[1].peBlue = 0; + pal[0].palPalEntry[1].peFlags = 0; + WCU->cmap = CreatePalette(&pal[0]); + WCU->colors[0].color = pal[0].palPalEntry[0]; + for (i = 1; i < G_MAXCOLORS; i++) + WCU->colors[i].color = pal[0].palPalEntry[1]; + SelectPalette(GC, WCU->cmap, FALSE); + RealizePalette(GC); + WCU->colors[0].inuse = TRUE; + WCU->colors[1].inuse = TRUE; + for (i = 2; i < G_MAXCOLORS; i++) + WCU->colors[i].inuse = FALSE; + WCU->gattr.color = 1; + brush = CreateSolidBrush(PALETTEINDEX(1)); + SelectObject(GC, brush); + pen = CreatePen(PS_SOLID, 1, PALETTEINDEX(1)); + SelectObject(GC, pen); + SetTextColor(GC, PALETTEINDEX(1)); + SetBkMode(GC, TRANSPARENT); + WCU->gattr.width = 0; + WCU->gattr.mode = G_SRC; + WCU->gattr.fill = 0; + WCU->gattr.style = 0; + WCU->defgattr = WCU->gattr; + WCU->font = NULL; + if (Gdepth == 1) { + for (i = 0; i < 17; i++) { + if (!(bmap = CreateBitmap(4, 4, 1, 1, &grays[i][0]))) + continue; + WCU->grays[i] = CreatePatternBrush(bmap); + } + } + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRCURSOR: + if (Strcmp(attrp[ai].u.t, "watch") == 0) { + curcursori = 1; + cursor = LoadCursor((HINSTANCE) NULL, IDC_WAIT); + } else if (Strcmp(attrp[ai].u.t, "default") == 0) { + curcursori = -1; + cursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + } else { + Gerr(POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); + return -1; + } + SetCursor(cursor); + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + WCU->colors[color].color.peRed = attrp[ai].u.c.r; + WCU->colors[color].color.peGreen = attrp[ai].u.c.g; + WCU->colors[color].color.peBlue = attrp[ai].u.c.b; + WCU->colors[color].color.peFlags = 0; + if (color >= WCU->ncolor) + ResizePalette(WCU->cmap, color + 1), WCU->ncolor = + color + 1; + SetPaletteEntries(WCU->cmap, (int) color, 1, + &WCU->colors[color].color); + RealizePalette(GC); + WCU->colors[color].inuse = TRUE; + if (color == WCU->gattr.color) + WCU->gattr.color = -1; + break; + case G_ATTRVIEWPORT: + if (attrp[ai].u.s.x == 0) + attrp[ai].u.s.x = 1; + if (attrp[ai].u.s.y == 0) + attrp[ai].u.s.y = 1; + WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); + WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, WCU->vsize.x, + WCU->vsize.y, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + break; + case G_ATTRWINDOW: + if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x) + attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1; + if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y) + attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1; + WCU->wrect = attrp[ai].u.r; + break; + } + } + if (parent && parent->type == G_ARRAYWIDGET) + Gawinsertchild(parent, widget); + Gadjustclip(widget); + return 0; +} + +int GCsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + HCURSOR cursor; + Gwidget_t *parent; + PIXsize_t ps; + DWORD wflags1; + int ai, color; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINCWSIZE); + Gadjustwrect(parent, &ps); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, + wflags1); + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTSETATTR2, "borderwidth"); + return -1; + case G_ATTRCURSOR: + if (Strcmp(attrp[ai].u.t, "watch") == 0) { + curcursori = 1; + cursor = LoadCursor((HINSTANCE) NULL, IDC_WAIT); + } else if (Strcmp(attrp[ai].u.t, "default") == 0) { + curcursori = -1; + cursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + } else { + Gerr(POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); + return -1; + } + SetCursor(cursor); + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + WCU->colors[color].color.peRed = attrp[ai].u.c.r; + WCU->colors[color].color.peGreen = attrp[ai].u.c.g; + WCU->colors[color].color.peBlue = attrp[ai].u.c.b; + WCU->colors[color].color.peFlags = 0; + if (color >= WCU->ncolor) + ResizePalette(WCU->cmap, color + 1), WCU->ncolor = + color + 1; + SetPaletteEntries(WCU->cmap, (int) color, 1, + &WCU->colors[color].color); + RealizePalette(GC); + WCU->colors[color].inuse = TRUE; + if (color == WCU->gattr.color) + WCU->gattr.color = -1; + break; + case G_ATTRVIEWPORT: + if (attrp[ai].u.s.x == 0) + attrp[ai].u.s.x = 1; + if (attrp[ai].u.s.y == 0) + attrp[ai].u.s.y = 1; + WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); + WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); + ps.x = WCU->vsize.x, ps.y = WCU->vsize.y; + Gadjustwrect(&Gwidgets[widget->pwi], &ps); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, + ps.y, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + Gadjustclip(widget); + break; + case G_ATTRWINDOW: + if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x) + attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1; + if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y) + attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1; + WCU->wrect = attrp[ai].u.r; + Gadjustclip(widget); + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTREVENTCB: + WCU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GCgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PALETTEENTRY *cp; + RECT r; + int color, ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GetWindowRect(widget->w, &r); + attrp[ai].u.s.x = r.right - r.left; + attrp[ai].u.s.y = r.bottom - r.top; + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTGETATTR, "borderwidth"); + return -1; + case G_ATTRCURSOR: + attrp[ai].u.t = (curcursori == -1) ? "default" : "watch"; + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + if (WCU->colors[color].inuse) { + cp = &WCU->colors[color].color; + attrp[ai].u.c.r = cp->peRed; + attrp[ai].u.c.g = cp->peGreen; + attrp[ai].u.c.b = cp->peBlue; + } else { + attrp[ai].u.c.r = -1; + attrp[ai].u.c.g = -1; + attrp[ai].u.c.b = -1; + } + break; + case G_ATTRVIEWPORT: + attrp[ai].u.s = WCU->vsize; + break; + case G_ATTRWINDOW: + attrp[ai].u.r = WCU->wrect; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", widget->w); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTREVENTCB: + attrp[ai].u.func = WCU->func; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GCdestroywidget(Gwidget_t * widget) +{ + Gwidget_t *parent; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + if (parent && parent->type == G_ARRAYWIDGET) + Gawdeletechild(parent, widget); + DestroyWindow(widget->w); + return 0; +} + +int GCcanvasclear(Gwidget_t * widget) +{ + Ggattr_t attr; + RECT r; + HBRUSH brush, pbrush; + + attr.flags = 0; + setgattr(widget, &attr); + brush = CreateSolidBrush(PALETTEINDEX(0)); + pbrush = SelectObject(GC, brush); + GetClientRect(widget->w, &r); + Rectangle(GC, r.left, r.top, r.right, r.bottom); + SelectObject(GC, pbrush); + DeleteObject(brush); + WCU->needredraw = FALSE; + return 0; +} + +int GCsetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + setgattr(widget, ap); + WCU->defgattr = WCU->gattr; + return 0; +} + +int GCgetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + if ((ap->flags & G_GATTRCOLOR)) + ap->color = WCU->gattr.color; + if ((ap->flags & G_GATTRWIDTH)) + ap->width = WCU->gattr.width; + if ((ap->flags & G_GATTRMODE)) + ap->mode = WCU->gattr.mode; + if ((ap->flags & G_GATTRFILL)) + ap->fill = WCU->gattr.fill; + if ((ap->flags & G_GATTRSTYLE)) + ap->style = WCU->gattr.style; + return 0; +} + +int GCarrow(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2, pa, pb, pd; + Grect_t gr; + double tangent, l; + + if (gp1.x < gp2.x) + gr.o.x = gp1.x, gr.c.x = gp2.x; + else + gr.o.x = gp2.x, gr.c.x = gp1.x; + if (gp1.y < gp2.y) + gr.o.y = gp1.y, gr.c.y = gp2.y; + else + gr.o.y = gp2.y, gr.c.y = gp1.y; + if (!ISVISIBLE(gr)) + return 1; + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y; + if (pd.x == 0 && pd.y == 0) + return 0; + tangent = atan2((double) pd.y, (double) pd.x); + if ((l = sqrt((double) (pd.x * pd.x + pd.y * pd.y))) > 30) + l = 30; + pa.x = l * cos(tangent + M_PI / 7) + pp2.x; + pa.y = l * sin(tangent + M_PI / 7) + pp2.y; + pb.x = l * cos(tangent - M_PI / 7) + pp2.x; + pb.y = l * sin(tangent - M_PI / 7) + pp2.y; + setgattr(widget, ap); + MoveToEx(GC, pp1.x, pp1.y, NULL), LineTo(GC, pp2.x, pp2.y); + MoveToEx(GC, pa.x, pa.y, NULL), LineTo(GC, pp2.x, pp2.y); + MoveToEx(GC, pb.x, pb.y, NULL), LineTo(GC, pp2.x, pp2.y); + return 0; +} + +int GCline(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2; + Grect_t gr; + + if (gp1.x < gp2.x) + gr.o.x = gp1.x, gr.c.x = gp2.x; + else + gr.o.x = gp2.x, gr.c.x = gp1.x; + if (gp1.y < gp2.y) + gr.o.y = gp1.y, gr.c.y = gp2.y; + else + gr.o.y = gp2.y, gr.c.y = gp1.y; + if (!ISVISIBLE(gr)) + return 1; + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + setgattr(widget, ap); + MoveToEx(GC, pp1.x, pp1.y, NULL); + LineTo(GC, pp2.x, pp2.y); + return 0; +} + +int GCbox(Gwidget_t * widget, Grect_t gr, Ggattr_t * ap) +{ + PIXrect_t pr; + Grect_t gr2; + + if (gr.o.x <= gr.c.x) + gr2.o.x = gr.o.x, gr2.c.x = gr.c.x; + else + gr2.o.x = gr.c.x, gr2.c.x = gr.o.x; + if (gr.o.y <= gr.c.y) + gr2.o.y = gr.o.y, gr2.c.y = gr.c.y; + else + gr2.o.y = gr.c.y, gr2.c.y = gr.o.y; + if (!ISVISIBLE(gr2)) + return 1; + pr = rdrawtopix(widget, gr); + setgattr(widget, ap); + if (WCU->gattr.fill) + Rectangle(GC, pr.o.x, pr.o.y, pr.c.x, pr.c.y); + else { + Gppp[0].x = pr.o.x, Gppp[0].y = pr.o.y; + Gppp[1].x = pr.c.x, Gppp[1].y = pr.o.y; + Gppp[2].x = pr.c.x, Gppp[2].y = pr.c.y; + Gppp[3].x = pr.o.x, Gppp[3].y = pr.c.y; + Gppp[4].x = pr.o.x, Gppp[4].y = pr.o.y; + Polyline(GC, Gppp, 5); + } + return 0; +} + +int GCpolygon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + Grect_t gr; + int n, i; + + if (gpn == 0) + return 0; + gr.o = gpp[0], gr.c = gpp[0]; + for (i = 1; i < gpn; i++) { + gr.o.x = min(gr.o.x, gpp[i].x); + gr.o.y = min(gr.o.y, gpp[i].y); + gr.c.x = max(gr.c.x, gpp[i].x); + gr.c.y = max(gr.c.y, gpp[i].y); + } + if (!ISVISIBLE(gr)) + return 1; + if (gpn + 1 > Gppn) { + n = (((gpn + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + for (i = 0; i < gpn; i++) + Gppp[i] = pdrawtopix(widget, gpp[i]); + setgattr(widget, ap); + if (WCU->gattr.fill) { + if (Gppp[gpn - 1].x != Gppp[0].x || Gppp[gpn - 1].y != Gppp[0].y) + Gppp[gpn] = Gppp[0], gpn++; + Polygon(GC, Gppp, (int) gpn); + } else + Polyline(GC, Gppp, (int) gpn); + return 0; +} + +int GCsplinegon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + PIXpoint_t p0, p1, p2, p3; + Grect_t gr; + int n, i; + + if (gpn == 0) + return 0; + gr.o = gpp[0], gr.c = gpp[0]; + for (i = 1; i < gpn; i++) { + gr.o.x = min(gr.o.x, gpp[i].x); + gr.o.y = min(gr.o.y, gpp[i].y); + gr.c.x = max(gr.c.x, gpp[i].x); + gr.c.y = max(gr.c.y, gpp[i].y); + } + if (!ISVISIBLE(gr)) + return 1; + Gppi = 1; + if (Gppi >= Gppn) { + n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + Gppp[0] = p3 = pdrawtopix(widget, gpp[0]); + for (i = 1; i < gpn; i += 3) { + p0 = p3; + p1 = pdrawtopix(widget, gpp[i]); + p2 = pdrawtopix(widget, gpp[i + 1]); + p3 = pdrawtopix(widget, gpp[i + 2]); + bezier(p0, p1, p2, p3); + } + setgattr(widget, ap); + if (WCU->gattr.fill) { + if (Gppp[Gppi - 1].x != Gppp[0].x || Gppp[Gppi - 1].y != Gppp[0].y) + Gppp[Gppi] = Gppp[0], Gppi++; + Polygon(GC, Gppp, (int) Gppi); + } else + Polyline(GC, Gppp, (int) Gppi); + return 0; +} + +static void bezier(PIXpoint_t p0, PIXpoint_t p1, + PIXpoint_t p2, PIXpoint_t p3) +{ + Gpoint_t gp0, gp1, gp2; + Gsize_t s; + PIXpoint_t p; + double t; + int n, i, steps; + + if ((s.x = p3.x - p0.x) < 0) + s.x = -s.x; + if ((s.y = p3.y - p0.y) < 0) + s.y = -s.y; + if (s.x > s.y) + steps = s.x / 5 + 1; + else + steps = s.y / 5 + 1; + for (i = 0; i <= steps; i++) { + t = i / (double) steps; + gp0.x = p0.x + t * (p1.x - p0.x); + gp0.y = p0.y + t * (p1.y - p0.y); + gp1.x = p1.x + t * (p2.x - p1.x); + gp1.y = p1.y + t * (p2.y - p1.y); + gp2.x = p2.x + t * (p3.x - p2.x); + gp2.y = p2.y + t * (p3.y - p2.y); + gp0.x = gp0.x + t * (gp1.x - gp0.x); + gp0.y = gp0.y + t * (gp1.y - gp0.y); + gp1.x = gp1.x + t * (gp2.x - gp1.x); + gp1.y = gp1.y + t * (gp2.y - gp1.y); + p.x = gp0.x + t * (gp1.x - gp0.x) + 0.5; + p.y = gp0.y + t * (gp1.y - gp0.y) + 0.5; + if (Gppi >= Gppn) { + n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + Gppp[Gppi++] = p; + } +} + +int GCarc(Gwidget_t * widget, Gpoint_t gc, Gsize_t gs, double ang1, + double ang2, Ggattr_t * ap) +{ + PIXpoint_t pc; + PIXsize_t ps; + Grect_t gr; + double a1, a2; + + gr.o.x = gc.x - gs.x, gr.o.y = gc.y - gs.y; + gr.c.x = gc.x + gs.x, gr.c.y = gc.y + gs.y; + if (!ISVISIBLE(gr)) + return 1; + pc = pdrawtopix(widget, gc), ps = sdrawtopix(widget, gs); + setgattr(widget, ap); + a1 = ang1 * M_PI / 180, a2 = ang2 * M_PI / 180; + if (WCU->gattr.fill) + Chord(GC, pc.x - ps.x, pc.y - ps.y, pc.x + ps.x, pc.y + ps.y, + (int) (cos(a1) * ps.x), (int) (sin(a1) * ps.x), + (int) (cos(a2) * ps.x), (int) (sin(a2) * ps.x)); + else + Arc(GC, pc.x - ps.x, pc.y - ps.y, pc.x + ps.x, pc.y + ps.y, + (int) (cos(a1) * ps.x), (int) (sin(a1) * ps.x), + (int) (cos(a2) * ps.x), (int) (sin(a2) * ps.x)); + return 0; +} + +#define YSCALE ((WCU->vsize.y) / (WCU->wrect.c.y - WCU->wrect.o.y)) + +int GCtext(Gwidget_t * widget, Gtextline_t * tlp, int n, Gpoint_t go, + char *fn, double fs, char *justs, Ggattr_t * ap) +{ + Gsize_t gs; + PIXpoint_t po; + PIXsize_t ps; + PIXrect_t pr; + Grect_t gr; + HFONT font; + SIZE size; + RECT r; + int x, y, w, h, i; + + po = pdrawtopix(widget, go); + gs.x = 0, gs.y = fs; + ps = sdrawtopix(widget, gs); + if (!(font = findfont(fn, ps.y))) { + Rectangle(GC, po.x, po.y, po.x + 1, po.y + 1); + return 0; + } + setgattr(widget, ap); + SETFONT(font); + for (w = h = 0, i = 0; i < n; i++) { + if (tlp[i].n) + GetTextExtentPoint32(GC, tlp[i].p, (int) tlp[i].n, &size); + else + GetTextExtentPoint32(GC, "M", (int) 1, &size); + tlp[i].w = size.cx, tlp[i].h = size.cy; + w = max(w, size.cx), h += size.cy; + } + switch (justs[0]) { + case 'l': + po.x += w / 2; + break; + case 'r': + po.x -= w / 2; + break; + } + switch (justs[1]) { + case 'd': + po.y -= h; + break; + case 'c': + po.y -= h / 2; + break; + } + pr.o.x = po.x - w / 2, pr.o.y = po.y; + pr.c.x = po.x + w / 2, pr.c.y = po.y + h; + gr = rpixtodraw(widget, pr); + if (!ISVISIBLE(gr)) + return 1; + for (i = 0; i < n; i++) { + switch (tlp[i].j) { + case 'l': + x = po.x - w / 2; + break; + case 'n': + x = po.x - tlp[i].w / 2; + break; + case 'r': + x = po.x - (tlp[i].w - w / 2); + break; + } + y = po.y + i * tlp[i].h; + r.left = x, r.top = y; + r.right = x + tlp[i].w, r.bottom = y + tlp[i].h; + DrawText(GC, tlp[i].p, (int) tlp[i].n, &r, DT_LEFT | DT_TOP); + } + return 0; +} + +int GCgettextsize(Gwidget_t * widget, Gtextline_t * tlp, int n, char *fn, + double fs, Gsize_t * gsp) +{ + Gsize_t gs; + PIXsize_t ps; + HFONT font; + int i; + SIZE size; + + gs.x = 0, gs.y = fs; + ps = sdrawtopix(widget, gs); + if (!(font = findfont(fn, ps.y))) { + gsp->x = 1, gsp->y = 1; + return 0; + } + SETFONT(font); + for (ps.x = ps.y = 0, i = 0; i < n; i++) { + GetTextExtentPoint32(GC, tlp[i].p, (int) tlp[i].n, &size); + ps.x = max(ps.x, size.cx), ps.y += size.cy; + } + *gsp = spixtodraw(widget, ps); + return 0; +} + +static HFONT findfont(char *name, int size) +{ + HFONT font; + int fi; + + if (name[0] == '\000') + return Gfontp[0].font; + + sprintf(&Gbufp[0], name, size); + for (fi = 0; fi < Gfontn; fi++) + if (Strcmp(&Gbufp[0], Gfontp[fi].name) == 0 + && Gfontp[fi].size == size) + return Gfontp[fi].font; + font = CreateFont((int) size, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &Gbufp[0]); + if (!font) + font = Gfontp[0].font; + + Gfontp = Marraygrow(Gfontp, (long) (Gfontn + 1) * FONTSIZE); + Gfontp[Gfontn].name = strdup(&Gbufp[0]); + Gfontp[Gfontn].size = size; + Gfontp[Gfontn].font = font; + Gfontn++; + return font; +} + +int GCcreatebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, Gsize_t s) +{ + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + if (!(bitmap->u.bmap.orig = CreateBitmap((int) s.x, (int) s.y, 1, + Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bitmap->u.bmap.scaled = 0; + bitmap->scale.x = bitmap->scale.y = 1; + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + return 0; +} + +int GCdestroybitmap(Gbitmap_t * bitmap) +{ + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + DeleteObject(bitmap->u.bmap.orig); + if (bitmap->u.bmap.scaled) + DeleteObject(bitmap->u.bmap.scaled); + return 0; +} + +int GCreadbitmap(Gwidget_t * widget, Gbitmap_t * bitmap, FILE * fp) +{ + Gsize_t s; + HDC gc; + char bufp[2048]; + unsigned int rgb[3]; + char *s1, *s2; + char c; + int bufn, bufi, step, x, y, k; + + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + step = 0; + while (step < 3) { + l1: + if (!fgets(bufp, 2048, fp)) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + s1 = &bufp[0]; + l2: + for (; *s1 && isspace(*s1); s1++); + if (!*s1 || *s1 == '#') + goto l1; + switch (step) { + case 0: + if (strncmp(s1, "P6", 2) != 0) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + step++, s1 += 2; + goto l2; + case 1: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.x = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + case 2: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.y = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + } + } + if (!(bitmap->u.bmap.orig = CreateBitmap((int) s.x, (int) s.y, 1, + Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + gc = CreateCompatibleDC(GC); + SelectObject(gc, bitmap->u.bmap.orig); + bitmap->u.bmap.scaled = 0; + bitmap->scale.x = bitmap->scale.y = 1; + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + bufi = bufn = 0; + bufp[bufi] = 0; + for (y = 0; y < s.y; y++) { + for (x = 0; x < s.x; x++) { + for (k = 0; k < 3; k++) { + if (bufi == bufn) { + if ((bufn = fread(bufp, 1, 2047, fp)) == 0) { + if (ferror(fp)) + bufn = -1; + DeleteDC(gc); + DeleteObject(bitmap->u.bmap.orig); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bufi = 0; + } + rgb[k] = (unsigned char) bufp[bufi++]; + } + SetPixel(gc, x, y, RGB(rgb[0], rgb[1], rgb[2])); + } + } + DeleteDC(gc); + return 0; +} + +int GCwritebitmap(Gbitmap_t * bitmap, FILE * fp) +{ + Gwidget_t *widget; + HDC gc; + COLORREF color; + char bufp[2048]; + int bufi, x, y, w, h; + + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + if (bitmap->canvas < 0 || bitmap->canvas >= Gwidgetn || + !Gwidgets[bitmap->canvas].inuse) { + Gerr(POS, G_ERRBADWIDGETID, bitmap->canvas); + return -1; + } + widget = &Gwidgets[bitmap->canvas]; + if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) { + Gerr(POS, G_ERRNOTACANVAS, bitmap->canvas); + return -1; + } + gc = CreateCompatibleDC(GC); + SelectObject(gc, bitmap->u.bmap.orig); + fprintf(fp, "P6\n%d %d 255\n", (int) bitmap->size.x, + (int) bitmap->size.y); + bufi = 0; + w = bitmap->size.x; + h = bitmap->size.y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + color = GetPixel(gc, x, y); + bufp[bufi++] = GetRValue(color); + bufp[bufi++] = GetGValue(color); + bufp[bufi++] = GetBValue(color); + if (bufi + 3 >= 2048) { + fwrite(bufp, 1, bufi, fp); + bufi = 0; + } + } + } + if (bufi > 0) + fwrite(bufp, 1, bufi, fp); + DeleteDC(gc); + return 0; +} + +int GCbitblt(Gwidget_t * widget, Gpoint_t gp, Grect_t gr, + Gbitmap_t * bitmap, char *mode, Ggattr_t * ap) +{ + PIXrect_t pr, r; + PIXpoint_t pp; + PIXsize_t s; + Gsize_t scale; + Gxy_t p; + HBITMAP pix; + HDC gc; + double tvx, tvy, twx, twy; + + if (gr.o.x > gr.c.x) + p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x; + if (gr.o.y > gr.c.y) + p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y; + if (strcmp(mode, "b2c") == 0) { + if (!ISVISIBLE(gr)) + return 1; + tvx = WCU->vsize.x, tvy = WCU->vsize.y; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + scale.x = tvx / twx, scale.y = tvy / twy; + if (scale.x == 1 && scale.y == 1) + pix = bitmap->u.bmap.orig; + else { + if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y) + scalebitmap(widget, bitmap, scale, TRUE, 1); + pix = bitmap->u.bmap.scaled; + } + pr = rdrawtopix(widget, gr); + pp = pdrawtobpix(bitmap, gp); + s.x = pr.c.x - pr.o.x + 1, s.y = pr.c.y - pr.o.y + 1; + r.o.x = pp.x, r.o.y = pp.y - s.y + 1; + r.c.x = r.o.x + s.x - 1, r.c.y = r.o.y + s.y - 1; + if (r.o.x < 0) + pr.o.x -= r.o.x, r.o.x = 0; + if (r.o.y < 0) + pr.o.y -= r.o.y, r.o.y = 0; + if (r.c.x >= bitmap->size.x * scale.x) { + pr.c.x -= (r.c.x + 1 - bitmap->size.x * scale.x); + r.c.x = bitmap->size.x * scale.x - 1; + } + if (r.c.y >= bitmap->size.y * scale.y) { + pr.c.y -= (r.c.y + 1 - bitmap->size.y * scale.y); + r.c.y = bitmap->size.y * scale.y - 1; + } + if (pr.o.x < 0) + r.o.x -= pr.o.x, pr.o.x = 0; + if (pr.o.y < 0) + r.o.y -= pr.o.y, pr.o.y = 0; + setgattr(widget, ap); + gc = CreateCompatibleDC(GC); + SelectObject(gc, pix); + BitBlt(GC, pr.o.x, pr.o.y, r.c.x - r.o.x + 1, r.c.y - r.o.y + 1, + gc, r.o.x, r.o.y, (WCU->gattr.mode == G_SRC) ? + SRCCOPY : SRCINVERT); + DeleteDC(gc); + } else if (strcmp(mode, "c2b") == 0) { + tvx = WCU->vsize.x, tvy = WCU->vsize.y; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + scale.x = tvx / twx, scale.y = tvy / twy; + if (scale.x == 1 && scale.y == 1) + pix = bitmap->u.bmap.orig; + else { + if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y) + scalebitmap(widget, bitmap, scale, FALSE, 1); + pix = bitmap->u.bmap.scaled; + } + pr = rdrawtobpix(bitmap, gr); + pp = pdrawtopix(widget, gp); + s.x = pr.c.x - pr.o.x + 1, s.y = pr.c.y - pr.o.y + 1; + r.o.x = pp.x, r.o.y = pp.y - s.y + 1; + r.c.x = r.o.x + s.x - 1, r.c.y = r.o.y + s.y - 1; + if (pr.o.x < 0) + r.o.x -= pr.o.x, pr.o.x = 0; + if (pr.o.y < 0) + r.o.y -= pr.o.y, pr.o.y = 0; + if (pr.c.x >= bitmap->size.x * scale.x) { + r.c.x -= (pr.c.x + 1 - bitmap->size.x * scale.x); + pr.c.x = bitmap->size.x * scale.x - 1; + } + if (pr.c.y >= bitmap->size.y * scale.y) { + r.c.y -= (pr.c.y + 1 - bitmap->size.y * scale.y); + pr.c.y = bitmap->size.y * scale.y - 1; + } + if (r.o.x < 0) + pr.o.x -= r.o.x, r.o.x = 0; + if (r.o.y < 0) + pr.o.y -= r.o.y, r.o.y = 0; + setgattr(widget, ap); + gc = CreateCompatibleDC(GC); + SelectObject(gc, pix); + BitBlt(gc, pr.o.x, pr.o.y, r.c.x - r.o.x + 1, r.c.y - r.o.y + 1, + GC, r.o.x, r.o.y, (WCU->gattr.mode == G_SRC) ? + SRCCOPY : SRCINVERT); + if (pix != bitmap->u.bmap.orig) + scalebitmap(widget, bitmap, scale, TRUE, -1); + DeleteDC(gc); + } + return 0; +} + +static int scalebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, + Gsize_t scale, int copybits, int dir) +{ + Gsize_t nsize, o2n; + HBITMAP opix, spix; + COLORREF color; + HDC gc1, gc2; + int x, y, x2, y2, xp, yp; + double prod, rgb[3], xr2, yr2, xl2, yl2, xf2, yf2, xr, yr, xl, yl; + + if (!copybits) { + if (dir == 1) { + nsize.x = (int) (bitmap->size.x * scale.x); + nsize.y = (int) (bitmap->size.y * scale.y); + if (!(spix = CreateBitmap((int) nsize.x, (int) nsize.y, 1, + Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + if (bitmap->u.bmap.scaled) + DeleteObject(bitmap->u.bmap.scaled); + bitmap->u.bmap.scaled = spix; + bitmap->scale = scale; + } + return 0; + } + if (dir == 1) { + nsize.x = (int) (bitmap->size.x * scale.x); + nsize.y = (int) (bitmap->size.y * scale.y); + o2n.x = 1 / scale.x, o2n.y = 1 / scale.y; + if (!(spix = CreateBitmap((int) nsize.x, (int) nsize.y, 1, + Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + opix = bitmap->u.bmap.orig; + } else { + nsize.x = (int) bitmap->size.x; + nsize.y = (int) bitmap->size.y; + o2n.x = scale.x, o2n.y = scale.y; + spix = bitmap->u.bmap.orig; + opix = bitmap->u.bmap.scaled; + } + gc1 = CreateCompatibleDC(GC); + SelectObject(gc1, opix); + gc2 = CreateCompatibleDC(GC); + SelectObject(gc2, spix); + prod = o2n.x * o2n.y; + y = 0; + yr = o2n.y; + yl = 0; + for (yp = 0; yp < nsize.y; yp++) { + x = 0; + xr = o2n.x; + xl = 0; + for (xp = 0; xp < nsize.x; xp++) { + y2 = y; + yr2 = yr; + yl2 = yl; + rgb[0] = rgb[1] = rgb[2] = 0; + do { + x2 = x; + xr2 = xr; + xl2 = xl; + yf2 = (yl2 + yr2 > 1) ? 1 - yl2 : yr2, yr2 -= yf2; + do { + xf2 = (xl2 + xr2 > 1) ? 1 - xl2 : xr2, xr2 -= xf2; + color = GetPixel(gc1, x2, y2); + rgb[0] += (GetRValue(color) * xf2 * yf2 / prod); + rgb[1] += (GetGValue(color) * xf2 * yf2 / prod); + rgb[2] += (GetBValue(color) * xf2 * yf2 / prod); + xl2 += xf2; + if (xl2 >= 1) + x2++, xl2 -= 1; + } while (xr2 > 0); + xr2 = o2n.x; + yl2 += yf2; + if (yl2 >= 1) + y2++, yl2 -= 1; + } while (yr2 > 0); + yr2 = o2n.y; + SetPixel(gc2, xp, yp, RGB(rgb[0], rgb[1], rgb[2])); + x = x2; + xr = xr2; + xl = xl2; + } + y = y2; + yr = yr2; + yl = yl2; + } + DeleteDC(gc1); + DeleteDC(gc2); + if (dir == 1) { + if (bitmap->u.bmap.scaled) + DeleteObject(bitmap->u.bmap.scaled); + bitmap->u.bmap.scaled = spix; + bitmap->scale = scale; + } + return 0; +} + +int GCgetmousecoords(Gwidget_t * widget, Gpoint_t * gpp, int *count) +{ + PIXpoint_t pp; + POINT p; + int n1, n2, n3; + + GetCursorPos(&p); + ScreenToClient(widget->w, &p); + pp.x = p.x, pp.y = p.y; + *gpp = ppixtodraw(widget, pp); + n1 = GetAsyncKeyState(VK_LBUTTON); + n2 = GetAsyncKeyState(VK_MBUTTON); + n3 = GetAsyncKeyState(VK_RBUTTON); + *count = (n1 < 0 ? 1 : 0) + (n2 < 0 ? 1 : 0) + (n3 < 0 ? 1 : 0); + return 0; +} + +static void setgattr(Gwidget_t * widget, Ggattr_t * ap) +{ + HBRUSH brush, pbrush; + HPEN pen, ppen; + PALETTEENTRY *colorp; + long color, mode, style, width, flag, pati; + double intens; + + if (!(ap->flags & G_GATTRCOLOR)) + ap->color = WCU->defgattr.color; + if (!(ap->flags & G_GATTRWIDTH)) + ap->width = WCU->defgattr.width; + if (!(ap->flags & G_GATTRMODE)) + ap->mode = WCU->defgattr.mode; + if (!(ap->flags & G_GATTRFILL)) + ap->fill = WCU->defgattr.fill; + if (!(ap->flags & G_GATTRSTYLE)) + ap->style = WCU->defgattr.style; + flag = FALSE; + mode = ap->mode; + if (mode != WCU->gattr.mode) { + WCU->gattr.mode = mode; + SetROP2(GC, (int) mode); + } + WCU->gattr.fill = ap->fill; + color = ap->color; + if (color >= G_MAXCOLORS || !(WCU->colors[color].inuse)) + color = 1; + if (color != WCU->gattr.color) + WCU->gattr.color = color, flag = TRUE; + width = ap->width; + if (width != WCU->gattr.width) + WCU->gattr.width = width, flag = TRUE; + style = ap->style; + if (style != WCU->gattr.style) + WCU->gattr.style = style, style = TRUE; + + if (!flag) + return; + WCU->gattr.color = color; + if (Gdepth == 1) { + colorp = &WCU->colors[color].color; + intens = (0.3 * colorp->peBlue + 0.59 * colorp->peRed + + 0.11 * colorp->peGreen) / 255.0; + pati = + (intens <= 0.0625) ? 16 : -16.0 * (log(intens) / 2.7725887222); + brush = WCU->grays[pati]; + } else + brush = CreateSolidBrush(PALETTEINDEX(WCU->gattr.color)); + pbrush = SelectObject(GC, brush); + if (Gdepth != 1) + DeleteObject(pbrush); + pen = CreatePen((int) gstyles[WCU->gattr.style], WCU->gattr.width, + PALETTEINDEX(WCU->gattr.color)); + ppen = SelectObject(GC, pen); + DeleteObject(ppen); + SetTextColor(GC, PALETTEINDEX(WCU->gattr.color)); +} + +static PIXrect_t rdrawtopix(Gwidget_t * widget, Grect_t gr) +{ + PIXrect_t pr; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + pr.o.x = tvx * (gr.o.x - WCU->wrect.o.x) / twx + 0.5; + pr.o.y = tvy * (1.0 - (gr.c.y - WCU->wrect.o.y) / twy) + 0.5; + pr.c.x = tvx * (gr.c.x - WCU->wrect.o.x) / twx + 0.5; + pr.c.y = tvy * (1.0 - (gr.o.y - WCU->wrect.o.y) / twy) + 0.5; + return pr; +} + +static PIXpoint_t pdrawtopix(Gwidget_t * widget, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + pp.x = tvx * (gp.x - WCU->wrect.o.x) / twx + 0.5; + pp.y = tvy * (1.0 - (gp.y - WCU->wrect.o.y) / twy) + 0.5; + return pp; +} + +static PIXsize_t sdrawtopix(Gwidget_t * widget, Gsize_t gs) +{ + PIXsize_t ps; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + ps.x = tvx * (gs.x - 1) / twx + 1.5; + ps.y = tvy * (gs.y - 1) / twy + 1.5; + return ps; +} + +Gpoint_t ppixtodraw(Gwidget_t * widget, PIXpoint_t pp) +{ + Gpoint_t gp; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + gp.x = (pp.x / tvx) * twx + WCU->wrect.o.x; + gp.y = (1.0 - pp.y / tvy) * twy + WCU->wrect.o.y; + return gp; +} + +static Gsize_t spixtodraw(Gwidget_t * widget, PIXsize_t ps) +{ + Gsize_t gs; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + gs.x = ((ps.x - 1) / tvx) * twx + 1; + gs.y = ((ps.y - 1) / tvy) * twy + 1; + return gs; +} + +static Grect_t rpixtodraw(Gwidget_t * widget, PIXrect_t pr) +{ + Grect_t gr; + double tvx, tvy, twx, twy, n; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + gr.o.x = (pr.o.x / tvx) * twx + WCU->wrect.o.x; + gr.o.y = (1.0 - pr.c.y / tvy) * twy + WCU->wrect.o.y; + gr.c.x = (pr.c.x / tvx) * twx + WCU->wrect.o.x; + gr.c.y = (1.0 - pr.o.y / tvy) * twy + WCU->wrect.o.y; + if (gr.o.x > gr.c.x) + n = gr.o.x, gr.o.x = gr.c.x, gr.c.x = n; + if (gr.o.y > gr.c.y) + n = gr.o.y, gr.o.y = gr.c.y, gr.c.y = n; + return gr; +} + +static PIXrect_t rdrawtobpix(Gbitmap_t * bitmap, Grect_t gr) +{ + PIXrect_t pr; + double tvy; + + tvy = (int) ((bitmap->size.y - 1) * bitmap->scale.y); + pr.o.x = gr.o.x + 0.5; + pr.o.y = tvy - gr.c.y + 0.5; + pr.c.x = gr.c.x + 0.5; + pr.c.y = tvy - gr.o.y + 0.5; + return pr; +} + +static PIXpoint_t pdrawtobpix(Gbitmap_t * bitmap, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvy; + + tvy = (int) ((bitmap->size.y - 1) * bitmap->scale.y); + pp.x = gp.x + 0.5; + pp.y = tvy - gp.y + 0.5; + return pp; +} + +void Gadjustclip(Gwidget_t * widget) +{ + Gwidget_t *parent; + PIXrect_t pr; + RECT r1, r2, r3; + + parent = &Gwidgets[widget->pwi]; + GetWindowRect(widget->w, &r1); + GetClientRect(parent->w, &r2); + GetWindowRect(parent->w, &r3); + pr.o.x = max(0, -(r1.left - r3.left)); + pr.o.y = max(0, -(r1.top - r3.top)); + pr.c.x = min(r1.right - r1.left, pr.o.x + r2.right - r2.left); + pr.c.y = min(r1.bottom - r1.top, pr.o.y + r2.bottom - r2.top); + pr.c.x = max(pr.o.x, pr.c.x); + pr.c.y = max(pr.o.y, pr.c.y); + WCU->clip = rpixtodraw(widget, pr); +} diff --git a/cmd/lefty/ws/mswin32/gcommon.c b/cmd/lefty/ws/mswin32/gcommon.c new file mode 100644 index 000000000..0018becba --- /dev/null +++ b/cmd/lefty/ws/mswin32/gcommon.c @@ -0,0 +1,762 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WCU widget->u.c +#define WVU widget->u.v + +FILE *Gxfp; +int Gxfd; +int Gpopdownflag; +int Gdepth; +int Gnocallbacks; +int menuselected; +int menupoped; + +char *Gbufp = NULL; +int Gbufn = 0, Gbufi = 0; + +PIXpoint_t *Gppp; +int Gppn, Gppi; + +Gfont_t *Gfontp; +int Gfontn; + +static HFONT deffont; +static int twobmouse; +static HWND palettechanged; + +LRESULT CALLBACK LeftyWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK ArrayWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK CanvasWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK LabelWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK ScrollWndProc(HWND, UINT, WPARAM, LPARAM); + +static void processcommand(Gwidget_t *, WPARAM, LPARAM); +static void handleresize(Gwidget_t *); + +int Ginitgraphics(void) +{ + WNDCLASS wc; + HDC hdc; + ATOM rtn; + + if (!hprevinstance) { + wc.style = NULL; + wc.lpfnWndProc = LeftyWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hinstance; + wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName = "LeftyClass"; + if (!(rtn = RegisterClass(&wc))) + panic(POS, "GXinit", "register class rtn = %d", (int) rtn); + + wc.style = NULL; + wc.lpfnWndProc = ArrayWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hinstance; + wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName = "ArrayClass"; + if (!(rtn = RegisterClass(&wc))) + panic(POS, "GXinit", "register class rtn = %d", (int) rtn); + + wc.style = CS_OWNDC; + wc.lpfnWndProc = CanvasWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hinstance; + wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); + wc.hCursor = NULL; + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName = "CanvasClass"; + if (!(rtn = RegisterClass(&wc))) + panic(POS, "GXinit", "register class rtn = %d", (int) rtn); + + wc.style = NULL; + wc.lpfnWndProc = ScrollWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hinstance; + wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName = "ScrollClass"; + if (!(rtn = RegisterClass(&wc))) + panic(POS, "GXinit", "register class rtn = %d", (int) rtn); + + wc.style = NULL; + wc.lpfnWndProc = LabelWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hinstance; + wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName = "LabelClass"; + if (!(rtn = RegisterClass(&wc))) + panic(POS, "GXinit", "register class rtn = %d", (int) rtn); + } + if (getenv("LEFTY3BMOUSE")) + twobmouse = FALSE; + else + twobmouse = TRUE; + hdc = GetDC((HWND) NULL); + Gdepth = GetDeviceCaps(hdc, BITSPIXEL); + deffont = GetStockObject(SYSTEM_FONT); +#ifndef FEATURE_MS + if (!(Gxfp = fopen("/dev/windows", "r"))) + panic(POS, "GXinit", "cannot open windows device"); + Gxfd = fileno(Gxfp); +#endif + Gpopdownflag = FALSE; + Gbufp = Marrayalloc((long) BUFINCR * BUFSIZE); + Gbufn = BUFINCR; + Gppp = Marrayalloc((long) PPINCR * PPSIZE); + Gppn = PPINCR; + Gfontp = Marrayalloc((long) FONTSIZE); + Gfontn = 1; + Gfontp[0].name = strdup("default"); + if (!Gdefaultfont) + Gfontp[0].font = deffont; + else if (Gdefaultfont[0] != '\000') + Gfontp[0].font = CreateFont(0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, Gdefaultfont); + else + Gfontp[0].font = NULL; + ReleaseDC((HWND) NULL, hdc); + Gnocallbacks = FALSE; + return 0; +} + +int Gtermgraphics(void) +{ + int fi; + + for (fi = 0; fi < Gfontn; fi++) + free(Gfontp[fi].name); + Marrayfree(Gfontp), Gfontp = NULL, Gfontn = 0; + Marrayfree(Gppp), Gppp = NULL, Gppn = 0; + Marrayfree(Gbufp), Gbufp = NULL, Gbufn = 0; + return 0; +} + +int Gsync(void) +{ + return 0; +} + +int Gresetbstate(int wi) +{ + Gcw_t *cw; + int bn; + + cw = Gwidgets[wi].u.c; + bn = cw->bstate[0] + cw->bstate[1] + cw->bstate[2]; + cw->bstate[0] = cw->bstate[1] = cw->bstate[2] = 0; + cw->buttonsdown -= bn; + Gbuttonsdown -= bn; + return 0; +} + +int Gprocessevents(int waitflag, Geventmode_t mode) +{ + MSG msg; + int rtn; + + rtn = 0; + switch (waitflag) { + case TRUE: + if (!GetMessage(&msg, (HWND) NULL, (UINT) NULL, (UINT) NULL)) + exit(msg.wParam); + TranslateMessage(&msg); + DispatchMessage(&msg); + if (mode == G_ONEEVENT) + return 1; + rtn = 1; + /* FALL THROUGH */ + case FALSE: + while (PeekMessage(&msg, (HWND) 0, (UINT) 0, (UINT) 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) + exit(msg.wParam); + TranslateMessage(&msg); + DispatchMessage(&msg); + if (mode == G_ONEEVENT) + return 1; + rtn = 1; + } + break; + } + return rtn; +} + +LRESULT CALLBACK LeftyWndProc(HWND hwnd, + UINT message, WPARAM wparam, LPARAM lparam) +{ + Gwidget_t *widget; + WINDOWPOS *wpos; + Gevent_t gev; + + widget = findwidget(hwnd, G_VIEWWIDGET); + switch (message) { + case WM_WINDOWPOSCHANGED: + if (Gnocallbacks || !widget) + return (DefWindowProc(hwnd, message, wparam, lparam)); + wpos = (WINDOWPOS *) lparam; + if (!(wpos->flags & SWP_NOSIZE)) + handleresize(widget); + break; + case WM_COMMAND: + if (Gnocallbacks || !widget) + return (DefWindowProc(hwnd, message, wparam, lparam)); + processcommand(widget, wparam, lparam); + break; + case WM_CLOSE: + if (!widget) + exit(0); + if (WVU->closing) + DestroyWindow(hwnd); + if (Gnocallbacks) + exit(0); + gev.type = 0, gev.code = 0, gev.data = 0; + gev.wi = widget - &Gwidgets[0]; + if (WVU->func) + (*WVU->func) (&gev); + else + exit(0); + break; + case WM_PALETTECHANGED: + palettechanged = (HWND) wparam; + break; + default: + return (DefWindowProc(hwnd, message, wparam, lparam)); + } + return 0; +} + +LRESULT CALLBACK ArrayWndProc(HWND hwnd, + UINT message, WPARAM wparam, LPARAM lparam) +{ + Gwidget_t *widget; + WINDOWPOS *wpos; + + if (Gnocallbacks || !(widget = findwidget(hwnd, G_ARRAYWIDGET))) + return (DefWindowProc(hwnd, message, wparam, lparam)); + switch (message) { + case WM_WINDOWPOSCHANGED: + wpos = (WINDOWPOS *) lparam; + if (!(wpos->flags & SWP_NOSIZE)) + handleresize(widget); + break; + case WM_COMMAND: + processcommand(widget, wparam, lparam); + break; + default: + return (DefWindowProc(hwnd, message, wparam, lparam)); + } + return 0; +} + +LRESULT CALLBACK CanvasWndProc(HWND hwnd, + UINT message, WPARAM wparam, LPARAM lparam) +{ + Gwidget_t *widget; + WINDOWPOS *wpos; + PIXpoint_t pp; + Gevent_t gev; + POINT p; + int wi, bn; + + if (Gnocallbacks || !(widget = findwidget(hwnd, G_CANVASWIDGET))) + return (DefWindowProc(hwnd, message, wparam, lparam)); + Gpopdownflag = FALSE; + switch (message) { + case WM_PAINT: + if (palettechanged != hwnd) + RealizePalette(widget->u.c->gc); + Gneedredraw = widget->u.c->needredraw = TRUE; + Gadjustclip(widget); + return (DefWindowProc(hwnd, message, wparam, lparam)); + case WM_WINDOWPOSCHANGED: + wpos = (WINDOWPOS *) lparam; + if (!(wpos->flags & SWP_NOSIZE)) + handleresize(widget); + return 0; + case WM_MOUSEACTIVATE: + SetFocus(widget->w); + return (DefWindowProc(hwnd, message, wparam, lparam)); + case WM_COMMAND: + processcommand(widget, wparam, lparam); + return 0; + case WM_CHAR: + gev.type = G_KEYBD; + gev.code = G_DOWN; /* I don't know how to get up events so I make */ + Gpopdownflag = TRUE; /* the code after this switch send the up event */ + gev.data = wparam; + GetCursorPos(&p); + ScreenToClient(widget->w, &p); + pp.x = p.x, pp.y = p.y; + gev.p = ppixtodraw(widget, pp); + /* continues after the end of this switch */ + break; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + gev.type = G_MOUSE; + if (twobmouse) { + if (message == WM_LBUTTONDOWN && (wparam & MK_CONTROL)) + message = WM_MBUTTONDOWN; + if (message == WM_LBUTTONUP && (wparam & MK_CONTROL)) + message = WM_MBUTTONUP; + } + switch (message) { + case WM_LBUTTONDOWN: + gev.code = G_DOWN, gev.data = G_LEFT; + break; + case WM_LBUTTONUP: + gev.code = G_UP, gev.data = G_LEFT; + break; + case WM_MBUTTONDOWN: + gev.code = G_DOWN, gev.data = G_MIDDLE; + break; + case WM_MBUTTONUP: + gev.code = G_UP, gev.data = G_MIDDLE; + break; + case WM_RBUTTONDOWN: + gev.code = G_DOWN, gev.data = G_RIGHT; + break; + case WM_RBUTTONUP: + gev.code = G_UP, gev.data = G_RIGHT; + break; + } + pp.x = LOWORD(lparam), pp.y = HIWORD(lparam); + gev.p = ppixtodraw(widget, pp); + bn = WCU->bstate[gev.data]; + WCU->bstate[gev.data] = (gev.code == G_DOWN) ? 1 : 0; + bn = WCU->bstate[gev.data] - bn; + widget->u.c->buttonsdown += bn; + Gbuttonsdown += bn; + /* continues after the end of this switch */ + break; + default: + return (DefWindowProc(hwnd, message, wparam, lparam)); + } + wi = gev.wi = widget - &Gwidgets[0]; + if (widget->u.c->func) + (*widget->u.c->func) (&gev); + if (Gpopdownflag) { + Gpopdownflag = FALSE; + if (gev.code == G_DOWN) { + gev.code = G_UP; + widget = &Gwidgets[wi]; + WCU->bstate[gev.data] = 0; + widget->u.c->buttonsdown--; + Gbuttonsdown--; + if (widget->inuse && widget->u.c->func) + (*widget->u.c->func) (&gev); + } + } + return 0; +} + +LRESULT CALLBACK LabelWndProc(HWND hwnd, + UINT message, WPARAM wparam, LPARAM lparam) +{ + Gwidget_t *widget; + PAINTSTRUCT paintstruct; + WINDOWPOS *wpos; + Gevent_t gev; + RECT r; + HDC hdc; + int wi; + + if (Gnocallbacks || !(widget = findwidget(hwnd, G_LABELWIDGET))) + return (DefWindowProc(hwnd, message, wparam, lparam)); + switch (message) { + case WM_PAINT: + hdc = BeginPaint(widget->w, &paintstruct); + GetWindowText(widget->w, &Gbufp[0], Gbufn); + GetClientRect(widget->w, &r); + DrawText(hdc, (LPCSTR) & Gbufp[0], strlen(Gbufp), &r, DT_LEFT); + EndPaint(widget->w, &paintstruct); + return (DefWindowProc(hwnd, message, wparam, lparam)); + case WM_WINDOWPOSCHANGED: + wpos = (WINDOWPOS *) lparam; + if (!(wpos->flags & SWP_NOSIZE)) + handleresize(widget); + return 0; + case WM_COMMAND: + processcommand(widget, wparam, lparam); + return 0; + case WM_KEYDOWN: + case WM_KEYUP: + gev.type = G_KEYBD; + gev.code = (message == WM_KEYDOWN) ? G_DOWN : G_UP; + gev.data = wparam; + /* continues after the end of this switch */ + break; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + gev.type = G_MOUSE; + if (wparam & MK_CONTROL) { + if (message == WM_LBUTTONDOWN) + message = WM_MBUTTONDOWN; + else if (message == WM_LBUTTONUP) + message = WM_MBUTTONUP; + } + switch (message) { + case WM_LBUTTONDOWN: + gev.code = G_DOWN, gev.data = G_LEFT; + break; + case WM_LBUTTONUP: + gev.code = G_UP, gev.data = G_LEFT; + break; + case WM_MBUTTONDOWN: + gev.code = G_DOWN, gev.data = G_MIDDLE; + break; + case WM_MBUTTONUP: + gev.code = G_UP, gev.data = G_MIDDLE; + break; + case WM_RBUTTONDOWN: + gev.code = G_DOWN, gev.data = G_RIGHT; + break; + case WM_RBUTTONUP: + gev.code = G_UP, gev.data = G_RIGHT; + break; + } + /* continues after the end of this switch */ + break; + default: + return (DefWindowProc(hwnd, message, wparam, lparam)); + } + wi = gev.wi = widget - &Gwidgets[0]; + if (widget->u.l->func) + (*widget->u.l->func) (&gev); + if (Gpopdownflag) { + Gpopdownflag = FALSE; + if (gev.type == G_MOUSE && gev.code == G_DOWN) { + gev.code = G_UP; + widget = &Gwidgets[wi]; + if (widget->inuse && widget->u.l->func) + (*widget->u.l->func) (&gev); + } + } + return 0; +} + +LRESULT CALLBACK ScrollWndProc(HWND hwnd, + UINT message, WPARAM wparam, LPARAM lparam) +{ + Gwidget_t *widget, *child; + WINDOWPOS *wpos; + PIXpoint_t po; + RECT r; + int dummy, dx, dy, wi; + + if (Gnocallbacks || !(widget = findwidget(hwnd, G_SCROLLWIDGET))) + return (DefWindowProc(hwnd, message, wparam, lparam)); + switch (message) { + case WM_WINDOWPOSCHANGED: + wpos = (WINDOWPOS *) lparam; + if (!(wpos->flags & SWP_NOSIZE)) + handleresize(widget); + break; + case WM_HSCROLL: + case WM_VSCROLL: + for (wi = 0; wi < Gwidgetn; wi++) { + child = &Gwidgets[wi]; + if (child->inuse && child->pwi == widget - &Gwidgets[0]) + break; + } + if (wi == Gwidgetn) + return (DefWindowProc(hwnd, message, wparam, lparam)); + GetClientRect(widget->w, &r); + GetScrollRange(widget->w, SB_HORZ, &dummy, &dx); + GetScrollRange(widget->w, SB_VERT, &dummy, &dy); + po.x = GetScrollPos(widget->w, SB_HORZ); + po.y = GetScrollPos(widget->w, SB_VERT); + switch (message) { + case WM_HSCROLL: + switch (LOWORD(wparam)) { + case SB_BOTTOM: + po.x = dx; + break; + case SB_LINEDOWN: + po.x += 10; + break; + case SB_LINEUP: + po.x -= 10; + break; + case SB_PAGEDOWN: + po.x += (r.right - r.left); + break; + case SB_PAGEUP: + po.x -= (r.right - r.left); + break; + case SB_THUMBPOSITION: + po.x = HIWORD(wparam); + break; + case SB_THUMBTRACK: + po.x = HIWORD(wparam); + break; + case SB_TOP: + po.x = 0; + break; + } + po.x = min(po.x, dx); + po.x = max(po.x, 0); + SetScrollPos(widget->w, SB_HORZ, po.x, TRUE); + SetWindowPos(child->w, (HWND) NULL, -po.x, -po.y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + break; + case WM_VSCROLL: + switch (LOWORD(wparam)) { + case SB_BOTTOM: + po.y = dy; + break; + case SB_LINEDOWN: + po.y += 10; + break; + case SB_LINEUP: + po.y -= 10; + break; + case SB_PAGEDOWN: + po.y += (r.bottom - r.top); + break; + case SB_PAGEUP: + po.y -= (r.bottom - r.top); + break; + case SB_THUMBPOSITION: + po.y = HIWORD(wparam); + break; + case SB_THUMBTRACK: + po.y = HIWORD(wparam); + break; + case SB_TOP: + po.y = 0; + break; + } + po.y = min(po.y, dy); + po.y = max(po.y, 0); + SetScrollPos(widget->w, SB_VERT, po.y, TRUE); + SetWindowPos(child->w, (HWND) NULL, -po.x, -po.y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + break; + } + break; + default: + return (DefWindowProc(hwnd, message, wparam, lparam)); + } + return 0; +} + +static void processcommand(Gwidget_t * widget, WPARAM wparam, + LPARAM lparam) +{ + Gwidget_t *child; + WORD l; + int n; + + if (lparam == 0) { /* it's a menu */ + if (LOWORD(wparam) != 999) + menuselected = LOWORD(wparam); + menupoped = FALSE; + return; + } + if (!(LOWORD(wparam) > 0 && LOWORD(wparam) < Gwidgetn)) + return; + child = &Gwidgets[LOWORD(wparam)]; + if (!child->inuse) + return; + + switch (child->type) { + case G_TEXTWIDGET: + if (HIWORD(wparam) == EN_CHANGE) { /* it's a text widget message */ + if ((n = SendMessage(child->w, EM_GETLINECOUNT, 0, 0L)) < 2) + return; + *((WORD *) & Gbufp[0]) = Gbufn - 1; + l = SendMessage(child->w, EM_GETLINE, n - 1, + (LPARAM) (LPSTR) & Gbufp[0]); + if (l != 0) + return; /* no carriage return yet */ + *((WORD *) & Gbufp[0]) = Gbufn - 1; + l = SendMessage(child->w, EM_GETLINE, n - 2, + (LPARAM) (LPSTR) & Gbufp[0]); + Gbufp[l] = 0; + if (l > 0 && child->u.t->func) + (*child->u.t->func) (child - &Gwidgets[0], &Gbufp[0]); + } + break; + case G_BUTTONWIDGET: + if (child->u.b->func) + (*child->u.b->func) (child - &Gwidgets[0], child->udata); + break; + } +} + +void Gadjustwrect(Gwidget_t * parent, PIXsize_t * psp) +{ + RECT r; + + GetClientRect(parent->w, &r); + switch (parent->type) { + case G_ARRAYWIDGET: + if (parent->u.a->data.type == G_AWHARRAY) + psp->y = r.bottom - r.top; + else + psp->x = r.right - r.left; + break; + case G_SCROLLWIDGET: + psp->x = max(psp->x, r.right - r.left); + psp->y = max(psp->y, r.bottom - r.top); + break; + case G_VIEWWIDGET: + case G_QUERYWIDGET: + psp->x = r.right - r.left; + psp->y = r.bottom - r.top; + break; + } +} + +static void handleresize(Gwidget_t * widget) +{ + Gwidget_t *parent, *child; + PIXsize_t ps1, ps2; + PIXpoint_t po; + DWORD wflags1, wflags2; + RECT r; + int dx, dy, wi, i; + + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + wflags2 = SWP_NOSIZE | SWP_NOZORDER; + GetWindowRect(widget->w, &r); + ps1.x = r.right - r.left, ps1.y = r.bottom - r.top; + ps2 = ps1; + /* first, take care of parent */ + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + if (!parent) + goto handlechildren; + switch (parent->type) { + case G_VIEWWIDGET: + Gadjustwrect(parent, &ps1); + if (ps1.x != ps2.x || ps1.y != ps2.y) { + Gnocallbacks = TRUE; + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, + wflags1); + Gnocallbacks = FALSE; + } + break; + case G_ARRAYWIDGET: + Gnocallbacks = TRUE; + Gawresize(parent); + Gnocallbacks = FALSE; + break; + case G_SCROLLWIDGET: + Gnocallbacks = TRUE; + for (i = 0; i < 2; i++) { + Gadjustwrect(parent, &ps1); + if (ps1.x > ps2.x || ps1.y > ps2.y) + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, + wflags1); + GetClientRect(parent->w, &r); + ps2.x = r.right - r.left, ps2.y = r.bottom - r.top; + dx = max(0, ps1.x - ps2.x); + dy = max(0, ps1.y - ps2.y); + SetScrollRange(parent->w, SB_HORZ, 0, dx, TRUE); + SetScrollRange(parent->w, SB_VERT, 0, dy, TRUE); + po.x = GetScrollPos(parent->w, SB_HORZ); + po.y = GetScrollPos(parent->w, SB_VERT); + po.x = min(po.x, dx); + po.x = max(po.x, 0); + SetScrollPos(parent->w, SB_HORZ, po.x, TRUE); + po.y = min(po.y, dy); + po.y = max(po.y, 0); + SetScrollPos(parent->w, SB_VERT, po.y, TRUE); + SetWindowPos(widget->w, (HWND) NULL, -po.x, -po.y, 0, 0, + wflags2); + ps2 = ps1; + } + Gnocallbacks = FALSE; + break; + } + + handlechildren: + for (wi = 0; wi < Gwidgetn; wi++) { + child = &Gwidgets[wi]; + if (child->inuse && child->pwi == widget - &Gwidgets[0]) + break; + } + if (wi == Gwidgetn) + return; + GetWindowRect(child->w, &r); + ps1.x = r.right - r.left, ps1.y = r.bottom - r.top; + ps2 = ps1; + switch (widget->type) { + case G_VIEWWIDGET: + Gadjustwrect(widget, &ps1); + if (ps1.x != ps2.x || ps1.y != ps2.y) + SetWindowPos(child->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, + wflags1); + break; + case G_ARRAYWIDGET: + Gawresize(widget); + break; + case G_SCROLLWIDGET: + Gadjustwrect(widget, &ps1); + if (ps1.x > ps2.x || ps1.y > ps2.y) + SetWindowPos(child->w, (HWND) NULL, 0, 0, ps1.x, ps1.y, + wflags1); + GetClientRect(widget->w, &r); + ps2.x = r.right - r.left, ps2.y = r.bottom - r.top; + dx = max(0, ps1.x - ps2.x); + dy = max(0, ps1.y - ps2.y); + SetScrollRange(widget->w, SB_HORZ, 0, dx, TRUE); + SetScrollRange(widget->w, SB_VERT, 0, dy, TRUE); + po.x = GetScrollPos(widget->w, SB_HORZ); + po.y = GetScrollPos(widget->w, SB_VERT); + po.x = min(po.x, dx); + po.x = max(po.x, 0); + SetScrollPos(widget->w, SB_HORZ, po.x, TRUE); + po.y = min(po.y, dy); + po.y = max(po.y, 0); + SetScrollPos(widget->w, SB_VERT, po.y, TRUE); + SetWindowPos(child->w, (HWND) NULL, -po.x, -po.y, 0, 0, wflags2); + break; + } +} diff --git a/cmd/lefty/ws/mswin32/gcommon.h b/cmd/lefty/ws/mswin32/gcommon.h new file mode 100644 index 000000000..5e3461cc8 --- /dev/null +++ b/cmd/lefty/ws/mswin32/gcommon.h @@ -0,0 +1,179 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#ifndef _GCOMMON_H +#define _GCOMMON_H + extern HANDLE hinstance, hprevinstance; + +/* point and rect structures */ + typedef POINT PIXxy_t; + typedef PIXxy_t PIXpoint_t; + typedef PIXxy_t PIXsize_t; + typedef struct PIXrect_t { + PIXxy_t o, c; + } PIXrect_t; + + extern int Gpopdownflag; + extern int Gdepth; + extern int Gnocallbacks; + extern int menuselected; + extern int menupoped; + + extern char *Gbufp; + extern int Gbufn, Gbufi; +#define BUFINCR 1024 +#define BUFSIZE sizeof (char) + + extern PIXpoint_t *Gppp; + extern int Gppn, Gppi; +#define PPINCR 100 +#define PPSIZE sizeof (PIXpoint_t) + + typedef struct Gfont_t { + char *name; + int size; + HFONT font; + } Gfont_t; + extern Gfont_t *Gfontp; + extern int Gfontn; +#define FONTSIZE sizeof (Gfont_t) +#define SETFONT(font) { \ + if (font != WCU->font) { \ + WCU->font = font; \ + SelectObject (GC, font); \ + } \ +} + +#define GETSIZE(sin, sout, smin) \ + sout.x = (sin.x > smin) ? sin.x + 0.5 : smin, \ + sout.y = (sin.y > smin) ? sin.y + 0.5 : smin +#define GETORIGIN(oin, oout) \ + oout.x = oin.x + 0.5, oout.y = oin.y + 0.5 + + int Ginitgraphics(void); + int Gtermgraphics(void); + int Gsync(void); + + int GAcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GAsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GAgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GAdestroywidget(Gwidget_t *); + + int GBcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GBsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GBgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GBdestroywidget(Gwidget_t *); + + int GCcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GCsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GCgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GCdestroywidget(Gwidget_t *); + int GCcanvasclear(Gwidget_t *); + int GCsetgfxattr(Gwidget_t *, Ggattr_t *); + int GCgetgfxattr(Gwidget_t *, Ggattr_t *); + int GCarrow(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GCline(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GCbox(Gwidget_t *, Grect_t, Ggattr_t *); + int GCpolygon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GCsplinegon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GCarc(Gwidget_t *, Gpoint_t, Gsize_t, double, double, Ggattr_t *); + int GCtext(Gwidget_t *, Gtextline_t *, int, Gpoint_t, + char *, double, char *, Ggattr_t *); + int GCgettextsize(Gwidget_t *, Gtextline_t *, int, char *, double, + Gsize_t *); + int GCcreatebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t); + int GCdestroybitmap(Gbitmap_t *); + int GCreadbitmap(Gwidget_t *, Gbitmap_t *, FILE *); + int GCwritebitmap(Gbitmap_t *, FILE *); + int GCbitblt(Gwidget_t *, Gpoint_t, Grect_t, Gbitmap_t *, char *, + Ggattr_t *); + int GCgetmousecoords(Gwidget_t *, Gpoint_t *, int *); + + int GLcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GLsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GLgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GLdestroywidget(Gwidget_t *); + + int GMcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GMsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GMgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GMdestroywidget(Gwidget_t *); + int GMmenuaddentries(Gwidget_t *, int, char **); + int GMmenudisplay(Gwidget_t *, Gwidget_t *); + + int GPcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GPsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GPgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GPdestroywidget(Gwidget_t *); + int GPcanvasclear(Gwidget_t *); + int GPsetgfxattr(Gwidget_t *, Ggattr_t *); + int GPgetgfxattr(Gwidget_t *, Ggattr_t *); + int GParrow(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GPline(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GPbox(Gwidget_t *, Grect_t, Ggattr_t *); + int GPpolygon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GPsplinegon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GParc(Gwidget_t *, Gpoint_t, Gsize_t, double, double, Ggattr_t *); + int GPtext(Gwidget_t *, Gtextline_t *, int, Gpoint_t, + char *, double, char *, Ggattr_t *); + int GPcreatebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t); + int GPdestroybitmap(Gbitmap_t *); + int GPreadbitmap(Gwidget_t *, Gbitmap_t *, FILE *); + int GPwritebitmap(Gbitmap_t *, FILE *); + int GPbitblt(Gwidget_t *, Gpoint_t, Grect_t, Gbitmap_t *, char *, + Ggattr_t *); + + int GQcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GQsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GQgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GQdestroywidget(Gwidget_t *); + int GQqueryask(Gwidget_t *, char *, char *, char *, int); + + int GScreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GSsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GSgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GSdestroywidget(Gwidget_t *); + + int GTcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GTsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GTgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GTdestroywidget(Gwidget_t *); + + int GVcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GVsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GVgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GVdestroywidget(Gwidget_t *); + + void Gawinitialize(Gwidget_t *, int); + void Gawdestroy(Gwidget_t *); + void Gawresize(Gwidget_t *); + void Gawinsertchild(Gwidget_t *, Gwidget_t *); + void Gawdeletechild(Gwidget_t *, Gwidget_t *); + + void Gadjustwrect(Gwidget_t *, PIXsize_t *); + void Gadjustclip(Gwidget_t *); + Gpoint_t ppixtodraw(Gwidget_t *, PIXpoint_t); +#endif /* _GCOMMON_H */ + +#ifdef __cplusplus +} +#endif diff --git a/cmd/lefty/ws/mswin32/glabel.c b/cmd/lefty/ws/mswin32/glabel.c new file mode 100644 index 000000000..6031d0eb8 --- /dev/null +++ b/cmd/lefty/ws/mswin32/glabel.c @@ -0,0 +1,174 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WLU widget->u.l + +int GLcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + DWORD wflags; + char *s; + int ai; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + wflags = WS_CHILDWINDOW; + WLU->func = NULL; + ps.x = ps.y = MINLWSIZE; + s = ""; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINLWSIZE); + break; + case G_ATTRBORDERWIDTH: + wflags |= WS_BORDER; + break; + case G_ATTRTEXT: + s = attrp[ai].u.t; + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTREVENTCB: + WLU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + Gadjustwrect(parent, &ps); + if (! + (widget->w = + CreateWindow("LabelClass", s, wflags, 0, 0, ps.x, ps.y, parent->w, + (HMENU) (widget - &Gwidgets[0]), hinstance, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + ShowWindow(widget->w, SW_SHOW); + UpdateWindow(widget->w); + if (parent && parent->type == G_ARRAYWIDGET) + Gawinsertchild(parent, widget); + return 0; +} + +int GLsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Gwidget_t *parent; + PIXsize_t ps; + RECT r; + DWORD wflags1; + int ai; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINLWSIZE); + Gadjustwrect(parent, &ps); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, + wflags1); + r.top = r.left = 0; + r.bottom = ps.y, r.right = ps.x; + InvalidateRect(widget->w, NULL, FALSE); + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTSETATTR2, "borderwidth"); + return -1; + case G_ATTRTEXT: + SetWindowText(widget->w, attrp[ai].u.t); + GetClientRect(widget->w, &r); + InvalidateRect(widget->w, &r, TRUE); + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTREVENTCB: + attrp[ai].u.func = WLU->func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GLgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + RECT r; + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GetWindowRect(widget->w, &r); + attrp[ai].u.s.x = r.right - r.left; + attrp[ai].u.s.y = r.bottom - r.top; + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTGETATTR, "borderwidth"); + return -1; + case G_ATTRTEXT: + GetWindowText(widget->w, &Gbufp[0], Gbufn); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", widget->w); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTREVENTCB: + attrp[ai].u.func = WLU->func; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GLdestroywidget(Gwidget_t * widget) +{ + Gwidget_t *parent; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + if (parent && parent->type == G_ARRAYWIDGET) + Gawdeletechild(parent, widget); + DestroyWindow(widget->w); + return 0; +} diff --git a/cmd/lefty/ws/mswin32/gmenu.c b/cmd/lefty/ws/mswin32/gmenu.c new file mode 100644 index 000000000..f6800daf3 --- /dev/null +++ b/cmd/lefty/ws/mswin32/gmenu.c @@ -0,0 +1,121 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WMU widget->u.m + +int GMcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + if (!(widget->w = CreatePopupMenu())) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + WMU->count = 0; + return 0; +} + +int GMsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GMgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GMdestroywidget(Gwidget_t * widget) +{ + DestroyMenu(widget->w); + return 0; +} + +int GMmenuaddentries(Gwidget_t * widget, int en, char **ep) +{ + int ei; + + for (ei = 0; ei < en; ei++) + AppendMenu(widget->w, MF_ENABLED | MF_STRING, WMU->count++, + ep[ei]); + return 0; +} + +int GMmenudisplay(Gwidget_t * parent, Gwidget_t * widget) +{ + MSG msg; + POINT p; + UINT flag; + + /* FIXME not only right button */ + menupoped = TRUE; + menuselected = -1; + GetCursorPos(&p); + if (GetAsyncKeyState(VK_LBUTTON) < 0) + flag = TPM_LEFTALIGN | TPM_LEFTBUTTON; + else + flag = TPM_LEFTALIGN | TPM_RIGHTBUTTON; + TrackPopupMenu(widget->w, flag, p.x, p.y, 0, parent->w, NULL); + PostMessage(parent->w, WM_COMMAND, 999, 0); + if (!GetMessage(&msg, parent->w, WM_COMMAND, WM_COMMAND)) + panic(POS, "GMmenudisplay", "exit code in GetMessage"); + TranslateMessage(&msg); + DispatchMessage(&msg); + Gpopdownflag = TRUE; + return menuselected; +} diff --git a/cmd/lefty/ws/mswin32/gpcanvas.c b/cmd/lefty/ws/mswin32/gpcanvas.c new file mode 100644 index 000000000..1ee11ea87 --- /dev/null +++ b/cmd/lefty/ws/mswin32/gpcanvas.c @@ -0,0 +1,1226 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WPU widget->u.p +#define WINDOW widget->u.p->window +#define GC widget->u.p->gc + +static long gstyles[5] = { + /* G_SOLID */ PS_SOLID, + /* G_DASHED */ PS_DASH, + /* G_DOTTED */ PS_DOT, + /* G_LONGDASHED */ PS_DASH, + /* G_SHORTDASHED */ PS_DASH, +}; + +static char grays[][4] = { + {0x00, 0x00, 0x00, 0x00,}, + {0x08, 0x00, 0x00, 0x00,}, + {0x08, 0x00, 0x02, 0x00,}, + {0x0A, 0x00, 0x02, 0x00,}, + {0x0A, 0x00, 0x0A, 0x00,}, + {0x0A, 0x04, 0x0A, 0x00,}, + {0x0A, 0x04, 0x0A, 0x01,}, + {0x0A, 0x05, 0x0A, 0x01,}, + {0x0A, 0x05, 0x0A, 0x05,}, + {0x0E, 0x05, 0x0A, 0x05,}, + {0x0E, 0x05, 0x0B, 0x05,}, + {0x0F, 0x05, 0x0B, 0x05,}, + {0x0F, 0x05, 0x0F, 0x05,}, + {0x0F, 0x0D, 0x0F, 0x05,}, + {0x0F, 0x0D, 0x0F, 0x07,}, + {0x0F, 0x0F, 0x0F, 0x07,}, + {0x0F, 0x0F, 0x0F, 0x0F,}, +}; + +char *Gpscanvasname = "out.emf"; + +static void bezier(PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t); +static HFONT findfont(char *, int); +static int scalebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t, int, int); +static void setgattr(Gwidget_t *, Ggattr_t *); + +static PIXrect_t rdrawtopix(Gwidget_t *, Grect_t); +static PIXpoint_t pdrawtopix(Gwidget_t *, Gpoint_t); +static PIXsize_t sdrawtopix(Gwidget_t *, Gsize_t); +static PIXrect_t rdrawtobpix(Gbitmap_t *, Grect_t); +static PIXpoint_t pdrawtobpix(Gbitmap_t *, Gpoint_t); + +int GPcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXpoint_t po; + PIXsize_t ps; + PRINTDLG pd; + DOCINFO di; + DEVMODE *dmp; + LOGPALETTE pal[2]; /* the 2 here is to provide enough space + for palPalEntry[0] and [1] */ + HBRUSH brush; + HPEN pen; + HBITMAP bmap; + char *s, *s1; + int color, lflag, ai, dpix, dpiy, i; + + s = Gpscanvasname; + lflag = FALSE; + po.x = po.y = 0; + ps.x = ps.y = MINPWSIZE; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + GETORIGIN(attrp[ai].u.p, po); + break; + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINPWSIZE); + break; + case G_ATTRNAME: + if (attrp[ai].u.t && attrp[ai].u.t[0]) + s = attrp[ai].u.t; + break; + case G_ATTRMODE: + if (Strcmp("landscape", attrp[ai].u.t) == 0) + lflag = TRUE; + else if (Strcmp("portrait", attrp[ai].u.t) == 0) + lflag = FALSE; + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRCOLOR: + /* will do it after the widget is created */ + break; + case G_ATTRVIEWPORT: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOW: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + s1 = s + strlen(s) - 3; + if (s1 > s && strncmp(s1, "emf", 3) == 0) { + WPU->mode = 1; + ps.x *= 8.235, ps.y *= 8.235; + if (! + (GC = + CreateEnhMetaFile(NULL, s, NULL, "LEFTY\\0GRAPH\\0\\0"))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + } else { /* open the printer device */ + WPU->mode = 2; + di.cbSize = sizeof(DOCINFO); + di.lpszDocName = NULL; + di.lpszOutput = NULL; + di.lpszDatatype = "LEFTY"; + di.fwType = 0; + pd.lStructSize = sizeof(pd); + pd.hwndOwner = NULL; + pd.hDevMode = NULL; + pd.hDevNames = NULL; + pd.hDC = NULL; + pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT; + pd.nFromPage = 0; + pd.nToPage = 0; + pd.nMinPage = 0; + pd.nMaxPage = 0; + pd.nCopies = 1; + pd.hInstance = NULL; + pd.lCustData = NULL; + pd.lpfnPrintHook = NULL; + pd.lpfnSetupHook = NULL; + pd.lpPrintTemplateName = NULL; + pd.lpSetupTemplateName = NULL; + pd.hPrintTemplate = NULL; + pd.hSetupTemplate = NULL; + if (!PrintDlg(&pd)) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + if (lflag && pd.hDevMode) { + dmp = (DEVMODE *) GlobalLock(pd.hDevMode); + dmp->dmOrientation = DMORIENT_LANDSCAPE; + GlobalUnlock(pd.hDevMode); + pd.Flags = PD_RETURNDC; + if (!PrintDlg(&pd)) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + } + GC = pd.hDC; + dpix = GetDeviceCaps(GC, LOGPIXELSX); + if (dpix != 300) + ps.x = ps.x * (double) dpix / 300.0; + dpiy = GetDeviceCaps(GC, LOGPIXELSY); + if (dpiy != 300) + ps.y = ps.y * (double) dpiy / 300.0; + if (StartDoc(GC, &di) <= 0 || StartPage(GC) <= 0) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + } + WPU->wrect.o.x = 0.0, WPU->wrect.o.y = 0.0; + WPU->wrect.c.x = 1.0, WPU->wrect.c.y = 1.0; + WPU->vsize.x = ps.x, WPU->vsize.y = ps.y; + WPU->ncolor = 2; + pal[0].palVersion = 0x300; /* HA HA HA */ + pal[0].palNumEntries = 2; + pal[0].palPalEntry[0].peRed = 255; + pal[0].palPalEntry[0].peGreen = 255; + pal[0].palPalEntry[0].peBlue = 255; + pal[0].palPalEntry[0].peFlags = 0; + pal[0].palPalEntry[1].peRed = 0; + pal[0].palPalEntry[1].peGreen = 0; + pal[0].palPalEntry[1].peBlue = 0; + pal[0].palPalEntry[1].peFlags = 0; + WPU->cmap = CreatePalette(&pal[0]); + WPU->colors[0].color = pal[0].palPalEntry[0]; + for (i = 1; i < G_MAXCOLORS; i++) + WPU->colors[i].color = pal[0].palPalEntry[1]; + SelectPalette(GC, WPU->cmap, FALSE); + RealizePalette(GC); + WPU->colors[0].inuse = TRUE; + WPU->colors[1].inuse = TRUE; + for (i = 2; i < G_MAXCOLORS; i++) + WPU->colors[i].inuse = FALSE; + WPU->gattr.color = 1; + brush = CreateSolidBrush(PALETTEINDEX(1)); + SelectObject(GC, brush); + pen = CreatePen(PS_SOLID, 1, PALETTEINDEX(1)); + SelectObject(GC, pen); + SetTextColor(GC, PALETTEINDEX(1)); + SetBkMode(GC, TRANSPARENT); + WPU->gattr.width = 0; + WPU->gattr.mode = G_SRC; + WPU->gattr.fill = 0; + WPU->gattr.style = 0; + WPU->defgattr = WPU->gattr; + WPU->font = NULL; + if (Gdepth == 1) { + for (i = 0; i < 17; i++) { + if (!(bmap = CreateBitmap(4, 4, 1, 1, &grays[i][0]))) + continue; + WPU->grays[i] = CreatePatternBrush(bmap); + } + } + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + WPU->colors[color].color.peRed = attrp[ai].u.c.r; + WPU->colors[color].color.peGreen = attrp[ai].u.c.g; + WPU->colors[color].color.peBlue = attrp[ai].u.c.b; + WPU->colors[color].color.peFlags = 0; + if (color >= WPU->ncolor) + ResizePalette(WPU->cmap, color + 1), WPU->ncolor = + color + 1; + SetPaletteEntries(WPU->cmap, (int) color, 1, + &WPU->colors[color].color); + RealizePalette(GC); + WPU->colors[color].inuse = TRUE; + if (color == WPU->gattr.color) + WPU->gattr.color = -1; + break; + case G_ATTRVIEWPORT: + if (attrp[ai].u.s.x == 0) + attrp[ai].u.s.x = 1; + if (attrp[ai].u.s.y == 0) + attrp[ai].u.s.y = 1; + WPU->vsize.x = attrp[ai].u.s.x + 0.5; + WPU->vsize.y = attrp[ai].u.s.y + 0.5; + SetWindowPos(widget->w, (HWND) NULL, 0, 0, WPU->vsize.x, + WPU->vsize.y, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + break; + case G_ATTRWINDOW: + if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x) + attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1; + if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y) + attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1; + WPU->wrect = attrp[ai].u.r; + break; + } + } + return 0; +} + +int GPsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + int color, ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + break; + case G_ATTRSIZE: + break; + case G_ATTRNAME: + break; + case G_ATTRMODE: + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + WPU->colors[color].color.peRed = attrp[ai].u.c.r; + WPU->colors[color].color.peGreen = attrp[ai].u.c.g; + WPU->colors[color].color.peBlue = attrp[ai].u.c.b; + WPU->colors[color].color.peFlags = 0; + if (color >= WPU->ncolor) + ResizePalette(WPU->cmap, color + 1), WPU->ncolor = + color + 1; + SetPaletteEntries(WPU->cmap, (int) color, 1, + &WPU->colors[color].color); + RealizePalette(GC); + WPU->colors[color].inuse = TRUE; + if (color == WPU->gattr.color) + WPU->gattr.color = -1; + break; + case G_ATTRVIEWPORT: + if (attrp[ai].u.s.x == 0) + attrp[ai].u.s.x = 1; + if (attrp[ai].u.s.y == 0) + attrp[ai].u.s.y = 1; + WPU->vsize.x = attrp[ai].u.s.x + 0.5; + WPU->vsize.y = attrp[ai].u.s.y + 0.5; + ps.x = WPU->vsize.x, ps.y = WPU->vsize.y; + break; + case G_ATTRWINDOW: + if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x) + attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1; + if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y) + attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1; + WPU->wrect = attrp[ai].u.r; + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GPgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PALETTEENTRY *cp; + int color, ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + break; + case G_ATTRSIZE: + break; + case G_ATTRNAME: + break; + case G_ATTRMODE: + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + if (WPU->colors[color].inuse) { + cp = &WPU->colors[color].color; + attrp[ai].u.c.r = cp->peRed; + attrp[ai].u.c.g = cp->peGreen; + attrp[ai].u.c.b = cp->peBlue; + } else { + attrp[ai].u.c.r = -1; + attrp[ai].u.c.g = -1; + attrp[ai].u.c.b = -1; + } + break; + case G_ATTRVIEWPORT: + attrp[ai].u.s = WPU->vsize; + break; + case G_ATTRWINDOW: + attrp[ai].u.r = WPU->wrect; + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTGETATTR, "windowid"); + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GPdestroywidget(Gwidget_t * widget) +{ + HENHMETAFILE mfile; + + if (WPU->mode == 1) { + mfile = CloseEnhMetaFile(GC); + OpenClipboard(NULL); + EmptyClipboard(); + SetClipboardData(CF_ENHMETAFILE, mfile); + CloseClipboard(); + DeleteMetaFile(mfile); + } else { + EndPage(GC); + EndDoc(GC); + } + return 0; +} + +int GPcanvasclear(Gwidget_t * widget) +{ + HBRUSH brush, pbrush; + + /* FIXME: drain repaint messages */ + brush = CreateSolidBrush(PALETTEINDEX(0)); + pbrush = SelectObject(GC, brush); + Rectangle(GC, 0, 0, (int) WPU->vsize.x, (int) WPU->vsize.y); + SelectObject(GC, pbrush); + return 0; +} + +int GPsetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + setgattr(widget, ap); + WPU->defgattr = WPU->gattr; + return 0; +} + +int GPgetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + if ((ap->flags & G_GATTRCOLOR)) + ap->color = WPU->gattr.color; + if ((ap->flags & G_GATTRWIDTH)) + ap->width = WPU->gattr.width; + if ((ap->flags & G_GATTRMODE)) + ap->mode = WPU->gattr.mode; + if ((ap->flags & G_GATTRFILL)) + ap->fill = WPU->gattr.fill; + if ((ap->flags & G_GATTRSTYLE)) + ap->style = WPU->gattr.style; + return 0; +} + +int GParrow(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2, pa, pb, pd; + double tangent, l; + + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y; + if (pd.x == 0 && pd.y == 0) + return 0; + tangent = atan2((double) pd.y, (double) pd.x); + if ((l = sqrt((double) (pd.x * pd.x + pd.y * pd.y))) > 30) + l = 30; + pa.x = l * cos(tangent + M_PI / 7) + pp2.x; + pa.y = l * sin(tangent + M_PI / 7) + pp2.y; + pb.x = l * cos(tangent - M_PI / 7) + pp2.x; + pb.y = l * sin(tangent - M_PI / 7) + pp2.y; + setgattr(widget, ap); + MoveToEx(GC, pp1.x, pp1.y, NULL), LineTo(GC, pp2.x, pp2.y); + MoveToEx(GC, pa.x, pa.y, NULL), LineTo(GC, pp2.x, pp2.y); + MoveToEx(GC, pb.x, pb.y, NULL), LineTo(GC, pp2.x, pp2.y); + return 0; +} + +int GPline(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2; + + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + setgattr(widget, ap); + MoveToEx(GC, pp1.x, pp1.y, NULL); + LineTo(GC, pp2.x, pp2.y); + return 0; +} + +int GPbox(Gwidget_t * widget, Grect_t gr, Ggattr_t * ap) +{ + PIXrect_t pr; + Grect_t gr2; + + if (gr.o.x <= gr.c.x) + gr2.o.x = gr.o.x, gr2.c.x = gr.c.x; + else + gr2.o.x = gr.c.x, gr2.c.x = gr.o.x; + if (gr.o.y <= gr.c.y) + gr2.o.y = gr.o.y, gr2.c.y = gr.c.y; + else + gr2.o.y = gr.c.y, gr2.c.y = gr.o.y; + pr = rdrawtopix(widget, gr); + setgattr(widget, ap); + if (WPU->gattr.fill) + Rectangle(GC, pr.o.x, pr.o.y, pr.c.x, pr.c.y); + else { + Gppp[0].x = pr.o.x, Gppp[0].y = pr.o.y; + Gppp[1].x = pr.c.x, Gppp[1].y = pr.o.y; + Gppp[2].x = pr.c.x, Gppp[2].y = pr.c.y; + Gppp[3].x = pr.o.x, Gppp[3].y = pr.c.y; + Gppp[4].x = pr.o.x, Gppp[4].y = pr.o.y; + Polyline(GC, Gppp, 5); + } + return 0; +} + +int GPpolygon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + int n, i; + + if (gpn == 0) + return 0; + if (gpn + 1 > Gppn) { + n = (((gpn + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + for (i = 0; i < gpn; i++) + Gppp[i] = pdrawtopix(widget, gpp[i]); + setgattr(widget, ap); + if (WPU->gattr.fill) { + if (Gppp[gpn - 1].x != Gppp[0].x || Gppp[gpn - 1].y != Gppp[0].y) + Gppp[gpn] = Gppp[0], gpn++; + Polygon(GC, Gppp, (int) gpn); + } else + Polyline(GC, Gppp, (int) gpn); + return 0; +} + +int GPsplinegon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + PIXpoint_t p0, p1, p2, p3; + int n, i; + + if (gpn == 0) + return 0; + Gppi = 1; + if (Gppi >= Gppn) { + n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + Gppp[0] = p3 = pdrawtopix(widget, gpp[0]); + for (i = 1; i < gpn; i += 3) { + p0 = p3; + p1 = pdrawtopix(widget, gpp[i]); + p2 = pdrawtopix(widget, gpp[i + 1]); + p3 = pdrawtopix(widget, gpp[i + 2]); + bezier(p0, p1, p2, p3); + } + setgattr(widget, ap); + if (WPU->gattr.fill) { + if (Gppp[Gppi - 1].x != Gppp[0].x || Gppp[Gppi - 1].y != Gppp[0].y) + Gppp[Gppi] = Gppp[0], Gppi++; + Polygon(GC, Gppp, (int) Gppi); + } else + Polyline(GC, Gppp, (int) Gppi); + return 0; +} + +static void bezier(PIXpoint_t p0, PIXpoint_t p1, + PIXpoint_t p2, PIXpoint_t p3) +{ + Gpoint_t gp0, gp1, gp2; + Gsize_t s; + PIXpoint_t p; + double t; + int n, i, steps; + + if ((s.x = p3.x - p0.x) < 0) + s.x = -s.x; + if ((s.y = p3.y - p0.y) < 0) + s.y = -s.y; + if (s.x > s.y) + steps = s.x / 5 + 1; + else + steps = s.y / 5 + 1; + for (i = 0; i <= steps; i++) { + t = i / (double) steps; + gp0.x = p0.x + t * (p1.x - p0.x); + gp0.y = p0.y + t * (p1.y - p0.y); + gp1.x = p1.x + t * (p2.x - p1.x); + gp1.y = p1.y + t * (p2.y - p1.y); + gp2.x = p2.x + t * (p3.x - p2.x); + gp2.y = p2.y + t * (p3.y - p2.y); + gp0.x = gp0.x + t * (gp1.x - gp0.x); + gp0.y = gp0.y + t * (gp1.y - gp0.y); + gp1.x = gp1.x + t * (gp2.x - gp1.x); + gp1.y = gp1.y + t * (gp2.y - gp1.y); + p.x = gp0.x + t * (gp1.x - gp0.x) + 0.5; + p.y = gp0.y + t * (gp1.y - gp0.y) + 0.5; + if (Gppi >= Gppn) { + n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + Gppp[Gppi++] = p; + } +} + +int GParc(Gwidget_t * widget, Gpoint_t gc, Gsize_t gs, + double ang1, double ang2, Ggattr_t * ap) +{ + PIXpoint_t pc; + PIXsize_t ps; + double a1, a2; + + pc = pdrawtopix(widget, gc), ps = sdrawtopix(widget, gs); + setgattr(widget, ap); + a1 = ang1 * M_PI / 180, a2 = ang2 * M_PI / 180; + if (WPU->gattr.fill) + Chord(GC, pc.x - ps.x, pc.y - ps.y, pc.x + ps.x, pc.y + ps.y, + (int) (cos(a1) * ps.x), (int) (sin(a1) * ps.x), + (int) (cos(a2) * ps.x), (int) (sin(a2) * ps.x)); + else + Arc(GC, pc.x - ps.x, pc.y - ps.y, pc.x + ps.x, pc.y + ps.y, + (int) (cos(a1) * ps.x), (int) (sin(a1) * ps.x), + (int) (cos(a2) * ps.x), (int) (sin(a2) * ps.x)); + return 0; +} + +int GPtext(Gwidget_t * widget, Gtextline_t * tlp, int n, Gpoint_t go, + char *fn, double fs, char *justs, Ggattr_t * ap) +{ + Gsize_t gs; + PIXpoint_t po; + PIXsize_t ps; + PIXrect_t pr; + HFONT font; + SIZE size; + RECT r; + int x, y, w, h, i; + + po = pdrawtopix(widget, go); + gs.x = 0, gs.y = fs; + ps = sdrawtopix(widget, gs); + if (!(font = findfont(fn, ps.y))) { + Rectangle(GC, po.x, po.y, po.x + 1, po.y + 1); + return 0; + } + setgattr(widget, ap); + if (font != WPU->font) { + WPU->font = font; + SelectObject(GC, font); + } + for (w = h = 0, i = 0; i < n; i++) { + if (tlp[i].n) + GetTextExtentPoint32(GC, tlp[i].p, (int) tlp[i].n, &size); + else + GetTextExtentPoint32(GC, "M", (int) 1, &size); + tlp[i].w = size.cx, tlp[i].h = size.cy; + w = max(w, size.cx), h += size.cy; + } + switch (justs[0]) { + case 'l': + po.x += w / 2; + break; + case 'r': + po.x -= w / 2; + break; + } + switch (justs[1]) { + case 'd': + po.y -= h; + break; + case 'c': + po.y -= h / 2; + break; + } + pr.o.x = po.x - w / 2, pr.o.y = po.y; + pr.c.x = po.x + w / 2, pr.c.y = po.y + h; + for (i = 0; i < n; i++) { + switch (tlp[i].j) { + case 'l': + x = po.x - w / 2; + break; + case 'n': + x = po.x - tlp[i].w / 2; + break; + case 'r': + x = po.x - (tlp[i].w - w / 2); + break; + } + y = po.y + i * tlp[i].h; + r.left = x, r.top = y; + r.right = x + tlp[i].w, r.bottom = y + tlp[i].h; + DrawText(GC, tlp[i].p, (int) tlp[i].n, &r, DT_LEFT | DT_TOP); + } + return 0; +} + +static HFONT findfont(char *name, int size) +{ + HFONT font; + int fi; + + if (name[0] == '\000') + return Gfontp[0].font; + + sprintf(&Gbufp[0], name, size); + for (fi = 0; fi < Gfontn; fi++) + if (Strcmp(&Gbufp[0], Gfontp[fi].name) == 0 + && Gfontp[fi].size == size) + return Gfontp[fi].font; + font = CreateFont((int) size, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &Gbufp[0]); + if (!font) + font = Gfontp[0].font; + + Gfontp = Marraygrow(Gfontp, (long) (Gfontn + 1) * FONTSIZE); + Gfontp[Gfontn].name = strdup(&Gbufp[0]); + Gfontp[Gfontn].size = size; + Gfontp[Gfontn].font = font; + Gfontn++; + return font; +} + +int GPcreatebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, Gsize_t s) +{ + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + if (!(bitmap->u.bmap.orig = CreateBitmap((int) s.x, (int) s.y, + 1, Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bitmap->u.bmap.scaled = 0; + bitmap->scale.x = bitmap->scale.y = 1; + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + return 0; +} + +int GPdestroybitmap(Gbitmap_t * bitmap) +{ + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + DeleteObject(bitmap->u.bmap.orig); + return 0; +} + +int GPreadbitmap(Gwidget_t * widget, Gbitmap_t * bitmap, FILE * fp) +{ + Gsize_t s; + HDC gc; + char bufp[2048]; + unsigned int rgb[3]; + char *s1, *s2; + char c; + int bufn, bufi, step, x, y, k; + + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + step = 0; + while (step < 3) { + l1: + if (!fgets(bufp, 2048, fp)) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + s1 = &bufp[0]; + l2: + for (; *s1 && isspace(*s1); s1++); + if (!*s1 || *s1 == '#') + goto l1; + switch (step) { + case 0: + if (strncmp(s1, "P6", 2) != 0) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + step++, s1 += 2; + goto l2; + case 1: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.x = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + case 2: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.y = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + } + } + if (!(bitmap->u.bmap.orig = CreateBitmap((int) s.x, (int) s.y, + 1, Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + gc = CreateCompatibleDC(GC); + SelectObject(gc, bitmap->u.bmap.orig); + bitmap->u.bmap.scaled = 0; + bitmap->scale.x = bitmap->scale.y = 1; + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + bufi = bufn = 0; + bufp[bufi] = 0; + for (y = 0; y < s.y; y++) { + for (x = 0; x < s.x; x++) { + for (k = 0; k < 3; k++) { + if (bufi == bufn) { + if ((bufn = fread(bufp, 1, 2047, fp)) == 0) { + if (ferror(fp)) + bufn = -1; + DeleteDC(gc); + DeleteObject(bitmap->u.bmap.orig); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bufi = 0; + } + rgb[k] = (unsigned char) bufp[bufi++]; + } + SetPixel(gc, x, y, RGB(rgb[0], rgb[1], rgb[2])); + } + } + DeleteDC(gc); + return 0; +} + +int GPwritebitmap(Gbitmap_t * bitmap, FILE * fp) +{ + Gwidget_t *widget; + HDC gc; + COLORREF color; + char bufp[2048]; + int bufi, x, y, w, h; + + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + if (bitmap->canvas < 0 || bitmap->canvas >= Gwidgetn || + !Gwidgets[bitmap->canvas].inuse) { + Gerr(POS, G_ERRBADWIDGETID, bitmap->canvas); + return -1; + } + widget = &Gwidgets[bitmap->canvas]; + if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) { + Gerr(POS, G_ERRNOTACANVAS, bitmap->canvas); + return -1; + } + gc = CreateCompatibleDC(GC); + SelectObject(gc, bitmap->u.bmap.orig); + fprintf(fp, "P6\n%d %d 255\n", (int) bitmap->size.x, + (int) bitmap->size.y); + bufi = 0; + w = bitmap->size.x; + h = bitmap->size.y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + color = GetPixel(gc, x, y); + bufp[bufi++] = GetRValue(color); + bufp[bufi++] = GetGValue(color); + bufp[bufi++] = GetBValue(color); + if (bufi + 3 >= 2048) { + fwrite(bufp, 1, bufi, fp); + bufi = 0; + } + } + } + if (bufi > 0) + fwrite(bufp, 1, bufi, fp); + DeleteDC(gc); + return 0; +} + +int GPbitblt(Gwidget_t * widget, Gpoint_t gp, Grect_t gr, + Gbitmap_t * bitmap, char *mode, Ggattr_t * ap) +{ + PIXrect_t pr, r; + PIXpoint_t pp; + PIXsize_t s; + Gsize_t scale; + Gxy_t p; + HBITMAP pix; + HDC gc; + double tvx, tvy, twx, twy; + + if (gr.o.x > gr.c.x) + p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x; + if (gr.o.y > gr.c.y) + p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y; + if (strcmp(mode, "b2c") == 0) { + tvx = WPU->vsize.x, tvy = WPU->vsize.y; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + scale.x = tvx / twx, scale.y = tvy / twy; + if (scale.x == 1 && scale.y == 1) { + pix = bitmap->u.bmap.orig; + bitmap->scale = scale; + } else { + if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y) + scalebitmap(widget, bitmap, scale, TRUE, 1); + pix = bitmap->u.bmap.scaled; + } + pr = rdrawtopix(widget, gr); + pp = pdrawtobpix(bitmap, gp); + s.x = pr.c.x - pr.o.x + 1, s.y = pr.c.y - pr.o.y + 1; + r.o.x = pp.x, r.o.y = pp.y - s.y + 1; + r.c.x = r.o.x + s.x - 1, r.c.y = r.o.y + s.y - 1; + if (r.o.x < 0) + pr.o.x -= r.o.x, r.o.x = 0; + if (r.o.y < 0) + pr.o.y -= r.o.y, r.o.y = 0; + if (r.c.x >= bitmap->size.x * scale.x) { + pr.c.x -= (r.c.x + 1 - bitmap->size.x * scale.x); + r.c.x = bitmap->size.x * scale.x - 1; + } + if (r.c.y >= bitmap->size.y * scale.y) { + pr.c.y -= (r.c.y + 1 - bitmap->size.y * scale.y); + r.c.y = bitmap->size.y * scale.y - 1; + } + if (pr.o.x < 0) + r.o.x -= pr.o.x, pr.o.x = 0; + if (pr.o.y < 0) + r.o.y -= pr.o.y, pr.o.y = 0; + setgattr(widget, ap); + gc = CreateCompatibleDC(GC); + SelectObject(gc, pix); + BitBlt(GC, pr.o.x, pr.o.y, r.c.x - r.o.x + 1, r.c.y - r.o.y + 1, + gc, r.o.x, r.o.y, (WPU->gattr.mode == G_SRC) ? + SRCCOPY : SRCINVERT); + DeleteDC(gc); + } else if (strcmp(mode, "c2b") == 0) { + tvx = WPU->vsize.x, tvy = WPU->vsize.y; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + scale.x = tvx / twx, scale.y = tvy / twy; + if (scale.x == 1 && scale.y == 1) { + pix = bitmap->u.bmap.orig; + bitmap->scale = scale; + } else { + if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y) + scalebitmap(widget, bitmap, scale, FALSE, 1); + pix = bitmap->u.bmap.scaled; + } + pr = rdrawtobpix(bitmap, gr); + pp = pdrawtopix(widget, gp); + s.x = pr.c.x - pr.o.x + 1, s.y = pr.c.y - pr.o.y + 1; + r.o.x = pp.x, r.o.y = pp.y - s.y + 1; + r.c.x = r.o.x + s.x - 1, r.c.y = r.o.y + s.y - 1; + if (pr.o.x < 0) + r.o.x -= pr.o.x, pr.o.x = 0; + if (pr.o.y < 0) + r.o.y -= pr.o.y, pr.o.y = 0; + if (pr.c.x >= bitmap->size.x * scale.x) { + r.c.x -= (pr.c.x + 1 - bitmap->size.x * scale.x); + pr.c.x = bitmap->size.x * scale.x - 1; + } + if (pr.c.y >= bitmap->size.y * scale.y) { + r.c.y -= (pr.c.y + 1 - bitmap->size.y * scale.y); + pr.c.y = bitmap->size.y * scale.y - 1; + } + if (r.o.x < 0) + pr.o.x -= r.o.x, r.o.x = 0; + if (r.o.y < 0) + pr.o.y -= r.o.y, r.o.y = 0; + setgattr(widget, ap); + gc = CreateCompatibleDC(GC); + SelectObject(gc, pix); + BitBlt(gc, pr.o.x, pr.o.y, r.c.x - r.o.x + 1, r.c.y - r.o.y + 1, + GC, r.o.x, r.o.y, (WPU->gattr.mode == G_SRC) ? + SRCCOPY : SRCINVERT); + if (pix != bitmap->u.bmap.orig) + scalebitmap(widget, bitmap, scale, TRUE, -1); + DeleteDC(gc); + } + return 0; +} + +static int scalebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, + Gsize_t scale, int copybits, int dir) +{ + Gsize_t nsize, o2n; + HBITMAP opix, spix; + COLORREF color; + HDC gc1, gc2; + int x, y, x2, y2, xp, yp; + double prod, rgb[3], xr2, yr2, xl2, yl2, xf2, yf2, xr, yr, xl, yl; + + if (!copybits) { + if (dir == 1) { + nsize.x = (int) (bitmap->size.x * scale.x); + nsize.y = (int) (bitmap->size.y * scale.y); + if (!(spix = CreateBitmap((int) nsize.x, (int) nsize.y, 1, + Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + if (bitmap->u.bmap.scaled) + DeleteObject(bitmap->u.bmap.scaled); + bitmap->u.bmap.scaled = spix; + bitmap->scale = scale; + } + return 0; + } + if (dir == 1) { + nsize.x = (int) (bitmap->size.x * scale.x); + nsize.y = (int) (bitmap->size.y * scale.y); + o2n.x = 1 / scale.x, o2n.y = 1 / scale.y; + if (!(spix = CreateBitmap((int) nsize.x, (int) nsize.y, 1, + Gdepth, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + opix = bitmap->u.bmap.orig; + } else { + nsize.x = (int) bitmap->size.x; + nsize.y = (int) bitmap->size.y; + o2n.x = scale.x, o2n.y = scale.y; + spix = bitmap->u.bmap.orig; + opix = bitmap->u.bmap.scaled; + } + gc1 = CreateCompatibleDC(GC); + SelectObject(gc1, opix); + gc2 = CreateCompatibleDC(GC); + SelectObject(gc2, spix); + prod = o2n.x * o2n.y; + y = 0; + yr = o2n.y; + yl = 0; + for (yp = 0; yp < nsize.y; yp++) { + x = 0; + xr = o2n.x; + xl = 0; + for (xp = 0; xp < nsize.x; xp++) { + y2 = y; + yr2 = yr; + yl2 = yl; + rgb[0] = rgb[1] = rgb[2] = 0; + do { + x2 = x; + xr2 = xr; + xl2 = xl; + yf2 = (yl2 + yr2 > 1) ? 1 - yl2 : yr2, yr2 -= yf2; + do { + xf2 = (xl2 + xr2 > 1) ? 1 - xl2 : xr2, xr2 -= xf2; + color = GetPixel(gc1, x2, y2); + rgb[0] += (GetRValue(color) * xf2 * yf2 / prod); + rgb[1] += (GetGValue(color) * xf2 * yf2 / prod); + rgb[2] += (GetBValue(color) * xf2 * yf2 / prod); + xl2 += xf2; + if (xl2 >= 1) + x2++, xl2 -= 1; + } while (xr2 > 0); + xr2 = o2n.x; + yl2 += yf2; + if (yl2 >= 1) + y2++, yl2 -= 1; + } while (yr2 > 0); + yr2 = o2n.y; + SetPixel(gc2, xp, yp, RGB(rgb[0], rgb[1], rgb[2])); + x = x2; + xr = xr2; + xl = xl2; + } + y = y2; + yr = yr2; + yl = yl2; + } + DeleteDC(gc1); + DeleteDC(gc2); + if (dir == 1) { + if (bitmap->u.bmap.scaled) + DeleteObject(bitmap->u.bmap.scaled); + bitmap->u.bmap.scaled = spix; + bitmap->scale = scale; + } + return 0; +} + +static void setgattr(Gwidget_t * widget, Ggattr_t * ap) +{ + HBRUSH brush, pbrush; + HPEN pen, ppen; + PALETTEENTRY *colorp; + long color, mode, style, width, flag, pati; + double intens; + + if (!(ap->flags & G_GATTRCOLOR)) + ap->color = WPU->defgattr.color; + if (!(ap->flags & G_GATTRWIDTH)) + ap->width = WPU->defgattr.width; + if (!(ap->flags & G_GATTRMODE)) + ap->mode = WPU->defgattr.mode; + if (!(ap->flags & G_GATTRFILL)) + ap->fill = WPU->defgattr.fill; + if (!(ap->flags & G_GATTRSTYLE)) + ap->style = WPU->defgattr.style; + flag = FALSE; + mode = ap->mode; + if (mode != WPU->gattr.mode) { + WPU->gattr.mode = mode; + SetROP2(GC, (int) mode); + } + WPU->gattr.fill = ap->fill; + color = ap->color; + if (color >= G_MAXCOLORS || !(WPU->colors[color].inuse)) + color = 1; + if (color != WPU->gattr.color) + WPU->gattr.color = color, flag = TRUE; + width = ap->width; + if (width != WPU->gattr.width) + WPU->gattr.width = width, flag = TRUE; + style = ap->style; + if (style != WPU->gattr.style) + WPU->gattr.style = style, style = TRUE; + + if (!flag) + return; + WPU->gattr.color = color; + if (Gdepth == 1) { + colorp = &WPU->colors[color].color; + intens = (0.3 * colorp->peBlue + 0.59 * colorp->peRed + + 0.11 * colorp->peGreen) / 255.0; + pati = + (intens <= 0.0625) ? 16 : -16.0 * (log(intens) / 2.7725887222); + brush = WPU->grays[pati]; + } else + brush = CreateSolidBrush(PALETTEINDEX(WPU->gattr.color)); + pbrush = SelectObject(GC, brush); + if (Gdepth != 1) + DeleteObject(pbrush); + pen = CreatePen((int) gstyles[WPU->gattr.style], WPU->gattr.width, + PALETTEINDEX(WPU->gattr.color)); + ppen = SelectObject(GC, pen); + DeleteObject(ppen); + SetTextColor(GC, PALETTEINDEX(WPU->gattr.color)); +} + +static PIXrect_t rdrawtopix(Gwidget_t * widget, Grect_t gr) +{ + PIXrect_t pr; + double tvx, tvy, twx, twy; + + tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + pr.o.x = tvx * (gr.o.x - WPU->wrect.o.x) / twx + 0.5; + pr.o.y = tvy * (1.0 - (gr.c.y - WPU->wrect.o.y) / twy) + 0.5; + pr.c.x = tvx * (gr.c.x - WPU->wrect.o.x) / twx + 0.5; + pr.c.y = tvy * (1.0 - (gr.o.y - WPU->wrect.o.y) / twy) + 0.5; + return pr; +} + +static PIXpoint_t pdrawtopix(Gwidget_t * widget, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvx, tvy, twx, twy; + + tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + pp.x = tvx * (gp.x - WPU->wrect.o.x) / twx + 0.5; + pp.y = tvy * (1.0 - (gp.y - WPU->wrect.o.y) / twy) + 0.5; + return pp; +} + +static PIXsize_t sdrawtopix(Gwidget_t * widget, Gsize_t gs) +{ + PIXsize_t ps; + double tvx, tvy, twx, twy; + + tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + ps.x = tvx * (gs.x - 1) / twx + 1.5; + ps.y = tvy * (gs.y - 1) / twy + 1.5; + return ps; +} + +static PIXrect_t rdrawtobpix(Gbitmap_t * bitmap, Grect_t gr) +{ + PIXrect_t pr; + double tvy; + + tvy = (int) ((bitmap->size.y - 1) * bitmap->scale.y); + pr.o.x = gr.o.x + 0.5; + pr.o.y = tvy - gr.c.y + 0.5; + pr.c.x = gr.c.x + 0.5; + pr.c.y = tvy - gr.o.y + 0.5; + return pr; +} + +static PIXpoint_t pdrawtobpix(Gbitmap_t * bitmap, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvy; + + tvy = (int) ((bitmap->size.y - 1) * bitmap->scale.y); + pp.x = gp.x + 0.5; + pp.y = tvy - gp.y + 0.5; + return pp; +} diff --git a/cmd/lefty/ws/mswin32/gquery.c b/cmd/lefty/ws/mswin32/gquery.c new file mode 100644 index 000000000..0b7c9fb1c --- /dev/null +++ b/cmd/lefty/ws/mswin32/gquery.c @@ -0,0 +1,262 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" +#include "resource.h" + +#define WQU widget->u.q + +BOOL CALLBACK stringproc(HWND, UINT, WPARAM, LPARAM); +BOOL CALLBACK choiceproc(HWND, UINT, WPARAM, LPARAM); + +int GQcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + DWORD wflags; + int ai; + + WQU->mode = G_QWSTRING; + wflags = WS_OVERLAPPEDWINDOW; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRMODE: + if (Strcmp("string", attrp[ai].u.t) == 0) + WQU->mode = G_QWSTRING; + else if (Strcmp("file", attrp[ai].u.t) == 0) + WQU->mode = G_QWFILE; + else if (Strcmp("choice", attrp[ai].u.t) == 0) + WQU->mode = G_QWCHOICE; + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + switch (WQU->mode) { + case G_QWSTRING: + widget->w = 0; + break; + case G_QWFILE: + widget->w = 0; + break; + case G_QWCHOICE: + widget->w = 0; + break; + } + return 0; +} + +int GQsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRMODE: + Gerr(POS, G_ERRCANNOTSETATTR2, "mode"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GQgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRMODE: + switch (WQU->mode) { + case G_QWSTRING: + attrp[ai].u.t = "string"; + break; + case G_QWFILE: + attrp[ai].u.t = "file"; + break; + case G_QWCHOICE: + attrp[ai].u.t = "choice"; + break; + } + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GQdestroywidget(Gwidget_t * widget) +{ + return 0; +} + +static Gwidget_t *choicew; +static char *buttons[20]; +static char *stringp; +static int stringn; + +int GQqueryask(Gwidget_t * widget, char *prompt, char *args, + char *responsep, int responsen) +{ + OPENFILENAME ofn; + char buf[256]; + char *s1, *s2; + char c; + int i; + + switch (WQU->mode) { + case G_QWSTRING: + stringp = responsep; + stringn = responsen; + buttons[0] = prompt; + buttons[1] = args; + DialogBox(hinstance, (LPCSTR) "STRINGDIALOG", (HWND) NULL, + stringproc); + Gpopdownflag = TRUE; + if (stringp) + return 0; + return -1; + break; + case G_QWFILE: + strcpy(buf, args); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = (HWND) NULL; + ofn.lpstrFilter = "All Files (*.*)\0*.*\0"; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = buf; + ofn.nMaxFile = 256; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.lpstrTitle = prompt; + ofn.Flags = 0; + ofn.lpstrDefExt = NULL; + if (!GetOpenFileName(&ofn)) { + Gpopdownflag = TRUE; + return -1; + } + strncpy(responsep, buf, responsen); + Gpopdownflag = TRUE; + break; + case G_QWCHOICE: + if (!args) + return -1; + WQU->button = 0; + choicew = widget; + buttons[0] = prompt; + for (s1 = args, i = 1; *s1; i++) { + buttons[i] = s1; + s2 = s1; + while (*s2 && *s2 != '|') + s2++; + c = *s2, *s2 = 0; + s1 = s2; + if (c) + s1++; + } + buttons[i] = NULL; + DialogBox(hinstance, "CHOICEDIALOG", (HWND) NULL, choiceproc); + if (WQU->button > 0) + strncpy(responsep, buttons[WQU->button], responsen); + for (s2 = args; s2 < s1; s2++) + if (!*s2) + *s2 = '|'; + Gpopdownflag = TRUE; + if (WQU->button > 0) + return 0; + return -1; + break; + } + if (responsep[0] && responsep[strlen(responsep) - 1] == '\n') + responsep[strlen(responsep) - 1] = 0; + return 0; +} + +BOOL CALLBACK stringproc(HWND hdlg, UINT message, + WPARAM wparam, LPARAM lparam) +{ + switch (message) { + case WM_INITDIALOG: + SetDlgItemText(hdlg, IDC_STATIC1, (LPCSTR) buttons[0]); + if (buttons[1]) + SetDlgItemText(hdlg, IDC_EDIT1, (LPCSTR) buttons[1]); + return TRUE; + break; + case WM_COMMAND: + switch (wparam) { + case IDOK: + GetDlgItemText(hdlg, IDC_EDIT1, stringp, stringn); + EndDialog(hdlg, TRUE); + return TRUE; + case IDCANCEL: + stringp = NULL; + EndDialog(hdlg, TRUE); + return TRUE; + break; + } + } + return FALSE; +} + +BOOL CALLBACK choiceproc(HWND hdlg, UINT message, + WPARAM wparam, LPARAM lparam) +{ + int sel, i; + + switch (message) { + case WM_INITDIALOG: + SetDlgItemText(hdlg, IDC_STATIC1, (LPCSTR) buttons[0]); + for (i = 1; buttons[i]; i++) + SendDlgItemMessage(hdlg, IDC_LIST1, LB_ADDSTRING, + 0, (LPARAM) buttons[i]); + return TRUE; + break; + case WM_COMMAND: + if ((sel = (int) SendDlgItemMessage(hdlg, IDC_LIST1, + LB_GETCURSEL, 0, 0)) >= 0) { + choicew->u.q->button = sel + 1; + EndDialog(hdlg, TRUE); + } + return TRUE; + break; + } + return FALSE; +} diff --git a/cmd/lefty/ws/mswin32/gscroll.c b/cmd/lefty/ws/mswin32/gscroll.c new file mode 100644 index 000000000..1f197e831 --- /dev/null +++ b/cmd/lefty/ws/mswin32/gscroll.c @@ -0,0 +1,210 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +int GScreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + DWORD wflags; + int ai; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + wflags = WS_CHILDWINDOW | WS_HSCROLL | WS_VSCROLL; + ps.x = ps.y = MINSWSIZE; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINSWSIZE); + break; + case G_ATTRBORDERWIDTH: + wflags |= WS_BORDER; + break; + case G_ATTRCHILDCENTER: + Gerr(POS, G_ERRCANNOTSETATTR1, "childcenter"); + return -1; + case G_ATTRMODE: + if (Strcmp("forcebars", attrp[ai].u.t) != 0) { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + Gadjustwrect(parent, &ps); + if (!(widget->w = CreateWindow("ScrollClass", "scroll", wflags, 0, 0, + ps.x, ps.y, parent->w, + (HMENU) (widget - &Gwidgets[0]), + hinstance, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + ShowWindow(widget->w, SW_SHOW); + UpdateWindow(widget->w); + if (parent && parent->type == G_ARRAYWIDGET) + Gawinsertchild(parent, widget); + return 0; +} + +int GSsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Gwidget_t *parent, *child; + PIXpoint_t po; + PIXsize_t ps, pps, cps; + RECT r; + DWORD wflags1, wflags2; + int ai, wi; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + wflags2 = SWP_NOSIZE | SWP_NOZORDER; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINSWSIZE); + Gadjustwrect(parent, &ps); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, + wflags1); + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTSETATTR2, "borderwidth"); + return -1; + case G_ATTRCHILDCENTER: + for (wi = 0; wi < Gwidgetn; wi++) { + child = &Gwidgets[wi]; + if (child->inuse && child->pwi == widget - &Gwidgets[0]) + break; + } + if (wi == Gwidgetn) + return 0; + GETORIGIN(attrp[ai].u.p, po); + GetClientRect(widget->w, &r); + pps.x = r.right - r.left, pps.y = r.bottom - r.top; + po.x -= pps.x / 2, po.y -= pps.y / 2; + GetWindowRect(child->w, &r); + cps.x = r.right - r.left, cps.y = r.bottom - r.top; + if (po.x < 0) + po.x = 0; + if (po.y < 0) + po.y = 0; + if (po.x > cps.x - pps.x) + po.x = cps.x - pps.x; + if (po.y > cps.y - pps.y) + po.y = cps.y - pps.y; + SetWindowPos(child->w, (HWND) NULL, -po.x, -po.y, 0, 0, + wflags2); + SetScrollPos(widget->w, SB_HORZ, po.x, TRUE); + SetScrollPos(widget->w, SB_VERT, po.y, TRUE); + break; + case G_ATTRMODE: + if (Strcmp("forcebars", attrp[ai].u.t) != 0) { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GSgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Gwidget_t *child; + RECT r; + int width, height, ai, wi; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GetWindowRect(widget->w, &r); + attrp[ai].u.s.x = r.right - r.left; + attrp[ai].u.s.y = r.bottom - r.top; + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTGETATTR, "borderwidth"); + return -1; + case G_ATTRCHILDCENTER: + for (wi = 0; wi < Gwidgetn; wi++) { + child = &Gwidgets[wi]; + if (child->inuse && child->pwi == widget - &Gwidgets[0]) + break; + } + if (wi == Gwidgetn) { + Gerr(POS, G_ERRNOCHILDWIDGET); + return -1; + } + GetWindowRect(widget->w, &r); + width = r.right - r.left; + height = r.bottom - r.top; + GetWindowRect(widget->w, &r); + attrp[ai].u.p.x = width / 2 - r.left; + attrp[ai].u.p.y = height / 2 - r.top; + break; + case G_ATTRMODE: + attrp[ai].u.t = "forcebars"; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", widget->w); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GSdestroywidget(Gwidget_t * widget) +{ + Gwidget_t *parent; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + if (parent && parent->type == G_ARRAYWIDGET) + Gawdeletechild(parent, widget); + DestroyWindow(widget->w); + return 0; +} diff --git a/cmd/lefty/ws/mswin32/gtext.c b/cmd/lefty/ws/mswin32/gtext.c new file mode 100644 index 000000000..13eed9c72 --- /dev/null +++ b/cmd/lefty/ws/mswin32/gtext.c @@ -0,0 +1,219 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WTU widget->u.t + +int GTcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + DWORD wflags; + char *s; + int ai; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + wflags = WS_CHILDWINDOW; + WTU->func = NULL; + ps.x = ps.y = MINTWSIZE; + s = ""; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINTWSIZE); + break; + case G_ATTRBORDERWIDTH: + wflags |= WS_BORDER; + break; + case G_ATTRTEXT: + s = attrp[ai].u.t; + break; + case G_ATTRAPPENDTEXT: + Gerr(POS, G_ERRCANNOTSETATTR1, "appendtext"); + return -1; + case G_ATTRMODE: + if (Strcmp("oneline", attrp[ai].u.t) != 0 && + Strcmp("input", attrp[ai].u.t) != 0 && + Strcmp("output", attrp[ai].u.t) != 0) { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRNEWLINECB: + WTU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + Gadjustwrect(parent, &ps); + wflags |= (ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL); + if (ps.y > 40) + wflags |= (WS_HSCROLL | WS_VSCROLL); + if (!(widget->w = CreateWindow("EDIT", s, wflags, 0, 0, ps.x, ps.y, + parent->w, + (HMENU) (widget - &Gwidgets[0]), + hinstance, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + ShowWindow(widget->w, SW_SHOW); + UpdateWindow(widget->w); + if (parent && parent->type == G_ARRAYWIDGET) + Gawinsertchild(parent, widget); + return 0; +} + +int GTsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Gwidget_t *parent; + PIXsize_t ps; + DWORD wflags1; + int ai; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINTWSIZE); + Gadjustwrect(parent, &ps); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, + wflags1); + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTSETATTR2, "borderwidth"); + return -1; + case G_ATTRTEXT: + Gnocallbacks = TRUE; + SendMessage(widget->w, WM_SETTEXT, 0, ""); + SendMessage(widget->w, EM_SETSEL, -1, 32760); + SendMessage(widget->w, EM_REPLACESEL, 0, + (LPARAM) attrp[ai].u.t); + SendMessage(widget->w, EM_SETSEL, -1, 32760); + /* SendMessage (widget->w, EM_REPLACESEL, 0, (LPARAM) "\r\n"); */ + /* SendMessage (widget->w, EM_SETSEL, -1, 32760); */ + Gnocallbacks = FALSE; + break; + case G_ATTRAPPENDTEXT: + Gnocallbacks = TRUE; + SendMessage(widget->w, EM_SETSEL, -1, 32760); + SendMessage(widget->w, EM_REPLACESEL, 0, + (LPARAM) attrp[ai].u.t); + SendMessage(widget->w, EM_SETSEL, -1, 32760); + SendMessage(widget->w, EM_REPLACESEL, 0, (LPARAM) "\r\n"); + SendMessage(widget->w, EM_SETSEL, -1, 32760); + Gnocallbacks = FALSE; + break; + case G_ATTRMODE: + if (Strcmp("oneline", attrp[ai].u.t) != 0 && + Strcmp("input", attrp[ai].u.t) != 0 && + Strcmp("output", attrp[ai].u.t) != 0) { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GTgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + RECT r; + int rtn, ai, i, j; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GetWindowRect(widget->w, &r); + attrp[ai].u.s.x = r.right - r.left; + attrp[ai].u.s.y = r.bottom - r.top; + break; + case G_ATTRBORDERWIDTH: + Gerr(POS, G_ERRCANNOTGETATTR, "borderwidth"); + return -1; + case G_ATTRTEXT: + if ((rtn = GetWindowTextLength(widget->w)) + 1 > Gbufn) { + Gbufp = Marraygrow(Gbufp, (long) (rtn + 1) * BUFSIZE); + Gbufn = rtn + 1; + } + GetWindowText(widget->w, &Gbufp[0], Gbufn - 1); + for (i = 0, j = 0; Gbufp[i]; i++) + if (Gbufp[i] != '\r') + Gbufp[j++] = Gbufp[i]; + Gbufp[j++] = 0; + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRAPPENDTEXT: + Gerr(POS, G_ERRCANNOTGETATTR, "appendtext"); + return -1; + case G_ATTRMODE: + attrp[ai].u.t = "oneline"; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", widget->w); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRNEWLINECB: + attrp[ai].u.func = WTU->func; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GTdestroywidget(Gwidget_t * widget) +{ + Gwidget_t *parent; + + parent = (widget->pwi == -1) ? NULL : &Gwidgets[widget->pwi]; + if (parent && parent->type == G_ARRAYWIDGET) + Gawdeletechild(parent, widget); + DestroyWindow(widget->w); + return 0; +} diff --git a/cmd/lefty/ws/mswin32/gview.c b/cmd/lefty/ws/mswin32/gview.c new file mode 100644 index 000000000..70508050c --- /dev/null +++ b/cmd/lefty/ws/mswin32/gview.c @@ -0,0 +1,180 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WVU widget->u.v + +int GVcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXpoint_t po; + PIXsize_t ps; + DWORD wflags; + char *s; + int ai; + + WVU->func = NULL; + WVU->closing = FALSE; + wflags = WS_OVERLAPPEDWINDOW; + s = "LEFTY"; + po.x = po.y = CW_USEDEFAULT; + ps.x = ps.y = MINVWSIZE; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + GETORIGIN(attrp[ai].u.p, po); + break; + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINVWSIZE); + break; + case G_ATTRNAME: + s = attrp[ai].u.t; + break; + case G_ATTRZORDER: + Gerr(POS, G_ERRCANNOTSETATTR1, "zorder"); + return -1; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTREVENTCB: + WVU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + if (!(widget->w = CreateWindow("LeftyClass", s, wflags, po.x, po.y, + ps.x, ps.y, (HWND) 0, (HMENU) 0, + hinstance, NULL))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + ShowWindow(widget->w, SW_SHOW); + UpdateWindow(widget->w); + return 0; +} + +int GVsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXpoint_t po; + PIXsize_t ps; + DWORD wflags1, wflags2, wflags3, wflags4; + int ai; + + wflags1 = SWP_NOMOVE | SWP_NOZORDER; + wflags2 = SWP_NOSIZE | SWP_NOZORDER; + wflags3 = SWP_NOSIZE | SWP_NOMOVE; + wflags4 = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + GETORIGIN(attrp[ai].u.p, po); + SetWindowPos(widget->w, (HWND) NULL, po.x, po.y, 0, 0, + wflags2); + break; + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINVWSIZE); + SetWindowPos(widget->w, (HWND) NULL, 0, 0, ps.x, ps.y, + wflags1); + break; + case G_ATTRNAME: + SetWindowText(widget->w, attrp[ai].u.t); + return -1; + case G_ATTRZORDER: + if (Strcmp(attrp[ai].u.t, "top") == 0) + SetWindowPos(widget->w, (HWND) HWND_TOP, 0, 0, 0, 0, + wflags3); + else if (Strcmp(attrp[ai].u.t, "bottom") == 0) + SetWindowPos(widget->w, (HWND) HWND_BOTTOM, + 0, 0, 0, 0, wflags4); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTREVENTCB: + WVU->func = attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GVgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + RECT r; + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + GetWindowRect(widget->w, &r); + attrp[ai].u.p.x = r.left, attrp[ai].u.p.y = r.top; + break; + case G_ATTRSIZE: + GetWindowRect(widget->w, &r); + attrp[ai].u.s.x = r.right - r.left; + attrp[ai].u.s.y = r.bottom - r.top; + break; + case G_ATTRNAME: + Gerr(POS, G_ERRNOTIMPLEMENTED); + return -1; + case G_ATTRZORDER: + Gerr(POS, G_ERRNOTIMPLEMENTED); + return -1; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", widget->w); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTREVENTCB: + attrp[ai].u.func = WVU->func; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GVdestroywidget(Gwidget_t * widget) +{ + WVU->closing = TRUE; + DestroyWindow(widget->w); + return 0; +} diff --git a/cmd/lefty/ws/mswin32/lefty.rc b/cmd/lefty/ws/mswin32/lefty.rc new file mode 100644 index 000000000..7de1ae667 --- /dev/null +++ b/cmd/lefty/ws/mswin32/lefty.rc @@ -0,0 +1,94 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +CHOICEDIALOG DIALOG MOVEABLE IMPURE 0, 0, 186, 92 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + LISTBOX IDC_LIST1,40,21,105,71,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | + WS_TABSTOP + CTEXT "Static",IDC_STATIC1,8,3,171,12 +END + +STRINGDIALOG DIALOG DISCARDABLE 0, 0, 186, 75 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,114,56,50,14 + PUSHBUTTON "Cancel",IDCANCEL,20,57,50,14 + EDITTEXT IDC_EDIT1,19,31,147,18,ES_AUTOHSCROLL + CTEXT "Static",IDC_STATIC1,15,5,155,19 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/cmd/lefty/ws/mswin32/resource.h b/cmd/lefty/ws/mswin32/resource.h new file mode 100644 index 000000000..3c995540a --- /dev/null +++ b/cmd/lefty/ws/mswin32/resource.h @@ -0,0 +1,44 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by lefty.rc +// +#define IDD_DIALOG1 101 +#define IDC_LIST1 1000 +#define IDC_EDIT1 1002 +#define IDC_STATIC1 1005 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 104 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1006 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#ifdef __cplusplus +} +#endif diff --git a/cmd/lefty/ws/none/garray.c b/cmd/lefty/ws/none/garray.c new file mode 100644 index 000000000..847938ebb --- /dev/null +++ b/cmd/lefty/ws/none/garray.c @@ -0,0 +1,62 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +int GAcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GAsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GAgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GAdestroywidget(Gwidget_t * widget) +{ + return 0; +} + +int Gaworder(Gwidget_t * widget, void *data, Gawordercb func) +{ + return 0; +} + +int Gawsetmode(Gwidget_t * widget, int mode) +{ + return 0; +} + +int Gawgetmode(Gwidget_t * widget) +{ + return 0; +} + +void Gawdefcoordscb(int wi, Gawdata_t * dp) +{ +} diff --git a/cmd/lefty/ws/none/gbutton.c b/cmd/lefty/ws/none/gbutton.c new file mode 100644 index 000000000..494000193 --- /dev/null +++ b/cmd/lefty/ws/none/gbutton.c @@ -0,0 +1,43 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +int GBcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; + return 0; +} + +int GBsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GBgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GBdestroywidget(Gwidget_t * widget) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gcanvas.c b/cmd/lefty/ws/none/gcanvas.c new file mode 100644 index 000000000..5b756548d --- /dev/null +++ b/cmd/lefty/ws/none/gcanvas.c @@ -0,0 +1,137 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +int GCcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GCsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GCgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GCdestroywidget(Gwidget_t * widget) +{ + return 0; +} + +int GCcanvasclear(Gwidget_t * widget) +{ + return 0; +} + +int GCsetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + return 0; +} + +int GCgetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + return 0; +} + +int GCarrow(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + return 0; +} + +int GCline(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + return 0; +} + +int GCbox(Gwidget_t * widget, Grect_t gr, Ggattr_t * ap) +{ + return 0; +} + +int GCpolygon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + return 0; +} + +int GCsplinegon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + return 0; +} + +int GCarc(Gwidget_t * widget, Gpoint_t gc, Gsize_t gs, double ang1, + double ang2, Ggattr_t * ap) +{ + return 0; +} + +int GCtext(Gwidget_t * widget, Gtextline_t * tlp, int n, Gpoint_t go, + char *fn, double fs, char *justs, Ggattr_t * ap) +{ + return 0; +} + +int GCgettextsize(Gwidget_t * widget, Gtextline_t * tlp, int n, char *fn, + double fs, Gsize_t * gsp) +{ + return -1; +} + +int GCcreatebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, Gsize_t s) +{ + return 0; +} + +int GCdestroybitmap(Gbitmap_t * bitmap) +{ + return 0; +} + +#define COMPDIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a)) +#define CDIFF(a, b) (COMPDIFF (a.red, b[0]) + COMPDIFF (a.green, b[1]) + \ + COMPDIFF (a.blue, b[2])) +#define CMINMAXDIFF 20000 + +int GCreadbitmap(Gwidget_t * widget, Gbitmap_t * bitmap, FILE * fp) +{ + return 0; +} + +int GCwritebitmap(Gbitmap_t * bitmap, FILE * fp) +{ + return 0; +} + +int GCbitblt(Gwidget_t * widget, Gpoint_t gp, Grect_t gr, + Gbitmap_t * bitmap, char *mode, Ggattr_t * ap) +{ + return 0; +} + +int GCgetmousecoords(Gwidget_t * widget, Gpoint_t * gpp, int *count) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gcommon.c b/cmd/lefty/ws/none/gcommon.c new file mode 100644 index 000000000..d0b6d31f9 --- /dev/null +++ b/cmd/lefty/ws/none/gcommon.c @@ -0,0 +1,54 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +int Gxfd; +Widget Groot; +Display *Gdisplay; +int Gpopdownflag; +int Gscreenn; +int Gdepth; + +int Ginitgraphics(void) +{ + return 0; +} + +int Gtermgraphics(void) +{ + return 0; +} + +int Gsync(void) +{ + return 0; +} + +int Gresetbstate(int wi) +{ + return 0; +} + +int Gprocessevents(int waitflag, Geventmode_t mode) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gcommon.h b/cmd/lefty/ws/none/gcommon.h new file mode 100644 index 000000000..584ad22a7 --- /dev/null +++ b/cmd/lefty/ws/none/gcommon.h @@ -0,0 +1,138 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#ifndef _GCOMMON_H +#define _GCOMMON_H + + typedef struct { + int x, y; + } XPoint; + typedef int Widget; + typedef int Display; + + extern Widget Groot; + extern Display *Gdisplay; + extern int Gpopdownflag; + extern int Gscreenn; + extern int Gdepth; + + int Ginitgraphics(void); + int Gtermgraphics(void); + int Gsync(void); + + int GAcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GAsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GAgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GAdestroywidget(Gwidget_t *); + + int GBcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GBsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GBgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GBdestroywidget(Gwidget_t *); + + int GCcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GCsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GCgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GCdestroywidget(Gwidget_t *); + int GCcanvasclear(Gwidget_t *); + int GCsetgfxattr(Gwidget_t *, Ggattr_t *); + int GCgetgfxattr(Gwidget_t *, Ggattr_t *); + int GCarrow(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GCline(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GCbox(Gwidget_t *, Grect_t, Ggattr_t *); + int GCpolygon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GCsplinegon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GCarc(Gwidget_t *, Gpoint_t, Gsize_t, double, double, Ggattr_t *); + int GCtext(Gwidget_t *, Gtextline_t *, int, Gpoint_t, + char *, double, char *, Ggattr_t *); + int GCgettextsize(Gwidget_t *, Gtextline_t *, int, char *, double, + Gsize_t *); + int GCcreatebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t); + int GCdestroybitmap(Gbitmap_t *); + int GCreadbitmap(Gwidget_t *, Gbitmap_t *, FILE *); + int GCwritebitmap(Gbitmap_t *, FILE *); + int GCbitblt(Gwidget_t *, Gpoint_t, Grect_t, Gbitmap_t *, char *, + Ggattr_t *); + int GCgetmousecoords(Gwidget_t *, Gpoint_t *, int *); + + int GLcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GLsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GLgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GLdestroywidget(Gwidget_t *); + + int GMcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GMsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GMgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GMdestroywidget(Gwidget_t *); + int GMmenuaddentries(Gwidget_t *, int, char **); + int GMmenudisplay(Gwidget_t *, Gwidget_t *); + + int GPcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GPsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GPgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GPdestroywidget(Gwidget_t *); + int GPcanvasclear(Gwidget_t *); + int GPsetgfxattr(Gwidget_t *, Ggattr_t *); + int GPgetgfxattr(Gwidget_t *, Ggattr_t *); + int GParrow(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GPline(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GPbox(Gwidget_t *, Grect_t, Ggattr_t *); + int GPpolygon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GPsplinegon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GParc(Gwidget_t *, Gpoint_t, Gsize_t, double, double, Ggattr_t *); + int GPtext(Gwidget_t *, Gtextline_t *, int, Gpoint_t, + char *, double, char *, Ggattr_t *); + int GPcreatebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t); + int GPdestroybitmap(Gbitmap_t *); + int GPreadbitmap(Gwidget_t *, Gbitmap_t *, FILE *); + int GPwritebitmap(Gbitmap_t *, FILE *); + int GPbitblt(Gwidget_t *, Gpoint_t, Grect_t, Gbitmap_t *, char *, + Ggattr_t *); + + int GQcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GQsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GQgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GQdestroywidget(Gwidget_t *); + int GQqueryask(Gwidget_t *, char *, char *, char *, int); + + int GScreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GSsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GSgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GSdestroywidget(Gwidget_t *); + + int GTcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GTsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GTgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GTdestroywidget(Gwidget_t *); + + int GVcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GVsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GVgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GVdestroywidget(Gwidget_t *); + + void Gawdefcoordscb(int, Gawdata_t *); + +#endif /* _GCOMMON_H */ + +#ifdef __cplusplus +} +#endif diff --git a/cmd/lefty/ws/none/glabel.c b/cmd/lefty/ws/none/glabel.c new file mode 100644 index 000000000..c683240bd --- /dev/null +++ b/cmd/lefty/ws/none/glabel.c @@ -0,0 +1,42 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +int GLcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GLsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GLgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GLdestroywidget(Gwidget_t * widget) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gmenu.c b/cmd/lefty/ws/none/gmenu.c new file mode 100644 index 000000000..fdc51577f --- /dev/null +++ b/cmd/lefty/ws/none/gmenu.c @@ -0,0 +1,52 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +int GMcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GMsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GMgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GMdestroywidget(Gwidget_t * widget) +{ + return 0; +} + +int GMmenuaddentries(Gwidget_t * widget, int en, char **ep) +{ + return 0; +} + +int GMmenudisplay(Gwidget_t * parent, Gwidget_t * widget) +{ + return -1; +} diff --git a/cmd/lefty/ws/none/gpcanvas.c b/cmd/lefty/ws/none/gpcanvas.c new file mode 100644 index 000000000..52ea5807c --- /dev/null +++ b/cmd/lefty/ws/none/gpcanvas.c @@ -0,0 +1,128 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +char *Gpscanvasname = "out.ps"; + +int GPcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GPsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GPgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GPdestroywidget(Gwidget_t * widget) +{ + return 0; +} + +int GPcanvasclear(Gwidget_t * widget) +{ + return 0; +} + +int GPsetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + return 0; +} + +int GPgetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + return 0; +} + +int GParrow(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + return 0; +} + +int GPline(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + return 0; +} + +int GPbox(Gwidget_t * widget, Grect_t gr, Ggattr_t * ap) +{ + return 0; +} + +int GPpolygon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + return 0; +} + +int GPsplinegon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + return 0; +} + +int GParc(Gwidget_t * widget, Gpoint_t gc, Gsize_t gs, + double ang1, double ang2, Ggattr_t * ap) +{ + return 0; +} + +int GPtext(Gwidget_t * widget, Gtextline_t * tlp, int n, Gpoint_t go, + char *fn, double fs, char *justs, Ggattr_t * ap) +{ + return 0; +} + +static char *findfont(char *name) +{ + return NULL; +} + +int GPcreatebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, Gsize_t s) +{ + return 0; +} + +int GPdestroybitmap(Gbitmap_t * bitmap) +{ + return 0; +} + +int GPreadbitmap(Gwidget_t * widget, Gbitmap_t * bitmap, FILE * fp) +{ + return 0; +} + +int GPwritebitmap(Gbitmap_t * bitmap, FILE * fp) +{ + return -1; +} + +int GPbitblt(Gwidget_t * widget, Gpoint_t gp, Grect_t gr, + Gbitmap_t * bitmap, char *mode, Ggattr_t * ap) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gquery.c b/cmd/lefty/ws/none/gquery.c new file mode 100644 index 000000000..2da52292a --- /dev/null +++ b/cmd/lefty/ws/none/gquery.c @@ -0,0 +1,48 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +int GQcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GQsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GQgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GQdestroywidget(Gwidget_t * widget) +{ + return 0; +} + +int GQqueryask(Gwidget_t * widget, char *prompt, char *args, + char *responsep, int responsen) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gscroll.c b/cmd/lefty/ws/none/gscroll.c new file mode 100644 index 000000000..c49cbb233 --- /dev/null +++ b/cmd/lefty/ws/none/gscroll.c @@ -0,0 +1,42 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +int GScreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GSsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GSgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GSdestroywidget(Gwidget_t * widget) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gtext.c b/cmd/lefty/ws/none/gtext.c new file mode 100644 index 000000000..b8aa4beda --- /dev/null +++ b/cmd/lefty/ws/none/gtext.c @@ -0,0 +1,43 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +int GTcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GTsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GTgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GTdestroywidget(Gwidget_t * widget) +{ + return 0; +} diff --git a/cmd/lefty/ws/none/gview.c b/cmd/lefty/ws/none/gview.c new file mode 100644 index 000000000..3335875b0 --- /dev/null +++ b/cmd/lefty/ws/none/gview.c @@ -0,0 +1,42 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +int GVcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + return -1; +} + +int GVsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GVgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + return 0; +} + +int GVdestroywidget(Gwidget_t * widget) +{ + return 0; +} diff --git a/cmd/lefty/ws/x11/.cvsignore b/cmd/lefty/ws/x11/.cvsignore new file mode 100644 index 000000000..9fb985742 --- /dev/null +++ b/cmd/lefty/ws/x11/.cvsignore @@ -0,0 +1,6 @@ +*.la +*.lo +.deps +.libs +Makefile +Makefile.in diff --git a/cmd/lefty/ws/x11/Makefile.am b/cmd/lefty/ws/x11/Makefile.am new file mode 100644 index 000000000..2418ae944 --- /dev/null +++ b/cmd/lefty/ws/x11/Makefile.am @@ -0,0 +1,17 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = libfilereq + +AM_CPPFLAGS = -I$(top_srcdir)/lefty @XAW_INCLUDES@ + +AM_CFLAGS = @X_CFLAGS@ + +noinst_HEADERS = gcommon.h +if WITH_X +noinst_LTLIBRARIES = libws.la +endif + +libws_la_SOURCES = garray.c gbutton.c gcanvas.c gcommon.c glabel.c \ + gmenu.c gpcanvas.c gquery.c gscroll.c gtext.c gview.c + +EXTRA_DIST = $(libws_la_SOURCES) diff --git a/cmd/lefty/ws/x11/garray.c b/cmd/lefty/ws/x11/garray.c new file mode 100644 index 000000000..4291c30e8 --- /dev/null +++ b/cmd/lefty/ws/x11/garray.c @@ -0,0 +1,562 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WAU widget->u.a + +extern WidgetClass arrayWidgetClass; + +static void awcallback(Widget, XtPointer, XtPointer); + +int GAcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + int ai; + XColor c; + int color; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + WAU->func = NULL; + ps.x = ps.y = MINAWSIZE; + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINAWSIZE); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRMODE: + if (Strcmp("horizontal", attrp[ai].u.t) == 0) { + ADD2ARGS(XtNorientation, XtorientHorizontal); + WAU->mode = G_AWHARRAY; + } else if (Strcmp("vertical", attrp[ai].u.t) == 0) { + WAU->mode = G_AWVARRAY; + } else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRLAYOUT: + if (Strcmp("on", attrp[ai].u.t) == 0) + Gawsetmode(widget, FALSE); + else if (Strcmp("off", attrp[ai].u.t) == 0) + Gawsetmode(widget, TRUE); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRRESIZECB: + WAU->func = (Gawcoordscb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + if (!(widget->w = XtCreateWidget("array", arrayWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XtAddCallback(widget->w, XtNcallback, awcallback, (XtPointer) NULL); + Glazymanage(widget->w); + return 0; +} + +int GAsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + int ai; + + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINAWSIZE); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRMODE: + Gerr(POS, G_ERRCANNOTSETATTR2, "mode"); + return -1; + case G_ATTRLAYOUT: + if (Strcmp("on", attrp[ai].u.t) == 0) + Gawsetmode(widget, FALSE); + else if (Strcmp("off", attrp[ai].u.t) == 0) + Gawsetmode(widget, TRUE); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRRESIZECB: + WAU->func = (Gawcoordscb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + XtSetValues(widget->w, argp, argn); + return 0; +} + +int GAgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Dimension width, height; + int ai; + + for (ai = 0; ai < attrn; ai++) { + RESETARGS; + switch (attrp[ai].id) { + case G_ATTRSIZE: + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.s.x = width, attrp[ai].u.s.y = height; + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, &width); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.i = width; + break; + case G_ATTRMODE: + attrp[ai].u.t = (WAU->mode == G_AWHARRAY) ? + "horizontal" : "vertical"; + break; + case G_ATTRLAYOUT: + attrp[ai].u.t = (Gawgetmode(widget)) ? "off" : "on"; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", XtWindow(widget->w)); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRRESIZECB: + attrp[ai].u.func = (void *) (WAU->func); + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GAdestroywidget(Gwidget_t * widget) +{ + XtDestroyWidget(widget->w); + return 0; +} + +static void awcallback(Widget w, XtPointer clientdata, XtPointer calldata) +{ + Gwidget_t *widget; + + if (!(widget = findwidget((unsigned long) w, G_ARRAYWIDGET))) + return; + if (WAU->func) + (*WAU->func) (widget - &Gwidgets[0], (Gawdata_t *) calldata); + else + Gawdefcoordscb(widget - &Gwidgets[0], (Gawdata_t *) calldata); +} + +/* the rest of this file contains the implementation of the array widget */ + +#include <X11/IntrinsicP.h> + +typedef struct _ArrayClassRec *ArrayWidgetClass; +typedef struct _ArrayRec *ArrayWidget; + +typedef struct _ArrayClassPart { + int dummy; /* not used */ +} ArrayClassPart; + +typedef struct _ArrayClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ArrayClassPart array_class; +} ArrayClassRec; + +typedef struct _ArrayPart { + XtCallbackList callbacks; + XtOrientation orientation; + Gawdata_t data; + int batchmode; +} ArrayPart; + +typedef struct _ArrayRec { + CorePart core; + CompositePart composite; + ArrayPart array; +} ArrayRec; + +#define CHILDINCR 10 +#define CHILDSIZE sizeof (Gawcarray_t) + +static XtResource resources[] = { + { + XtNcallback, + XtCCallback, + XtRCallback, + sizeof(XtPointer), + XtOffsetOf(ArrayRec, array.callbacks), + XtRCallback, (XtPointer) NULL} + , + { + XtNorientation, + XtCOrientation, + XtROrientation, + sizeof(XtOrientation), + XtOffsetOf(ArrayRec, array.orientation), + XtRImmediate, (XtPointer) XtorientVertical} +}; + +static void ClassInitialize(void); +static void Initialize(Widget, Widget, ArgList, Cardinal *); +static void Destroy(Widget); +static void Resize(Widget); +static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *); +static XtGeometryResult GeometryManager(Widget, + XtWidgetGeometry *, + XtWidgetGeometry *); +static void ChangeManaged(Widget); +static void InsertChild(Widget); +static void DeleteChild(Widget); +static void dolayout(ArrayWidget, int); + +ArrayClassRec arrayClassRec = { + { /* core_class fields */ + /* superclass */ (WidgetClass) & compositeClassRec, + /* class_name */ "Array", + /* widget_size */ sizeof(ArrayRec), + /* class_initialize */ ClassInitialize, + /* class_part_init */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ Resize, + /* expose */ XtInheritExpose, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + } + , + { /* composite_class fields */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ InsertChild, + /* delete_child */ DeleteChild, + /* extension */ NULL + } + , + { /* array_class fields */ + /* dummy */ 0 + } +}; + +WidgetClass arrayWidgetClass = (WidgetClass) & arrayClassRec; + +int Gaworder(Gwidget_t * widget, void *data, Gawordercb func) +{ + ArrayWidget aw; + + aw = (ArrayWidget) widget->w; + (*func) (data, &aw->array.data); + dolayout(aw, TRUE); + return 0; +} + +int Gawsetmode(Gwidget_t * widget, int mode) +{ + ArrayWidget aw; + + aw = (ArrayWidget) widget->w; + aw->array.batchmode = mode; + dolayout(aw, TRUE); + return 0; +} + +int Gawgetmode(Gwidget_t * widget) +{ + ArrayWidget aw; + + aw = (ArrayWidget) widget->w; + return aw->array.batchmode; +} + +void Gawdefcoordscb(int wi, Gawdata_t * dp) +{ + Gawcarray_t *cp; + int sx, sy, csx, csy, ci; + + sx = dp->sx, sy = dp->sy; + csx = csy = 0; + for (ci = 0; ci < dp->cj; ci++) { + cp = &dp->carray[ci]; + if (!cp->flag) + continue; + cp->ox = csx, cp->oy = csy; + if (dp->type == G_AWVARRAY) + cp->sx = sx - 2 * cp->bs, csy += cp->sy + 2 * cp->bs; + else + cp->sy = sy - 2 * cp->bs, csx += cp->sx + 2 * cp->bs; + } + if (dp->type == G_AWVARRAY) + dp->sy = csy; + else + dp->sx = csx; +} + +static void ClassInitialize(void) +{ + XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation, + NULL, (Cardinal) 0); +} + +static void Initialize(Widget reqw, Widget neww, + ArgList args, Cardinal * num_args) +{ + ArrayWidget aw; + + aw = (ArrayWidget) neww; + if (aw->array.orientation == XtorientVertical) + aw->array.data.type = G_AWVARRAY; + else + aw->array.data.type = G_AWHARRAY; + aw->array.data.carray = Marrayalloc((long) CHILDINCR * CHILDSIZE); + aw->array.data.cn = CHILDINCR; + aw->array.data.cj = 0; + aw->array.batchmode = FALSE; + if (aw->core.width == 0) + aw->core.width = 100; + if (aw->core.height == 0) + aw->core.height = 100; +} + +static void Destroy(Widget w) +{ + ArrayWidget aw; + + aw = (ArrayWidget) w; + Marrayfree(aw->array.data.carray); + aw->array.data.cn = aw->array.data.cj = 0; +} + +static void Resize(Widget w) +{ + dolayout((ArrayWidget) w, FALSE); +} + +static Boolean SetValues(Widget curw, Widget reqw, Widget neww, + ArgList args, Cardinal * num_args) +{ + ArrayWidget curaw; + ArrayWidget newaw; + + curaw = (ArrayWidget) curw; + newaw = (ArrayWidget) neww; + if (curaw->array.orientation != newaw->array.orientation) { + if (newaw->array.orientation == XtorientVertical) + newaw->array.data.type = G_AWVARRAY; + else + newaw->array.data.type = G_AWHARRAY; + dolayout(newaw, TRUE); + return TRUE; + } + return FALSE; +} + +static XtGeometryResult GeometryManager(Widget w, + XtWidgetGeometry * req, + XtWidgetGeometry * rep) +{ + Dimension width, height; + + if (req->request_mode & ~(CWX | CWY | CWWidth | CWHeight)) + return XtGeometryNo; + + if (req->request_mode & (CWX | CWY | CWWidth | CWHeight)) { + width = (req->request_mode & CWWidth) ? req->width : w->core.width; + height = + (req->request_mode & CWHeight) ? req->height : w->core.height; + w->core.width = width, w->core.height = height; + dolayout((ArrayWidget) XtParent(w), TRUE); + return XtGeometryYes; + } + return XtGeometryYes; +} + +static void ChangeManaged(Widget w) +{ + ArrayWidget aw; + + aw = (ArrayWidget) w; + if (!aw->array.batchmode) + dolayout(aw, TRUE); +} + +static void InsertChild(Widget w) +{ + ArrayWidget aw; + CompositeWidgetClass sclass; + + sclass = (CompositeWidgetClass) compositeWidgetClass; + (*sclass->composite_class.insert_child) (w); + aw = (ArrayWidget) XtParent(w); + if (aw->array.data.cj == aw->array.data.cn) { + aw->array.data.carray = Marraygrow(aw->array.data.carray, + (long) (aw->array.data.cn + + CHILDINCR) * CHILDSIZE); + aw->array.data.cn += CHILDINCR; + } + aw->array.data.carray[aw->array.data.cj++].w = w; +} + +static void DeleteChild(Widget w) +{ + ArrayWidget aw; + CompositeWidgetClass sclass; + int ci; + + sclass = (CompositeWidgetClass) compositeWidgetClass; + (*sclass->composite_class.delete_child) (w); + aw = (ArrayWidget) XtParent(w); + for (ci = 0; ci < aw->array.data.cj; ci++) + if (aw->array.data.carray[ci].w == w) + break; + if (ci < aw->array.data.cj) { + for (; ci + 1 < aw->array.data.cj; ci++) + aw->array.data.carray[ci].w = aw->array.data.carray[ci + 1].w; + aw->array.data.cj--; + } +} + +static void dolayout(ArrayWidget aw, int flag) +{ + XtWidgetGeometry req, ret_req; + Gawdata_t *dp; + Gawcarray_t *cp; + int sx, sy, ci; + + if (aw->array.batchmode) + return; + dp = &aw->array.data; + for (ci = 0; ci < dp->cj; ci++) { + if (!XtIsManaged(dp->carray[ci].w)) { + dp->carray[ci].flag = 0; + continue; + } + cp = &dp->carray[ci]; + cp->flag = 1; + cp->ox = cp->w->core.x; + cp->oy = cp->w->core.y; + cp->sx = cp->w->core.width; + cp->sy = cp->w->core.height; + cp->bs = cp->w->core.border_width; + } + dp->sx = aw->core.width, dp->sy = aw->core.height; + XtCallCallbackList((Widget) aw, aw->array.callbacks, dp); + if ((sx = dp->sx) < MINAWSIZE) + sx = MINAWSIZE; + if ((sy = dp->sy) < MINAWSIZE) + sy = MINAWSIZE; + if (flag && (aw->core.width != sx || aw->core.height != sy)) { + req.width = sx, req.height = sy; + req.request_mode = CWWidth | CWHeight; + if (XtMakeGeometryRequest((Widget) aw, &req, &ret_req) == + XtGeometryAlmost) { + req = ret_req; + XtMakeGeometryRequest((Widget) aw, &req, &ret_req); + dp->sx = req.width, dp->sy = req.height; + XtCallCallbackList((Widget) aw, aw->array.callbacks, dp); + } + } + for (ci = 0; ci < dp->cj; ci++) { + cp = &dp->carray[ci]; + if (!cp->flag) + continue; + XtConfigureWidget(cp->w, cp->ox, cp->oy, cp->sx, cp->sy, cp->bs); + } +} diff --git a/cmd/lefty/ws/x11/gbutton.c b/cmd/lefty/ws/x11/gbutton.c new file mode 100644 index 000000000..bf66b6d8b --- /dev/null +++ b/cmd/lefty/ws/x11/gbutton.c @@ -0,0 +1,223 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +#define WBU widget->u.b + +static void bwcallback(Widget, XtPointer, XtPointer); + +int GBcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + char *s; + int ai; + XColor c; + int color; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + WBU->func = NULL; + ps.x = ps.y = MINBWSIZE; + s = NULL; + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINBWSIZE); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRTEXT: + s = attrp[ai].u.t; + ADD2ARGS(XtNlabel, s); + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRBUTTONCB: + WBU->func = (Gbuttoncb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + if (!s || s[0] == '\000') { + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + } else { + if (ps.x > MINBWSIZE) + ADD2ARGS(XtNwidth, ps.x); + if (ps.y > MINBWSIZE) + ADD2ARGS(XtNheight, ps.y); + } + ADD2ARGS(XtNhighlightThickness, 0); + ADD2ARGS(XtNinternalHeight, 0); + ADD2ARGS(XtNinternalWidth, 0); + ADD2ARGS(XtNjustify, XtJustifyLeft); + if (!(widget->w = XtCreateWidget("command", commandWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XtAddCallback(widget->w, XtNcallback, bwcallback, + (XtPointer) widget->udata); + Glazymanage(widget->w); + return 0; +} + +int GBsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + int ai; + XColor c; + int color; + + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINBWSIZE); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRTEXT: + ADD2ARGS(XtNlabel, attrp[ai].u.t); + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRBUTTONCB: + WBU->func = (Gbuttoncb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + XtSetValues(widget->w, argp, argn); + return 0; +} + +int GBgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Dimension width, height; + char *s; + int ai; + + for (ai = 0; ai < attrn; ai++) { + RESETARGS; + switch (attrp[ai].id) { + case G_ATTRSIZE: + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.s.x = width, attrp[ai].u.s.y = height; + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, &width); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.i = width; + break; + case G_ATTRTEXT: + ADD2ARGS(XtNlabel, &s); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.t = s; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", XtWindow(widget->w)); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRBUTTONCB: + attrp[ai].u.func = (void *) (WBU->func); + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GBdestroywidget(Gwidget_t * widget) +{ + XtDestroyWidget(widget->w); + return 0; +} + +static void bwcallback(Widget w, XtPointer clientdata, XtPointer calldata) +{ + Gwidget_t *widget; + + widget = findwidget((unsigned long) w, G_BUTTONWIDGET); + if (WBU->func) + (*WBU->func) (widget - &Gwidgets[0], clientdata); +} diff --git a/cmd/lefty/ws/x11/gcanvas.c b/cmd/lefty/ws/x11/gcanvas.c new file mode 100644 index 000000000..72c876613 --- /dev/null +++ b/cmd/lefty/ws/x11/gcanvas.c @@ -0,0 +1,1664 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" +#ifdef FEATURE_GMAP +#include <gmap.h> +#endif + +#define WCU widget->u.c +#define WINDOW widget->u.c->window +#define GC widget->u.c->gc +#define ISVISIBLE(r) ( \ + (r.o.x <= WCU->clip.c.x) && (r.c.x >= WCU->clip.o.x) && \ + (r.o.y <= WCU->clip.c.y) && (r.c.y >= WCU->clip.o.y) \ +) + +#define IS8BIT(font) ((font)->min_byte1 == 0 && (font)->max_byte1 == 0) + +static struct cursormap_t { + Cursor id; + char name[40]; +} cursormap[XC_num_glyphs]; +static int curcursori = -1; + +#define max(a, b) (((a) >= (b)) ? (a) : (b)) +#define min(a, b) (((a) <= (b)) ? (a) : (b)) + +static char gstyles[][2] = { + /* G_SOLID */ {16, 0,}, + /* G_DASHED */ {4, 4,}, + /* G_DOTTED */ {2, 2,}, + /* G_LONGDASHED */ {4, 12,}, + /* G_SHORTDASHED */ {12, 4,}, +}; + +static char grays[][4] = { + {0x00, 0x00, 0x00, 0x00,}, + {0x08, 0x00, 0x00, 0x00,}, + {0x08, 0x00, 0x02, 0x00,}, + {0x0A, 0x00, 0x02, 0x00,}, + {0x0A, 0x00, 0x0A, 0x00,}, + {0x0A, 0x04, 0x0A, 0x00,}, + {0x0A, 0x04, 0x0A, 0x01,}, + {0x0A, 0x05, 0x0A, 0x01,}, + {0x0A, 0x05, 0x0A, 0x05,}, + {0x0E, 0x05, 0x0A, 0x05,}, + {0x0E, 0x05, 0x0B, 0x05,}, + {0x0F, 0x05, 0x0B, 0x05,}, + {0x0F, 0x05, 0x0F, 0x05,}, + {0x0F, 0x0D, 0x0F, 0x05,}, + {0x0F, 0x0D, 0x0F, 0x07,}, + {0x0F, 0x0F, 0x0F, 0x07,}, + {0x0F, 0x0F, 0x0F, 0x0F,}, +}; + +static void bezier(PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t); +static XFontStruct *findfont(char *, int); +static int scalebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t, int, int); +static void setgattr(Gwidget_t *, Ggattr_t *); + +static PIXrect_t rdrawtopix(Gwidget_t *, Grect_t); +static PIXpoint_t pdrawtopix(Gwidget_t *, Gpoint_t); +static PIXsize_t sdrawtopix(Gwidget_t *, Gsize_t); +static Gpoint_t Gppixtodraw(Gwidget_t *, PIXpoint_t); +static Gsize_t spixtodraw(Gwidget_t *, PIXsize_t); +static Grect_t rpixtodraw(Gwidget_t *, PIXrect_t); +static PIXrect_t rdrawtobpix(Gbitmap_t *, Grect_t); +static PIXpoint_t pdrawtobpix(Gbitmap_t *, Gpoint_t); +static void adjustclip(Gwidget_t *); + +static Bool cwvpredicate(Display *, XEvent *, XPointer); +static void cweventhandler(Widget, XtPointer, XEvent *, Boolean *); +static Bool cwepredicate(Display *, XEvent *, XPointer); + +int GCcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + Dimension width, height; +#ifdef FEATURE_BACKINGSTORE + XSetWindowAttributes xswa; +#endif + XEvent ev; + XColor *cp; + XGCValues gcv; + int curi, color, ai, r, g, b, i; +#ifdef FEATURE_GMAP + XVisualInfo *vip; + int gmapmode = FALSE; +#endif + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + WCU->func = NULL; + WCU->needredraw = FALSE; + WCU->buttonsdown = 0; + WCU->bstate[0] = WCU->bstate[1] = WCU->bstate[2] = 0; + ps.x = ps.y = MINCWSIZE; + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINCWSIZE); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; +#ifdef FEATURE_GMAP + case G_ATTRMODE: + if (Strcmp("gmap", attrp[ai].u.t) == 0) { + gmapmode = TRUE; + } else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; +#endif + case G_ATTRCURSOR: + /* will do it after the widget is created */ + break; + case G_ATTRCOLOR: + /* will do it after the widget is created */ + break; + case G_ATTRVIEWPORT: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOW: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTREVENTCB: + WCU->func = (Gcanvascb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); +#ifdef FEATURE_GMAP + if (gmapmode) { + vip = pfChooseFBConfig(Gdisplay, -1, NULL); + ADD2ARGS(GLwNvisualInfo, vip); + if (! + (widget->w = + XtCreateWidget("graphics", glwDrawingAreaWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + } else { + if (!(widget->w = XtCreateWidget("graphics", coreWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + } + WCU->gmapmode = gmapmode; +#else + if (!(widget->w = XtCreateWidget("graphics", coreWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } +#endif + XtOverrideTranslations(widget->w, Gcwanytable); + XtAddEventHandler(widget->w, VisibilityChangeMask | ExposureMask, + FALSE, cweventhandler, (XtPointer) 0); + Glazymanage(widget->w); + Gflushlazyq(); +#ifdef FEATURE_BACKINGSTORE + xswa.backing_store = WhenMapped; + XChangeWindowAttributes(Gdisplay, XtWindow(widget->w), + CWBackingStore, &xswa); +#endif + /* wait for window to become visible */ + XPeekIfEvent(Gdisplay, &ev, cwvpredicate, + (XPointer) XtWindow(widget->w)); + RESETARGS; + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + ps.x = width, ps.y = height; + WCU->window = XtWindow(widget->w); + WCU->cmap = DefaultColormap(Gdisplay, Gscreenn); + WCU->gc = XCreateGC(Gdisplay, WCU->window, 0, NULL); + RESETARGS; + WCU->colors[0].color.pixel = WCU->colors[1].color.pixel = 1000000; + ADD2ARGS(XtNbackground, &WCU->colors[0].color.pixel); + ADD2ARGS(XtNforeground, &WCU->colors[1].color.pixel); + XtGetValues(widget->w, argp, argn); + if (WCU->colors[0].color.pixel == 1000000) { + if (XGetGCValues(Gdisplay, GC, GCBackground, &gcv) != 0) + WCU->colors[0].color.pixel = gcv.background; + else + WCU->colors[0].color.pixel = WhitePixel(Gdisplay, Gscreenn); + } + if (WCU->colors[1].color.pixel == 1000000) { + if (XGetGCValues(Gdisplay, GC, GCForeground, &gcv) != 0) + WCU->colors[1].color.pixel = gcv.foreground; + else + WCU->colors[1].color.pixel = BlackPixel(Gdisplay, Gscreenn); + } + XQueryColor(Gdisplay, WCU->cmap, &WCU->colors[0].color); + WCU->colors[0].inuse = TRUE; + XQueryColor(Gdisplay, WCU->cmap, &WCU->colors[1].color); + WCU->colors[1].inuse = TRUE; + WCU->allocedcolor[0] = WCU->allocedcolor[1] = FALSE; + for (i = 2; i < G_MAXCOLORS; i++) + WCU->colors[i].inuse = FALSE; + WCU->gattr.color = 1; + XSetBackground(Gdisplay, GC, WCU->colors[0].color.pixel); + XSetForeground(Gdisplay, GC, WCU->colors[1].color.pixel); + WCU->gattr.width = 0; + WCU->gattr.mode = G_SRC; + WCU->gattr.fill = 0; + WCU->gattr.style = 0; + WCU->defgattr = WCU->gattr; + WCU->font = NULL; + WCU->wrect.o.x = 0.0, WCU->wrect.o.y = 0.0; + WCU->wrect.c.x = 1.0, WCU->wrect.c.y = 1.0; + WCU->vsize.x = ps.x, WCU->vsize.y = ps.y; + if (Gdepth == 1) { + XSetFillStyle(Gdisplay, GC, FillTiled); + for (i = 0; i < 17; i++) + WCU->grays[i] = + XCreatePixmapFromBitmapData(Gdisplay, WCU->window, + &grays[i][0], 4, 4, + BlackPixel(Gdisplay, Gscreenn), + WhitePixel(Gdisplay, Gscreenn), + 1); + } + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRCURSOR: + if ((curi = XmuCursorNameToIndex(attrp[ai].u.t)) == -1) { + if (Strcmp(attrp[ai].u.t, "default") == 0) { + XUndefineCursor(Gdisplay, XtWindow(widget->w)); + curcursori = -1; + } else { + Gerr(POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); + return -1; + } + } else { + if (!cursormap[curi].id) { + cursormap[curi].id = XCreateFontCursor(Gdisplay, curi); + strcpy(cursormap[curi].name, attrp[ai].u.t); + } + XDefineCursor(Gdisplay, XtWindow(widget->w), + cursormap[curi].id); + curcursori = curi; + } + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + r = attrp[ai].u.c.r * 257; + g = attrp[ai].u.c.g * 257; + b = attrp[ai].u.c.b * 257; + cp = &WCU->colors[color].color; + if (WCU->colors[color].inuse) + if (cp->red != r || cp->green != g || cp->blue != b) + if (color > 1 || WCU->allocedcolor[color]) + XFreeColors(Gdisplay, WCU->cmap, &cp->pixel, 1, 0); + cp->red = r, cp->green = g, cp->blue = b; + if (XAllocColor(Gdisplay, WCU->cmap, cp)) { + WCU->colors[color].inuse = TRUE; + if (color <= 1) + WCU->allocedcolor[color] = TRUE; + } + /* XAllocColor may change the rgb values */ + cp->red = r, cp->green = g, cp->blue = b; + if (color == WCU->gattr.color) + WCU->gattr.color = -1; + if (color == 0 || color == 1) { + RESETARGS; + if (color == 0) + ADD2ARGS(XtNbackground, cp->pixel); + else + ADD2ARGS(XtNforeground, cp->pixel); + XtSetValues(widget->w, argp, argn); + } + break; + case G_ATTRVIEWPORT: + WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); + WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); + RESETARGS; + ADD2ARGS(XtNwidth, WCU->vsize.x); + ADD2ARGS(XtNheight, WCU->vsize.y); + XtSetValues(widget->w, argp, argn); + break; + case G_ATTRWINDOW: + WCU->wrect = attrp[ai].u.r; + break; + } + } + adjustclip(widget); + return 0; +} + +int GCsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + XColor *cp; + int curi, color, ai, r, g, b; + + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINCWSIZE); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRCURSOR: + if ((curi = XmuCursorNameToIndex(attrp[ai].u.t)) == -1) { + if (Strcmp(attrp[ai].u.t, "default") == 0) { + XUndefineCursor(Gdisplay, XtWindow(widget->w)); + curcursori = -1; + } else { + Gerr(POS, G_ERRNOSUCHCURSOR, attrp[ai].u.t); + return -1; + } + } else { + if (!cursormap[curi].id) { + cursormap[curi].id = XCreateFontCursor(Gdisplay, curi); + strcpy(cursormap[curi].name, attrp[ai].u.t); + } + XDefineCursor(Gdisplay, XtWindow(widget->w), + cursormap[curi].id); + curcursori = curi; + } + Gsync(); + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + r = attrp[ai].u.c.r * 257; + g = attrp[ai].u.c.g * 257; + b = attrp[ai].u.c.b * 257; + cp = &WCU->colors[color].color; + if (WCU->colors[color].inuse) + if (cp->red != r || cp->green != g || cp->blue != b) + if (color > 1 || WCU->allocedcolor[color]) + XFreeColors(Gdisplay, WCU->cmap, &cp->pixel, 1, 0); + cp->red = r, cp->green = g, cp->blue = b; + if (XAllocColor(Gdisplay, WCU->cmap, cp)) { + WCU->colors[color].inuse = TRUE; + if (color <= 1) + WCU->allocedcolor[color] = TRUE; + } + /* XAllocColor may change the rgb values */ + cp->red = r, cp->green = g, cp->blue = b; + if (color == WCU->gattr.color) + WCU->gattr.color = -1; + break; + case G_ATTRVIEWPORT: + WCU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); + WCU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); + ADD2ARGS(XtNwidth, WCU->vsize.x); + ADD2ARGS(XtNheight, WCU->vsize.y); + XtSetValues(widget->w, argp, argn); + adjustclip(widget); + RESETARGS; + break; + case G_ATTRWINDOW: + WCU->wrect = attrp[ai].u.r; + XtSetValues(widget->w, argp, argn); + adjustclip(widget); + RESETARGS; + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTREVENTCB: + WCU->func = (Gcanvascb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + XtSetValues(widget->w, argp, argn); + return 0; +} + +int GCgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + XColor *cp; + Dimension width, height; + int ai, color; + + for (ai = 0; ai < attrn; ai++) { + RESETARGS; + switch (attrp[ai].id) { + case G_ATTRSIZE: + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.s.x = width, attrp[ai].u.s.y = height; + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, &width); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.i = width; + break; + case G_ATTRCURSOR: + attrp[ai].u.t = (curcursori == -1) ? + "default" : cursormap[curcursori].name; + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + if (WCU->colors[color].inuse) { + cp = &WCU->colors[color].color; + attrp[ai].u.c.r = cp->red / 257.0; + attrp[ai].u.c.g = cp->green / 257.0; + attrp[ai].u.c.b = cp->blue / 257.0; + } else { + attrp[ai].u.c.r = -1; + attrp[ai].u.c.g = -1; + attrp[ai].u.c.b = -1; + } + break; + case G_ATTRVIEWPORT: + attrp[ai].u.s = WCU->vsize; + break; + case G_ATTRWINDOW: + attrp[ai].u.r = WCU->wrect; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", XtWindow(widget->w)); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTREVENTCB: + attrp[ai].u.func = (void *) (WCU->func); + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GCdestroywidget(Gwidget_t * widget) +{ + XtDestroyWidget(widget->w); + return 0; +} + +int GCcanvasclear(Gwidget_t * widget) +{ + XEvent ev; + int gotit; + + XClearWindow(Gdisplay, WINDOW); + /* avoid a redraw */ + WCU->needredraw = FALSE; + XSync(Gdisplay, False); + gotit = FALSE; + while (XCheckIfEvent(Gdisplay, + &ev, cwepredicate, (XPointer) WINDOW) == True) + gotit = TRUE; + if (gotit) + adjustclip(widget); + return 0; +} + +int GCsetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + setgattr(widget, ap); + WCU->defgattr = WCU->gattr; + return 0; +} + +int GCgetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + if ((ap->flags & G_GATTRCOLOR)) + ap->color = WCU->gattr.color; + if ((ap->flags & G_GATTRWIDTH)) + ap->width = WCU->gattr.width; + if ((ap->flags & G_GATTRMODE)) + ap->mode = WCU->gattr.mode; + if ((ap->flags & G_GATTRFILL)) + ap->fill = WCU->gattr.fill; + if ((ap->flags & G_GATTRSTYLE)) + ap->style = WCU->gattr.style; + return 0; +} + +int GCarrow(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2, pa, pb, pd; + Grect_t gr; + double tangent, l; + + if (gp1.x < gp2.x) + gr.o.x = gp1.x, gr.c.x = gp2.x; + else + gr.o.x = gp2.x, gr.c.x = gp1.x; + if (gp1.y < gp2.y) + gr.o.y = gp1.y, gr.c.y = gp2.y; + else + gr.o.y = gp2.y, gr.c.y = gp1.y; + if (!ISVISIBLE(gr)) + return 1; + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y; + if (pd.x == 0 && pd.y == 0) + return 0; + tangent = atan2((double) pd.y, (double) pd.x); + if ((l = sqrt((double) (pd.x * pd.x + pd.y * pd.y))) > 30) + l = 30; + pa.x = l * cos(tangent + M_PI / 7) + pp2.x; + pa.y = l * sin(tangent + M_PI / 7) + pp2.y; + pb.x = l * cos(tangent - M_PI / 7) + pp2.x; + pb.y = l * sin(tangent - M_PI / 7) + pp2.y; + setgattr(widget, ap); + XDrawLine(Gdisplay, WINDOW, GC, pp1.x, pp1.y, pp2.x, pp2.y); + XDrawLine(Gdisplay, WINDOW, GC, pa.x, pa.y, pp2.x, pp2.y); + XDrawLine(Gdisplay, WINDOW, GC, pb.x, pb.y, pp2.x, pp2.y); + return 0; +} + +int GCline(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2; + Grect_t gr; + + if (gp1.x < gp2.x) + gr.o.x = gp1.x, gr.c.x = gp2.x; + else + gr.o.x = gp2.x, gr.c.x = gp1.x; + if (gp1.y < gp2.y) + gr.o.y = gp1.y, gr.c.y = gp2.y; + else + gr.o.y = gp2.y, gr.c.y = gp1.y; + if (!ISVISIBLE(gr)) + return 1; + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + setgattr(widget, ap); + XDrawLine(Gdisplay, WINDOW, GC, pp1.x, pp1.y, pp2.x, pp2.y); + return 0; +} + +int GCbox(Gwidget_t * widget, Grect_t gr, Ggattr_t * ap) +{ + PIXrect_t pr; + Gxy_t p; + + if (gr.o.x > gr.c.x) + p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x; + if (gr.o.y > gr.c.y) + p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y; + if (!ISVISIBLE(gr)) + return 1; + pr = rdrawtopix(widget, gr); + setgattr(widget, ap); + if (WCU->gattr.fill) + XFillRectangle(Gdisplay, WINDOW, GC, + pr.o.x, pr.o.y, pr.c.x - pr.o.x, pr.c.y - pr.o.y); + else + XDrawRectangle(Gdisplay, WINDOW, GC, + pr.o.x, pr.o.y, pr.c.x - pr.o.x, pr.c.y - pr.o.y); + return 0; +} + +int GCpolygon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + Grect_t gr; + int n, i; + + if (gpn == 0) + return 0; + gr.o = gpp[0], gr.c = gpp[0]; + for (i = 1; i < gpn; i++) { + gr.o.x = min(gr.o.x, gpp[i].x); + gr.o.y = min(gr.o.y, gpp[i].y); + gr.c.x = max(gr.c.x, gpp[i].x); + gr.c.y = max(gr.c.y, gpp[i].y); + } + if (!ISVISIBLE(gr)) + return 1; + if (gpn + 1 > Gppn) { + n = (((gpn + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + for (i = 0; i < gpn; i++) + Gppp[i] = pdrawtopix(widget, gpp[i]); + setgattr(widget, ap); + if (WCU->gattr.fill) { + if (Gppp[gpn - 1].x != Gppp[0].x || Gppp[gpn - 1].y != Gppp[0].y) + Gppp[gpn] = Gppp[0], gpn++; + XFillPolygon(Gdisplay, WINDOW, GC, Gppp, gpn, + Complex, CoordModeOrigin); + } else + XDrawLines(Gdisplay, WINDOW, GC, Gppp, gpn, CoordModeOrigin); + return 0; +} + +int GCsplinegon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + PIXpoint_t p0, p1, p2, p3; + Grect_t gr; + int n, i; + + if (gpn == 0) + return 0; + gr.o = gpp[0], gr.c = gpp[0]; + for (i = 1; i < gpn; i++) { + gr.o.x = min(gr.o.x, gpp[i].x); + gr.o.y = min(gr.o.y, gpp[i].y); + gr.c.x = max(gr.c.x, gpp[i].x); + gr.c.y = max(gr.c.y, gpp[i].y); + } + if (!ISVISIBLE(gr)) + return 1; + Gppi = 1; + if (Gppi >= Gppn) { + n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + Gppp[0] = p3 = pdrawtopix(widget, gpp[0]); + for (i = 1; i < gpn; i += 3) { + p0 = p3; + p1 = pdrawtopix(widget, gpp[i]); + p2 = pdrawtopix(widget, gpp[i + 1]); + p3 = pdrawtopix(widget, gpp[i + 2]); + bezier(p0, p1, p2, p3); + } + setgattr(widget, ap); + if (WCU->gattr.fill) { + if (Gppp[Gppi - 1].x != Gppp[0].x || Gppp[Gppi - 1].y != Gppp[0].y) + Gppp[Gppi] = Gppp[0], Gppi++; + XFillPolygon(Gdisplay, WINDOW, GC, Gppp, Gppi, + Complex, CoordModeOrigin); + } else + XDrawLines(Gdisplay, WINDOW, GC, Gppp, Gppi, CoordModeOrigin); + return 0; +} + +static void bezier(PIXpoint_t p0, PIXpoint_t p1, + PIXpoint_t p2, PIXpoint_t p3) +{ + Gpoint_t gp0, gp1, gp2; + Gsize_t s; + PIXpoint_t p; + double t; + int n, i, steps; + + if ((s.x = p3.x - p0.x) < 0) + s.x = -s.x; + if ((s.y = p3.y - p0.y) < 0) + s.y = -s.y; + if (s.x > s.y) + steps = s.x / 5 + 1; + else + steps = s.y / 5 + 1; + for (i = 0; i <= steps; i++) { + t = i / (double) steps; + gp0.x = p0.x + t * (p1.x - p0.x); + gp0.y = p0.y + t * (p1.y - p0.y); + gp1.x = p1.x + t * (p2.x - p1.x); + gp1.y = p1.y + t * (p2.y - p1.y); + gp2.x = p2.x + t * (p3.x - p2.x); + gp2.y = p2.y + t * (p3.y - p2.y); + gp0.x = gp0.x + t * (gp1.x - gp0.x); + gp0.y = gp0.y + t * (gp1.y - gp0.y); + gp1.x = gp1.x + t * (gp2.x - gp1.x); + gp1.y = gp1.y + t * (gp2.y - gp1.y); + p.x = gp0.x + t * (gp1.x - gp0.x) + 0.5; + p.y = gp0.y + t * (gp1.y - gp0.y) + 0.5; + if (Gppi >= Gppn) { + n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR; + Gppp = Marraygrow(Gppp, (long) n * PPSIZE); + Gppn = n; + } + Gppp[Gppi++] = p; + } +} + +int GCarc(Gwidget_t * widget, Gpoint_t gc, Gsize_t gs, double ang1, + double ang2, Ggattr_t * ap) +{ + PIXpoint_t pc; + PIXsize_t ps; + Grect_t gr; + + gr.o.x = gc.x - gs.x, gr.o.y = gc.y - gs.y; + gr.c.x = gc.x + gs.x, gr.c.y = gc.y + gs.y; + if (!ISVISIBLE(gr)) + return 1; + pc = pdrawtopix(widget, gc), ps = sdrawtopix(widget, gs); + setgattr(widget, ap); + if (WCU->gattr.fill) + XFillArc(Gdisplay, WINDOW, GC, pc.x - ps.x, pc.y - ps.y, + ps.x * 2, ps.y * 2, (int) (ang1 * 64), (int) (ang2 * 64)); + else + XDrawArc(Gdisplay, WINDOW, GC, pc.x - ps.x, pc.y - ps.y, + ps.x * 2, ps.y * 2, (int) (ang1 * 64), (int) (ang2 * 64)); + return 0; +} + +int GCtext(Gwidget_t * widget, Gtextline_t * tlp, int n, Gpoint_t go, + char *fn, double fs, char *justs, Ggattr_t * ap) +{ + Gsize_t gs; + PIXpoint_t po; + PIXsize_t ps; + PIXrect_t pr; + Grect_t gr; + XFontStruct *font; + int dir, asc, des, x = 0, y, w, h, i; + XCharStruct txtinfo; + + po = pdrawtopix(widget, go); + gs.x = 0, gs.y = fs; + ps = sdrawtopix(widget, gs); + if (!(font = findfont(fn, ps.y))) { + XDrawRectangle(Gdisplay, WINDOW, GC, po.x, po.y, 1, 1); + return 0; + } + setgattr(widget, ap); + SETFONT(font); + for (w = h = 0, i = 0; i < n; i++) { + if (IS8BIT(font)) + XTextExtents(font, tlp[i].p, tlp[i].n, &dir, &asc, &des, + &txtinfo); + else + XTextExtents16(font, (XChar2b *) tlp[i].p, tlp[i].n / 2, + &dir, &asc, &des, &txtinfo); + tlp[i].w = txtinfo.width, tlp[i].h = asc + des; + w = max(w, txtinfo.width), h += asc + des; + } + switch (justs[0]) { + case 'l': + po.x += w / 2; + break; + case 'r': + po.x -= w / 2; + break; + } + switch (justs[1]) { + case 'd': + po.y -= h; + break; + case 'c': + po.y -= h / 2; + break; + } + pr.o.x = po.x - w / 2, pr.o.y = po.y; + pr.c.x = po.x + w / 2, pr.c.y = po.y + h; + gr = rpixtodraw(widget, pr); + if (!ISVISIBLE(gr)) + return 1; + for (i = 0; i < n; i++) { + switch (tlp[i].j) { + case 'l': + x = po.x - w / 2; + break; + case 'n': + x = po.x - tlp[i].w / 2; + break; + case 'r': + x = po.x - (tlp[i].w - w / 2); + break; + } + y = po.y + (i + 1) * tlp[i].h - des; + if (IS8BIT(font)) + XDrawString(Gdisplay, WINDOW, GC, x, y, tlp[i].p, tlp[i].n); + else + XDrawString16(Gdisplay, WINDOW, GC, x, y, + (XChar2b *) tlp[i].p, tlp[i].n / 2); + } + return 0; +} + +int GCgettextsize(Gwidget_t * widget, Gtextline_t * tlp, int n, char *fn, + double fs, Gsize_t * gsp) +{ + Gsize_t gs; + PIXsize_t ps; + XFontStruct *font; + int i, dir, asc, des; + XCharStruct txtinfo; + + gs.x = 0, gs.y = fs; + ps = sdrawtopix(widget, gs); + if (!(font = findfont(fn, ps.y))) { + gsp->x = 1, gsp->y = 1; + return 0; + } + SETFONT(font); + for (ps.x = ps.y = 0, i = 0; i < n; i++) { + if (IS8BIT(font)) + XTextExtents(font, tlp[i].p, tlp[i].n, &dir, &asc, &des, + &txtinfo); + else + XTextExtents16(font, (XChar2b *) tlp[i].p, tlp[i].n / 2, + &dir, &asc, &des, &txtinfo); + ps.x = max(ps.x, txtinfo.width), ps.y += asc + des; + } + *gsp = spixtodraw(widget, ps); + return 0; +} + +static XFontStruct *findfont(char *name, int size) +{ + XFontStruct *font; + int fi, n, i; + + if (name[0] == '\000') + return Gfontp[0].font; + + sprintf(&Gbufp[0], name, size); + for (fi = 0; fi < Gfontn; fi++) + if (Strcmp(&Gbufp[0], Gfontp[fi].name) == 0) + return Gfontp[fi].font; + if (!(font = XLoadQueryFont(Gdisplay, &Gbufp[0]))) { + n = strlen(&Gbufp[0]) + 1; + for (i = 1; i < size; i++) { + sprintf(&Gbufp[n], name, size - i); + if ((font = XLoadQueryFont(Gdisplay, &Gbufp[n]))) + break; + sprintf(&Gbufp[n], name, size + i); + if ((font = XLoadQueryFont(Gdisplay, &Gbufp[n]))) + break; + } + } + if (!font) + font = Gfontp[0].font; + + Gfontp = Marraygrow(Gfontp, (long) (Gfontn + 1) * FONTSIZE); + Gfontp[Gfontn].name = strdup(&Gbufp[0]); + Gfontp[Gfontn].font = font; + Gfontn++; + return font; +} + +int GCcreatebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, Gsize_t s) +{ + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + if (! + (bitmap->u.bmap.orig = + XCreatePixmap(Gdisplay, XtWindow(widget->w), (int) s.x, (int) s.y, + Gdepth))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bitmap->u.bmap.scaled = 0; + bitmap->scale.x = bitmap->scale.y = 1; + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + return 0; +} + +int GCdestroybitmap(Gbitmap_t * bitmap) +{ + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + XFreePixmap(Gdisplay, bitmap->u.bmap.orig); + if (bitmap->u.bmap.scaled) + XFreePixmap(Gdisplay, bitmap->u.bmap.scaled); + return 0; +} + +#define COMPDIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a)) +#define CDIFF(a, b) (COMPDIFF (a.red, b[0]) + COMPDIFF (a.green, b[1]) + \ + COMPDIFF (a.blue, b[2])) +#define CMINMAXDIFF 20000 + +int GCreadbitmap(Gwidget_t * widget, Gbitmap_t * bitmap, FILE * fp) +{ + Gsize_t s = { 0, 0 }; + XImage *img; + XColor colors[G_MAXCOLORS]; + char bufp[2048]; + int rgb[3]; + char *s1, *s2; + char c; + int cmaxdiff, colori, colorn, bufn, bufi, step, x, y, k; + + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + step = 0; + while (step < 3) { + l1: + if (!fgets(bufp, 2048, fp)) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + s1 = &bufp[0]; + l2: + for (; *s1 && isspace(*s1); s1++); + if (!*s1 || *s1 == '#') + goto l1; + switch (step) { + case 0: + if (strncmp(s1, "P6", 2) != 0) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + step++, s1 += 2; + goto l2; + case 1: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.x = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + case 2: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.y = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + } + } + if (! + (bitmap->u.bmap.orig = + XCreatePixmap(Gdisplay, XtWindow(widget->w), (int) s.x, (int) s.y, + Gdepth))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bitmap->u.bmap.scaled = 0; + bitmap->scale.x = bitmap->scale.y = 1; + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + if ((img = XCreateImage(Gdisplay, DefaultVisual(Gdisplay, Gscreenn), + Gdepth, ZPixmap, 0, NULL, (int) s.x, (int) s.y, + 32, 0)) == NULL) { + XFreePixmap(Gdisplay, bitmap->u.bmap.orig); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + if ((img->data = malloc(img->bytes_per_line * img->height)) == NULL) { + XFreePixmap(Gdisplay, bitmap->u.bmap.orig); + XDestroyImage(img); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + colorn = 0; + for (colori = 0; colori < G_MAXCOLORS; colori++) { + if (widget->u.c->colors[colori].inuse) { + colors[colorn] = widget->u.c->colors[colori].color; + colorn++; + } + } + bufi = bufn = 0; + bufp[bufi] = 0; + for (y = 0; y < s.y; y++) { + for (x = 0; x < s.x; x++) { + for (k = 0; k < 3; k++) { + if (bufi == bufn) { + if ((bufn = fread(bufp, 1, 2047, fp)) == 0) { + XFreePixmap(Gdisplay, bitmap->u.bmap.orig); + XDestroyImage(img); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bufi = 0; + } + rgb[k] = 257 * (unsigned char) bufp[bufi++]; + } + cmaxdiff = CMINMAXDIFF; + l3: + for (colori = 0; colori < colorn; colori++) + if (CDIFF(colors[colori], rgb) < cmaxdiff) + break; + if (colori == colorn && colorn < G_MAXCOLORS && + cmaxdiff == CMINMAXDIFF) { + colors[colorn].red = rgb[0]; + colors[colorn].green = rgb[1]; + colors[colorn].blue = rgb[2]; + if (XAllocColor + (Gdisplay, widget->u.c->cmap, &colors[colorn])) + colorn++; + } + if (colori == colorn) { + cmaxdiff *= 10; + goto l3; + } + XPutPixel(img, x, y, colors[colori].pixel); + } + } + for (colori = 0; colori < G_MAXCOLORS && colori < colorn; colori++) { + if (!widget->u.c->colors[colori].inuse) { + widget->u.c->colors[colori].color = colors[colori]; + widget->u.c->colors[colori].inuse = TRUE; + } + } + XPutImage(Gdisplay, bitmap->u.bmap.orig, widget->u.c->gc, img, + 0, 0, 0, 0, (int) s.x, (int) s.y); + XDestroyImage(img); + return 0; +} + +int GCwritebitmap(Gbitmap_t * bitmap, FILE * fp) +{ + Gwidget_t *widget; + XImage *img; + XColor colors[G_MAXCOLORS]; + char bufp[2048]; + int colori, bufi, x, y, w, h; + + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + if (bitmap->canvas < 0 || bitmap->canvas >= Gwidgetn || + !Gwidgets[bitmap->canvas].inuse) { + Gerr(POS, G_ERRBADWIDGETID, bitmap->canvas); + return -1; + } + widget = &Gwidgets[bitmap->canvas]; + if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) { + Gerr(POS, G_ERRNOTACANVAS, bitmap->canvas); + return -1; + } + for (colori = 0; colori < G_MAXCOLORS; colori++) + colors[colori].pixel = colori; + XQueryColors(Gdisplay, widget->u.c->cmap, &colors[0], G_MAXCOLORS); + if (!(img = XGetImage(Gdisplay, bitmap->u.bmap.orig, 0, 0, + bitmap->size.x, bitmap->size.y, AllPlanes, + ZPixmap))) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + fprintf(fp, "P6\n%d %d 255\n", (int) bitmap->size.x, + (int) bitmap->size.y); + bufi = 0; + w = bitmap->size.x; + h = bitmap->size.y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + colori = XGetPixel(img, x, y); + bufp[bufi++] = colors[colori].red / 257; + bufp[bufi++] = colors[colori].green / 257; + bufp[bufi++] = colors[colori].blue / 257; + if (bufi + 3 >= 2048) { + fwrite(bufp, 1, bufi, fp); + bufi = 0; + } + } + } + if (bufi > 0) + fwrite(bufp, 1, bufi, fp); + XDestroyImage(img); + return 0; +} + +int GCbitblt(Gwidget_t * widget, Gpoint_t gp, Grect_t gr, + Gbitmap_t * bitmap, char *mode, Ggattr_t * ap) +{ + PIXrect_t pr; + PIXpoint_t pp; + Gsize_t scale; + Gxy_t p; + Pixmap pix; + double tvx, tvy, twx, twy; + + if (gr.o.x > gr.c.x) + p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x; + if (gr.o.y > gr.c.y) + p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y; + if (strcmp(mode, "b2c") == 0) { + if (!ISVISIBLE(gr)) + return 1; + tvx = WCU->vsize.x, tvy = WCU->vsize.y; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + scale.x = tvx / twx, scale.y = tvy / twy; + if (scale.x >= 1.0 - 1E-4 && scale.x <= 1.0 + 1E-4 && + scale.y >= 1.0 - 1E-4 && scale.y <= 1.0 + 1E-4) { + pix = bitmap->u.bmap.orig; + bitmap->scale = scale; + } else { + if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y) + scalebitmap(widget, bitmap, scale, TRUE, 1); + pix = bitmap->u.bmap.scaled; + } + pr = rdrawtopix(widget, gr); + pp = pdrawtobpix(bitmap, gp); + setgattr(widget, ap); + XCopyArea(Gdisplay, pix, WINDOW, GC, pp.x, pp.y - pr.c.y + pr.o.y, + pr.c.x - pr.o.x + 1, pr.c.y - pr.o.y + 1, pr.o.x, + pr.o.y); + } else if (strcmp(mode, "c2b") == 0) { + tvx = WCU->vsize.x, tvy = WCU->vsize.y; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + scale.x = tvx / twx, scale.y = tvy / twy; + if (scale.x >= 1.0 - 1E-4 && scale.x <= 1.0 + 1E-4 && + scale.y >= 1.0 - 1E-4 && scale.y <= 1.0 + 1E-4) { + pix = bitmap->u.bmap.orig; + bitmap->scale = scale; + } else { + if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y) + scalebitmap(widget, bitmap, scale, FALSE, 1); + pix = bitmap->u.bmap.scaled; + } + pr = rdrawtobpix(bitmap, gr); + pp = pdrawtopix(widget, gp); + setgattr(widget, ap); + XCopyArea(Gdisplay, WINDOW, pix, GC, pp.x, pp.y - pr.c.y + pr.o.y, + pr.c.x - pr.o.x + 1, pr.c.y - pr.o.y + 1, pr.o.x, + pr.o.y); + if (pix != bitmap->u.bmap.orig) + scalebitmap(widget, bitmap, scale, TRUE, -1); + } + return 0; +} + +static int scalebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, + Gsize_t scale, int copybits, int dir) +{ + Gsize_t nsize, o2n; + Pixmap spix; + XImage *oimg, *simg; + XColor colors[G_MAXCOLORS]; + int cmaxdiff, colorn, colori, x, y, x2, y2 = 0, xp, yp; + double prod, rgb[3], xr2, yr2 = 0, xl2, yl2 = + 0, xf2, yf2, xr, yr, xl, yl; + + if (!copybits) { + if (dir == 1) { + nsize.x = (int) (bitmap->size.x * scale.x); + nsize.y = (int) (bitmap->size.y * scale.y); + if (!(spix = XCreatePixmap(Gdisplay, XtWindow(widget->w), + (int) nsize.x, (int) nsize.y, + Gdepth))) { + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + if (bitmap->u.bmap.scaled) + XFreePixmap(Gdisplay, bitmap->u.bmap.scaled); + bitmap->u.bmap.scaled = spix; + bitmap->scale = scale; + } + return 0; + } + for (colori = 0; colori < G_MAXCOLORS; colori++) + colors[colori].pixel = colori; + colorn = G_MAXCOLORS; + XQueryColors(Gdisplay, widget->u.c->cmap, &colors[0], G_MAXCOLORS); + if (dir == 1) { + nsize.x = (int) (bitmap->size.x * scale.x); + nsize.y = (int) (bitmap->size.y * scale.y); + o2n.x = 1 / scale.x, o2n.y = 1 / scale.y; + if (!(oimg = XGetImage(Gdisplay, bitmap->u.bmap.orig, 0, 0, + (int) bitmap->size.x, (int) bitmap->size.y, + AllPlanes, ZPixmap))) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + if (!(spix = XCreatePixmap(Gdisplay, XtWindow(widget->w), + (int) nsize.x, (int) nsize.y, + Gdepth))) { + XDestroyImage(oimg); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + } else { + nsize.x = (int) bitmap->size.x; + nsize.y = (int) bitmap->size.y; + o2n.x = scale.x, o2n.y = scale.y; + if (!(oimg = XGetImage(Gdisplay, bitmap->u.bmap.scaled, 0, 0, + (int) (bitmap->size.x * scale.x), + (int) (bitmap->size.y * scale.y), AllPlanes, + ZPixmap))) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + spix = bitmap->u.bmap.orig; + } + prod = o2n.x * o2n.y; + if (!(simg = XCreateImage(Gdisplay, DefaultVisual(Gdisplay, Gscreenn), + Gdepth, ZPixmap, 0, NULL, (int) nsize.x, + (int) nsize.y, 32, 0))) { + XFreePixmap(Gdisplay, spix); + XDestroyImage(oimg); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + if ((simg->data = malloc(simg->bytes_per_line * simg->height)) == NULL) { + XFreePixmap(Gdisplay, spix); + XDestroyImage(oimg); + XDestroyImage(simg); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + y = 0; + yr = o2n.y; + yl = 0; + for (yp = 0; yp < nsize.y; yp++) { + x = 0; + xr = o2n.x; + xl = 0; + for (xp = 0; xp < nsize.x; xp++) { + y2 = y; + yr2 = yr; + yl2 = yl; + rgb[0] = rgb[1] = rgb[2] = 0; + do { + x2 = x; + xr2 = xr; + xl2 = xl; + yf2 = (yl2 + yr2 > 1) ? 1 - yl2 : yr2, yr2 -= yf2; + do { + xf2 = (xl2 + xr2 > 1) ? 1 - xl2 : xr2, xr2 -= xf2; + colori = XGetPixel(oimg, x2, y2); + rgb[0] += (colors[colori].red * xf2 * yf2 / prod); + rgb[1] += (colors[colori].green * xf2 * yf2 / prod); + rgb[2] += (colors[colori].blue * xf2 * yf2 / prod); + xl2 += xf2; + if (xl2 >= 1) + x2++, xl2 -= 1; + } while (xr2 > 0); + xr2 = o2n.x; + yl2 += yf2; + if (yl2 >= 1) + y2++, yl2 -= 1; + } while (yr2 > 0); + yr2 = o2n.y; + cmaxdiff = CMINMAXDIFF; + l4: + for (colori = 0; colori < colorn; colori++) + if (CDIFF(colors[colori], rgb) < cmaxdiff) + break; + if (colori == colorn) { + cmaxdiff *= 10; + goto l4; + } + XPutPixel(simg, xp, yp, colors[colori].pixel); + x = x2; + xr = xr2; + xl = xl2; + } + y = y2; + yr = yr2; + yl = yl2; + } + XPutImage(Gdisplay, spix, widget->u.c->gc, simg, 0, 0, 0, 0, + (int) nsize.x, (int) nsize.y); + XDestroyImage(simg); + XDestroyImage(oimg); + if (dir == 1) { + if (bitmap->u.bmap.scaled) + XFreePixmap(Gdisplay, bitmap->u.bmap.scaled); + bitmap->u.bmap.scaled = spix; + bitmap->scale = scale; + } + return 0; +} + +int GCgetmousecoords(Gwidget_t * widget, Gpoint_t * gpp, int *count) +{ + PIXpoint_t pp; + Window rwin, cwin; + int rx, ry, x, y; + unsigned int mask; + + XQueryPointer(Gdisplay, WINDOW, &rwin, &cwin, &rx, &ry, &x, &y, &mask); + pp.x = x, pp.y = y; + *gpp = Gppixtodraw(widget, pp); + *count = + ((mask & Button1Mask) ? 1 : 0) + ((mask & Button2Mask) ? 1 : 0) + + ((mask & Button3Mask) ? 1 : 0); + return 0; +} + +void Gcwbutaction(Widget w, XEvent * evp, char **app, unsigned int *anp) +{ + Gwidget_t *widget; + Gevent_t gev; + PIXpoint_t pp; + int wi, xtype, bn; + + widget = findwidget((unsigned long) w, G_CANVASWIDGET); + switch ((xtype = evp->type)) { + case ButtonPress: + case ButtonRelease: + gev.type = G_MOUSE; + gev.code = (xtype == ButtonPress) ? G_DOWN : G_UP; + gev.data = evp->xbutton.button - Button1; + if (gev.data > 2) + return; + pp.x = evp->xbutton.x, pp.y = evp->xbutton.y; + gev.p = Gppixtodraw(widget, pp); + bn = WCU->bstate[gev.data]; + WCU->bstate[gev.data] = (xtype == ButtonPress) ? 1 : 0; + bn = WCU->bstate[gev.data] - bn; + WCU->buttonsdown += bn; + Gbuttonsdown += bn; + break; + default: + return; + } + wi = gev.wi = widget - &Gwidgets[0]; + Gpopdownflag = FALSE; + if (WCU->func) + (*WCU->func) (&gev); + if (Gpopdownflag) { + Gpopdownflag = FALSE; + if (gev.code == G_DOWN) { + gev.code = G_UP; + widget = &Gwidgets[wi]; + WCU->bstate[gev.data] = 0; + WCU->buttonsdown--; + Gbuttonsdown--; + if (widget->inuse && WCU->func) + (*WCU->func) (&gev); + } + } +} + +void Gcwkeyaction(Widget w, XEvent * evp, char **app, unsigned int *anp) +{ + Gwidget_t *widget; + Gevent_t gev; + PIXpoint_t pp; + Window rwin, cwin; + int xtype, rx, ry, x, y; + unsigned int mask; + char c; + + widget = findwidget((unsigned long) w, G_CANVASWIDGET); + switch ((xtype = evp->type)) { + case KeyPress: + case KeyRelease: + if (!XLookupString((XKeyEvent *) evp, &c, 1, NULL, NULL)) + return; + XQueryPointer(Gdisplay, WCU->window, &rwin, &cwin, + &rx, &ry, &x, &y, &mask); + gev.type = G_KEYBD; + gev.code = (xtype == KeyPress) ? G_DOWN : G_UP; + gev.data = c; + pp.x = x, pp.y = y; + gev.p = Gppixtodraw(widget, pp); + break; + default: + return; + } + gev.wi = widget - &Gwidgets[0]; + Gpopdownflag = FALSE; + if (WCU->func) + (*WCU->func) (&gev); + if (Gpopdownflag) + Gpopdownflag = FALSE; +} + +static void setgattr(Gwidget_t * widget, Ggattr_t * ap) +{ + XGCValues gcv; + XColor *cp; + int color, width, mode, style, pati; + double intens; + + if (!(ap->flags & G_GATTRCOLOR)) + ap->color = WCU->defgattr.color; + if (!(ap->flags & G_GATTRWIDTH)) + ap->width = WCU->defgattr.width; + if (!(ap->flags & G_GATTRMODE)) + ap->mode = WCU->defgattr.mode; + if (!(ap->flags & G_GATTRFILL)) + ap->fill = WCU->defgattr.fill; + if (!(ap->flags & G_GATTRSTYLE)) + ap->style = WCU->defgattr.style; + color = ap->color; + if (color >= G_MAXCOLORS || !(WCU->colors[color].inuse)) + color = 1; + if (color != WCU->gattr.color) { + WCU->gattr.color = color; + if (ap->mode == G_XOR) + XSetForeground(Gdisplay, GC, + WCU->colors[WCU->gattr.color].color.pixel ^ + WCU->colors[0].color.pixel); + else + XSetForeground(Gdisplay, GC, + WCU->colors[WCU->gattr.color].color.pixel); + if (Gdepth == 1) { + cp = &WCU->colors[color].color; + intens = (0.3 * cp->blue + 0.59 * cp->red + + 0.11 * cp->green) / 65535.0; + pati = (intens <= 0.0625) ? 16 : + -16.0 * (log(intens) / 2.7725887222); + XSetTile(Gdisplay, GC, WCU->grays[pati]); + } + } + mode = ap->mode; + if (mode != WCU->gattr.mode) { + WCU->gattr.mode = mode; + XSetFunction(Gdisplay, GC, WCU->gattr.mode); + if (mode == G_XOR) + XSetForeground(Gdisplay, GC, + WCU->colors[WCU->gattr.color].color.pixel ^ + WCU->colors[0].color.pixel); + else + XSetForeground(Gdisplay, GC, + WCU->colors[WCU->gattr.color].color.pixel); + } + width = ap->width; + if (width != WCU->gattr.width) { + gcv.line_width = WCU->gattr.width = width; + XChangeGC(Gdisplay, GC, GCLineWidth, &gcv); + } + WCU->gattr.fill = ap->fill; + style = ap->style; + if (style != WCU->gattr.style) { + WCU->gattr.style = style; + if (style == G_SOLID) { + gcv.line_style = LineSolid; + XChangeGC(Gdisplay, GC, GCLineStyle, &gcv); + } else { + XSetDashes(Gdisplay, GC, 0, gstyles[style], 2); + gcv.line_style = LineOnOffDash; + XChangeGC(Gdisplay, GC, GCLineStyle, &gcv); + } + } +} + +static PIXrect_t rdrawtopix(Gwidget_t * widget, Grect_t gr) +{ + PIXrect_t pr; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + pr.o.x = tvx * (gr.o.x - WCU->wrect.o.x) / twx + 0.5; + pr.o.y = tvy * (1.0 - (gr.c.y - WCU->wrect.o.y) / twy) + 0.5; + pr.c.x = tvx * (gr.c.x - WCU->wrect.o.x) / twx + 0.5; + pr.c.y = tvy * (1.0 - (gr.o.y - WCU->wrect.o.y) / twy) + 0.5; + return pr; +} + +static PIXpoint_t pdrawtopix(Gwidget_t * widget, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + pp.x = tvx * (gp.x - WCU->wrect.o.x) / twx + 0.5; + pp.y = tvy * (1.0 - (gp.y - WCU->wrect.o.y) / twy) + 0.5; + return pp; +} + +static PIXsize_t sdrawtopix(Gwidget_t * widget, Gsize_t gs) +{ + PIXsize_t ps; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + ps.x = tvx * (gs.x - 1) / twx + 1.5; + ps.y = tvy * (gs.y - 1) / twy + 1.5; + return ps; +} + +static Gpoint_t Gppixtodraw(Gwidget_t * widget, PIXpoint_t pp) +{ + Gpoint_t gp; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + gp.x = (pp.x / tvx) * twx + WCU->wrect.o.x; + gp.y = (1.0 - pp.y / tvy) * twy + WCU->wrect.o.y; + return gp; +} + +static Gsize_t spixtodraw(Gwidget_t * widget, PIXsize_t ps) +{ + Gsize_t gs; + double tvx, tvy, twx, twy; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + gs.x = ((ps.x - 1) / tvx) * twx + 1; + gs.y = ((ps.y - 1) / tvy) * twy + 1; + return gs; +} + +static Grect_t rpixtodraw(Gwidget_t * widget, PIXrect_t pr) +{ + Grect_t gr; + double tvx, tvy, twx, twy, n; + + tvx = WCU->vsize.x - 1, tvy = WCU->vsize.y - 1; + twx = WCU->wrect.c.x - WCU->wrect.o.x; + twy = WCU->wrect.c.y - WCU->wrect.o.y; + gr.o.x = (pr.o.x / tvx) * twx + WCU->wrect.o.x; + gr.o.y = (1.0 - pr.c.y / tvy) * twy + WCU->wrect.o.y; + gr.c.x = (pr.c.x / tvx) * twx + WCU->wrect.o.x; + gr.c.y = (1.0 - pr.o.y / tvy) * twy + WCU->wrect.o.y; + if (gr.o.x > gr.c.x) + n = gr.o.x, gr.o.x = gr.c.x, gr.c.x = n; + if (gr.o.y > gr.c.y) + n = gr.o.y, gr.o.y = gr.c.y, gr.c.y = n; + return gr; +} + +static PIXrect_t rdrawtobpix(Gbitmap_t * bitmap, Grect_t gr) +{ + PIXrect_t pr; + double tvy; + + tvy = (bitmap->size.y - 1) * bitmap->scale.y; + pr.o.x = gr.o.x + 0.5; + pr.o.y = tvy - gr.c.y + 0.5; + pr.c.x = gr.c.x + 0.5; + pr.c.y = tvy - gr.o.y + 0.5; + return pr; +} + +static PIXpoint_t pdrawtobpix(Gbitmap_t * bitmap, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvy; + + tvy = (bitmap->size.y - 1) * bitmap->scale.y; + pp.x = gp.x + 0.5; + pp.y = tvy - gp.y + 0.5; + return pp; +} + +static void adjustclip(Gwidget_t * widget) +{ + Gwidget_t *parent; + Dimension width, height, pwidth, pheight; + Position x, y; + PIXrect_t pr; + + parent = &Gwidgets[widget->pwi]; + RESETARGS; + ADD2ARGS(XtNx, &x); + ADD2ARGS(XtNy, &y); + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + RESETARGS; + ADD2ARGS(XtNwidth, &pwidth); + ADD2ARGS(XtNheight, &pheight); + XtGetValues(parent->w, argp, argn); + pr.o.x = max(0, -x); + pr.o.y = max(0, -y); + pr.c.x = min(width, pr.o.x + pwidth); + pr.c.y = min(height, pr.o.y + pheight); + pr.c.x = max(pr.o.x, pr.c.x); + pr.c.y = max(pr.o.y, pr.c.y); + WCU->clip = rpixtodraw(widget, pr); +#ifdef FEATURE_GMAP + if (WCU->gmapmode) { + GMAPwinsetsize(XtWindow(widget->w), width, height); + GMAPchansetaspect(XtWindow(widget->w), width, height); + } +#endif +} + +static Bool cwepredicate(Display * display, XEvent * evp, XPointer data) +{ + if (evp->type == Expose + && ((XAnyEvent *) evp)->window == (Window) data) + return True; + return False; +} + +static void cweventhandler(Widget w, XtPointer data, XEvent * evp, + Boolean * cont) +{ + Gwidget_t *widget; + + widget = findwidget((unsigned long) w, G_CANVASWIDGET); + Gneedredraw = WCU->needredraw = TRUE; + adjustclip(widget); +#ifdef FEATURE_GMAP + if (WCU->gmapmode) + GMAPneedupdate = TRUE; +#endif +} + +static Bool cwvpredicate(Display * display, XEvent * evp, XPointer data) +{ + if (evp->type == VisibilityNotify && + ((XAnyEvent *) evp)->window == (Window) data) + return True; + return False; +} diff --git a/cmd/lefty/ws/x11/gcommon.c b/cmd/lefty/ws/x11/gcommon.c new file mode 100644 index 000000000..952d489c3 --- /dev/null +++ b/cmd/lefty/ws/x11/gcommon.c @@ -0,0 +1,319 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +int Gxfd; +Widget Groot; +Display *Gdisplay; +int Gpopdownflag; +int Gscreenn; +int Gdepth; +Glazyq_t Glazyq; + +PIXpoint_t *Gppp; +int Gppn, Gppi; + +char *Gbufp = NULL; +int Gbufn = 0, Gbufi = 0; + +Gfont_t *Gfontp; +int Gfontn; + +/* Xt[GS]etValues arguments */ +Arg argp[MAXARGS]; +int argn; + +/* action and translation tables */ +static XtActionsRec actiontable[] = { + {"cwbut", Gcwbutaction}, + {"cwkey", Gcwkeyaction}, + {"lwbut", Glwbutaction}, + {"lwkey", Glwkeyaction}, + {"tweol", Gtweolaction}, + {"qwpop", Gqwpopaction}, + {"wmdel", Gwmdelaction}, +}; +static char defcwanytrans[] = "\ + <BtnDown>: cwbut()\n\ + <BtnUp>: cwbut()\n\ + <KeyDown>: cwkey()\n\ + <KeyUp>: cwkey()"; +static char deflwanytrans[] = "\ + <BtnDown>: lwbut()\n\ + <BtnUp>: lwbut()\n\ + <KeyDown>: lwkey()\n\ + <KeyUp>: lwkey()"; +static char deftweoltrans[] = + "<Key>Return: newline()\n<KeyUp>Return: tweol()"; +static char defqwpoptrans[] = "<KeyDown>Return:\n<KeyUp>Return: qwpop()"; +static char defwmdeltrans[] = "<Message>WM_PROTOCOLS: wmdel()\n"; +XtTranslations Gtweoltable; +XtTranslations Gqwpoptable; +XtTranslations Glwanytable; +XtTranslations Gcwanytable; +XtTranslations Gwmdeltable; + +Atom Gwmdelatom; + +static XtAppContext appcontext; +static XFontStruct *deffont; + +#ifdef FEATURE_NEXTAW +static char *props[] = { + "*Font: -*-lucidatypewriter-*-r-*-*-*-120-*-*-*-*-iso8859-1", + "*ShapeStyle: Rectangle", + "*Command.ShapeStyle: Rectangle", + "*Toggle.ShapeStyle: Rectangle", + "*ShadowWidth: 2", + "*Form*Text*Background: white", + "*Form*Text*Scrollbar*Background: gray", + "*Text*Background: white", + "*Text*Foreground: black", + "*Text*ThreeD*Background: gray", + "*Text*Scrollbar*Background: gray", + "*Viewport.background: gray", + "*BeNiceToColormap: 0", + "*Toggle.Font: -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*Command.Font: -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*Command.Background: gray", + "*Command.highlightThickness: 0", + "*Toggle.highlightThickness: 0", + "*Toggle.Background: gray", + "*MenuButton.Background: gray", + "*SimpleMenu.Background: gray", + "*List*Background: gray", + "*Box.Background: gray", + "*Label.Background: gray", + "*Label.ShadowWidth: 0", + "*Label*shadowWidth: 2", + "*Scrollbar.Background: gray", + "*SimpleMenu*MenuLabel*Background: black", + "*SimpleMenu*MenuLabel*Font: -adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*", + "*SimpleMenu*Font: -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*Dialog.Background: gray", + "*Form*Background: gray", + "*Form*Viewport*Background: white", + "*Form*Viewport*Scrollbar*Background: grey", + "*MenuButton.translations: Any<BtnDown>: PopupMenu()", + NULL +}; +#else +#ifdef FEATURE_XAW3D +static char *props[] = { + "*Font: -*-lucidatypewriter-*-r-*-*-*-120-*-*-*-*-iso8859-1", + "*ShapeStyle: Rectangle", + "*Command.ShapeStyle: Rectangle", + "*Toggle.ShapeStyle: Rectangle", + "*ShadowWidth: 2", + "*Form*Text*Background: white", + "*Form*Text*Scrollbar*Background: gray", + "*Text*Background: white", + "*Text*Foreground: black", + "*Text*ThreeD*Background: gray", + "*Text*Scrollbar*Background: gray", + "*Viewport.background: gray", + "*BeNiceToColormap: 0", + "*Toggle.Font: -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*Command.Font: -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*Command.Background: gray", + "*Command.highlightThickness: 0", + "*Toggle.highlightThickness: 0", + "*Toggle.Background: gray", + "*MenuButton.Background: gray", + "*SimpleMenu.Background: gray", + "*List*Background: gray", + "*Box.Background: gray", + "*Label.Background: gray", + "*Label.ShadowWidth: 0", + "*Label*shadowWidth: 2", + "*Scrollbar.Background: gray", + "*SimpleMenu*MenuLabel*Background: black", + "*SimpleMenu*MenuLabel*Font: -adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*", + "*SimpleMenu*Font: -adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*Dialog.Background: gray", + "*Form*Background: gray", + "*Form*Viewport*Background: white", + "*Form*Viewport*Scrollbar*Background: grey", + "*MenuButton.translations: Any<BtnDown>: PopupMenu()", + NULL +}; +#endif +#endif + +int Ginitgraphics(void) +{ + argn = 0; +#if defined(FEATURE_NEXTAW) || defined(FEATURE_XAW3D) + if (!(Groot = XtAppInitialize(&appcontext, "LEFTY", NULL, 0, + &argn, NULL, props, NULL, 0))) +#else + if (!(Groot = XtAppInitialize(&appcontext, "LEFTY", NULL, 0, + &argn, NULL, NULL, NULL, 0))) +#endif + Gerr(POS, G_ERRINITFAILED); + XtAppAddActions(appcontext, actiontable, XtNumber(actiontable)); + Gtweoltable = XtParseTranslationTable(deftweoltrans); + Gqwpoptable = XtParseTranslationTable(defqwpoptrans); + Glwanytable = XtParseTranslationTable(deflwanytrans); + Gcwanytable = XtParseTranslationTable(defcwanytrans); + Gwmdeltable = XtParseTranslationTable(defwmdeltrans); + XtRegisterGrabAction(Glwbutaction, True, + ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync); + XtRegisterGrabAction(Gcwbutaction, True, + ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync); + Gdisplay = XtDisplay(Groot); + Gscreenn = DefaultScreen(Gdisplay); + Gdepth = DefaultDepth(Gdisplay, Gscreenn); + deffont = XLoadQueryFont(Gdisplay, "fixed"); + Gxfd = ConnectionNumber(Gdisplay); + Gwmdelatom = XInternAtom(Gdisplay, "WM_DELETE_WINDOW", False); + Gpopdownflag = FALSE; + Glazyq.flag = LAZYUNDEF; + Gbufp = Marrayalloc((long) BUFINCR * BUFSIZE); + Gbufn = BUFINCR; + Gppp = Marrayalloc((long) PPINCR * PPSIZE); + Gppn = PPINCR; + Gfontp = Marrayalloc((long) FONTSIZE); + Gfontn = 1; + Gfontp[0].name = strdup("default"); + if (!Gdefaultfont) + Gfontp[0].font = deffont; + else if (Gdefaultfont[0] != '\000') + Gfontp[0].font = XLoadQueryFont(Gdisplay, Gdefaultfont); + else + Gfontp[0].font = NULL; + return 0; +} + +int Gtermgraphics(void) +{ + int fi; + + for (fi = 0; fi < Gfontn; fi++) + free(Gfontp[fi].name); + Marrayfree(Gfontp), Gfontp = NULL, Gfontn = 0; + Marrayfree(Gppp), Gppp = NULL, Gppn = 0; + Marrayfree(Gbufp), Gbufp = NULL, Gbufn = 0; + XtDestroyWidget(Groot); + return 0; +} + +void Gflushlazyq(void) +{ + if (Glazyq.flag & LAZYMANAGE) { + XtManageChildren(Glazyq.mws, Glazyq.mwn); + Glazyq.flag &= ~LAZYMANAGE; + } + if (Glazyq.flag & LAZYREALIZE) { + XtRealizeWidget(Glazyq.rw); + if (Glazyq.flag & LAZYRHINTS) + XSetWMNormalHints(Gdisplay, XtWindow(Glazyq.rw), + &Glazyq.hints); + XSetWMProtocols(Gdisplay, XtWindow(Glazyq.rw), &Gwmdelatom, 1); + XtOverrideTranslations(Glazyq.rw, Gwmdeltable); + Glazyq.flag &= ~LAZYRHINTS; + Glazyq.flag &= ~LAZYREALIZE; + } +} + +void Glazyrealize(Widget w, int hintsflag, XSizeHints * hintsp) +{ + if (Glazyq.flag & LAZYREALIZE) { + XtRealizeWidget(Glazyq.rw); + if (Glazyq.flag & LAZYRHINTS) + XSetWMNormalHints(Gdisplay, XtWindow(Glazyq.rw), + &Glazyq.hints); + XSetWMProtocols(Gdisplay, XtWindow(Glazyq.rw), &Gwmdelatom, 1); + XtOverrideTranslations(Glazyq.rw, Gwmdeltable); + } else + Glazyq.flag |= LAZYREALIZE; + Glazyq.rw = w; + if (hintsflag) { + Glazyq.flag |= LAZYRHINTS; + Glazyq.hints = *hintsp; + } else + Glazyq.flag &= ~LAZYRHINTS; +} + +void Glazymanage(Widget w) +{ + if (Glazyq.flag & LAZYMANAGE) { + if (XtParent(Glazyq.mws[Glazyq.mwn - 1]) != XtParent(w) || + Glazyq.mwn >= LAZYQNUM) { + XtManageChildren(Glazyq.mws, Glazyq.mwn); + Glazyq.mwn = 0; + } + } else { + Glazyq.flag |= LAZYMANAGE; + Glazyq.mwn = 0; + } + Glazyq.mws[Glazyq.mwn++] = w; +} + +int Gsync(void) +{ + if (Glazyq.flag) + Gflushlazyq(); + XFlush(Gdisplay); + return 0; +} + +int Gresetbstate(int wi) +{ + Gcw_t *cw; + int bn; + + cw = Gwidgets[wi].u.c; + bn = cw->bstate[0] + cw->bstate[1] + cw->bstate[2]; + cw->bstate[0] = cw->bstate[1] = cw->bstate[2] = 0; + cw->buttonsdown -= bn; + Gbuttonsdown -= bn; + return 0; +} + +int Gprocessevents(int waitflag, Geventmode_t mode) +{ + int rtn; + + if (Glazyq.flag) + Gflushlazyq(); + rtn = 0; + switch (waitflag) { + case TRUE: + XtAppProcessEvent(appcontext, XtIMAll); + if (mode == G_ONEEVENT) + return 1; + rtn = 1; + /* FALL THROUGH */ + case FALSE: + while (XtAppPending(appcontext)) { + XtAppProcessEvent(appcontext, XtIMAll); + if (mode == G_ONEEVENT) + return 1; + rtn = 1; + } + break; + } + return rtn; +} diff --git a/cmd/lefty/ws/x11/gcommon.h b/cmd/lefty/ws/x11/gcommon.h new file mode 100644 index 000000000..5683b398d --- /dev/null +++ b/cmd/lefty/ws/x11/gcommon.h @@ -0,0 +1,212 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#ifndef _GCOMMON_H +#define _GCOMMON_H +#if XlibSpecificationRelease < 5 + typedef char *XPointer; +#endif + +/* point and rect structures */ + typedef XPoint PIXxy_t; + typedef PIXxy_t PIXpoint_t; + typedef PIXxy_t PIXsize_t; + typedef struct PIXrect_t { + PIXxy_t o, c; + } PIXrect_t; + + extern Widget Groot; + extern Display *Gdisplay; + extern int Gpopdownflag; + extern int Gscreenn; + extern int Gdepth; + + extern Arg argp[]; + extern int argn; +#define MAXARGS 50 +#define RESETARGS (argn = 0) +#define ADD2ARGS(var, val) \ + XtSetArg (argp[argn], (var), (val)), argn++ + +/* structures used to minimize number of calls to + XtManage and XtRealize functions (which are expensive) */ + typedef enum { + LAZYUNDEF = 0, LAZYREALIZE = 1, LAZYRHINTS = 2, LAZYMANAGE = 4 + } Glazyflag_t; +#define LAZYQNUM 100 + typedef struct Glazyq_t { + Glazyflag_t flag; + Widget rw; + XSizeHints hints; + Widget mws[LAZYQNUM]; + int mwn; + } Glazyq_t; + extern Glazyq_t Glazyq; + + typedef struct Gfont_t { + char *name; + XFontStruct *font; + } Gfont_t; + extern Gfont_t *Gfontp; + extern int Gfontn; +#define FONTSIZE sizeof (Gfont_t) +#define SETFONT(font) { \ + XGCValues gcv; \ + if (font != WCU->font) { \ + WCU->font = font, gcv.font = font->fid; \ + XChangeGC (Gdisplay, GC, GCFont, &gcv); \ + } \ +} + + extern char *Gbufp; + extern int Gbufn, Gbufi; +#define BUFINCR 1024 +#define BUFSIZE sizeof (char) + + extern PIXpoint_t *Gppp; + extern int Gppn, Gppi; +#define PPINCR 100 +#define PPSIZE sizeof (PIXpoint_t) + +#define GETSIZE(sin, sout, smin) \ + sout.x = (sin.x > smin) ? sin.x + 0.5 : smin, \ + sout.y = (sin.y > smin) ? sin.y + 0.5 : smin +#define GETORIGIN(oin, oout) \ + oout.x = oin.x + 0.5, oout.y = oin.y + 0.5 + + int Ginitgraphics(void); + int Gtermgraphics(void); + void Gflushlazyq(void); + void Glazyrealize(Widget, int, XSizeHints *); + void Glazymanage(Widget); + int Gsync(void); + + int GAcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GAsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GAgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GAdestroywidget(Gwidget_t *); + + int GBcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GBsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GBgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GBdestroywidget(Gwidget_t *); + + int GCcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GCsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GCgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GCdestroywidget(Gwidget_t *); + int GCcanvasclear(Gwidget_t *); + int GCsetgfxattr(Gwidget_t *, Ggattr_t *); + int GCgetgfxattr(Gwidget_t *, Ggattr_t *); + int GCarrow(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GCline(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GCbox(Gwidget_t *, Grect_t, Ggattr_t *); + int GCpolygon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GCsplinegon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GCarc(Gwidget_t *, Gpoint_t, Gsize_t, double, double, Ggattr_t *); + int GCtext(Gwidget_t *, Gtextline_t *, int, Gpoint_t, + char *, double, char *, Ggattr_t *); + int GCgettextsize(Gwidget_t *, Gtextline_t *, int, char *, double, + Gsize_t *); + int GCcreatebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t); + int GCdestroybitmap(Gbitmap_t *); + int GCreadbitmap(Gwidget_t *, Gbitmap_t *, FILE *); + int GCwritebitmap(Gbitmap_t *, FILE *); + int GCbitblt(Gwidget_t *, Gpoint_t, Grect_t, Gbitmap_t *, char *, + Ggattr_t *); + int GCgetmousecoords(Gwidget_t *, Gpoint_t *, int *); + + int GLcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GLsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GLgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GLdestroywidget(Gwidget_t *); + + int GMcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GMsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GMgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GMdestroywidget(Gwidget_t *); + int GMmenuaddentries(Gwidget_t *, int, char **); + int GMmenudisplay(Gwidget_t *, Gwidget_t *); + + int GPcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GPsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GPgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GPdestroywidget(Gwidget_t *); + int GPcanvasclear(Gwidget_t *); + int GPsetgfxattr(Gwidget_t *, Ggattr_t *); + int GPgetgfxattr(Gwidget_t *, Ggattr_t *); + int GParrow(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GPline(Gwidget_t *, Gpoint_t, Gpoint_t, Ggattr_t *); + int GPbox(Gwidget_t *, Grect_t, Ggattr_t *); + int GPpolygon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GPsplinegon(Gwidget_t *, int, Gpoint_t *, Ggattr_t *); + int GParc(Gwidget_t *, Gpoint_t, Gsize_t, double, double, Ggattr_t *); + int GPtext(Gwidget_t *, Gtextline_t *, int, Gpoint_t, + char *, double, char *, Ggattr_t *); + int GPcreatebitmap(Gwidget_t *, Gbitmap_t *, Gsize_t); + int GPdestroybitmap(Gbitmap_t *); + int GPreadbitmap(Gwidget_t *, Gbitmap_t *, FILE *); + int GPwritebitmap(Gbitmap_t *, FILE *); + int GPbitblt(Gwidget_t *, Gpoint_t, Grect_t, Gbitmap_t *, char *, + Ggattr_t *); + + int GQcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GQsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GQgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GQdestroywidget(Gwidget_t *); + int GQqueryask(Gwidget_t *, char *, char *, char *, int); + + int GScreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GSsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GSgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GSdestroywidget(Gwidget_t *); + + int GTcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GTsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GTgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GTdestroywidget(Gwidget_t *); + + int GVcreatewidget(Gwidget_t *, Gwidget_t *, int, Gwattr_t *); + int GVsetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GVgetwidgetattr(Gwidget_t *, int, Gwattr_t *); + int GVdestroywidget(Gwidget_t *); + + void Gcwbutaction(Widget, XEvent *, char **, unsigned int *); + void Gcwkeyaction(Widget, XEvent *, char **, unsigned int *); + void Glwbutaction(Widget, XEvent *, char **, unsigned int *); + void Glwkeyaction(Widget, XEvent *, char **, unsigned int *); + void Gtweolaction(Widget, XEvent *, char **, unsigned int *); + void Gqwpopaction(Widget, XEvent *, char **, unsigned int *); + void Gwmdelaction(Widget, XEvent *, char **, unsigned int *); + extern XtTranslations Gtweoltable; + extern XtTranslations Gqwpoptable; + extern XtTranslations Glwanytable; + extern XtTranslations Gcwanytable; + extern XtTranslations Gwmdeltable; + + extern Atom Gwmdelatom; + +#endif /* _GCOMMON_H */ + +#ifdef __cplusplus +} +#endif diff --git a/cmd/lefty/ws/x11/glabel.c b/cmd/lefty/ws/x11/glabel.c new file mode 100644 index 000000000..bff2885fc --- /dev/null +++ b/cmd/lefty/ws/x11/glabel.c @@ -0,0 +1,259 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +#define WLU widget->u.l + +int GLcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + int ai; + XColor c; + int color; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + WLU->func = NULL; + ps.x = ps.y = MINLWSIZE; + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINLWSIZE); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRTEXT: + ADD2ARGS(XtNlabel, attrp[ai].u.t); + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTREVENTCB: + WLU->func = (Glabelcb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + ADD2ARGS(XtNhighlightThickness, 0); + ADD2ARGS(XtNinternalHeight, 0); + ADD2ARGS(XtNinternalWidth, 0); + ADD2ARGS(XtNjustify, XtJustifyLeft); + if (!(widget->w = XtCreateWidget("label", labelWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XtOverrideTranslations(widget->w, Glwanytable); + Glazymanage(widget->w); + return 0; +} + +int GLsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + int ai; + XColor c; + int color; + + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINLWSIZE); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRTEXT: + ADD2ARGS(XtNlabel, attrp[ai].u.t); + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTREVENTCB: + WLU->func = (Glabelcb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + XtSetValues(widget->w, argp, argn); + return 0; +} + +int GLgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Dimension width, height; + char *s; + int ai; + + for (ai = 0; ai < attrn; ai++) { + RESETARGS; + switch (attrp[ai].id) { + case G_ATTRSIZE: + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.s.x = width, attrp[ai].u.s.y = height; + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, &width); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.i = width; + break; + case G_ATTRTEXT: + ADD2ARGS(XtNlabel, &s); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.t = s; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", XtWindow(widget->w)); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTREVENTCB: + attrp[ai].u.func = (void *) (WLU->func); + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GLdestroywidget(Gwidget_t * widget) +{ + XtDestroyWidget(widget->w); + return 0; +} + +void Glwbutaction(Widget w, XEvent * evp, char **app, unsigned int *anp) +{ + Gwidget_t *widget; + Gevent_t gev; + int wi, xtype; + + widget = findwidget((unsigned long) w, G_LABELWIDGET); + switch ((xtype = evp->type)) { + case ButtonPress: + case ButtonRelease: + gev.type = G_MOUSE; + gev.code = (xtype == ButtonPress) ? G_DOWN : G_UP; + gev.data = evp->xbutton.button - Button1; + break; + default: + return; + } + wi = gev.wi = widget - &Gwidgets[0]; + if (WLU->func) + (*WLU->func) (&gev); + if (Gpopdownflag) { + Gpopdownflag = FALSE; + if (gev.code == G_DOWN) { + gev.code = G_UP; + widget = &Gwidgets[wi]; + if (widget->inuse && WLU->func) + (*WLU->func) (&gev); + } + } +} + +void Glwkeyaction(Widget w, XEvent * evp, char **app, unsigned int *anp) +{ + Gwidget_t *widget; + Gevent_t gev; + int xtype; + char c; + + widget = findwidget((unsigned long) w, G_LABELWIDGET); + switch ((xtype = evp->type)) { + case KeyPress: + case KeyRelease: + if (!XLookupString((XKeyEvent *) evp, &c, 1, NULL, NULL)) + return; + gev.type = G_KEYBD; + gev.code = (xtype == KeyPress) ? G_DOWN : G_UP; + gev.data = c; + break; + default: + return; + } + gev.wi = widget - &Gwidgets[0]; + if (WLU->func) + (*WLU->func) (&gev); + if (Gpopdownflag) + Gpopdownflag = FALSE; +} diff --git a/cmd/lefty/ws/x11/gmenu.c b/cmd/lefty/ws/x11/gmenu.c new file mode 100644 index 000000000..b1d533f3a --- /dev/null +++ b/cmd/lefty/ws/x11/gmenu.c @@ -0,0 +1,151 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +#define WMU widget->u.m + +static int menupoped; +static int menuselected; + +static void mwcallback(Widget, XtPointer, XtPointer); + +int GMcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + if (!(widget->w = XtCreatePopupShell("menu", + simpleMenuWidgetClass, Groot, + NULL, 0))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XtAddCallback(widget->w, XtNpopdownCallback, mwcallback, + (XtPointer) - 1); + WMU->count = 0; + return 0; +} + +int GMsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GMgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GMdestroywidget(Gwidget_t * widget) +{ + XtDestroyWidget(widget->w); + return 0; +} + +int GMmenuaddentries(Gwidget_t * widget, int en, char **ep) +{ + Widget mep; + int ei; + + for (ei = 0; ei < en; ei++) { + mep = XtCreateManagedWidget(ep[ei], smeBSBObjectClass, + widget->w, NULL, 0); + XtAddCallback(mep, XtNcallback, mwcallback, + (XtPointer) WMU->count++); + } + return 0; +} + +int GMmenudisplay(Gwidget_t * parent, Gwidget_t * widget) +{ + Window rwin, cwin; + Dimension width, height; + int rx, ry, x, y; + unsigned int mask; + + XQueryPointer(Gdisplay, XtWindow(parent->w), + &rwin, &cwin, &rx, &ry, &x, &y, &mask); + XtRealizeWidget(widget->w); + RESETARGS; + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + if (rx + width > DisplayWidth(Gdisplay, Gscreenn)) + rx = DisplayWidth(Gdisplay, Gscreenn) - width; + if (ry + height > DisplayHeight(Gdisplay, Gscreenn)) + ry = DisplayHeight(Gdisplay, Gscreenn) - height; + if (rx < 0) + rx = 0; + if (ry < 0) + ry = 0; + RESETARGS; + ADD2ARGS(XtNx, rx); + ADD2ARGS(XtNy, ry); + XtSetValues(widget->w, argp, argn); + menupoped = TRUE; + menuselected = -1; + XtPopupSpringLoaded(widget->w); + while (menupoped) + Gprocessevents(TRUE, G_ONEEVENT); + Gpopdownflag = TRUE; + return menuselected; +} + +static void mwcallback(Widget w, XtPointer clientdata, XtPointer calldata) +{ + if (((long) clientdata) > -1) + menuselected = (long) clientdata; + menupoped = FALSE; +} diff --git a/cmd/lefty/ws/x11/gpcanvas.c b/cmd/lefty/ws/x11/gpcanvas.c new file mode 100644 index 000000000..328b022d1 --- /dev/null +++ b/cmd/lefty/ws/x11/gpcanvas.c @@ -0,0 +1,777 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define PSDPI 300.0 +#define PSMAXPIXW (8.0 * PSDPI) +#define PSMAXPIXH (10.5 * PSDPI) +#define PSPTPI 72.0 +#define PSMAXPTW (8.0 * PSPTPI) +#define PSMAXPTH (10.5 * PSPTPI) +#define PSXOFF 18 +#define PSYOFF 18 + +static PIXsize_t maxsize = { PSMAXPIXW, PSMAXPIXH }; +static long count; + +#define WPU widget->u.p +#define FP widget->u.p->fp + +#define RED WPU->colors[WPU->gattr.color].nr +#define GREEN WPU->colors[WPU->gattr.color].ng +#define BLUE WPU->colors[WPU->gattr.color].nb + +static char *gstyles[5] = { + /* G_SOLID */ "16 0", + /* G_DASHED */ " 4 4", + /* G_DOTTED */ " 2 2", + /* G_LONGDASHED */ " 4 12", + /* G_SHORTDASHED */ "12 4", +}; + +char *Gpscanvasname = "out.ps"; + +static char *findfont(char *); +static void setgattr(Gwidget_t *, Ggattr_t *); + +static PIXrect_t rdrawtopix(Gwidget_t *, Grect_t); +static PIXpoint_t pdrawtopix(Gwidget_t *, Gpoint_t); +static PIXsize_t sdrawtopix(Gwidget_t *, Gsize_t); +static PIXpoint_t pdrawtobpix(Gbitmap_t *, Gpoint_t); + +int GPcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXpoint_t po; + PIXsize_t ps; + struct Gpwcolor_t *cp; + FILE *pfp; + char buf[120]; + char *s, *path; + int color, lflag, ai, i, x, y, w, h, r, g, b; + + if (!(path = buildpath("lefty.psp", 0)) || !(pfp = fopen(path, "r"))) { + Gerr(POS, G_ERRCANNOTOPENFILE, "lefty.psp"); + return -1; + } + s = Gpscanvasname; + lflag = FALSE; + po.x = po.y = 0; + ps.x = ps.y = MINPWSIZE; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + GETORIGIN(attrp[ai].u.p, po); + break; + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINPWSIZE); + break; + case G_ATTRNAME: + if (attrp[ai].u.t && attrp[ai].u.t[0]) + s = attrp[ai].u.t; + break; + case G_ATTRMODE: + if (Strcmp("landscape", attrp[ai].u.t) == 0) + lflag = TRUE; + else if (Strcmp("portrait", attrp[ai].u.t) == 0) + lflag = FALSE; + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRCOLOR: + /* will do it after the widget is created */ + break; + case G_ATTRVIEWPORT: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOW: + /* will do it after the widget is created */ + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + if (!(FP = fopen(s, "w"))) { + Gerr(POS, G_ERRCANNOTOPENFILE, s); + return -1; + } + WPU->colors[0].r = WPU->colors[0].g = WPU->colors[0].b = 255; + WPU->colors[0].nr = WPU->colors[0].ng = WPU->colors[0].nb = 1.0; + WPU->colors[0].inuse = TRUE; + WPU->colors[1].r = WPU->colors[1].g = WPU->colors[1].b = 0; + WPU->colors[1].nr = WPU->colors[1].ng = WPU->colors[1].nb = 0.0; + WPU->colors[1].inuse = TRUE; + for (i = 2; i < G_MAXCOLORS; i++) + WPU->colors[i].inuse = FALSE; + WPU->gattr.color = 1; + WPU->gattr.width = 0; + WPU->gattr.mode = -1; + WPU->gattr.fill = 0; + WPU->gattr.style = 0; + WPU->wrect.o.x = 0.0, WPU->wrect.o.y = 0.0; + WPU->wrect.c.x = 1.0, WPU->wrect.c.y = 1.0; + WPU->vsize.x = ps.x, WPU->vsize.y = ps.y; + if (lflag) + x = po.y, y = po.x, w = ps.y, h = ps.x; + else + x = po.x, y = po.y, w = ps.x, h = ps.y; + fprintf(FP, "%%! LEFTY Output\n"); + fprintf(FP, "%%%%BoundingBox: %d %d %d %d\n", + (int) (PSXOFF + PSMAXPTW * x / maxsize.x + 0.5), + (int) (PSYOFF + PSMAXPTH * y / maxsize.y + 0.5), + (int) (PSXOFF + PSMAXPTW * w / maxsize.x + 0.5), + (int) (PSYOFF + PSMAXPTH * h / maxsize.y + 0.5)); + fprintf(FP, "%%%%EndComments\n"); + while (fgets(buf, 120, pfp)) + fputs(&buf[0], FP); + fclose(pfp); + fprintf(FP, "/ICP { %d %d %d %d SCP } def\n", + (int) po.x, (int) po.y, + (int) (po.x + ps.x - 1), (int) (po.y + ps.y - 1)); + fprintf(FP, "/BB { %d %d %d %d } def\n", + (int) po.x, (int) po.y, + (int) (po.x + ps.x - 1), (int) (po.y + ps.y - 1)); + if (!lflag) + fprintf(FP, "[%f 0 0 %f %d %d] concat\n", + PSPTPI / PSDPI, PSPTPI / PSDPI, PSXOFF, PSYOFF); + else + fprintf(FP, "[0 %f %f 0 %d %d] concat\n", + PSPTPI / PSDPI, -PSPTPI / PSDPI, + (int) (PSXOFF + ps.y * PSPTPI / PSDPI), PSYOFF); + fprintf(FP, "%d %d translate ICP\n", (int) po.x, (int) po.y); + fprintf(FP, "1 setlinecap\n"); + fprintf(FP, "ICP\n"); + WPU->gattr.color = 1; + fprintf(FP, "%f %f %f CL\n", RED, GREEN, BLUE); + WPU->defgattr = WPU->gattr; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, attrp[ai].u.c.index); + return -1; + } + cp = &WPU->colors[color]; + r = attrp[ai].u.c.r; + g = attrp[ai].u.c.g; + b = attrp[ai].u.c.b; + cp->r = r, cp->g = g, cp->b = b; + cp->nr = r / 256.0, cp->ng = g / 256.0, cp->nb = b / 256.0; + cp->inuse = TRUE; + break; + case G_ATTRVIEWPORT: + WPU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); + WPU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); + fprintf(FP, "0 0 %d %d SCP\n", + (int) WPU->vsize.x, (int) WPU->vsize.y); + break; + case G_ATTRWINDOW: + WPU->wrect = attrp[ai].u.r; + break; + } + } + return 0; +} + +int GPsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + struct Gpwcolor_t *cp; + int color, ai, r, g, b; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + break; + case G_ATTRSIZE: + break; + case G_ATTRNAME: + break; + case G_ATTRMODE: + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS) { + Gerr(POS, G_ERRBADCOLORINDEX, attrp[ai].u.c.index); + return -1; + } + cp = &WPU->colors[color]; + r = attrp[ai].u.c.r; + g = attrp[ai].u.c.g; + b = attrp[ai].u.c.b; + cp->r = r, cp->g = g, cp->b = b; + cp->nr = r / 256.0, cp->ng = g / 256.0, cp->nb = b / 256.0; + cp->inuse = TRUE; + break; + case G_ATTRVIEWPORT: + WPU->vsize.x = (int) (attrp[ai].u.s.x + 0.5); + WPU->vsize.y = (int) (attrp[ai].u.s.y + 0.5); + fprintf(FP, "0 0 %d %d SCP\n", + (int) WPU->vsize.x, (int) WPU->vsize.y); + break; + case G_ATTRWINDOW: + WPU->wrect = attrp[ai].u.r; + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GPgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + struct Gpwcolor_t *cp; + int color, ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + break; + case G_ATTRSIZE: + break; + case G_ATTRNAME: + break; + case G_ATTRMODE: + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color < 0 || color > G_MAXCOLORS + || !WPU->colors[color].inuse) { + Gerr(POS, G_ERRBADCOLORINDEX, attrp[ai].u.c.index); + return -1; + } + cp = &WPU->colors[color]; + attrp[ai].u.c.r = cp->r; + attrp[ai].u.c.g = cp->g; + attrp[ai].u.c.b = cp->b; + break; + case G_ATTRVIEWPORT: + attrp[ai].u.s = WPU->vsize; + break; + case G_ATTRWINDOW: + attrp[ai].u.r = WPU->wrect; + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTGETATTR, "windowid"); + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GPdestroywidget(Gwidget_t * widget) +{ + fprintf(FP, "stroke showpage\n"); + fclose(FP); + return 0; +} + +int GPcanvasclear(Gwidget_t * widget) +{ + fprintf(FP, "ICP DO\n"); + WPU->gattr.color = 0; + fprintf(FP, "%f %f %f CL\n", RED, GREEN, BLUE); + fprintf(FP, "BB BOX FI\n"); + WPU->gattr.color = -1; + fprintf(FP, "0 0 %d %d SCP\n", (int) WPU->vsize.x, (int) WPU->vsize.y); + return 0; +} + +int GPsetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + setgattr(widget, ap); + WPU->defgattr = WPU->gattr; + return 0; +} + +int GPgetgfxattr(Gwidget_t * widget, Ggattr_t * ap) +{ + if ((ap->flags & G_GATTRCOLOR)) + ap->color = WPU->gattr.color; + if ((ap->flags & G_GATTRWIDTH)) + ap->width = WPU->gattr.width; + if ((ap->flags & G_GATTRMODE)) + ap->mode = WPU->gattr.mode; + if ((ap->flags & G_GATTRFILL)) + ap->fill = WPU->gattr.fill; + if ((ap->flags & G_GATTRSTYLE)) + ap->style = WPU->gattr.style; + return 0; +} + +int GParrow(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2, pa, pb, pd; + double tangent; + int l; + + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y; + if (pd.x == 0 && pd.y == 0) + return 0; + tangent = atan2((double) pd.y, (double) pd.x); + if ((l = sqrt((double) (pd.x * pd.x + pd.y * pd.y))) < 30) + l = 30; + pa.x = l * cos(tangent + M_PI / 7) + pp2.x; + pa.y = l * sin(tangent + M_PI / 7) + pp2.y; + pb.x = l * cos(tangent - M_PI / 7) + pp2.x; + pb.y = l * sin(tangent - M_PI / 7) + pp2.y; + setgattr(widget, ap); + fprintf(FP, "%d %d %d %d LI\n", + (int) pp2.x, (int) pp2.y, (int) pp1.x, (int) pp1.y); + fprintf(FP, "%d %d %d %d LI\n", + (int) pp2.x, (int) pp2.y, (int) pa.x, (int) pa.y); + fprintf(FP, "%d %d %d %d LI\n", + (int) pp2.x, (int) pp2.y, (int) pb.x, (int) pb.y); + return 0; +} + +int GPline(Gwidget_t * widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t * ap) +{ + PIXpoint_t pp1, pp2; + + pp1 = pdrawtopix(widget, gp1), pp2 = pdrawtopix(widget, gp2); + if (count++ == 100) + count = 0, fprintf(FP, "DO\n"); + setgattr(widget, ap); + fprintf(FP, "%d %d %d %d LI\n", + (int) pp2.x, (int) pp2.y, (int) pp1.x, (int) pp1.y); + return 0; +} + +int GPbox(Gwidget_t * widget, Grect_t gr, Ggattr_t * ap) +{ + PIXrect_t pr; + + pr = rdrawtopix(widget, gr); + setgattr(widget, ap); + if (WPU->gattr.fill) + fprintf(FP, "DO %d %d %d %d BOX FI\n", + (int) pr.o.x, (int) pr.o.y, (int) pr.c.x, (int) pr.c.y); + else + fprintf(FP, "DO %d %d %d %d BOX DO\n", + (int) pr.o.x, (int) pr.o.y, (int) pr.c.x, (int) pr.c.y); + return 0; +} + +int GPpolygon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + PIXpoint_t pp; + int i; + + if (gpn == 0) + return 0; + + pp = pdrawtopix(widget, gpp[0]); + setgattr(widget, ap); + fprintf(FP, "DO %d %d moveto\n", (int) pp.x, (int) pp.y); + for (i = 1; i < gpn; i++) { + pp = pdrawtopix(widget, gpp[i]); + fprintf(FP, "%d %d lineto\n", (int) pp.x, (int) pp.y); + } + if (WPU->gattr.fill) + fprintf(FP, "FI\n"); + else + fprintf(FP, "DO\n"); + return 0; +} + +int GPsplinegon(Gwidget_t * widget, int gpn, Gpoint_t * gpp, Ggattr_t * ap) +{ + PIXpoint_t p0, p1, p2, p3; + int i; + + if (gpn == 0) + return 0; + + p0 = pdrawtopix(widget, gpp[0]); + setgattr(widget, ap); + fprintf(FP, "DO %d %d moveto\n", (int) p0.x, (int) p0.y); + for (i = 1; i < gpn; i += 3) { + p1 = pdrawtopix(widget, gpp[i]); + p2 = pdrawtopix(widget, gpp[i + 1]); + p3 = pdrawtopix(widget, gpp[i + 2]); + fprintf(FP, "%d %d %d %d %d %d CT\n", (int) p1.x, (int) p1.y, + (int) p2.x, (int) p2.y, (int) p3.x, (int) p3.y); + } + if (WPU->gattr.fill) + fprintf(FP, "FI\n"); + else + fprintf(FP, "DO\n"); + return 0; +} + +int GParc(Gwidget_t * widget, Gpoint_t gc, Gsize_t gs, + double ang1, double ang2, Ggattr_t * ap) +{ + PIXpoint_t pc; + PIXsize_t ps; + + pc = pdrawtopix(widget, gc), ps = sdrawtopix(widget, gs); + setgattr(widget, ap); + if (WPU->gattr.fill) + fprintf(FP, "DO %d %d %f %d %f %f ARF\n", + pc.x, pc.y, (double) ps.y / (double) ps.x, ps.x, ang1, + ang2); + else + fprintf(FP, "DO %d %d %f %d %f %f AR\n", + pc.x, pc.y, (double) ps.y / (double) ps.x, ps.x, ang1, + ang2); + return 0; +} + +int GPtext(Gwidget_t * widget, Gtextline_t * tlp, int n, Gpoint_t go, + char *fn, double fs, char *justs, Ggattr_t * ap) +{ + Gsize_t gs; + PIXpoint_t po; + PIXsize_t ps; + char *font; + char c, *p; + int i; + + po = pdrawtopix(widget, go); + gs.x = 0, gs.y = fs; + ps = sdrawtopix(widget, gs); + font = findfont(fn); + setgattr(widget, ap); + fprintf(FP, "DO %d (%c) %d (%c) [", + (int) po.x, justs[0], (int) po.y, justs[1]); + for (i = 0; i < n; i++) { + c = tlp[i].p[tlp[i].n], tlp[i].p[tlp[i].n] = '\000'; + fprintf(FP, "[ ("); + for (p = tlp[i].p; *p; p++) { /* generate PS escapes as needed */ + if ((*p == '(') || (*p == ')') || (*p == '\\')) + fputc('\\', FP); + fputc(*p, FP); + } + fprintf(FP, ") (%c) ] ", tlp[i].j); + tlp[i].p[tlp[i].n] = c; + } + fprintf(FP, "] %d /%s %d TXT\n", n, font, (int) ps.y); + return 0; +} + +static char *findfont(char *name) +{ + char *font; + + if (name[0] == '\000' || Strcmp(name, "default") == 0) + font = "Times-Roman"; + else + font = name; + return font; +} + +int GPcreatebitmap(Gwidget_t * widget, Gbitmap_t * bitmap, Gsize_t s) +{ + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + bitmap->u.bits = Marrayalloc((long) ((int) s.x * (int) s.y * 3)); + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + return 0; +} + +int GPdestroybitmap(Gbitmap_t * bitmap) +{ + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + Marrayfree(bitmap->u.bits); + return 0; +} + +int GPreadbitmap(Gwidget_t * widget, Gbitmap_t * bitmap, FILE * fp) +{ + Gsize_t s = { 0, 0 }; + char bufp[2048]; + char *s1, *s2; + char c; + int bufn, bufi, step, x, y, k; + + if (!widget) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + if (!bitmap) { + Gerr(POS, G_ERRNOBITMAP); + return -1; + } + step = 0; + while (step < 3) { + l1: + if (!fgets(bufp, 2048, fp)) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + s1 = &bufp[0]; + l2: + for (; *s1 && isspace(*s1); s1++); + if (!*s1 || *s1 == '#') + goto l1; + switch (step) { + case 0: + if (strncmp(s1, "P6", 2) != 0) { + Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + step++, s1 += 2; + goto l2; + case 1: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.x = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + case 2: + for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++); + c = *s2, *s2 = 0; + if (s2 == s1 || (s.y = atoi(s1)) <= 0) { + *s2 = c, Gerr(POS, G_ERRCANNOTREADBITMAP); + return -1; + } + *s2 = c, step++, s1 = s2; + goto l2; + } + } + bitmap->u.bits = Marrayalloc((long) ((int) s.x * (int) s.y * 3)); + bitmap->ctype = widget->type; + bitmap->canvas = widget - &Gwidgets[0]; + bitmap->size = s; + bufi = bufn = 0; + bufp[bufi] = 0; + s1 = (char *) bitmap->u.bits; + for (y = 0; y < s.y; y++) { + for (x = 0; x < s.x; x++) { + for (k = 0; k < 3; k++) { + if (bufi == bufn) { + if ((bufn = fread(bufp, 1, 2047, fp)) == 0) { + Marrayfree(bitmap->u.bits); + Gerr(POS, G_ERRCANNOTCREATEBITMAP); + return -1; + } + bufi = 0; + } + *s1++ = bufp[bufi++]; + } + } + } + return 0; +} + +int GPwritebitmap(Gbitmap_t * bitmap, FILE * fp) +{ + return -1; +} + +int GPbitblt(Gwidget_t * widget, Gpoint_t gp, Grect_t gr, + Gbitmap_t * bitmap, char *mode, Ggattr_t * ap) +{ + PIXrect_t pr, br; + PIXpoint_t pp; + PIXsize_t bs; + Gsize_t scale; + Gxy_t p; + int x, y, hi, lo; + double tvx, tvy, twx, twy; + char *s; + + if (gr.o.x > gr.c.x) + p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x; + if (gr.o.y > gr.c.y) + p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y; + tvx = WPU->vsize.x, tvy = WPU->vsize.y; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + scale.x = tvx / twx, scale.y = tvy / twy; + pr = rdrawtopix(widget, gr); + pp = pdrawtobpix(bitmap, gp); + bs.x = (pr.c.x - pr.o.x + 1) / scale.x; + bs.y = (pr.c.y - pr.o.y + 1) / scale.y; + br.o.x = pp.x, br.o.y = pp.y - bs.y + 1; + br.c.x = br.o.x + bs.x - 1, br.c.y = br.o.y + bs.y - 1; + if (br.o.x < 0) + pr.o.x -= br.o.x * scale.x, br.o.x = 0; + if (br.o.y < 0) + pr.o.y -= br.o.y * scale.y, br.o.y = 0; + if (br.c.x >= bitmap->size.x) { + pr.c.x -= (br.c.x + 1 - bitmap->size.x) * scale.x; + br.c.x = bitmap->size.x - 1; + } + if (br.c.y >= bitmap->size.y) { + pr.c.y -= (br.c.y + 1 - bitmap->size.y) * scale.y; + br.c.y = bitmap->size.y - 1; + } + if (pr.o.x < 0) + br.o.x -= pr.o.x / scale.x, pr.o.x = 0; + if (pr.o.y < 0) + br.o.y -= pr.o.y / scale.y, pr.o.y = 0; + if (pr.c.x >= tvx) + br.c.x -= (pr.c.x + 1 - tvx) / scale.x, pr.c.x = tvx - 1; + if (pr.c.y >= tvy) + br.c.y -= (pr.c.y + 1 - tvy) / scale.y, pr.c.y = tvy - 1; + bs.x = (pr.c.x - pr.o.x + 1) / scale.x; + bs.y = (pr.c.y - pr.o.y + 1) / scale.y; + setgattr(widget, ap); + fprintf(FP, "DO gsave\n"); + fprintf(FP, "%d %d translate\n", pr.o.x, pr.o.y); + fprintf(FP, "%f %f scale\n", scale.x * bs.x, scale.y * bs.y); + fprintf(FP, "/mystr %d string def\n", 3 * bs.x); + fprintf(FP, "%d %d 8\n", bs.x, bs.y); + fprintf(FP, "[%d 0 0 %d 0 %d]\n", bs.x, -bs.y, bs.y); + fprintf(FP, + "{currentfile mystr readhexstring pop} false 3 colorimage\n"); + for (y = 0; y < bs.y; y++) { + s = (char *) (bitmap->u.bits + + 3 * ((int) bitmap->size.x * (br.o.y + y) + br.o.x)); + for (x = 0; x < bs.x; x++) { + hi = (*s >> 4) & 15, lo = *s++ && 15; + fprintf(FP, "%x%x", hi, lo); + hi = (*s >> 4) & 15, lo = *s++ && 15; + fprintf(FP, "%x%x", hi, lo); + hi = (*s >> 4) & 15, lo = *s++ && 15; + fprintf(FP, "%x%x", hi, lo); + } + fprintf(FP, "\n"); + } + fprintf(FP, "grestore\nNP\n"); + return 0; +} + +static void setgattr(Gwidget_t * widget, Ggattr_t * ap) +{ + int color, width, style; + + if (!(ap->flags & G_GATTRCOLOR)) + ap->color = WPU->defgattr.color; + if (!(ap->flags & G_GATTRWIDTH)) + ap->width = WPU->defgattr.width; + if (!(ap->flags & G_GATTRFILL)) + ap->fill = WPU->defgattr.fill; + if (!(ap->flags & G_GATTRSTYLE)) + ap->style = WPU->defgattr.style; + color = ap->color; + if (color >= G_MAXCOLORS || !(WPU->colors[color].inuse)) + color = 1; + if (color != WPU->gattr.color) { + WPU->gattr.color = color; + fprintf(FP, "%f %f %f CL\n", RED, GREEN, BLUE); + } + width = ap->width; + if (width != WPU->gattr.width) { + WPU->gattr.width = width; + fprintf(FP, "DO %d setlinewidth NP\n", width); + } + WPU->gattr.fill = ap->fill; + style = ap->style; + if (style != WPU->gattr.style) { + WPU->gattr.style = style; + fprintf(FP, "DO [ %s ] 0 setdash NP\n", gstyles[style]); + } +} + +static PIXrect_t rdrawtopix(Gwidget_t * widget, Grect_t gr) +{ + PIXrect_t pr; + double tvx, tvy, twx, twy; + + tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + pr.o.x = tvx * (gr.o.x - WPU->wrect.o.x) / twx + 0.5; + pr.o.y = tvy * (gr.o.y - WPU->wrect.o.y) / twy + 0.5; + pr.c.x = tvx * (gr.c.x - WPU->wrect.o.x) / twx + 0.5; + pr.c.y = tvy * (gr.c.y - WPU->wrect.o.y) / twy + 0.5; + return pr; +} + +static PIXpoint_t pdrawtopix(Gwidget_t * widget, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvx, tvy, twx, twy; + + tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + pp.x = tvx * (gp.x - WPU->wrect.o.x) / twx + 0.5; + pp.y = tvy * (gp.y - WPU->wrect.o.y) / twy + 0.5; + return pp; +} + +static PIXsize_t sdrawtopix(Gwidget_t * widget, Gsize_t gs) +{ + PIXsize_t ps; + double tvx, tvy, twx, twy; + + tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1; + twx = WPU->wrect.c.x - WPU->wrect.o.x; + twy = WPU->wrect.c.y - WPU->wrect.o.y; + ps.x = tvx * (gs.x - 1) / twx + 1.5; + ps.y = tvy * (gs.y - 1) / twy + 1.5; + return ps; +} + +static PIXpoint_t pdrawtobpix(Gbitmap_t * bitmap, Gpoint_t gp) +{ + PIXpoint_t pp; + double tvy; + + tvy = bitmap->size.y - 1; + pp.x = gp.x + 0.5; + pp.y = tvy - gp.y + 0.5; + return pp; +} diff --git a/cmd/lefty/ws/x11/gquery.c b/cmd/lefty/ws/x11/gquery.c new file mode 100644 index 000000000..593c5c906 --- /dev/null +++ b/cmd/lefty/ws/x11/gquery.c @@ -0,0 +1,335 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +#define WQU widget->u.q + +static void qwcallback(Widget, XtPointer, XtPointer); +static void qbwcallback(Widget, XtPointer, XtPointer); + +int GQcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + Widget w; + int ai; + + WQU->mode = G_QWSTRING; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRMODE: + if (Strcmp("string", attrp[ai].u.t) == 0) + WQU->mode = G_QWSTRING; + else if (Strcmp("file", attrp[ai].u.t) == 0) + WQU->mode = G_QWFILE; + else if (Strcmp("choice", attrp[ai].u.t) == 0) + WQU->mode = G_QWCHOICE; + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + switch (WQU->mode) { + case G_QWSTRING: + if (!(widget->w = XtCreatePopupShell("popup", + transientShellWidgetClass, + Groot, NULL, 0))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XtAddCallback(widget->w, XtNpopdownCallback, qwcallback, NULL); + RESETARGS; + ADD2ARGS(XtNlabel, "abcdefghijklmno"); + ADD2ARGS(XtNvalue, ""); + if (!(WQU->w = XtCreateManagedWidget("dialog", + dialogWidgetClass, widget->w, + argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XawDialogAddButton(WQU->w, "Cancel", qbwcallback, (XtPointer) 1); + XawDialogAddButton(WQU->w, "OK", qbwcallback, (XtPointer) 2); + if (!(w = XtNameToWidget(WQU->w, "value"))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XtOverrideTranslations(w, Gqwpoptable); + break; + case G_QWFILE: + widget->w = 0; + break; + case G_QWCHOICE: + if (!(widget->w = XtCreatePopupShell("popup", + transientShellWidgetClass, + Groot, NULL, 0))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + XtAddCallback(widget->w, XtNpopdownCallback, qwcallback, NULL); + RESETARGS; + ADD2ARGS(XtNlabel, "abcdefghijklmno"); + if (!(WQU->w = XtCreateManagedWidget("dialog", + dialogWidgetClass, widget->w, + argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + break; + } + return 0; +} + +int GQsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRMODE: + Gerr(POS, G_ERRCANNOTSETATTR2, "mode"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GQgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + int ai; + + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRMODE: + switch (WQU->mode) { + case G_QWSTRING: + attrp[ai].u.t = "string"; + break; + case G_QWFILE: + attrp[ai].u.t = "file"; + break; + case G_QWCHOICE: + attrp[ai].u.t = "choice"; + break; + } + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GQdestroywidget(Gwidget_t * widget) +{ + switch (WQU->mode) { + case G_QWSTRING: + XtDestroyWidget(widget->w); + break; + case G_QWFILE: + break; + case G_QWCHOICE: + XtDestroyWidget(widget->w); + break; + } + return 0; +} + +int XsraSelFile(Widget toplevel, char *prompt, char *ok, char *cancel, + char *failed, char *init_path, char *mode, + int (*show_entry) (), char *name_return, int name_size); + +int GQqueryask(Gwidget_t * widget, char *prompt, char *args, + char *responsep, int responsen) +{ + Window rwin, cwin; + Dimension width, height; + int rx, ry, x, y; + long i; + unsigned int mask; + Widget widgets[20]; + char buttons[20][40]; + char *s1, *s2; + char c; + + switch (WQU->mode) { + case G_QWSTRING: + RESETARGS; + ADD2ARGS(XtNlabel, prompt); + ADD2ARGS(XtNvalue, args ? args : ""); + XtSetValues(WQU->w, argp, argn); + XtRealizeWidget(widget->w); + XQueryPointer(Gdisplay, XtWindow(widget->w), + &rwin, &cwin, &rx, &ry, &x, &y, &mask); + RESETARGS; + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + rx -= (width / 2), ry -= (height / 2); + if (rx + width > DisplayWidth(Gdisplay, Gscreenn)) + rx = DisplayWidth(Gdisplay, Gscreenn) - width; + if (ry + height > DisplayHeight(Gdisplay, Gscreenn)) + ry = DisplayHeight(Gdisplay, Gscreenn) - height; + if (rx < 0) + rx = 0; + if (ry < 0) + ry = 0; + RESETARGS; + ADD2ARGS(XtNx, rx); + ADD2ARGS(XtNy, ry); + XtSetValues(widget->w, argp, argn); + WQU->state = 2; + WQU->button = 0; + XtPopup(widget->w, XtGrabExclusive); + while (WQU->state) { + if (WQU->state == 1) { + if (WQU->button != 1) { + strncpy(responsep, + XawDialogGetValueString(WQU->w), responsen); + } + XtPopdown(widget->w); + } + Gprocessevents(TRUE, G_ONEEVENT); + } + XtUnrealizeWidget(widget->w); + Gpopdownflag = TRUE; + if (WQU->button == 1) + return -1; + break; + case G_QWFILE: + if (!XsraSelFile(Groot, prompt, "OK", "Cancel", "FAIL", + (args ? args : "/"), "r", NULL, responsep, + responsen)) { + Gpopdownflag = TRUE; + return -1; + } + Gpopdownflag = TRUE; + break; + case G_QWCHOICE: + if (!args) + return -1; + RESETARGS; + ADD2ARGS(XtNlabel, prompt); + XtSetValues(WQU->w, argp, argn); + for (s1 = args, i = 1; *s1; i++) { + s2 = s1; + while (*s2 && *s2 != '|') + s2++; + c = *s2, *s2 = 0; + strcpy(buttons[i], s1); + widgets[i] = XtCreateManagedWidget(s1, commandWidgetClass, + WQU->w, NULL, 0); + XtAddCallback(widgets[i], XtNcallback, qbwcallback, + (XtPointer) i); + *s2 = c; + s1 = s2; + if (*s1) + s1++; + } + XtRealizeWidget(widget->w); + XQueryPointer(Gdisplay, XtWindow(widget->w), + &rwin, &cwin, &rx, &ry, &x, &y, &mask); + RESETARGS; + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + rx -= (width / 2), ry -= (height / 2); + if (rx + width > DisplayWidth(Gdisplay, Gscreenn)) + rx = DisplayWidth(Gdisplay, Gscreenn) - width; + if (ry + height > DisplayHeight(Gdisplay, Gscreenn)) + ry = DisplayHeight(Gdisplay, Gscreenn) - height; + if (rx < 0) + rx = 0; + if (ry < 0) + ry = 0; + RESETARGS; + ADD2ARGS(XtNx, rx); + ADD2ARGS(XtNy, ry); + XtSetValues(widget->w, argp, argn); + WQU->state = 2; + WQU->button = 0; + XtPopup(widget->w, XtGrabExclusive); + while (WQU->state) { + if (WQU->state == 1) { + if (WQU->button > 0) + strncpy(responsep, buttons[WQU->button], responsen); + XtPopdown(widget->w); + } + Gprocessevents(TRUE, G_ONEEVENT); + } + XtUnrealizeWidget(widget->w); + for (i--; i > 0; i--) + XtDestroyWidget(widgets[i]); + Gpopdownflag = TRUE; + break; + } + if (responsep[0] && responsep[strlen(responsep) - 1] == '\n') + responsep[strlen(responsep) - 1] = 0; + return 0; +} + +void Gqwpopaction(Widget w, XEvent * evp, char **app, unsigned int *anp) +{ + Gwidget_t *widget; + char c; + + if (evp->type == KeyPress || evp->type == KeyRelease) + XLookupString((XKeyEvent *) evp, &c, 1, NULL, NULL); + if (c != 13) + return; + widget = findwidget((unsigned long) XtParent(XtParent(w)), + G_QUERYWIDGET); + WQU->state = 1; +} + +static void qwcallback(Widget w, XtPointer clientdata, XtPointer calldata) +{ + Gwidget_t *widget; + + widget = findwidget((unsigned long) w, G_QUERYWIDGET); + WQU->state = 0; +} + +static void qbwcallback(Widget w, XtPointer clientdata, XtPointer calldata) +{ + Gwidget_t *widget; + + widget = findwidget((unsigned long) XtParent(XtParent(w)), + G_QUERYWIDGET); + WQU->button = (long) clientdata; + WQU->state = 1; +} diff --git a/cmd/lefty/ws/x11/gscroll.c b/cmd/lefty/ws/x11/gscroll.c new file mode 100644 index 000000000..f7365779f --- /dev/null +++ b/cmd/lefty/ws/x11/gscroll.c @@ -0,0 +1,293 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +int GScreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; +#if XlibSpecificationRelease < 5 + Widget w; +#endif + int ai; + XColor c; + int color; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + ps.x = ps.y = MINSWSIZE; + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINSWSIZE); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRCHILDCENTER: + Gerr(POS, G_ERRCANNOTSETATTR1, "childcenter"); + return -1; + case G_ATTRMODE: + if (Strcmp("forcebars", attrp[ai].u.t) == 0) + ADD2ARGS(XtNforceBars, True); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + ADD2ARGS(XtNallowHoriz, True); + ADD2ARGS(XtNallowVert, True); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + if (!(widget->w = XtCreateWidget("scroll", viewportWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } +#if XlibSpecificationRelease < 5 + RESETARGS; + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + if (!(w = XtCreateWidget("owsucks", formWidgetClass, + widget->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + Glazymanage(w); + Glazymanage(widget->w); + XtDestroyWidget(w); +#else + Glazymanage(widget->w); +#endif + return 0; +} + +int GSsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXpoint_t po; + PIXsize_t ps; + Dimension width, height; + int ai; + XColor c; + int color; + + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINSWSIZE); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRCHILDCENTER: + GETORIGIN(attrp[ai].u.p, po); + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + po.x -= width / 2, po.y -= height / 2; + if (po.x < 0) + po.x = 0; + if (po.y < 0) + po.y = 0; + XawViewportSetCoordinates(widget->w, po.x, po.y); + break; + case G_ATTRMODE: + if (Strcmp("forcebars", attrp[ai].u.t) == 0) + ADD2ARGS(XtNforceBars, True); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + XtSetValues(widget->w, argp, argn); + return 0; +} + +int GSgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Dimension width, height; + Position x, y; + Boolean tf; + Gwidget_t *child; + int ai, wi; + child = 0; + + for (ai = 0; ai < attrn; ai++) { + RESETARGS; + switch (attrp[ai].id) { + case G_ATTRSIZE: + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.s.x = width, attrp[ai].u.s.y = height; + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, &width); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.i = width; + break; + case G_ATTRCHILDCENTER: + for (wi = 0; wi < Gwidgetn; wi++) { + child = &Gwidgets[wi]; + if (child->inuse && child->pwi == widget - &Gwidgets[0]) + break; + } + if (wi == Gwidgetn) { + Gerr(POS, G_ERRNOCHILDWIDGET); + return -1; + } + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + RESETARGS; + ADD2ARGS(XtNx, &x); + ADD2ARGS(XtNy, &y); + XtGetValues(child->w, argp, argn); + attrp[ai].u.p.x = width / 2 - x, attrp[ai].u.p.y = + height / 2 - y; + break; + case G_ATTRMODE: + ADD2ARGS(XtNforceBars, &tf); + attrp[ai].u.t = (tf == True) ? "forcebars" : ""; + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", XtWindow(widget->w)); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GSdestroywidget(Gwidget_t * widget) +{ + XtDestroyWidget(widget->w); + return 0; +} + +#if XlibSpecificationRelease < 5 +#include <X11/IntrinsicP.h> +#include <X11/Xaw/ViewportP.h> + +void XawViewportSetCoordinates(Widget gw, Position x, Position y) +{ + ViewportWidget w = (ViewportWidget) gw; + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + Position mx, my; + + if (x > (int) child->core.width) + x = child->core.width; + else if (x < 0) + x = child->core.x; + + if (y > (int) child->core.height) + y = child->core.height; + else if (y < 0) + y = child->core.y; + + mx = -x, my = -y; + + if (-mx + (int) clip->core.width > (int) child->core.width) + mx = -(child->core.width - clip->core.width); + + if (-my + (int) clip->core.height > (int) child->core.height) + my = -(child->core.height - clip->core.height); + + /* make sure we never move past left/top borders */ + if (mx >= 0) + mx = 0; + if (my >= 0) + my = 0; + + XtMoveWidget(child, mx, my); + XtUnmanageChild(child); + XtManageChild(child); +} +#endif diff --git a/cmd/lefty/ws/x11/gtext.c b/cmd/lefty/ws/x11/gtext.c new file mode 100644 index 000000000..86ec9d208 --- /dev/null +++ b/cmd/lefty/ws/x11/gtext.c @@ -0,0 +1,322 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" +#include "mem.h" + +#define WTU widget->u.t + +int GTcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + char *s; + int ai; + XColor c; + int color; + + static XawTextSelectType sarray[] = { + XawselectLine, XawselectNull + }; + + if (!parent) { + Gerr(POS, G_ERRNOPARENTWIDGET); + return -1; + } + WTU->func = NULL; + ps.x = ps.y = MINTWSIZE; + s = "oneline"; + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINTWSIZE); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRTEXT: + ADD2ARGS(XtNstring, attrp[ai].u.t); + break; + case G_ATTRAPPENDTEXT: + Gerr(POS, G_ERRCANNOTSETATTR1, "appendtext"); + return -1; + case G_ATTRMODE: + s = attrp[ai].u.t; + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTRNEWLINECB: + WTU->func = (Gtwnewlinecb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + if (Strcmp("oneline", s) == 0) + ADD2ARGS(XtNeditType, XawtextAppend); + else if (Strcmp("input", s) == 0 || Strcmp("select", s) == 0) + ADD2ARGS(XtNeditType, XawtextEdit); + else if (Strcmp("output", s) == 0) + ADD2ARGS(XtNeditType, XawtextRead); + else { + Gerr(POS, G_ERRBADATTRVALUE, s); + return -1; + } + ADD2ARGS(XtNscrollHorizontal, XawtextScrollWhenNeeded); + ADD2ARGS(XtNscrollVertical, XawtextScrollWhenNeeded); + if (!(widget->w = XtCreateWidget("ascii", asciiTextWidgetClass, + parent->w, argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + if (Strcmp("oneline", s) == 0 || Strcmp("input", s) == 0) + XtOverrideTranslations(widget->w, Gtweoltable); + else if (Strcmp("select", s) == 0) + XawTextSetSelectionArray(widget->w, sarray); + Glazymanage(widget->w); + return 0; +} + +int GTsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXsize_t ps; + XawTextBlock tb; + int ai, li; + XColor c; + int color; + + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINTWSIZE); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, attrp[ai].u.i); + break; + case G_ATTRTEXT: + ADD2ARGS(XtNstring, attrp[ai].u.t); + break; + case G_ATTRAPPENDTEXT: + XawTextSetInsertionPoint(widget->w, 327670000); + li = XawTextGetInsertionPoint(widget->w); + tb.firstPos = 0, tb.length = strlen(attrp[ai].u.t); + tb.ptr = attrp[ai].u.t, tb.format = FMT8BIT; + XawTextReplace(widget->w, li, li, &tb); + li = XawTextGetInsertionPoint(widget->w); + tb.firstPos = 0, tb.length = 1; + tb.ptr = "\n", tb.format = FMT8BIT; + XawTextReplace(widget->w, li, li, &tb); + break; + case G_ATTRMODE: + if (Strcmp("oneline", attrp[ai].u.t) == 0) + ADD2ARGS(XtNeditType, XawtextAppend); + else if (Strcmp("input", attrp[ai].u.t) == 0) + ADD2ARGS(XtNeditType, XawtextEdit); + else if (Strcmp("output", attrp[ai].u.t) == 0) + ADD2ARGS(XtNeditType, XawtextRead); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTRNEWLINECB: + WTU->func = (Gtwnewlinecb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + XtSetValues(widget->w, argp, argn); + return 0; +} + +int GTgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Dimension width, height; + XawTextEditType mode; + XawTextBlock tb; + Widget w; + int rtn, ai; + long fi, li; + + for (ai = 0; ai < attrn; ai++) { + RESETARGS; + switch (attrp[ai].id) { + case G_ATTRSIZE: + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.s.x = width, attrp[ai].u.s.y = height; + break; + case G_ATTRBORDERWIDTH: + ADD2ARGS(XtNborderWidth, &width); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.i = width; + break; + case G_ATTRTEXT: + w = XawTextGetSource(widget->w); + tb.firstPos = 0, tb.ptr = NULL, tb.format = + FMT8BIT, tb.length = 0; + rtn = XawTextSourceRead(w, 0, &tb, 30000); + if (rtn > Gbufn + 1) { + Gbufp = Marraygrow(Gbufp, (long) (rtn + 1) * BUFSIZE); + Gbufn = rtn + 1; + } + for (Gbufi = 0; Gbufi < rtn; Gbufi++) + Gbufp[Gbufi] = tb.ptr[Gbufi]; + Gbufp[Gbufi++] = '\000'; + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRAPPENDTEXT: + Gerr(POS, G_ERRCANNOTGETATTR, "appendtext"); + return -1; + case G_ATTRSELECTION: + w = XawTextGetSource(widget->w); + XawTextGetSelectionPos(widget->w, &fi, &li); + tb.firstPos = 0, tb.ptr = NULL, tb.format = + FMT8BIT, tb.length = 0; + rtn = XawTextSourceRead(w, fi, &tb, li - fi); + if (li - fi > Gbufn + 1) { + Gbufp = Marraygrow(Gbufp, (long) (rtn + 1) * BUFSIZE); + Gbufn = rtn + 1; + } + for (Gbufi = 0; Gbufi < li - fi; Gbufi++) + Gbufp[Gbufi] = tb.ptr[Gbufi]; + Gbufp[Gbufi++] = '\000'; + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRMODE: + ADD2ARGS(XtNeditType, &mode); + XtGetValues(widget->w, argp, argn); + if (mode == XawtextAppend) + attrp[ai].u.t = "oneline"; + else if (mode == XawtextEdit) + attrp[ai].u.t = "input"; + else if (mode == XawtextRead) + attrp[ai].u.t = "output"; + else { + panic(POS, "GTgetwidgetattr", "unexpected text mode"); + return -1; + } + break; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", XtWindow(widget->w)); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTRNEWLINECB: + attrp[ai].u.func = (void *) (WTU->func); + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GTdestroywidget(Gwidget_t * widget) +{ + XtDestroyWidget(widget->w); + return 0; +} + +/* used for one line text input widgets */ +void Gtweolaction(Widget w, XEvent * evp, char **app, unsigned int *anp) +{ + Gwidget_t *widget; + Widget ww; + XawTextBlock tb; + int ret, fi, li, n, i; + + widget = findwidget((unsigned long) w, G_TEXTWIDGET); + li = XawTextGetInsertionPoint(w) - 1; + ww = XawTextGetSource(w); + tb.firstPos = 0, tb.ptr = "\n", tb.format = FMT8BIT, tb.length = 1; + fi = XawTextSourceSearch(ww, li, XawsdLeft, &tb); + if (fi == XawTextSearchError) + fi = 0; + else + fi++; + n = li - fi; + Gbufp[(Gbufi = 0)] = '\000'; + while (Gbufi != n) { + ret = XawTextSourceRead(ww, fi, &tb, n - Gbufi) - fi; + for (i = 0; i < ret; i++) + Gbufp[Gbufi++] = tb.ptr[i]; + } + Gbufp[Gbufi] = '\000'; + if (n >= 0 && WTU->func) + (*WTU->func) (widget - &Gwidgets[0], Gbufp); +} diff --git a/cmd/lefty/ws/x11/gview.c b/cmd/lefty/ws/x11/gview.c new file mode 100644 index 000000000..c816adb72 --- /dev/null +++ b/cmd/lefty/ws/x11/gview.c @@ -0,0 +1,250 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +/* Lefteris Koutsofios - AT&T Bell Laboratories */ + +#include "common.h" +#include "g.h" +#include "gcommon.h" + +#define WVU widget->u.v + +int GVcreatewidget(Gwidget_t * parent, Gwidget_t * widget, + int attrn, Gwattr_t * attrp) +{ + PIXpoint_t po = { 0, 0 }; + PIXsize_t ps; + XSizeHints hints; + char *s; + int haveorigin, ai; + XColor c; + int color; + + WVU->func = NULL; + WVU->closing = FALSE; + s = "LEFTY"; + ps.x = ps.y = MINVWSIZE; + haveorigin = FALSE; + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + haveorigin = TRUE; + GETORIGIN(attrp[ai].u.p, po); + ADD2ARGS(XtNx, po.x); + ADD2ARGS(XtNy, po.y); + break; + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINVWSIZE); + break; + case G_ATTRNAME: + s = attrp[ai].u.t; + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRZORDER: + Gerr(POS, G_ERRCANNOTSETATTR1, "zorder"); + return -1; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR1, "windowid"); + return -1; + case G_ATTREVENTCB: + WVU->func = (Gviewcb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + if (!(widget->w = XtAppCreateShell(s, "LEFTY", + topLevelShellWidgetClass, Gdisplay, + argp, argn))) { + Gerr(POS, G_ERRCANNOTCREATEWIDGET); + return -1; + } + if (haveorigin) { + hints.x = po.x, hints.y = po.y; + hints.width = ps.x, hints.height = ps.y; + hints.flags = USPosition; + Glazyrealize(widget->w, TRUE, &hints); + } else + Glazyrealize(widget->w, FALSE, NULL); + return 0; +} + +int GVsetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + PIXpoint_t po; + PIXsize_t ps; + int ai; + XColor c; + int color; + + RESETARGS; + for (ai = 0; ai < attrn; ai++) { + switch (attrp[ai].id) { + case G_ATTRORIGIN: + GETORIGIN(attrp[ai].u.p, po); + ADD2ARGS(XtNx, po.x); + ADD2ARGS(XtNy, po.y); + break; + case G_ATTRSIZE: + GETSIZE(attrp[ai].u.s, ps, MINVWSIZE); + ADD2ARGS(XtNwidth, ps.x); + ADD2ARGS(XtNheight, ps.y); + break; + case G_ATTRNAME: +#if XlibSpecificationRelease < 5 + return -1; +#else + XmbSetWMProperties(Gdisplay, XtWindow(widget->w), + attrp[ai].u.t, attrp[ai].u.t, NULL, 0, NULL, + NULL, NULL); +#endif + break; + case G_ATTRCOLOR: + color = attrp[ai].u.c.index; + if (color != 0 && color != 1) { + Gerr(POS, G_ERRBADCOLORINDEX, color); + return -1; + } + c.red = attrp[ai].u.c.r * 257; + c.green = attrp[ai].u.c.g * 257; + c.blue = attrp[ai].u.c.b * 257; + if (XAllocColor + (Gdisplay, DefaultColormap(Gdisplay, Gscreenn), &c)) { + if (color == 0) + ADD2ARGS(XtNbackground, c.pixel); + else + ADD2ARGS(XtNforeground, c.pixel); + } + break; + case G_ATTRZORDER: + Gflushlazyq(); + if (Strcmp(attrp[ai].u.t, "top") == 0) + XRaiseWindow(Gdisplay, XtWindow(widget->w)); + else if (Strcmp(attrp[ai].u.t, "bottom") == 0) + XLowerWindow(Gdisplay, XtWindow(widget->w)); + else { + Gerr(POS, G_ERRBADATTRVALUE, attrp[ai].u.t); + return -1; + } + break; + case G_ATTRWINDOWID: + Gerr(POS, G_ERRCANNOTSETATTR2, "windowid"); + return -1; + case G_ATTREVENTCB: + WVU->func = (Gviewcb) attrp[ai].u.func; + break; + case G_ATTRUSERDATA: + widget->udata = attrp[ai].u.u; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + XtSetValues(widget->w, argp, argn); + return 0; +} + +int GVgetwidgetattr(Gwidget_t * widget, int attrn, Gwattr_t * attrp) +{ + Position x, y; + Dimension width, height; + int ai; + + for (ai = 0; ai < attrn; ai++) { + RESETARGS; + switch (attrp[ai].id) { + case G_ATTRORIGIN: + ADD2ARGS(XtNx, &x); + ADD2ARGS(XtNy, &y); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.p.x = x, attrp[ai].u.p.y = y; + break; + case G_ATTRSIZE: + ADD2ARGS(XtNwidth, &width); + ADD2ARGS(XtNheight, &height); + XtGetValues(widget->w, argp, argn); + attrp[ai].u.s.x = width, attrp[ai].u.s.y = height; + break; + case G_ATTRNAME: + Gerr(POS, G_ERRNOTIMPLEMENTED); + return -1; + case G_ATTRZORDER: + Gerr(POS, G_ERRNOTIMPLEMENTED); + return -1; + case G_ATTRWINDOWID: + sprintf(&Gbufp[0], "0x%lx", XtWindow(widget->w)); + attrp[ai].u.t = &Gbufp[0]; + break; + case G_ATTREVENTCB: + attrp[ai].u.func = (void *) (WVU->func); + break; + case G_ATTRUSERDATA: + attrp[ai].u.u = widget->udata; + break; + default: + Gerr(POS, G_ERRBADATTRID, attrp[ai].id); + return -1; + } + } + return 0; +} + +int GVdestroywidget(Gwidget_t * widget) +{ + WVU->closing = TRUE; + XtDestroyWidget(widget->w); + return 0; +} + +void Gwmdelaction(Widget w, XEvent * evp, char **app, unsigned int *anp) +{ + Gwidget_t *widget; + Gevent_t gev; + + widget = findwidget((unsigned long) w, G_VIEWWIDGET); + if (!widget) + exit(0); + gev.type = G_MOUSE, gev.code = 0, gev.data = 0; + gev.wi = widget - &Gwidgets[0]; + if (WVU->func) + (*WVU->func) (&gev); + else + exit(0); +} diff --git a/cmd/lefty/ws/x11/libfilereq/.cvsignore b/cmd/lefty/ws/x11/libfilereq/.cvsignore new file mode 100644 index 000000000..9fb985742 --- /dev/null +++ b/cmd/lefty/ws/x11/libfilereq/.cvsignore @@ -0,0 +1,6 @@ +*.la +*.lo +.deps +.libs +Makefile +Makefile.in diff --git a/cmd/lefty/ws/x11/libfilereq/Dir.c b/cmd/lefty/ws/x11/libfilereq/Dir.c new file mode 100644 index 000000000..d3dc853e2 --- /dev/null +++ b/cmd/lefty/ws/x11/libfilereq/Dir.c @@ -0,0 +1,206 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef FEATURE_CS +#include <ast.h> +#endif +/* + * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Software Research Associates + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Erik M. van der Poel + * Software Research Associates, Inc., Tokyo, Japan + * erik@sra.co.jp + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> + +#ifdef SEL_FILE_IGNORE_CASE +#include <ctype.h> +#endif /* def SEL_FILE_IGNORE_CASE */ + +#include "SFinternal.h" + +#if HAVE_DIRENT_H +# include <dirent.h> +# define DIRENT_DONE +#else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# define DIRENT_DONE +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# define DIRENT_DONE +# endif +#endif + +#ifndef DIRENT_DONE +#if defined(SVR4) || defined(SYSV) || defined(USG) || defined(__osf__) || defined (__svr4__) || defined (__FreeBSD__) || defined(SCO) +#include <dirent.h> +#else /* defined(SVR4) || defined(SYSV) || defined(USG) */ +#include <sys/dir.h> +#define dirent direct +#endif /* defined(SVR4) || defined(SYSV) || defined(USG) */ +#endif + +#include <sys/stat.h> + +#if defined(SVR4) || defined(SYSV) || defined(USG) +extern void qsort(); +#endif /* defined(SVR4) || defined(SYSV) || defined(USG) */ + +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#include "SFDecls.h" + +#ifdef SEL_FILE_IGNORE_CASE +int SFcompareEntries(const void *vp, const void *vq) +{ + SFEntry *p = (SFEntry *) vp, *q = (SFEntry *) vq; + register char *r, *s; + register char c1, c2; + + r = p->real; + s = q->real; + + c1 = *r++; + if (islower(c1)) { + c1 = toupper(c1); + } + c2 = *s++; + if (islower(c2)) { + c2 = toupper(c2); + } + + while (c1 == c2) { + if (!c1) { + return strcmp(p->real, q->real); + } + c1 = *r++; + if (islower(c1)) { + c1 = toupper(c1); + } + c2 = *s++; + if (islower(c2)) { + c2 = toupper(c2); + } + } + + return c1 - c2; +} +#else /* def SEL_FILE_IGNORE_CASE */ +int SFcompareEntries(const void *vp, const void *vq) +{ + SFEntry *p = (SFEntry *) vp, *q = (SFEntry *) vq; + return strcmp(p->real, q->real); +} +#endif /* def SEL_FILE_IGNORE_CASE */ + +int SFgetDir(dir) +SFDir *dir; +{ + SFEntry *result = NULL; + int alloc = 0; + int i; + DIR *dirp; + struct dirent *dp; + char *str; + int len; + int maxChars; + struct stat statBuf; + + maxChars = strlen(dir->dir) - 1; + + dir->entries = NULL; + dir->nEntries = 0; + dir->nChars = 0; + + result = NULL; + i = 0; + + dirp = opendir("."); + if (!dirp) { + return 1; + } + + (void) stat(".", &statBuf); + dir->mtime = statBuf.st_mtime; + + (void) readdir(dirp); /* throw away "." */ + +#ifndef S_IFLNK + (void) readdir(dirp); /* throw away ".." */ +#endif /* ndef S_IFLNK */ + + while ((dp = readdir(dirp))) { + if (i >= alloc) { + alloc = 2 * (alloc + 1); + result = (SFEntry *) XtRealloc((char *) result, + (unsigned) (alloc * + sizeof(SFEntry))); + } + result[i].statDone = 0; + str = dp->d_name; + len = strlen(str); + result[i].real = XtMalloc((unsigned) (len + 2)); + (void) strcat(strcpy(result[i].real, str), " "); + if (len > maxChars) { + maxChars = len; + } + result[i].shown = result[i].real; + i++; + } + +#if defined(SVR4) || defined(SYSV) || defined(USG) + qsort((char *) result, (unsigned) i, sizeof(SFEntry), + SFcompareEntries); +#else /* defined(SVR4) || defined(SYSV) || defined(USG) */ + qsort((char *) result, i, sizeof(SFEntry), SFcompareEntries); +#endif /* defined(SVR4) || defined(SYSV) || defined(USG) */ + + dir->entries = result; + dir->nEntries = i; + dir->nChars = maxChars + 1; + + closedir(dirp); + + return 0; +} diff --git a/cmd/lefty/ws/x11/libfilereq/Draw.c b/cmd/lefty/ws/x11/libfilereq/Draw.c new file mode 100644 index 000000000..4586dcd81 --- /dev/null +++ b/cmd/lefty/ws/x11/libfilereq/Draw.c @@ -0,0 +1,858 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef FEATURE_CS +#include <ast.h> +#endif +/* + * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Software Research Associates + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Erik M. van der Poel + * Software Research Associates, Inc., Tokyo, Japan + * erik@sra.co.jp + */ + +#include <stdio.h> +#include "SFinternal.h" +#include "xstat.h" +#include <X11/StringDefs.h> +#include <X11/Xaw/Scrollbar.h> +#include <X11/Xaw/Cardinals.h> + +#include "SFDecls.h" + +#define SF_DEFAULT_FONT "9x15" + +#ifdef ABS +#undef ABS +#endif +#define ABS(x) (((x) < 0) ? (-(x)) : (x)) + +typedef struct { + char *fontname; +} TextData, *textPtr; + +int SFcharWidth, SFcharAscent, SFcharHeight; + +int SFcurrentInvert[3] = { -1, -1, -1 }; + +static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC; + +static XtResource textResources[] = { + {XtNfont, XtCFont, XtRString, sizeof(char *), + XtOffset(textPtr, fontname), XtRString, SF_DEFAULT_FONT}, +}; + +static XFontStruct *SFfont; + +static int SFcurrentListY; + +static XtIntervalId SFscrollTimerId; + +void SFinitFont() +{ + TextData *data; + + data = XtNew(TextData); + + XtGetApplicationResources(selFileForm, (XtPointer) data, textResources, + XtNumber(textResources), (Arg *) NULL, ZERO); + + SFfont = XLoadQueryFont(SFdisplay, data->fontname); + if (!SFfont) { + SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT); + if (!SFfont) { + char sbuf[256]; + + (void) sprintf(sbuf, "XsraSelFile: can't get font %s", + SF_DEFAULT_FONT); + + XtAppError(SFapp, sbuf); + } + } + + SFcharWidth = + (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2; + SFcharAscent = SFfont->max_bounds.ascent; + SFcharHeight = SFcharAscent + SFfont->max_bounds.descent; +} + +void SFcreateGC() +{ + XGCValues gcValues; + XRectangle rectangles[1]; + + gcValues.foreground = SFfore; + + SFlineGC = XtGetGC(selFileLists[0], (XtGCMask) + GCForeground | 0, &gcValues); + + SFscrollGC = XtGetGC(selFileLists[0], (XtGCMask) + 0, &gcValues); + + gcValues.function = GXinvert; + gcValues.plane_mask = (SFfore ^ SFback); + + SFinvertGC = XtGetGC(selFileLists[0], (XtGCMask) + GCFunction | GCPlaneMask | 0, &gcValues); + + gcValues.foreground = SFfore; + gcValues.background = SFback; + gcValues.font = SFfont->fid; + + SFtextGC = XCreateGC(SFdisplay, + XtWindow(selFileLists[0]), (unsigned long) + GCForeground | + GCBackground | GCFont | 0, &gcValues); + + rectangles[0].x = SFlineToTextH + SFbesideText; + rectangles[0].y = 0; + rectangles[0].width = SFcharsPerEntry * SFcharWidth; + rectangles[0].height = SFupperY + 1; + + XSetClipRectangles(SFdisplay, SFtextGC, 0, 0, rectangles, 1, Unsorted); +} + +void SFclearList(n, doScroll) +long n; +int doScroll; +{ + SFDir *dir; + + SFcurrentInvert[n] = -1; + + XClearWindow(SFdisplay, XtWindow(selFileLists[n])); + + XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, + 2); + + if (doScroll) { + dir = &(SFdirs[SFdirPtr + n]); + + if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) { + XawScrollbarSetThumb(selFileVScrolls[n], + (float) (((double) dir->vOrigin) / + dir->nEntries), + (float) (((double) + ((dir->nEntries < SFlistSize) + ? dir-> + nEntries : SFlistSize)) / + dir->nEntries) + ); + + XawScrollbarSetThumb(selFileHScrolls[n], + (float) (((double) dir->hOrigin) / + dir->nChars), + (float) (((double) + ((dir->nChars < + SFcharsPerEntry) ? dir-> + nChars : SFcharsPerEntry)) / + dir->nChars) + ); + } else { + XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0, + (float) 1.0); + XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0, + (float) 1.0); + } + } +} + +static void SFdeleteEntry(dir, entry) +SFDir *dir; +SFEntry *entry; +{ + register SFEntry *e; + register SFEntry *end; + int n; + int idx; + + idx = entry - dir->entries; + + if (idx < dir->beginSelection) { + dir->beginSelection--; + } + if (idx <= dir->endSelection) { + dir->endSelection--; + } + if (dir->beginSelection > dir->endSelection) { + dir->beginSelection = dir->endSelection = -1; + } + + if (idx < dir->vOrigin) { + dir->vOrigin--; + } + + XtFree(entry->real); + + end = &(dir->entries[dir->nEntries - 1]); + + for (e = entry; e < end; e++) { + *e = *(e + 1); + } + + if (!(--dir->nEntries)) { + return; + } + + n = dir - &(SFdirs[SFdirPtr]); + if ((n < 0) || (n > 2)) { + return; + } + + XawScrollbarSetThumb(selFileVScrolls[n], + (float) (((double) dir->vOrigin) / dir->nEntries), + (float) (((double) ((dir->nEntries < SFlistSize) ? + dir->nEntries : SFlistSize)) / + dir->nEntries) + ); +} + +static void SFwriteStatChar(name, last, statBuf) +char *name; +int last; +struct stat *statBuf; +{ + name[last] = SFstatChar(statBuf); +} + +static int SFstatAndCheck(dir, entry) +SFDir *dir; +SFEntry *entry; +{ + struct stat statBuf; + char save; + int last; + + /* + * must be restored before returning + */ + save = *(dir->path); + *(dir->path) = 0; + + if (!SFchdir(SFcurrentPath)) { + last = strlen(entry->real) - 1; + entry->real[last] = 0; + entry->statDone = 1; + if ((!stat(entry->real, &statBuf)) +#ifdef S_IFLNK + || (!lstat(entry->real, &statBuf)) +#endif /* ndef S_IFLNK */ + ) { + if (SFfunc) { + char *shown; + + shown = NULL; + if (SFfunc(entry->real, &shown, &statBuf)) { + if (shown) { + int len; + + len = strlen(shown); + entry->shown = XtMalloc((unsigned) (len + 2) + ); + (void) strcpy(entry->shown, shown); + SFwriteStatChar(entry->shown, len, &statBuf); + entry->shown[len + 1] = 0; + } + } else { + SFdeleteEntry(dir, entry); + + *(dir->path) = save; + return 1; + } + } + SFwriteStatChar(entry->real, last, &statBuf); + } else { + entry->real[last] = ' '; + } + } + + *(dir->path) = save; + return 0; +} + +static void SFdrawStrings(w, dir, from, to) +register Window w; +register SFDir *dir; +register int from; +register int to; +{ + register int i; + register SFEntry *entry; + int x; + + x = SFtextX - dir->hOrigin * SFcharWidth; + + if (dir->vOrigin + to >= dir->nEntries) { + to = dir->nEntries - dir->vOrigin - 1; + } + for (i = from; i <= to; i++) { + entry = &(dir->entries[dir->vOrigin + i]); + if (!(entry->statDone)) { + if (SFstatAndCheck(dir, entry)) { + if (dir->vOrigin + to >= dir->nEntries) { + to = dir->nEntries - dir->vOrigin - 1; + } + i--; + continue; + } + } + XDrawImageString(SFdisplay, + w, + SFtextGC, + x, + SFtextYoffset + i * SFentryHeight, + entry->shown, strlen(entry->shown) + ); + if (dir->vOrigin + i == dir->beginSelection) { + XDrawLine(SFdisplay, + w, + SFlineGC, + SFlineToTextH + 1, + SFlowerY + i * SFentryHeight, + SFlineToTextH + SFentryWidth - 2, + SFlowerY + i * SFentryHeight); + } + if ((dir->vOrigin + i >= dir->beginSelection) && + (dir->vOrigin + i <= dir->endSelection) + ) { + SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 = + SFlowerY + i * SFentryHeight; + SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 = + SFlowerY + (i + 1) * SFentryHeight - 1; + XDrawSegments(SFdisplay, w, SFlineGC, SFcompletionSegs, 2); + } + if (dir->vOrigin + i == dir->endSelection) { + XDrawLine(SFdisplay, + w, + SFlineGC, + SFlineToTextH + 1, + SFlowerY + (i + 1) * SFentryHeight - 1, + SFlineToTextH + SFentryWidth - 2, + SFlowerY + (i + 1) * SFentryHeight - 1); + } + } +} + +void SFdrawList(n, doScroll) +long n; +int doScroll; +{ + SFDir *dir; + Window w; + + SFclearList(n, doScroll); + + if (SFdirPtr + n < SFdirEnd) { + dir = &(SFdirs[SFdirPtr + n]); + w = XtWindow(selFileLists[n]); + XDrawImageString(SFdisplay, + w, + SFtextGC, + SFtextX - dir->hOrigin * SFcharWidth, + SFlineToTextV + SFaboveAndBelowText + + SFcharAscent, dir->dir, strlen(dir->dir) + ); + SFdrawStrings(w, dir, 0, SFlistSize - 1); + } +} + +void SFdrawLists(doScroll) +int doScroll; +{ + long i; + + for (i = 0; i < 3; i++) { + SFdrawList(i, doScroll); + } +} + +static void SFinvertEntry(n) +register int n; +{ + XFillRectangle(SFdisplay, + XtWindow(selFileLists[n]), + SFinvertGC, + SFlineToTextH, + SFcurrentInvert[n] * SFentryHeight + SFlowerY, + SFentryWidth, SFentryHeight); +} + +static unsigned long SFscrollTimerInterval() +{ + static int maxVal = 200; + static int varyDist = 50; + static int minDist = 50; + int t; + int dist; + + if (SFcurrentListY < SFlowerY) { + dist = SFlowerY - SFcurrentListY; + } else if (SFcurrentListY > SFupperY) { + dist = SFcurrentListY - SFupperY; + } else { + return (unsigned long) 1; + } + + t = maxVal - ((maxVal / varyDist) * (dist - minDist)); + + if (t < 1) { + t = 1; + } + + if (t > maxVal) { + t = maxVal; + } + + return (unsigned long) t; +} + +static void SFscrollTimer(p, id) +XtPointer p; +XtIntervalId *id; +{ + SFDir *dir; + int save; + long n; + + n = (long) p; + + dir = &(SFdirs[SFdirPtr + n]); + save = dir->vOrigin; + + if (SFcurrentListY < SFlowerY) { + if (dir->vOrigin > 0) { + SFvSliderMovedCallback(selFileVScrolls[n], n, + dir->vOrigin - 1); + } + } else if (SFcurrentListY > SFupperY) { + if (dir->vOrigin < dir->nEntries - SFlistSize) { + SFvSliderMovedCallback(selFileVScrolls[n], n, + dir->vOrigin + 1); + } + } + + if (dir->vOrigin != save) { + if (dir->nEntries) { + XawScrollbarSetThumb(selFileVScrolls[n], + (float) (((double) dir->vOrigin) / + dir->nEntries), + (float) (((double) + ((dir->nEntries < + SFlistSize) ? dir-> + nEntries : SFlistSize)) / + dir->nEntries) + ); + } + } + + if (SFbuttonPressed) { + SFscrollTimerId = XtAppAddTimeOut(SFapp, + SFscrollTimerInterval(), + SFscrollTimer, (XtPointer) n); + } +} + +static int SFnewInvertEntry(n, event) +register long n; +register XMotionEvent *event; +{ + register int x, y; + register int new; + static int SFscrollTimerAdded = 0; + + x = event->x; + y = event->y; + + if (SFdirPtr + n >= SFdirEnd) { + return -1; + } else if ((x >= 0) && (x <= SFupperX) && + (y >= SFlowerY) && (y <= SFupperY) + ) { + register SFDir *dir = &(SFdirs[SFdirPtr + n]); + + if (SFscrollTimerAdded) { + SFscrollTimerAdded = 0; + XtRemoveTimeOut(SFscrollTimerId); + } + + new = (y - SFlowerY) / SFentryHeight; + if (dir->vOrigin + new >= dir->nEntries) { + return -1; + } + return new; + } else { + if (SFbuttonPressed) { + SFcurrentListY = y; + if (!SFscrollTimerAdded) { + SFscrollTimerAdded = 1; + SFscrollTimerId = XtAppAddTimeOut(SFapp, + SFscrollTimerInterval(), + SFscrollTimer, + (XtPointer) n); + } + } + + return -1; + } +} + +/* ARGSUSED */ +void SFenterList(w, n, event) +Widget w; +register int n; +register XEnterWindowEvent *event; +{ + register int new; + + /* sanity */ + if (SFcurrentInvert[n] != -1) { + SFinvertEntry(n); + SFcurrentInvert[n] = -1; + } + + new = SFnewInvertEntry((long) n, (XMotionEvent *) event); + if (new != -1) { + SFcurrentInvert[n] = new; + SFinvertEntry(n); + } +} + +/* ARGSUSED */ +void SFleaveList(w, n, event) +Widget w; +register int n; +XEvent *event; +{ + if (SFcurrentInvert[n] != -1) { + SFinvertEntry(n); + SFcurrentInvert[n] = -1; + } +} + +/* ARGSUSED */ +void SFmotionList(w, n, event) +Widget w; +register int n; +register XMotionEvent *event; +{ + register int new; + + new = SFnewInvertEntry((long) n, event); + + if (new != SFcurrentInvert[n]) { + if (SFcurrentInvert[n] != -1) { + SFinvertEntry(n); + } + SFcurrentInvert[n] = new; + if (new != -1) { + SFinvertEntry(n); + } + } +} + +/* ARGSUSED */ +void SFvFloatSliderMovedCallback(w, n, fnew) +Widget w; +int n; +float *fnew; +{ + int new; + + new = (*fnew) * SFdirs[SFdirPtr + n].nEntries; + + SFvSliderMovedCallback(w, n, new); +} + +/* ARGSUSED */ +void SFvSliderMovedCallback(w, n, new) +Widget w; +int n; +int new; +{ + int old; + register Window win; + SFDir *dir; + + dir = &(SFdirs[SFdirPtr + n]); + + old = dir->vOrigin; + dir->vOrigin = new; + + if (old == new) { + return; + } + + win = XtWindow(selFileLists[n]); + + if (ABS(new - old) < SFlistSize) { + if (new > old) { + XCopyArea(SFdisplay, + win, + win, + SFscrollGC, + SFlineToTextH, + SFlowerY + (new - old) * SFentryHeight, + SFentryWidth + SFlineToTextH, + (SFlistSize - (new - old)) * SFentryHeight, + SFlineToTextH, SFlowerY); + XClearArea(SFdisplay, + win, + SFlineToTextH, + SFlowerY + (SFlistSize - (new - old)) * + SFentryHeight, + SFentryWidth + SFlineToTextH, + (new - old) * SFentryHeight, False); + SFdrawStrings(win, dir, SFlistSize - (new - old), + SFlistSize - 1); + } else { + XCopyArea(SFdisplay, + win, + win, + SFscrollGC, + SFlineToTextH, + SFlowerY, + SFentryWidth + SFlineToTextH, + (SFlistSize - (old - new)) * SFentryHeight, + SFlineToTextH, + SFlowerY + (old - new) * SFentryHeight); + XClearArea(SFdisplay, + win, + SFlineToTextH, + SFlowerY, + SFentryWidth + SFlineToTextH, + (old - new) * SFentryHeight, False); + SFdrawStrings(win, dir, 0, old - new); + } + } else { + XClearArea(SFdisplay, + win, + SFlineToTextH, + SFlowerY, + SFentryWidth + SFlineToTextH, + SFlistSize * SFentryHeight, False); + SFdrawStrings(win, dir, 0, SFlistSize - 1); + } +} + +/* ARGSUSED */ +void SFvAreaSelectedCallback(w, n, pnew) +Widget w; +int n; +int pnew; +{ + SFDir *dir; + int new; + + dir = &(SFdirs[SFdirPtr + n]); + + new = dir->vOrigin + + (((double) pnew) / SFvScrollHeight) * dir->nEntries; + + if (new > dir->nEntries - SFlistSize) { + new = dir->nEntries - SFlistSize; + } + + if (new < 0) { + new = 0; + } + + if (dir->nEntries) { + float f; + + f = ((double) new) / dir->nEntries; + + XawScrollbarSetThumb(w, + f, + (float) (((double) + ((dir->nEntries < + SFlistSize) ? dir-> + nEntries : SFlistSize)) / + dir->nEntries) + ); + } + + SFvSliderMovedCallback(w, n, new); +} + +/* ARGSUSED */ +void SFhSliderMovedCallback(w, n, new) +Widget w; +int n; +float *new; +{ + SFDir *dir; + int save; + + dir = &(SFdirs[SFdirPtr + n]); + save = dir->hOrigin; + dir->hOrigin = (*new) * dir->nChars; + if (dir->hOrigin == save) { + return; + } + + SFdrawList(n, SF_DO_NOT_SCROLL); +} + +/* ARGSUSED */ +void SFhAreaSelectedCallback(w, n, pnew) +Widget w; +int n; +int pnew; +{ + SFDir *dir; + int new; + + dir = &(SFdirs[SFdirPtr + n]); + + new = dir->hOrigin + (((double) pnew) / SFhScrollWidth) * dir->nChars; + + if (new > dir->nChars - SFcharsPerEntry) { + new = dir->nChars - SFcharsPerEntry; + } + + if (new < 0) { + new = 0; + } + + if (dir->nChars) { + float f; + + f = ((double) new) / dir->nChars; + + XawScrollbarSetThumb(w, + f, + (float) (((double) + ((dir->nChars < + SFcharsPerEntry) ? dir-> + nChars : SFcharsPerEntry)) / + dir->nChars) + ); + + SFhSliderMovedCallback(w, n, &f); + } +} + +/* ARGSUSED */ +void SFpathSliderMovedCallback(w, client_data, new) +Widget w; +XtPointer client_data; +float *new; +{ + SFDir *dir; + int n; + XawTextPosition pos; + int SFdirPtrSave; + + SFdirPtrSave = SFdirPtr; + SFdirPtr = (*new) * SFdirEnd; + if (SFdirPtr == SFdirPtrSave) { + return; + } + + SFdrawLists(SF_DO_SCROLL); + + n = 2; + while (SFdirPtr + n >= SFdirEnd) { + n--; + } + + dir = &(SFdirs[SFdirPtr + n]); + + pos = dir->path - SFcurrentPath; + + if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) { + pos -= strlen(SFstartDir); + if (pos < 0) { + pos = 0; + } + } + + XawTextSetInsertionPoint(selFileField, pos); +} + +/* ARGSUSED */ + +void SFpathAreaSelectedCallback(w, client_data, pnew) +Widget w; +XtPointer client_data; +int pnew; +{ + int new; + float f; + + new = SFdirPtr + (((double) pnew) / SFpathScrollWidth) * SFdirEnd; + + if (new > SFdirEnd - 3) { + new = SFdirEnd - 3; + } + + if (new < 0) { + new = 0; + } + + f = ((double) new) / SFdirEnd; + + XawScrollbarSetThumb(w, + f, + (float) (((double) + ((SFdirEnd < + 3) ? SFdirEnd : 3)) / SFdirEnd) + ); + + SFpathSliderMovedCallback(w, (XtPointer) NULL, &f); +} + +Boolean SFworkProc() +{ + register SFDir *dir; + register SFEntry *entry; + + for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) { + if (!(dir->nEntries)) { + continue; + } + for (entry = &(dir->entries[dir->nEntries - 1]); + entry >= dir->entries; entry--) { + if (!(entry->statDone)) { + (void) SFstatAndCheck(dir, entry); + return False; + } + } + } + + SFworkProcAdded = 0; + + return True; +} diff --git a/cmd/lefty/ws/x11/libfilereq/Makefile.am b/cmd/lefty/ws/x11/libfilereq/Makefile.am new file mode 100644 index 000000000..4b5bcbc1a --- /dev/null +++ b/cmd/lefty/ws/x11/libfilereq/Makefile.am @@ -0,0 +1,14 @@ +## Process this file with automake to produce Makefile.in + +AM_CPPFLAGS = @X_CFLAGS@ \ + $(XAW_INCLUDES) + +noinst_HEADERS = SFinternal.h SFDecls.h xstat.h +if WITH_X +noinst_LTLIBRARIES = libfilereq.la +endif + +libfilereq_la_SOURCES = Dir.c Draw.c Path.c SelFile.c +libfilereq_la_LIBADD = $(XAW_LIBS) + +EXTRA_DIST = README.selfile diff --git a/cmd/lefty/ws/x11/libfilereq/Path.c b/cmd/lefty/ws/x11/libfilereq/Path.c new file mode 100644 index 000000000..cfaceaa55 --- /dev/null +++ b/cmd/lefty/ws/x11/libfilereq/Path.c @@ -0,0 +1,893 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef FEATURE_CS +#include <ast.h> +#endif +/* + * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Software Research Associates + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Erik M. van der Poel + * Software Research Associates, Inc., Tokyo, Japan + * erik@sra.co.jp + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> + +#ifdef SEL_FILE_IGNORE_CASE +#include <ctype.h> +#endif /* def SEL_FILE_IGNORE_CASE */ + +#include <X11/Xos.h> +#include <pwd.h> +#include "SFinternal.h" +#include "xstat.h" +#include <X11/Xaw/Scrollbar.h> + +#if defined(SVR4) || defined(SYSV) || defined(USG) +extern uid_t getuid(); +extern void qsort(); +#endif /* defined(SVR4) || defined(SYSV) || defined(USG) */ + +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#include "SFDecls.h" + +typedef struct { + char *name; + char *dir; +} SFLogin; + +SFDir *SFdirs = NULL; + +int SFdirEnd; + +int SFdirPtr; + +int SFbuttonPressed = 0; + +static int SFdoNotTouchDirPtr = 0; + +static int SFdoNotTouchVorigin = 0; + +static SFDir SFrootDir, SFhomeDir; + +static SFLogin *SFlogins; + +static int SFtwiddle = 0; + +void SFsetText(char *path); + +int SFchdir(path) +char *path; +{ + int result; + + result = 0; + + if (strcmp(path, SFcurrentDir)) { + result = chdir(path); + if (!result) { + (void) strcpy(SFcurrentDir, path); + } + } + + return result; +} + +static void SFfree(i) +int i; +{ + register SFDir *dir; + register int j; + + dir = &(SFdirs[i]); + + for (j = dir->nEntries - 1; j >= 0; j--) { + if (dir->entries[j].shown != dir->entries[j].real) { + XtFree(dir->entries[j].shown); + } + XtFree(dir->entries[j].real); + } + + XtFree((char *) dir->entries); + + XtFree(dir->dir); + + dir->dir = NULL; +} + +static void SFstrdup(s1, s2) +char **s1; +char *s2; +{ + *s1 = strcpy(XtMalloc((unsigned) (strlen(s2) + 1)), s2); +} + +static void SFunreadableDir(dir) +SFDir *dir; +{ + char *cannotOpen = "<cannot open> "; + + dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry)); + dir->entries[0].statDone = 1; + SFstrdup(&dir->entries[0].real, cannotOpen); + dir->entries[0].shown = dir->entries[0].real; + dir->nEntries = 1; + dir->nChars = strlen(cannotOpen); +} + +#ifdef SEL_FILE_IGNORE_CASE +static SFstrncmp(p, q, n) +register char *p, *q; +register int n; +{ + register char c1, c2; + char *psave, *qsave; + int nsave; + + psave = p; + qsave = q; + nsave = n; + + c1 = *p++; + if (islower(c1)) { + c1 = toupper(c1); + } + c2 = *q++; + if (islower(c2)) { + c2 = toupper(c2); + } + + while ((--n >= 0) && (c1 == c2)) { + if (!c1) { + return strncmp(psave, qsave, nsave); + } + c1 = *p++; + if (islower(c1)) { + c1 = toupper(c1); + } + c2 = *q++; + if (islower(c2)) { + c2 = toupper(c2); + } + } + + if (n < 0) { + return strncmp(psave, qsave, nsave); + } + + return c1 - c2; +} +#endif /* def SEL_FILE_IGNORE_CASE */ + +static void SFreplaceText(dir, str) +SFDir *dir; +char *str; +{ + int len; + + *(dir->path) = 0; + len = strlen(str); + if (str[len - 1] == '/') { + (void) strcat(SFcurrentPath, str); + } else { + (void) strncat(SFcurrentPath, str, len - 1); + } + if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) { + SFsetText(SFcurrentPath); + } else { + SFsetText(&(SFcurrentPath[strlen(SFstartDir)])); + } + + SFtextChanged(); +} + +static void SFexpand(str) +char *str; +{ + int len; + int cmp; + char *name, *growing; + SFDir *dir; + SFEntry *entry, *max; + + len = strlen(str); + + dir = &(SFdirs[SFdirEnd - 1]); + + if (dir->beginSelection == -1) { + SFstrdup(&str, str); + SFreplaceText(dir, str); + XtFree(str); + return; + } else if (dir->beginSelection == dir->endSelection) { + SFreplaceText(dir, dir->entries[dir->beginSelection].shown); + return; + } + + max = &(dir->entries[dir->endSelection + 1]); + + name = dir->entries[dir->beginSelection].shown; + SFstrdup(&growing, name); + + cmp = 0; + while (!cmp) { + entry = &(dir->entries[dir->beginSelection]); + while (entry < max) { + if ((cmp = strncmp(growing, entry->shown, len))) { + break; + } + entry++; + } + len++; + } + + /* + * SFreplaceText() expects filename + */ + growing[len - 2] = ' '; + + growing[len - 1] = 0; + SFreplaceText(dir, growing); + XtFree(growing); +} + +static int SFfindFile(dir, str) +SFDir *dir; +register char *str; +{ + register int i, last, max; + register char *name, save; + SFEntry *entries; + int len; + int begin, end; + int result; + + len = strlen(str); + + if (str[len - 1] == ' ') { + SFexpand(str); + return 1; + } else if (str[len - 1] == '/') { + len--; + } + + max = dir->nEntries; + + entries = dir->entries; + + i = 0; + while (i < max) { + name = entries[i].shown; + last = strlen(name) - 1; + save = name[last]; + name[last] = 0; + +#ifdef SEL_FILE_IGNORE_CASE + result = SFstrncmp(str, name, len); +#else /* def SEL_FILE_IGNORE_CASE */ + result = strncmp(str, name, len); +#endif /* def SEL_FILE_IGNORE_CASE */ + + name[last] = save; + if (result <= 0) { + break; + } + i++; + } + begin = i; + while (i < max) { + name = entries[i].shown; + last = strlen(name) - 1; + save = name[last]; + name[last] = 0; + +#ifdef SEL_FILE_IGNORE_CASE + result = SFstrncmp(str, name, len); +#else /* def SEL_FILE_IGNORE_CASE */ + result = strncmp(str, name, len); +#endif /* def SEL_FILE_IGNORE_CASE */ + + name[last] = save; + if (result) { + break; + } + i++; + } + end = i; + + if (begin != end) { + if ((dir->beginSelection != begin) || + (dir->endSelection != end - 1) + ) { + dir->changed = 1; + dir->beginSelection = begin; + if (str[strlen(str) - 1] == '/') { + dir->endSelection = begin; + } else { + dir->endSelection = end - 1; + } + } + } else { + if (dir->beginSelection != -1) { + dir->changed = 1; + dir->beginSelection = -1; + dir->endSelection = -1; + } + } + + if (SFdoNotTouchVorigin || + ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize)) + ) { + SFdoNotTouchVorigin = 0; + return 0; + } + + i = begin - 1; + if (i > max - SFlistSize) { + i = max - SFlistSize; + } + if (i < 0) { + i = 0; + } + + if (dir->vOrigin != i) { + dir->vOrigin = i; + dir->changed = 1; + } + + return 0; +} + +static void SFunselect() +{ + SFDir *dir; + + dir = &(SFdirs[SFdirEnd - 1]); + if (dir->beginSelection != -1) { + dir->changed = 1; + } + dir->beginSelection = -1; + dir->endSelection = -1; +} + +static int SFcompareLogins(const void *vp, const void *vq) +{ + SFLogin *p = (SFLogin *) vp, *q = (SFLogin *) vq; + return strcmp(p->name, q->name); +} + +static void SFgetHomeDirs() +{ + struct passwd *pw; + int alloc; + int i; + SFEntry *entries = NULL; + int len; + int maxChars; + + { + alloc = 1; + i = 1; + entries = (SFEntry *) XtMalloc(sizeof(SFEntry)); + SFlogins = (SFLogin *) XtMalloc(sizeof(SFLogin)); + entries[0].real = XtMalloc(3); + (void) strcpy(entries[0].real, "~"); + entries[0].shown = entries[0].real; + entries[0].statDone = 1; + SFlogins[0].name = ""; + pw = getpwuid((int) getuid()); + SFstrdup(&SFlogins[0].dir, pw ? pw->pw_dir : "/"); + maxChars = 0; + } + + (void) setpwent(); + + while ((pw = getpwent()) && (*(pw->pw_name))) { + if (i >= alloc) { + alloc *= 2; + entries = (SFEntry *) XtRealloc((char *) entries, + (unsigned) (alloc * + sizeof(SFEntry)) + ); + SFlogins = (SFLogin *) XtRealloc((char *) SFlogins, + (unsigned) (alloc * + sizeof(SFLogin)) + ); + } + len = strlen(pw->pw_name); + entries[i].real = XtMalloc((unsigned) (len + 3)); + (void) strcat(strcpy(entries[i].real, "~"), pw->pw_name); + entries[i].shown = entries[i].real; + entries[i].statDone = 1; + if (len > maxChars) { + maxChars = len; + } + SFstrdup(&SFlogins[i].name, pw->pw_name); + SFstrdup(&SFlogins[i].dir, pw->pw_dir); + i++; + } + + SFhomeDir.dir = XtMalloc(1); + SFhomeDir.dir[0] = 0; + SFhomeDir.path = SFcurrentPath; + SFhomeDir.entries = entries; + SFhomeDir.nEntries = i; + SFhomeDir.vOrigin = 0; /* :-) */ + SFhomeDir.nChars = maxChars + 2; + SFhomeDir.hOrigin = 0; + SFhomeDir.changed = 1; + SFhomeDir.beginSelection = -1; + SFhomeDir.endSelection = -1; + +#if defined(SVR4) || defined(SYSV) || defined(USG) + qsort((char *) entries, (unsigned) i, sizeof(SFEntry), + SFcompareEntries); + qsort((char *) SFlogins, (unsigned) i, sizeof(SFLogin), + SFcompareLogins); +#else /* defined(SVR4) || defined(SYSV) || defined(USG) */ + qsort((char *) entries, i, sizeof(SFEntry), SFcompareEntries); + qsort((char *) SFlogins, i, sizeof(SFLogin), SFcompareLogins); +#endif /* defined(SVR4) || defined(SYSV) || defined(USG) */ + + for (i--; i >= 0; i--) { + (void) strcat(entries[i].real, "/"); + } +} + +static int SFfindHomeDir(begin, end) +char *begin, *end; +{ + char save; + char *theRest; + int i; + + save = *end; + *end = 0; + + for (i = SFhomeDir.nEntries - 1; i >= 0; i--) { + if (!strcmp(SFhomeDir.entries[i].real, begin)) { + *end = save; + SFstrdup(&theRest, end); + (void) strcat(strcat(strcpy(SFcurrentPath, + SFlogins[i].dir), "/"), theRest); + XtFree(theRest); + SFsetText(SFcurrentPath); + SFtextChanged(); + return 1; + } + } + + *end = save; + + return 0; +} + +void SFupdatePath() +{ + static int alloc; + static int wasTwiddle = 0; + char *begin, *end; + int i, j; + int prevChange; + int SFdirPtrSave, SFdirEndSave; + SFDir *dir; + + if (!SFdirs) { + SFdirs = (SFDir *) XtMalloc((alloc = 10) * sizeof(SFDir)); + dir = &(SFdirs[0]); + SFstrdup(&dir->dir, "/"); + (void) SFchdir("/"); + (void) SFgetDir(dir); + for (j = 1; j < alloc; j++) { + SFdirs[j].dir = NULL; + } + dir->path = SFcurrentPath + 1; + dir->vOrigin = 0; + dir->hOrigin = 0; + dir->changed = 1; + dir->beginSelection = -1; + dir->endSelection = -1; + SFhomeDir.dir = NULL; + } + + SFdirEndSave = SFdirEnd; + SFdirEnd = 1; + + SFdirPtrSave = SFdirPtr; + SFdirPtr = 0; + + begin = NULL; + + if (SFcurrentPath[0] == '~') { + if (!SFtwiddle) { + SFtwiddle = 1; + dir = &(SFdirs[0]); + SFrootDir = *dir; + if (!SFhomeDir.dir) { + SFgetHomeDirs(); + } + *dir = SFhomeDir; + dir->changed = 1; + } + end = SFcurrentPath; + SFdoNotTouchDirPtr = 1; + wasTwiddle = 1; + } else { + if (SFtwiddle) { + SFtwiddle = 0; + dir = &(SFdirs[0]); + *dir = SFrootDir; + dir->changed = 1; + } + end = SFcurrentPath + 1; + } + + i = 0; + + prevChange = 0; + + while (*end) { + while (*end++ == '/') { + ; + } + end--; + begin = end; + while ((*end) && (*end++ != '/')) { + ; + } + if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/')) { + SFdirPtr = i - 1; + if (SFdirPtr < 0) { + SFdirPtr = 0; + } + } + if (*begin) { + if (*(end - 1) == '/') { + char save = *end; + + if (SFtwiddle) { + if (SFfindHomeDir(begin, end)) { + return; + } + } + *end = 0; + i++; + SFdirEnd++; + if (i >= alloc) { + SFdirs = (SFDir *) XtRealloc((char *) SFdirs, + (unsigned) ((alloc *= 2) * + sizeof(SFDir)) + ); + for (j = alloc / 2; j < alloc; j++) { + SFdirs[j].dir = NULL; + } + } + dir = &(SFdirs[i]); + if ((!(dir->dir)) || prevChange || strcmp(dir->dir, begin) + ) { + if (dir->dir) { + SFfree(i); + } + prevChange = 1; + SFstrdup(&dir->dir, begin); + dir->path = end; + dir->vOrigin = 0; + dir->hOrigin = 0; + dir->changed = 1; + dir->beginSelection = -1; + dir->endSelection = -1; + (void) SFfindFile(dir - 1, begin); + if (SFchdir(SFcurrentPath) || SFgetDir(dir) + ) { + SFunreadableDir(dir); + break; + } + } + *end = save; + if (!save) { + SFunselect(); + } + } else { + if (SFfindFile(&(SFdirs[SFdirEnd - 1]), begin)) { + return; + } + } + } else { + SFunselect(); + } + } + + if ((end == SFcurrentPath + 1) && (!SFtwiddle)) { + SFunselect(); + } + + for (i = SFdirEnd; i < alloc; i++) { + if (SFdirs[i].dir) { + SFfree(i); + } + } + + if (SFdoNotTouchDirPtr) { + if (wasTwiddle) { + wasTwiddle = 0; + SFdirPtr = SFdirEnd - 2; + if (SFdirPtr < 0) { + SFdirPtr = 0; + } + } else { + SFdirPtr = SFdirPtrSave; + } + SFdoNotTouchDirPtr = 0; + } + + if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave)) { + XawScrollbarSetThumb(selFileHScroll, + (float) (((double) SFdirPtr) / SFdirEnd), + (float) (((double) + ((SFdirEnd < + 3) ? SFdirEnd : 3)) / SFdirEnd) + ); + } + + if (SFdirPtr != SFdirPtrSave) { + SFdrawLists(SF_DO_SCROLL); + } else { + for (i = 0; i < 3; i++) { + if (SFdirPtr + i < SFdirEnd) { + if (SFdirs[SFdirPtr + i].changed) { + SFdirs[SFdirPtr + i].changed = 0; + SFdrawList(i, SF_DO_SCROLL); + } + } else { + SFclearList(i, SF_DO_SCROLL); + } + } + } +} + +void SFsetText(path) +char *path; +{ + XawTextBlock text; + + text.firstPos = 0; + text.length = strlen(path); + text.ptr = path; + text.format = FMT8BIT; + + XawTextReplace(selFileField, 0, strlen(SFtextBuffer), &text); + XawTextSetInsertionPoint(selFileField, strlen(SFtextBuffer)); +} + +/* ARGSUSED */ +void SFbuttonPressList(w, n, event) +Widget w; +int n; +XButtonPressedEvent *event; +{ + SFbuttonPressed = 1; +} + +/* ARGSUSED */ +void SFbuttonReleaseList(w, n, event) +Widget w; +int n; +XButtonReleasedEvent *event; +{ + SFDir *dir; + + SFbuttonPressed = 0; + + if (SFcurrentInvert[n] != -1) { + if (n < 2) { + SFdoNotTouchDirPtr = 1; + } + SFdoNotTouchVorigin = 1; + dir = &(SFdirs[SFdirPtr + n]); + SFreplaceText(dir, + dir->entries[dir->vOrigin + + SFcurrentInvert[n]].shown); + SFmotionList(w, n, event); + } +} + +static int SFcheckDir(n, dir) +int n; +SFDir *dir; +{ + struct stat statBuf; + int i; + + if ((!stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime) + ) { + + /* + * If the pointer is currently in the window that we are about + * to update, we must warp it to prevent the user from + * accidentally selecting the wrong file. + */ + if (SFcurrentInvert[n] != -1) { + XWarpPointer(SFdisplay, + None, + XtWindow(selFileLists[n]), 0, 0, 0, 0, 0, 0); + } + + for (i = dir->nEntries - 1; i >= 0; i--) { + if (dir->entries[i].shown != dir->entries[i].real) { + XtFree(dir->entries[i].shown); + } + XtFree(dir->entries[i].real); + } + XtFree((char *) dir->entries); + if (SFgetDir(dir)) { + SFunreadableDir(dir); + } + if (dir->vOrigin > dir->nEntries - SFlistSize) { + dir->vOrigin = dir->nEntries - SFlistSize; + } + if (dir->vOrigin < 0) { + dir->vOrigin = 0; + } + if (dir->hOrigin > dir->nChars - SFcharsPerEntry) { + dir->hOrigin = dir->nChars - SFcharsPerEntry; + } + if (dir->hOrigin < 0) { + dir->hOrigin = 0; + } + dir->beginSelection = -1; + dir->endSelection = -1; + SFdoNotTouchVorigin = 1; + if ((dir + 1)->dir) { + (void) SFfindFile(dir, (dir + 1)->dir); + } else { + (void) SFfindFile(dir, dir->path); + } + + if (!SFworkProcAdded) { + SFworkProcId = XtAppAddWorkProc(SFapp, SFworkProc, NULL); + SFworkProcAdded = 1; + } + + return 1; + } + + return 0; +} + +static int SFcheckFiles(dir) +SFDir *dir; +{ + int from, to; + int result; + char old, new; + int i; + char *str; + int last; + struct stat statBuf; + + result = 0; + + from = dir->vOrigin; + to = dir->vOrigin + SFlistSize; + if (to > dir->nEntries) { + to = dir->nEntries; + } + + for (i = from; i < to; i++) { + str = dir->entries[i].real; + last = strlen(str) - 1; + old = str[last]; + str[last] = 0; + if (stat(str, &statBuf)) { + new = ' '; + } else { + new = SFstatChar(&statBuf); + } + str[last] = new; + if (new != old) { + result = 1; + } + } + + return result; +} + +void SFdirModTimer(cl, id) +XtPointer cl; +XtIntervalId *id; +{ + static int n = -1; + static int f = 0; + char save; + SFDir *dir; + + if ((!SFtwiddle) && (SFdirPtr < SFdirEnd)) { + n++; + if ((n > 2) || (SFdirPtr + n >= SFdirEnd)) { + n = 0; + f++; + if ((f > 2) || (SFdirPtr + f >= SFdirEnd)) { + f = 0; + } + } + dir = &(SFdirs[SFdirPtr + n]); + save = *(dir->path); + *(dir->path) = 0; + if (SFchdir(SFcurrentPath)) { + *(dir->path) = save; + + /* + * force a re-read + */ + *(dir->dir) = 0; + + SFupdatePath(); + } else { + *(dir->path) = save; + if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir)) + ) { + SFdrawList(n, SF_DO_SCROLL); + } + } + } + + SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000, + SFdirModTimer, (XtPointer) NULL); +} + +/* Return a single character describing what kind of file STATBUF is. */ + +char SFstatChar(statBuf) +struct stat *statBuf; +{ + if (S_ISDIR(statBuf->st_mode)) { + return '/'; + } else if (S_ISREG(statBuf->st_mode)) { + return S_ISXXX(statBuf->st_mode) ? '*' : ' '; +#ifdef S_ISSOCK + } else if (S_ISSOCK(statBuf->st_mode)) { + return '='; +#endif /* S_ISSOCK */ + } else { + return ' '; + } +} -- 2.40.0