--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+ }
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+//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
+
--- /dev/null
+/* $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
--- /dev/null
+/* $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)
+{
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+*.la
+*.lo
+.deps
+.libs
+Makefile
+Makefile.in
--- /dev/null
+## 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)
--- /dev/null
+/* $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);
+ }
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+*.la
+*.lo
+.deps
+.libs
+Makefile
+Makefile.in
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+## 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
--- /dev/null
+/* $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 ' ';
+ }
+}