diff options
Diffstat (limited to 'xorg-server/hw/dmx/config/xdmxconfig.c')
-rw-r--r-- | xorg-server/hw/dmx/config/xdmxconfig.c | 1191 |
1 files changed, 1191 insertions, 0 deletions
diff --git a/xorg-server/hw/dmx/config/xdmxconfig.c b/xorg-server/hw/dmx/config/xdmxconfig.c new file mode 100644 index 000000000..033b52512 --- /dev/null +++ b/xorg-server/hw/dmx/config/xdmxconfig.c @@ -0,0 +1,1191 @@ +/* + * Copyright 2002 Red Hat Inc., Durham, North Carolina. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Authors: + * Rickard E. (Rik) Faith <faith@redhat.com> + * + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Box.h> +/* #include <X11/Xaw/Paned.h> */ +#include <X11/Xaw/Command.h> +#include <X11/Xaw/SimpleMenu.h> +#include <X11/Xaw/SmeBSB.h> +#include <X11/Xaw/MenuButton.h> +#include <X11/Xaw/Viewport.h> +#include <X11/Xaw/Dialog.h> +#include <X11/keysym.h> +#include <X11/Xmu/SysUtil.h> +#include "Canvas.h" + +#include "dmxparse.h" +#include "dmxprint.h" +#include "dmxlog.h" + +extern int yyparse(void); +extern FILE *yyin; + +#define DMX_INFO "xdmxconfig v0.9\nCopyright 2002 Red Hat Inc.\n" + +#define DMX_MAIN_WIDTH 800 +#define DMX_MAIN_HEIGHT 600 +#define DMX_DATA_WIDTH 200 +#define DMX_DATA_HEIGHT 200 +#define DMX_CANVAS_WIDTH 400 +#define DMX_CANVAS_HEIGHT 500 + +DMXConfigEntryPtr dmxConfigEntry; +static DMXConfigVirtualPtr dmxConfigCurrent, dmxConfigNewVirtual; +static DMXConfigDisplayPtr dmxConfigCurrentDisplay, dmxConfigNewDisplay; +static int dmxConfigGrabbed, dmxConfigGrabbedFine; +static int dmxConfigGrabbedX, dmxConfigGrabbedY; +static char *dmxConfigFilename; +static GC dmxConfigGC, dmxConfigGCRev, dmxConfigGCHL; +static int dmxConfigGCInit = 0; +static Dimension dmxConfigWidgetWidth, dmxConfigWidgetHeight; +static Dimension dmxConfigWallWidth, dmxConfigWallHeight; +static double dmxConfigScaleX, dmxConfigScaleY; +static int dmxConfigNotSaved; +static enum { + dmxConfigStateOpen, + dmxConfigStateSave +} dmxConfigState; + +/* Global widgets */ +static Widget canvas; +static Widget cnamebox, cdimbox; +static Widget openpopup, opendialog; +static Widget namebox, dimbox, rtbox, origbox; +static Widget okbutton, buttonpopup; +static Widget ecbutton, dcbutton; +static Widget ndbutton0, ndbutton1, edbutton, ddbutton; +static Widget ecpopup, ecdialog0, ecdialog1; +static Widget edpopup, eddialog0, eddialog1, eddialog2; +static Widget aboutpopup, quitpopup; + +static void dmxConfigCanvasGCs(void) +{ + Display *dpy = XtDisplay(canvas); + Window win = XtWindow(canvas); + XGCValues gcvals; + unsigned long mask; + Colormap colormap; + XColor fg, bg, hl, tmp; + + if (dmxConfigGCInit++) return; + + XtVaGetValues(canvas, XtNcolormap, &colormap, NULL); + XAllocNamedColor(XtDisplay(canvas), colormap, "black", &bg, &tmp); + XAllocNamedColor(XtDisplay(canvas), colormap, "white", &fg, &tmp); + XAllocNamedColor(XtDisplay(canvas), colormap, "red", &hl, &tmp); + + mask = (GCFunction | GCPlaneMask | GCClipMask | GCForeground | + GCBackground | GCLineWidth | GCLineStyle | GCCapStyle | + GCFillStyle); + + /* FIXME: copy this from widget */ + gcvals.function = GXcopy; + gcvals.plane_mask = AllPlanes; + gcvals.clip_mask = None; + gcvals.foreground = fg.pixel; + gcvals.background = bg.pixel; + gcvals.line_width = 0; + gcvals.line_style = LineSolid; + gcvals.cap_style = CapNotLast; + gcvals.fill_style = FillSolid; + + dmxConfigGC = XCreateGC(dpy, win, mask, &gcvals); + gcvals.foreground = hl.pixel; + dmxConfigGCHL = XCreateGC(dpy, win, mask, &gcvals); + gcvals.foreground = bg.pixel; + gcvals.background = fg.pixel; + dmxConfigGCRev = XCreateGC(dpy, win, mask, &gcvals); +} + +static void dmxConfigGetDims(int *maxWidth, int *maxHeight) +{ + DMXConfigSubPtr pt; + DMXConfigEntryPtr e; + + *maxWidth = dmxConfigWallWidth = 0; + *maxWidth = dmxConfigWallHeight = 0; + if (!dmxConfigCurrent) return; + + dmxConfigWallWidth = dmxConfigCurrent->width; + dmxConfigWallHeight = dmxConfigCurrent->height; + if (!dmxConfigWallWidth || !dmxConfigWallHeight) { + for (pt = dmxConfigCurrent->subentry; pt; pt = pt->next) { + if (pt->type == dmxConfigDisplay) { + int x = pt->display->scrnWidth + pt->display->rootXOrigin; + int y = pt->display->scrnHeight + pt->display->rootYOrigin; + if (x > dmxConfigWallWidth) dmxConfigWallWidth = x; + if (y > dmxConfigWallHeight) dmxConfigWallHeight = y; + } + } + } + /* Compute maximums */ + *maxWidth = *maxHeight = 0; + for (e = dmxConfigEntry; e; e = e->next) { + if (e->type != dmxConfigVirtual) continue; + for (pt = e->virtual->subentry; pt; pt = pt->next) { + if (pt->type == dmxConfigDisplay) { + int x = pt->display->scrnWidth + pt->display->rootXOrigin; + int y = pt->display->scrnHeight + pt->display->rootYOrigin; + if (x > *maxWidth) *maxWidth = x; + if (y > *maxHeight) *maxHeight = y; + } + } + } + if (dmxConfigWallWidth > *maxWidth) *maxWidth = dmxConfigWallWidth; + if (dmxConfigWallHeight > *maxHeight) *maxHeight = dmxConfigWallHeight; +} + +static int scalex(int x) { return (int)((x * dmxConfigScaleX) + .5); } +static int scaley(int y) { return (int)((y * dmxConfigScaleY) + .5); } +static int unscalex(int x) { return (int)((x / dmxConfigScaleX) + .5); } +static int unscaley(int y) { return (int)((y / dmxConfigScaleY) + .5); } + +static void dmxConfigDataUpdate(void) +{ + /* FIXME: could result in buffer overflows */ + char cnambuf[512]; + char cdimbuf[128]; + char nambuf[512]; + char dimbuf[128]; + char rtbuf[128]; + char offbuf[128]; + const char *name; + + if (!dmxConfigCurrent) { + XtVaSetValues(cnamebox, XtNlabel, "", XtNsensitive, False, NULL); + XtVaSetValues(cdimbox, XtNlabel, "", XtNsensitive, False, NULL); + XtVaSetValues(ecbutton, XtNsensitive, False, NULL); + XtVaSetValues(dcbutton, XtNsensitive, False, NULL); + XtVaSetValues(ndbutton0, XtNsensitive, False, NULL); + XtVaSetValues(ndbutton1, XtNsensitive, False, NULL); + } else { + name = dmxConfigCurrent->name; + XmuSnprintf(cnambuf, sizeof(cnambuf), "%s", name ? name : ""); + XmuSnprintf(cdimbuf, sizeof(cdimbuf), "%dx%d", + dmxConfigWallWidth, dmxConfigWallHeight); + XtVaSetValues(cnamebox, XtNlabel, cnambuf, XtNsensitive, True, NULL); + XtVaSetValues(cdimbox, XtNlabel, cdimbuf, XtNsensitive, True, NULL); + XtVaSetValues(ecbutton, XtNsensitive, True, NULL); + XtVaSetValues(dcbutton, XtNsensitive, True, NULL); + XtVaSetValues(ndbutton0, XtNsensitive, True, NULL); + XtVaSetValues(ndbutton1, XtNsensitive, True, NULL); + } + + if (!dmxConfigCurrentDisplay) { + XtVaSetValues(namebox, XtNlabel, "", XtNsensitive, False, NULL); + XtVaSetValues(dimbox, XtNlabel, "", XtNsensitive, False, NULL); + XtVaSetValues(rtbox, XtNlabel, "", XtNsensitive, False, NULL); + XtVaSetValues(origbox, XtNlabel, "", XtNsensitive, False, NULL); + XtVaSetValues(edbutton, XtNsensitive, False, NULL); + XtVaSetValues(ddbutton, XtNsensitive, False, NULL); + } else { + name = dmxConfigCurrentDisplay->name; + XmuSnprintf(nambuf, sizeof(nambuf), "%s", name ? name : ""); + XmuSnprintf(dimbuf, sizeof(dimbuf), "%dx%d%c%d%c%d", + dmxConfigCurrentDisplay->scrnWidth, + dmxConfigCurrentDisplay->scrnHeight, + dmxConfigCurrentDisplay->scrnXSign < 0 ? '-' : '+', + dmxConfigCurrentDisplay->scrnX, + dmxConfigCurrentDisplay->scrnYSign < 0 ? '-' : '+', + dmxConfigCurrentDisplay->scrnY); + XmuSnprintf(rtbuf, sizeof(dimbuf), "%dx%d%c%d%c%d", + dmxConfigCurrentDisplay->rootWidth, + dmxConfigCurrentDisplay->rootHeight, + dmxConfigCurrentDisplay->rootXSign < 0 ? '-' : '+', + dmxConfigCurrentDisplay->rootX, + dmxConfigCurrentDisplay->rootYSign < 0 ? '-' : '+', + dmxConfigCurrentDisplay->rootY); + XmuSnprintf(offbuf, sizeof(offbuf), "@%dx%d", + dmxConfigCurrentDisplay->rootXOrigin, + dmxConfigCurrentDisplay->rootYOrigin); + XtVaSetValues(namebox, XtNlabel, nambuf, XtNsensitive, True, NULL); + XtVaSetValues(dimbox, XtNlabel, dimbuf, XtNsensitive, True, NULL); + XtVaSetValues(rtbox, XtNlabel, rtbuf, XtNsensitive, True, NULL); + XtVaSetValues(origbox, XtNlabel, offbuf, XtNsensitive, True, NULL); + XtVaSetValues(edbutton, XtNsensitive, True, NULL); + XtVaSetValues(ddbutton, XtNsensitive, True, NULL); + } +} + +static void dmxConfigCanvasUpdate(void) +{ + DMXConfigSubPtr pt; + Display *dpy = XtDisplay(canvas); + Window win = XtWindow(canvas); + GContext gcontext = XGContextFromGC(dmxConfigGC); + XFontStruct *fs; + int w, h; + + XFillRectangle(dpy, win, dmxConfigGCRev, + 0, 0, dmxConfigWidgetWidth, dmxConfigWidgetHeight); + dmxConfigDataUpdate(); + if (!dmxConfigCurrent) return; + + w = scalex(dmxConfigWallWidth); + h = scaley(dmxConfigWallHeight); + if (w > dmxConfigWidgetWidth - 1) w = dmxConfigWidgetWidth - 1; + if (h > dmxConfigWidgetHeight - 1) h = dmxConfigWidgetHeight - 1; + XDrawRectangle(dpy, win, dmxConfigGC, 0, 0, w, h); + fs = XQueryFont(dpy, gcontext); + for (pt = dmxConfigCurrent->subentry; pt; pt = pt->next) { + int x, y, len; + int xo = 3, yo = fs->ascent + fs->descent + 2; + GC gc; + + if (pt->type != dmxConfigDisplay) continue; + gc = (pt->display == dmxConfigCurrentDisplay + ? dmxConfigGCHL + : dmxConfigGC); + x = scalex(pt->display->rootXOrigin); + y = scaley(pt->display->rootYOrigin); + w = scalex(pt->display->scrnWidth); + h = scaley(pt->display->scrnHeight); + len = pt->display->name ? strlen(pt->display->name) : 0; + if (x > dmxConfigWidgetWidth - 1) x = dmxConfigWidgetWidth - 1; + if (y > dmxConfigWidgetHeight - 1) y = dmxConfigWidgetHeight - 1; + XDrawRectangle(dpy, win, gc, x, y, w, h); + if (fs && len) { + while (len && XTextWidth(fs, pt->display->name, len) >= w - 2 * xo) + --len; + if (len) + XDrawString(dpy, win, gc, x+xo, y+yo, pt->display->name, len); + } + } + if (fs) XFreeFontInfo(NULL, fs, 0); +} + +static void dmxConfigCanvasDraw(Region region) +{ + Display *dpy = XtDisplay(canvas); + int maxWidth, maxHeight; + + dmxConfigCanvasGCs(); + if (region) { + XSetRegion(dpy, dmxConfigGC, region); + XSetRegion(dpy, dmxConfigGCRev, region); + XSetRegion(dpy, dmxConfigGCHL, region); + } + XtVaGetValues(canvas, + XtNwidth, &dmxConfigWidgetWidth, + XtNheight, &dmxConfigWidgetHeight, + NULL); + dmxConfigGetDims(&maxWidth, &maxHeight); + dmxConfigScaleX = (double)dmxConfigWidgetWidth / maxWidth; + dmxConfigScaleY = (double)dmxConfigWidgetHeight / maxHeight; + if (dmxConfigScaleX > dmxConfigScaleY) dmxConfigScaleX = dmxConfigScaleY; + if (dmxConfigScaleY > dmxConfigScaleX) dmxConfigScaleY = dmxConfigScaleX; + dmxConfigCanvasUpdate(); + if (region) { + XSetClipMask(dpy, dmxConfigGC, None); + XSetClipMask(dpy, dmxConfigGCRev, None); + XSetClipMask(dpy, dmxConfigGCHL, None); + } +} + +static void dmxConfigSelectCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + dmxConfigCurrent = closure; + dmxConfigVirtualPrint(stdout, dmxConfigCurrent); + dmxConfigCanvasDraw(NULL); +} + +static void dmxConfigCopystrings(void) +{ + DMXConfigEntryPtr pt; + DMXConfigSubPtr sub; + + if (!dmxConfigCurrent) return; + + /* FIXME: this is all a per-config file + * memory leak */ + for (pt = dmxConfigEntry; pt; pt = pt->next) { + if (pt->type == dmxConfigVirtual) { + pt->virtual->name = XtNewString(pt->virtual->name + ? pt->virtual->name + : ""); + + for (sub = pt->virtual->subentry; sub; sub = sub->next) { + if (sub->type != dmxConfigDisplay) continue; + sub->display->name = XtNewString(sub->display->name + ? sub->display->name + : ""); + } + } + } +} + +static void dmxConfigGetValueString(char **d, Widget w) +{ + const char *tmp = XawDialogGetValueString(w); + if (*d) XtFree(*d); + *d = XtNewString(tmp); +} + +static void dmxConfigSetupCnamemenu(void) +{ + static Widget cnamemenu = NULL; + Widget w; + DMXConfigEntryPtr pt; + + if (cnamemenu) XtDestroyWidget(cnamemenu); + cnamemenu = NULL; + + if (!dmxConfigCurrent) return; + cnamemenu = XtVaCreatePopupShell("cnamemenu", simpleMenuWidgetClass, + cnamebox, + NULL); + + for (pt = dmxConfigEntry; pt; pt = pt->next) { + if (pt->type == dmxConfigVirtual) { + w = XtVaCreateManagedWidget(pt->virtual->name + ? pt->virtual->name + : "", + smeBSBObjectClass, cnamemenu, + NULL); + XtAddCallback(w, XtNcallback, + dmxConfigSelectCallback, pt->virtual); + } + } +} + +static void dmxConfigReadFile(void) +{ + FILE *str; + DMXConfigEntryPtr pt; + + if (!(str = fopen(dmxConfigFilename, "r"))) { + dmxLog(dmxWarning, "Unable to read configuration file %s\n", + dmxConfigFilename); + return; + } + yyin = str; + yydebug = 0; + yyparse(); + fclose(str); + dmxLog(dmxInfo, "Read configuration file %s\n", dmxConfigFilename); + + for (pt = dmxConfigEntry; pt; pt = pt->next) { + if (pt->type == dmxConfigVirtual) { + dmxConfigCurrent = pt->virtual; + break; + } + } + + + + if (XtIsRealized(canvas)) { + dmxConfigCopystrings(); + dmxConfigSetupCnamemenu(); + dmxConfigCanvasDraw(NULL); + } + dmxConfigVirtualPrint(stdout, dmxConfigCurrent); +} + +static void dmxConfigWriteFile(void) +{ + FILE *str; + + if (!(str = fopen(dmxConfigFilename, "w"))) { + dmxLog(dmxWarning, "Unable to write configuration file %s\n", + dmxConfigFilename); + return; + } + dmxConfigPrint(str, dmxConfigEntry); + fclose(str); +} + +static DMXConfigDisplayPtr dmxConfigFindDisplay(int x, int y) +{ + DMXConfigSubPtr pt; + + if (!dmxConfigCurrent) return NULL; + for (pt = dmxConfigCurrent->subentry; pt; pt = pt->next) { + DMXConfigDisplayPtr d = pt->display; + if (pt->type != dmxConfigDisplay) continue; + if (x >= scalex(d->rootXOrigin) + && x <= scalex(d->rootXOrigin + d->scrnWidth) + && y >= scaley(d->rootYOrigin) + && y <= scaley(d->rootYOrigin + d->scrnHeight)) return d; + } + return NULL; +} + +static void dmxConfigSetPopupPosition(Widget popup) +{ + Position x, y; + Window t1, t2; + int root_x, root_y; + int temp_x, temp_y; + unsigned int temp; + + + XtRealizeWidget(popup); + if (!XQueryPointer(XtDisplay(popup), XtWindow(popup), &t1, &t2, + &root_x, &root_y, &temp_x, &temp_y, &temp)) + root_x = root_y = 0; + + x = root_x - 5; + y = root_y - 5; + XtVaSetValues(popup, XtNx, x, XtNy, y, NULL); +} + +static void dmxConfigPlaceMenu(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + dmxConfigSetPopupPosition(buttonpopup); +} + +static void dmxConfigMove(int deltaX, int deltaY) +{ + dmxConfigCurrentDisplay->rootXOrigin += deltaX; + dmxConfigCurrentDisplay->rootYOrigin += deltaY; + if (dmxConfigCurrentDisplay->rootXOrigin < 0) + dmxConfigCurrentDisplay->rootXOrigin = 0; + if (dmxConfigCurrentDisplay->rootYOrigin < 0) + dmxConfigCurrentDisplay->rootYOrigin = 0; + if (dmxConfigWallWidth && dmxConfigWallHeight) { + if (dmxConfigCurrentDisplay->rootXOrigin >= dmxConfigWallWidth) + dmxConfigCurrentDisplay->rootXOrigin = dmxConfigWallWidth - 1; + if (dmxConfigCurrentDisplay->rootYOrigin >= dmxConfigWallHeight) + dmxConfigCurrentDisplay->rootYOrigin = dmxConfigWallHeight - 1; + } + dmxConfigCanvasUpdate(); + dmxConfigNotSaved = 1; +} + +static void dmxConfigCanvasInput(Widget w, XtPointer closure, + XtPointer callData) +{ + XEvent *e = (XEvent *)callData; + DMXConfigDisplayPtr display = NULL; + + switch (e->type) { + case ButtonPress: + if (e->xbutton.button == Button1) { + dmxConfigGrabbed = 1; + dmxConfigGrabbedFine = 0; + dmxConfigGrabbedX = e->xbutton.x; + dmxConfigGrabbedY = e->xbutton.y; + } + if (e->xbutton.button == Button2) { + dmxConfigGrabbed = 1; + dmxConfigGrabbedFine = 1; + dmxConfigGrabbedX = e->xbutton.x; + dmxConfigGrabbedY = e->xbutton.y; + } + break; + case ButtonRelease: + if (e->xbutton.button == Button1) dmxConfigGrabbed = 0; + if (e->xbutton.button == Button2) dmxConfigGrabbed = 0; + break; + case MotionNotify: + if (dmxConfigGrabbed && dmxConfigCurrentDisplay) { + int deltaX = e->xmotion.x - dmxConfigGrabbedX; + int deltaY = e->xmotion.y - dmxConfigGrabbedY; + dmxConfigMove(dmxConfigGrabbedFine ? deltaX : unscalex(deltaX), + dmxConfigGrabbedFine ? deltaY : unscaley(deltaY)); + dmxConfigGrabbedX = e->xmotion.x; + dmxConfigGrabbedY = e->xmotion.y; + } else { + display = dmxConfigFindDisplay(e->xmotion.x, e->xmotion.y); + if (display != dmxConfigCurrentDisplay) { + dmxConfigCurrentDisplay = display; + dmxConfigCanvasUpdate(); + } + } + break; + case KeyPress: + switch (XLookupKeysym(&e->xkey, 0)) { + case XK_Right: dmxConfigMove(1,0); break; + case XK_Left: dmxConfigMove(-1,0); break; + case XK_Down: dmxConfigMove(0,1); break; + case XK_Up: dmxConfigMove(0,-1); break; + } + break; + } +} + +static void dmxConfigCanvasResize(Widget w, XtPointer closure, + XtPointer callData) +{ + dmxConfigCanvasDraw(NULL); +} + +static void dmxConfigCanvasExpose(Widget w, XtPointer closure, + XtPointer callData) +{ + CanvasExposeDataPtr data = (CanvasExposeDataPtr)callData; + + dmxConfigCanvasDraw(data->region); +} + +static void dmxConfigOpenCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + dmxConfigState = dmxConfigStateOpen; + XtVaSetValues(okbutton, XtNlabel, "Open", NULL); + dmxConfigSetPopupPosition(openpopup); + XtPopup(openpopup, XtGrabExclusive); +} + +static void dmxConfigSaveCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + dmxConfigState = dmxConfigStateSave; + XtVaSetValues(okbutton, XtNlabel, "Save", NULL); + dmxConfigSetPopupPosition(openpopup); + XtPopup(openpopup, XtGrabExclusive); +} + +static void dmxConfigOkCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + dmxConfigGetValueString(&dmxConfigFilename, opendialog); + XtPopdown(openpopup); + if (dmxConfigState == dmxConfigStateOpen) dmxConfigReadFile(); + else dmxConfigWriteFile(); + dmxConfigNotSaved = 0; +} + +static void dmxConfigCanCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + XtPopdown(openpopup); +} + +static void dmxConfigECCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + char buf[256]; /* RATS: Only used in XmuSnprintf */ + + if (!dmxConfigCurrent) return; + dmxConfigSetPopupPosition(ecpopup); + XtVaSetValues(ecdialog0, XtNvalue, + dmxConfigCurrent->name ? dmxConfigCurrent->name : "", + NULL); + XmuSnprintf(buf, sizeof(buf), "%dx%d", + dmxConfigCurrent->width, dmxConfigCurrent->height); + XtVaSetValues(ecdialog1, XtNvalue, buf, NULL); + XtPopup(ecpopup, XtGrabExclusive); +} + +static void dmxConfigNCCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + int width = 1280*2, height = 1024*2; + + if (dmxConfigCurrent) { + width = dmxConfigCurrent->width; + height = dmxConfigCurrent->height; + } + + dmxConfigCurrent = dmxConfigCreateVirtual(NULL, NULL, NULL, + NULL, NULL, NULL); + dmxConfigNewVirtual = dmxConfigCurrent; + dmxConfigCurrent->width = width; + dmxConfigCurrent->height = height; + dmxConfigEntry = dmxConfigAddEntry(dmxConfigEntry, dmxConfigVirtual, NULL, + dmxConfigCurrent); + dmxConfigECCallback(w, closure, callData); +} + +static void dmxConfigDCCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + DMXConfigEntryPtr pt; + + if (!dmxConfigEntry) return; + if (dmxConfigEntry + && dmxConfigEntry->type == dmxConfigVirtual + && dmxConfigEntry->virtual == dmxConfigCurrent) { + dmxConfigEntry = dmxConfigEntry->next; + } else { + for (pt = dmxConfigEntry; pt && pt->next; pt = pt->next) + if (pt->next->type == dmxConfigVirtual + && pt->next->virtual == dmxConfigCurrent) { + pt->next = pt->next->next; + break; + } + } + dmxConfigFreeVirtual(dmxConfigCurrent); + dmxConfigCurrent = NULL; + dmxConfigCurrentDisplay = NULL; + + /* Make the first entry current */ + for (pt = dmxConfigEntry; pt; pt = pt->next) { + if (pt->type == dmxConfigVirtual) { + dmxConfigCurrent = pt->virtual; + break; + } + } + + dmxConfigSetupCnamemenu(); + dmxConfigCanvasDraw(NULL); +} + +static void dmxConfigECOkCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + const char *value; + char *endpt; + + dmxConfigGetValueString((char **)&dmxConfigCurrent->name, ecdialog0); + value = XawDialogGetValueString(ecdialog1); + dmxConfigCurrent->width = strtol(value, &endpt, 10); + dmxConfigCurrent->height = strtol(endpt+1, NULL, 10); + XtPopdown(ecpopup); + dmxConfigCurrentDisplay = NULL; + dmxConfigNewVirtual = NULL; + dmxConfigSetupCnamemenu(); + dmxConfigCanvasDraw(NULL); + dmxConfigNotSaved = 1; +} + +static void dmxConfigECCanCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + if (dmxConfigNewVirtual) dmxConfigDCCallback(w, closure, callData); + dmxConfigNewVirtual = NULL; + XtPopdown(ecpopup); +} + +static void dmxConfigEDCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + char buf[256]; /* RATS: Only used in XmuSnprintf */ + + if (!dmxConfigCurrent || !dmxConfigCurrentDisplay) return; + dmxConfigSetPopupPosition(edpopup); + XtVaSetValues(eddialog0, XtNvalue, + dmxConfigCurrentDisplay->name + ? dmxConfigCurrentDisplay->name + : "", + NULL); + XmuSnprintf(buf, sizeof(buf), "%dx%d%c%d%c%d", + dmxConfigCurrentDisplay->scrnWidth, + dmxConfigCurrentDisplay->scrnHeight, + dmxConfigCurrentDisplay->scrnXSign < 0 ? '-' : '+', + dmxConfigCurrentDisplay->scrnY, + dmxConfigCurrentDisplay->scrnYSign < 0 ? '-' : '+', + dmxConfigCurrentDisplay->scrnY); + XtVaSetValues(eddialog1, XtNvalue, buf, NULL); + XmuSnprintf(buf, sizeof(buf), "@%dx%d", + dmxConfigCurrentDisplay->rootXOrigin, + dmxConfigCurrentDisplay->rootYOrigin); + XtVaSetValues(eddialog2, XtNvalue, buf, NULL); + XtPopup(edpopup, XtGrabExclusive); +} + +static void dmxConfigNDCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + int width = 1280, height = 1024; + + if (!dmxConfigCurrent) return; + if (dmxConfigCurrentDisplay) { + width = dmxConfigCurrentDisplay->scrnWidth; + height = dmxConfigCurrentDisplay->scrnHeight; + } + dmxConfigCurrentDisplay = dmxConfigCreateDisplay(NULL, NULL, NULL, + NULL, NULL); + dmxConfigNewDisplay = dmxConfigCurrentDisplay; + dmxConfigCurrentDisplay->scrnWidth = width; + dmxConfigCurrentDisplay->scrnHeight = height; + + dmxConfigCurrent->subentry + = dmxConfigAddSub(dmxConfigCurrent->subentry, + dmxConfigSubDisplay(dmxConfigCurrentDisplay)); + dmxConfigEDCallback(w, closure, callData); +} + +static void dmxConfigDDCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + DMXConfigSubPtr pt; + + if (!dmxConfigCurrent || !dmxConfigCurrentDisplay) return; + /* First */ + if (dmxConfigCurrent->subentry + && dmxConfigCurrent->subentry->type == dmxConfigDisplay + && dmxConfigCurrent->subentry->display == dmxConfigCurrentDisplay) { + dmxConfigCurrent->subentry = dmxConfigCurrent->subentry->next; + } else { + for (pt = dmxConfigCurrent->subentry; pt && pt->next; pt = pt->next) + if (pt->next->type == dmxConfigDisplay + && pt->next->display == dmxConfigCurrentDisplay) { + pt->next = pt->next->next; + break; + } + } + dmxConfigFreeDisplay(dmxConfigCurrentDisplay); + dmxConfigCurrentDisplay = NULL; + dmxConfigSetupCnamemenu(); + dmxConfigCanvasDraw(NULL); +} + +static void dmxConfigAboutCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + dmxConfigSetPopupPosition(aboutpopup); + XtPopup(aboutpopup, XtGrabExclusive); +} + +static void dmxConfigAboutOkCallback(Widget w, XtPointer closure, + XtPointer CallData) +{ + XtPopdown(aboutpopup); +} + +static void dmxConfigQuitCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + if (dmxConfigNotSaved) { + dmxConfigSetPopupPosition(quitpopup); + XtPopup(quitpopup, XtGrabExclusive); + return; + } + exit(0); +} + +static void dmxConfigQuitOkCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + XtPopdown(quitpopup); + exit(0); +} + +static void dmxConfigQuitCanCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + XtPopdown(quitpopup); +} + +static void dmxConfigEDOkCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + char *value; + char *endpt; + + dmxConfigNewDisplay = NULL; + dmxConfigGetValueString((char **)&dmxConfigCurrentDisplay->name, + eddialog0); + value = XawDialogGetValueString(eddialog1); + if (*value == '-' || *value == '+') { + dmxConfigCurrentDisplay->scrnWidth = 0; + dmxConfigCurrentDisplay->scrnHeight = 0; + endpt = value; + } else { + dmxConfigCurrentDisplay->scrnWidth = strtol(value, &endpt, 10); + dmxConfigCurrentDisplay->scrnHeight = strtol(endpt+1, &endpt, 10); + } + if (*endpt) { + dmxConfigCurrentDisplay->scrnXSign = (*endpt == '-') ? -1 : 1; + dmxConfigCurrentDisplay->scrnX = strtol(endpt+1, &endpt, 10); + dmxConfigCurrentDisplay->scrnYSign = (*endpt == '-') ? -1 : 1; + dmxConfigCurrentDisplay->scrnY = strtol(endpt+1, NULL, 10); + } + if (dmxConfigCurrentDisplay->scrnX < 0) + dmxConfigCurrentDisplay->scrnX = -dmxConfigCurrentDisplay->scrnX; + if (dmxConfigCurrentDisplay->scrnY < 0) + dmxConfigCurrentDisplay->scrnY = -dmxConfigCurrentDisplay->scrnY; + value = XawDialogGetValueString(eddialog2); + dmxConfigCurrentDisplay->rootXOrigin = strtol(value+1, &endpt, 10); + dmxConfigCurrentDisplay->rootYOrigin = strtol(endpt+1, NULL, 10); + XtPopdown(edpopup); + dmxConfigSetupCnamemenu(); + dmxConfigCanvasDraw(NULL); + dmxConfigNotSaved = 1; +} + +static void dmxConfigEDCanCallback(Widget w, XtPointer closure, + XtPointer callData) +{ + if (dmxConfigNewDisplay) dmxConfigDDCallback(w, closure, callData); + dmxConfigNewDisplay = NULL; + XtPopdown(edpopup); +} + +static void dmxConfigOkAction(Widget w, XEvent *event, + String *params, Cardinal *num_params) +{ + Widget p = XtParent(w); + Widget t; + + if (p == opendialog) dmxConfigOkCallback(w, NULL, NULL); + + if (p == ecdialog0) { + t = XtNameToWidget(ecdialog1, "value"); + XWarpPointer(XtDisplay(t), None, XtWindow(t), 0, 0, 0, 0, 0, 10); + } + if (p == ecdialog1) dmxConfigECOkCallback(w, NULL, NULL); + + if (p == eddialog0) { + t = XtNameToWidget(eddialog1, "value"); + XWarpPointer(XtDisplay(t), None, XtWindow(t), 0, 0, 0, 0, 0, 10); + } + if (p == eddialog1) { + t = XtNameToWidget(eddialog2, "value"); + XWarpPointer(XtDisplay(t), None, XtWindow(t), 0, 0, 0, 0, 0, 10); + } + if (p == eddialog2) dmxConfigEDOkCallback(w, NULL, NULL); +} + +int main(int argc, char **argv) +{ + XtAppContext appContext; + Widget toplevel; + Widget parent, menubox, bottombox, databox, canvasbox; + Widget filebutton, helpbutton; + Widget filemenu, openbutton, savebutton, quitbutton; + Widget helpmenu, aboutbutton, aboutbox, abouttext, aboutok; + Widget quitbox, quittext, quitok, quitcan; + Widget ncbutton; + Widget canbutton; + Widget ecbox, ecokbutton, eccanbutton; + Widget edbox, edokbutton; + Widget edcanbutton; + /* FIXME: add meta-i, ctrl,meta-z,v? */ + const char *opentrans = "<Key>Return: openOk()\n\ + <Key>Linefeed: openOk()\n\ + Ctrl<Key>M: openOk()\n\ + Ctrl<Key>J: openOk()\n\ + Ctrl<Key>O: noop()\n\ + Ctrl<Key>N: noop()\n\ + Ctrl<Key>P: noop()"; + const char *canvastrans = + "<Btn3Down>: placeMenu() XtMenuPopup(buttonpopup)"; + XtActionsRec actiontable[] = { + { "openOk", dmxConfigOkAction }, + { "placeMenu", dmxConfigPlaceMenu }, + { "noop", NULL } + }; + + dmxConfigFilename = XtNewString((argc >= 2) ? argv[1] : ""); + + toplevel = XtVaAppInitialize(&appContext, "XDmxconfig", + NULL, 0, + &argc, argv, + NULL, + NULL); + + /* Main boxes */ + parent = XtVaCreateManagedWidget("parent", formWidgetClass, toplevel, + XtNorientation, XtorientVertical, + XtNwidth, DMX_MAIN_WIDTH, + XtNheight, DMX_MAIN_HEIGHT, + NULL); + menubox = XtVaCreateManagedWidget("menubox", boxWidgetClass, parent, + XtNborderWidth, 0, + XtNorientation, XtorientHorizontal, + XtNtop, XtChainTop, + NULL); + bottombox = XtVaCreateManagedWidget("bottombox", formWidgetClass, parent, + XtNborderWidth, 0, + XtNfromVert, menubox, + XtNorientation, XtorientHorizontal, + NULL); + databox = XtVaCreateManagedWidget("databox", formWidgetClass, + bottombox, + XtNborderWidth, 0, + XtNhorizDistance, 0, + XtNwidth, DMX_DATA_WIDTH, + XtNheight, DMX_DATA_HEIGHT, + XtNleft, XtChainLeft, + XtNorientation, XtorientVertical, + NULL); + + /* Data */ + cnamebox = XtVaCreateManagedWidget("cnamebox", menuButtonWidgetClass, + databox, + XtNtop, XtChainTop, + XtNjustify, XtJustifyLeft, + XtNwidth, DMX_DATA_WIDTH, + XtNlabel, "", + XtNmenuName, "cnamemenu", + NULL); + cdimbox = XtVaCreateManagedWidget("cdimbox", labelWidgetClass, + databox, + XtNfromVert, cnamebox, + XtNjustify, XtJustifyLeft, + XtNwidth, DMX_DATA_WIDTH, + XtNlabel, "", + NULL); + namebox = XtVaCreateManagedWidget("namebox", labelWidgetClass, databox, + XtNfromVert, cdimbox, + XtNjustify, XtJustifyLeft, + XtNwidth, DMX_DATA_WIDTH, + XtNlabel, "", + NULL); + dimbox = XtVaCreateManagedWidget("dimbox", labelWidgetClass, + databox, + XtNfromVert, namebox, + XtNjustify, XtJustifyLeft, + XtNwidth, DMX_DATA_WIDTH, + XtNlabel, "", + NULL); + rtbox = XtVaCreateManagedWidget("rtbox", labelWidgetClass, + databox, + XtNfromVert, dimbox, + XtNjustify, XtJustifyLeft, + XtNwidth, DMX_DATA_WIDTH, + XtNlabel, "", + NULL); + origbox = XtVaCreateManagedWidget("origbox", labelWidgetClass, + databox, + XtNfromVert, rtbox, + XtNjustify, XtJustifyLeft, + XtNwidth, DMX_DATA_WIDTH, + XtNlabel, "", + NULL); + + /* Canvas */ + canvasbox = XtVaCreateManagedWidget("canvasbox", boxWidgetClass, + bottombox, + XtNborderWidth, 0, + XtNwidth, DMX_CANVAS_WIDTH, + XtNheight, DMX_CANVAS_HEIGHT, + XtNfromHoriz, databox, + NULL); + + canvas = XtVaCreateManagedWidget("canvas", canvasWidgetClass, + canvasbox, + XtNwidth, DMX_CANVAS_WIDTH, + XtNheight, DMX_CANVAS_HEIGHT, + NULL); + + + /* Main menu buttons */ + filebutton = XtVaCreateManagedWidget("File", menuButtonWidgetClass, + menubox, + XtNmenuName, "filemenu", + NULL); + helpbutton = XtVaCreateManagedWidget("Help", menuButtonWidgetClass, + menubox, + XtNmenuName, "helpmenu", + NULL); + + + /* File submenu buttons */ + filemenu = XtVaCreatePopupShell("filemenu", simpleMenuWidgetClass, + filebutton, NULL); + openbutton = XtVaCreateManagedWidget("Open File", smeBSBObjectClass, + filemenu, NULL); + savebutton = XtVaCreateManagedWidget("Save File", smeBSBObjectClass, + filemenu, + NULL); + ncbutton = XtVaCreateManagedWidget("New Global", smeBSBObjectClass, + filemenu, NULL); + ecbutton = XtVaCreateManagedWidget("Edit Global", smeBSBObjectClass, + filemenu, + NULL); + dcbutton = XtVaCreateManagedWidget("Delete Global", smeBSBObjectClass, + filemenu, + NULL); + ndbutton0 = XtVaCreateManagedWidget("New Display", smeBSBObjectClass, + filemenu, + NULL); + quitbutton = XtVaCreateManagedWidget("Quit", smeBSBObjectClass, + filemenu, NULL); + + /* Help submenu button */ + helpmenu = XtVaCreatePopupShell("helpmenu", simpleMenuWidgetClass, + helpbutton, NULL); + aboutbutton = XtVaCreateManagedWidget("About", smeBSBObjectClass, + helpmenu, NULL); + + /* Open popup */ + openpopup = XtVaCreatePopupShell("openpopup", transientShellWidgetClass, + toplevel, NULL); + opendialog = XtVaCreateManagedWidget("opendialog", dialogWidgetClass, + openpopup, + XtNlabel, "Filename: ", + XtNvalue, dmxConfigFilename, + NULL); + okbutton = XtVaCreateManagedWidget("Open", commandWidgetClass, + opendialog, NULL); + canbutton = XtVaCreateManagedWidget("Cancel", commandWidgetClass, + opendialog, NULL); + + /* EC popup */ + ecpopup = XtVaCreatePopupShell("ecpopup", transientShellWidgetClass, + toplevel, NULL); + ecbox = XtVaCreateManagedWidget("ecbox", boxWidgetClass, + ecpopup, NULL); + ecdialog0 = XtVaCreateManagedWidget("ecdialog0", dialogWidgetClass, + ecbox, + XtNlabel, "Name: ", + XtNvalue, "", + NULL); + ecdialog1 = XtVaCreateManagedWidget("ecdialog1", dialogWidgetClass, + ecbox, + XtNlabel, "Dimension: ", + XtNvalue, "", + NULL); + ecokbutton = XtVaCreateManagedWidget("OK", commandWidgetClass, + ecbox, NULL); + eccanbutton = XtVaCreateManagedWidget("Cancel", commandWidgetClass, + ecbox, NULL); + + /* ED popup */ + edpopup = XtVaCreatePopupShell("edpopup", transientShellWidgetClass, + toplevel, NULL); + edbox = XtVaCreateManagedWidget("edbox", boxWidgetClass, + edpopup, NULL); + eddialog0 = XtVaCreateManagedWidget("eddialog0", dialogWidgetClass, + edbox, + XtNlabel, "Display Name: ", + XtNvalue, "", + NULL); + eddialog1 = XtVaCreateManagedWidget("eddialog1", dialogWidgetClass, + edbox, + XtNlabel, "Geometry: ", + XtNvalue, "", + NULL); + eddialog2 = XtVaCreateManagedWidget("eddialog2", dialogWidgetClass, + edbox, + XtNlabel, "Offset: ", + XtNvalue, "", + NULL); + edokbutton = XtVaCreateManagedWidget("OK", commandWidgetClass, + edbox, NULL); + edcanbutton = XtVaCreateManagedWidget("Cancel", commandWidgetClass, + edbox, NULL); + + /* About popup */ + aboutpopup = XtVaCreatePopupShell("aboutpopup",transientShellWidgetClass, + toplevel, NULL); + aboutbox = XtVaCreateManagedWidget("aboutbox", boxWidgetClass, + aboutpopup, NULL); + abouttext = XtVaCreateManagedWidget("abouttext", labelWidgetClass, + aboutbox, + XtNlabel, DMX_INFO, + NULL); + aboutok = XtVaCreateManagedWidget("OK", commandWidgetClass, + aboutbox, NULL); + + /* Quit popup */ + quitpopup = XtVaCreatePopupShell("quitpopup",transientShellWidgetClass, + toplevel, NULL); + quitbox = XtVaCreateManagedWidget("quitbox", boxWidgetClass, + quitpopup, NULL); + quittext = XtVaCreateManagedWidget("quittext", labelWidgetClass, + quitbox, + XtNlabel, + "Changes to the configuration\n" + "been made that have not yet\n" + "been saved. Do you want to\n" + "quit without saving?", + NULL); + quitok = XtVaCreateManagedWidget("Quit WITHOUT Saving", + commandWidgetClass, + quitbox, NULL); + quitcan = XtVaCreateManagedWidget("Continue Editing", + commandWidgetClass, + quitbox, NULL); + + /* Button popup */ + buttonpopup = XtVaCreatePopupShell("buttonpopup", simpleMenuWidgetClass, + toplevel, NULL); + ndbutton1 = XtVaCreateManagedWidget("New Display", smeBSBObjectClass, + buttonpopup, + NULL); + edbutton = XtVaCreateManagedWidget("Edit Display", smeBSBObjectClass, + buttonpopup, + NULL); + ddbutton = XtVaCreateManagedWidget("Delete Display", smeBSBObjectClass, + buttonpopup, + NULL); + + /* Callbacks */ + XtAddCallback(openbutton, XtNcallback, dmxConfigOpenCallback, NULL); + XtAddCallback(savebutton, XtNcallback, dmxConfigSaveCallback, NULL); + XtAddCallback(okbutton, XtNcallback, dmxConfigOkCallback, NULL); + XtAddCallback(canbutton, XtNcallback, dmxConfigCanCallback, NULL); + + XtAppAddActions(appContext, actiontable, XtNumber(actiontable)); + XtOverrideTranslations(canvas, XtParseTranslationTable(canvastrans)); + XtOverrideTranslations(XtNameToWidget(opendialog, "value"), + XtParseTranslationTable(opentrans)); + XtOverrideTranslations(XtNameToWidget(ecdialog0, "value"), + XtParseTranslationTable(opentrans)); + XtOverrideTranslations(XtNameToWidget(ecdialog1, "value"), + XtParseTranslationTable(opentrans)); + XtOverrideTranslations(XtNameToWidget(eddialog0, "value"), + XtParseTranslationTable(opentrans)); + XtOverrideTranslations(XtNameToWidget(eddialog1, "value"), + XtParseTranslationTable(opentrans)); + XtOverrideTranslations(XtNameToWidget(eddialog2, "value"), + XtParseTranslationTable(opentrans)); + + XtAddCallback(ncbutton, XtNcallback, dmxConfigNCCallback, NULL); + XtAddCallback(ecbutton, XtNcallback, dmxConfigECCallback, NULL); + XtAddCallback(ecokbutton, XtNcallback, dmxConfigECOkCallback, NULL); + XtAddCallback(eccanbutton, XtNcallback, dmxConfigECCanCallback, NULL); + XtAddCallback(dcbutton, XtNcallback, dmxConfigDCCallback, NULL); + + XtAddCallback(ndbutton0, XtNcallback, dmxConfigNDCallback, NULL); + XtAddCallback(ndbutton1, XtNcallback, dmxConfigNDCallback, NULL); + XtAddCallback(edbutton, XtNcallback, dmxConfigEDCallback, NULL); + XtAddCallback(ddbutton, XtNcallback, dmxConfigDDCallback, NULL); + XtAddCallback(edokbutton, XtNcallback, dmxConfigEDOkCallback, NULL); + XtAddCallback(edcanbutton, XtNcallback, dmxConfigEDCanCallback, NULL); + + XtAddCallback(aboutbutton, XtNcallback, dmxConfigAboutCallback, NULL); + XtAddCallback(aboutok, XtNcallback, dmxConfigAboutOkCallback, NULL); + XtAddCallback(quitok, XtNcallback, dmxConfigQuitOkCallback, NULL); + XtAddCallback(quitcan, XtNcallback, dmxConfigQuitCanCallback, NULL); + + XtAddCallback(quitbutton, XtNcallback, dmxConfigQuitCallback, NULL); + + XtAddCallback(canvas, XtNcallback, dmxConfigCanvasInput, NULL); + XtAddCallback(canvas, XtNcanvasExposeCallback, dmxConfigCanvasExpose,NULL); + XtAddCallback(canvas, XtNcanvasResizeCallback, dmxConfigCanvasResize,NULL); + + if (dmxConfigFilename) dmxConfigReadFile(); + + XtRealizeWidget(toplevel); + dmxConfigCopystrings(); + dmxConfigSetupCnamemenu(); + XtAppMainLoop(appContext); + return 0; +} |