/* $XFree86$ */ /* * 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 * */ #ifdef HAVE_DMX_CONFIG_H #include #endif #include #include #include #include #include #include /* #include */ #include #include #include #include #include #include #include #include #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$Id: xdmxconfig.c,v 1.3 2005/10/06 02:40:41 kem Exp $" #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 = "Return: openOk()\n\ Linefeed: openOk()\n\ CtrlM: openOk()\n\ CtrlJ: openOk()\n\ CtrlO: noop()\n\ CtrlN: noop()\n\ CtrlP: noop()"; const char *canvastrans = ": 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; }