"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/hw/dmx/config/xdmxconfig.c" (29 Mar 2020, 44747 Bytes) of package /linux/misc/xorg-server-1.20.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "xdmxconfig.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.20.7_vs_1.20.8.

    1 /*
    2  * Copyright 2002 Red Hat Inc., Durham, North Carolina.
    3  *
    4  * All Rights Reserved.
    5  *
    6  * Permission is hereby granted, free of charge, to any person obtaining
    7  * a copy of this software and associated documentation files (the
    8  * "Software"), to deal in the Software without restriction, including
    9  * without limitation on the rights to use, copy, modify, merge,
   10  * publish, distribute, sublicense, and/or sell copies of the Software,
   11  * and to permit persons to whom the Software is furnished to do so,
   12  * subject to the following conditions:
   13  *
   14  * The above copyright notice and this permission notice (including the
   15  * next paragraph) shall be included in all copies or substantial
   16  * portions of the Software.
   17  *
   18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   21  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
   22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   25  * SOFTWARE.
   26  */
   27 
   28 /*
   29  * Authors:
   30  *   Rickard E. (Rik) Faith <faith@redhat.com>
   31  *
   32  */
   33 
   34 
   35 #include <stdio.h>
   36 #include <stdlib.h>
   37 #include <X11/Intrinsic.h>
   38 #include <X11/StringDefs.h>
   39 #include <X11/Xaw/Form.h>
   40 #include <X11/Xaw/Box.h>
   41 /* #include <X11/Xaw/Paned.h> */
   42 #include <X11/Xaw/Command.h>
   43 #include <X11/Xaw/SimpleMenu.h>
   44 #include <X11/Xaw/SmeBSB.h>
   45 #include <X11/Xaw/MenuButton.h>
   46 #include <X11/Xaw/Viewport.h>
   47 #include <X11/Xaw/Dialog.h>
   48 #include <X11/keysym.h>
   49 #include "Canvas.h"
   50 
   51 #include "dmxparse.h"
   52 #include "dmxprint.h"
   53 #include "dmxlog.h"
   54 
   55 extern int yyparse(void);
   56 extern int yydebug;
   57 extern FILE *yyin;
   58 
   59 #define DMX_INFO "xdmxconfig v0.9\nCopyright 2002 Red Hat Inc.\n"
   60 
   61 #define DMX_MAIN_WIDTH    800
   62 #define DMX_MAIN_HEIGHT   600
   63 #define DMX_DATA_WIDTH    200
   64 #define DMX_DATA_HEIGHT   200
   65 #define DMX_CANVAS_WIDTH  400
   66 #define DMX_CANVAS_HEIGHT 500
   67 
   68 extern DMXConfigEntryPtr dmxConfigEntry;
   69 static DMXConfigVirtualPtr dmxConfigCurrent, dmxConfigNewVirtual;
   70 static DMXConfigDisplayPtr dmxConfigCurrentDisplay, dmxConfigNewDisplay;
   71 static int dmxConfigGrabbed, dmxConfigGrabbedFine;
   72 static int dmxConfigGrabbedX, dmxConfigGrabbedY;
   73 static char *dmxConfigFilename;
   74 static GC dmxConfigGC, dmxConfigGCRev, dmxConfigGCHL;
   75 static int dmxConfigGCInit = 0;
   76 static Dimension dmxConfigWidgetWidth, dmxConfigWidgetHeight;
   77 static Dimension dmxConfigWallWidth, dmxConfigWallHeight;
   78 static double dmxConfigScaleX, dmxConfigScaleY;
   79 static int dmxConfigNotSaved;
   80 static enum {
   81     dmxConfigStateOpen,
   82     dmxConfigStateSave
   83 } dmxConfigState;
   84 
   85 /* Global widgets */
   86 static Widget canvas;
   87 static Widget cnamebox, cdimbox;
   88 static Widget openpopup, opendialog;
   89 static Widget namebox, dimbox, rtbox, origbox;
   90 static Widget okbutton, buttonpopup;
   91 static Widget ecbutton, dcbutton;
   92 static Widget ndbutton0, ndbutton1, edbutton, ddbutton;
   93 static Widget ecpopup, ecdialog0, ecdialog1;
   94 static Widget edpopup, eddialog0, eddialog1, eddialog2;
   95 static Widget aboutpopup, quitpopup;
   96 
   97 static void
   98 dmxConfigCanvasGCs(void)
   99 {
  100     Display *dpy = XtDisplay(canvas);
  101     Window win = XtWindow(canvas);
  102     XGCValues gcvals;
  103     unsigned long mask;
  104     Colormap colormap;
  105     XColor fg, bg, hl, tmp;
  106 
  107     if (dmxConfigGCInit++)
  108         return;
  109 
  110     XtVaGetValues(canvas, XtNcolormap, &colormap, NULL);
  111     XAllocNamedColor(XtDisplay(canvas), colormap, "black", &bg, &tmp);
  112     XAllocNamedColor(XtDisplay(canvas), colormap, "white", &fg, &tmp);
  113     XAllocNamedColor(XtDisplay(canvas), colormap, "red", &hl, &tmp);
  114 
  115     mask = (GCFunction | GCPlaneMask | GCClipMask | GCForeground |
  116             GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
  117             GCFillStyle);
  118 
  119     /* FIXME: copy this from widget */
  120     gcvals.function = GXcopy;
  121     gcvals.plane_mask = AllPlanes;
  122     gcvals.clip_mask = None;
  123     gcvals.foreground = fg.pixel;
  124     gcvals.background = bg.pixel;
  125     gcvals.line_width = 0;
  126     gcvals.line_style = LineSolid;
  127     gcvals.cap_style = CapNotLast;
  128     gcvals.fill_style = FillSolid;
  129 
  130     dmxConfigGC = XCreateGC(dpy, win, mask, &gcvals);
  131     gcvals.foreground = hl.pixel;
  132     dmxConfigGCHL = XCreateGC(dpy, win, mask, &gcvals);
  133     gcvals.foreground = bg.pixel;
  134     gcvals.background = fg.pixel;
  135     dmxConfigGCRev = XCreateGC(dpy, win, mask, &gcvals);
  136 }
  137 
  138 static void
  139 dmxConfigGetDims(int *maxWidth, int *maxHeight)
  140 {
  141     DMXConfigSubPtr pt;
  142     DMXConfigEntryPtr e;
  143 
  144     *maxWidth = dmxConfigWallWidth = 0;
  145     *maxHeight = dmxConfigWallHeight = 0;
  146     if (!dmxConfigCurrent)
  147         return;
  148 
  149     dmxConfigWallWidth = dmxConfigCurrent->width;
  150     dmxConfigWallHeight = dmxConfigCurrent->height;
  151     if (!dmxConfigWallWidth || !dmxConfigWallHeight) {
  152         for (pt = dmxConfigCurrent->subentry; pt; pt = pt->next) {
  153             if (pt->type == dmxConfigDisplay) {
  154                 int x = pt->display->scrnWidth + pt->display->rootXOrigin;
  155                 int y = pt->display->scrnHeight + pt->display->rootYOrigin;
  156 
  157                 if (x > dmxConfigWallWidth)
  158                     dmxConfigWallWidth = x;
  159                 if (y > dmxConfigWallHeight)
  160                     dmxConfigWallHeight = y;
  161             }
  162         }
  163     }
  164     /* Compute maximums */
  165     *maxWidth = *maxHeight = 0;
  166     for (e = dmxConfigEntry; e; e = e->next) {
  167         if (e->type != dmxConfigVirtual)
  168             continue;
  169         for (pt = e->virtual->subentry; pt; pt = pt->next) {
  170             if (pt->type == dmxConfigDisplay) {
  171                 int x = pt->display->scrnWidth + pt->display->rootXOrigin;
  172                 int y = pt->display->scrnHeight + pt->display->rootYOrigin;
  173 
  174                 if (x > *maxWidth)
  175                     *maxWidth = x;
  176                 if (y > *maxHeight)
  177                     *maxHeight = y;
  178             }
  179         }
  180     }
  181     if (dmxConfigWallWidth > *maxWidth)
  182         *maxWidth = dmxConfigWallWidth;
  183     if (dmxConfigWallHeight > *maxHeight)
  184         *maxHeight = dmxConfigWallHeight;
  185 }
  186 
  187 static int
  188 scalex(int x)
  189 {
  190     return (int) ((x * dmxConfigScaleX) + .5);
  191 }
  192 
  193 static int
  194 scaley(int y)
  195 {
  196     return (int) ((y * dmxConfigScaleY) + .5);
  197 }
  198 
  199 static int
  200 unscalex(int x)
  201 {
  202     return (int) ((x / dmxConfigScaleX) + .5);
  203 }
  204 
  205 static int
  206 unscaley(int y)
  207 {
  208     return (int) ((y / dmxConfigScaleY) + .5);
  209 }
  210 
  211 static void
  212 dmxConfigDataUpdate(void)
  213 {
  214     /* FIXME: could result in buffer overflows */
  215     char cnambuf[512];
  216     char cdimbuf[128];
  217     char nambuf[512];
  218     char dimbuf[128];
  219     char rtbuf[128];
  220     char offbuf[128];
  221     const char *name;
  222 
  223     if (!dmxConfigCurrent) {
  224         XtVaSetValues(cnamebox, XtNlabel, "", XtNsensitive, False, NULL);
  225         XtVaSetValues(cdimbox, XtNlabel, "", XtNsensitive, False, NULL);
  226         XtVaSetValues(ecbutton, XtNsensitive, False, NULL);
  227         XtVaSetValues(dcbutton, XtNsensitive, False, NULL);
  228         XtVaSetValues(ndbutton0, XtNsensitive, False, NULL);
  229         XtVaSetValues(ndbutton1, XtNsensitive, False, NULL);
  230     }
  231     else {
  232         name = dmxConfigCurrent->name;
  233         snprintf(cnambuf, sizeof(cnambuf), "%s", name ? name : "");
  234         snprintf(cdimbuf, sizeof(cdimbuf), "%dx%d",
  235                  dmxConfigWallWidth, dmxConfigWallHeight);
  236         XtVaSetValues(cnamebox, XtNlabel, cnambuf, XtNsensitive, True, NULL);
  237         XtVaSetValues(cdimbox, XtNlabel, cdimbuf, XtNsensitive, True, NULL);
  238         XtVaSetValues(ecbutton, XtNsensitive, True, NULL);
  239         XtVaSetValues(dcbutton, XtNsensitive, True, NULL);
  240         XtVaSetValues(ndbutton0, XtNsensitive, True, NULL);
  241         XtVaSetValues(ndbutton1, XtNsensitive, True, NULL);
  242     }
  243 
  244     if (!dmxConfigCurrentDisplay) {
  245         XtVaSetValues(namebox, XtNlabel, "", XtNsensitive, False, NULL);
  246         XtVaSetValues(dimbox, XtNlabel, "", XtNsensitive, False, NULL);
  247         XtVaSetValues(rtbox, XtNlabel, "", XtNsensitive, False, NULL);
  248         XtVaSetValues(origbox, XtNlabel, "", XtNsensitive, False, NULL);
  249         XtVaSetValues(edbutton, XtNsensitive, False, NULL);
  250         XtVaSetValues(ddbutton, XtNsensitive, False, NULL);
  251     }
  252     else {
  253         name = dmxConfigCurrentDisplay->name;
  254         snprintf(nambuf, sizeof(nambuf), "%s", name ? name : "");
  255         snprintf(dimbuf, sizeof(dimbuf), "%dx%d%c%d%c%d",
  256                  dmxConfigCurrentDisplay->scrnWidth,
  257                  dmxConfigCurrentDisplay->scrnHeight,
  258                  dmxConfigCurrentDisplay->scrnXSign < 0 ? '-' : '+',
  259                  dmxConfigCurrentDisplay->scrnX,
  260                  dmxConfigCurrentDisplay->scrnYSign < 0 ? '-' : '+',
  261                  dmxConfigCurrentDisplay->scrnY);
  262         snprintf(rtbuf, sizeof(dimbuf), "%dx%d%c%d%c%d",
  263                  dmxConfigCurrentDisplay->rootWidth,
  264                  dmxConfigCurrentDisplay->rootHeight,
  265                  dmxConfigCurrentDisplay->rootXSign < 0 ? '-' : '+',
  266                  dmxConfigCurrentDisplay->rootX,
  267                  dmxConfigCurrentDisplay->rootYSign < 0 ? '-' : '+',
  268                  dmxConfigCurrentDisplay->rootY);
  269         snprintf(offbuf, sizeof(offbuf), "@%dx%d",
  270                  dmxConfigCurrentDisplay->rootXOrigin,
  271                  dmxConfigCurrentDisplay->rootYOrigin);
  272         XtVaSetValues(namebox, XtNlabel, nambuf, XtNsensitive, True, NULL);
  273         XtVaSetValues(dimbox, XtNlabel, dimbuf, XtNsensitive, True, NULL);
  274         XtVaSetValues(rtbox, XtNlabel, rtbuf, XtNsensitive, True, NULL);
  275         XtVaSetValues(origbox, XtNlabel, offbuf, XtNsensitive, True, NULL);
  276         XtVaSetValues(edbutton, XtNsensitive, True, NULL);
  277         XtVaSetValues(ddbutton, XtNsensitive, True, NULL);
  278     }
  279 }
  280 
  281 static void
  282 dmxConfigCanvasUpdate(void)
  283 {
  284     DMXConfigSubPtr pt;
  285     Display *dpy = XtDisplay(canvas);
  286     Window win = XtWindow(canvas);
  287     GContext gcontext = XGContextFromGC(dmxConfigGC);
  288     XFontStruct *fs;
  289     int w, h;
  290 
  291     XFillRectangle(dpy, win, dmxConfigGCRev,
  292                    0, 0, dmxConfigWidgetWidth, dmxConfigWidgetHeight);
  293     dmxConfigDataUpdate();
  294     if (!dmxConfigCurrent)
  295         return;
  296 
  297     w = scalex(dmxConfigWallWidth);
  298     h = scaley(dmxConfigWallHeight);
  299     if (w > dmxConfigWidgetWidth - 1)
  300         w = dmxConfigWidgetWidth - 1;
  301     if (h > dmxConfigWidgetHeight - 1)
  302         h = dmxConfigWidgetHeight - 1;
  303     XDrawRectangle(dpy, win, dmxConfigGC, 0, 0, w, h);
  304     fs = XQueryFont(dpy, gcontext);
  305     for (pt = dmxConfigCurrent->subentry; pt; pt = pt->next) {
  306         int x, y, len;
  307         GC gc;
  308 
  309         if (pt->type != dmxConfigDisplay)
  310             continue;
  311         gc = (pt->display == dmxConfigCurrentDisplay
  312               ? dmxConfigGCHL : dmxConfigGC);
  313         x = scalex(pt->display->rootXOrigin);
  314         y = scaley(pt->display->rootYOrigin);
  315         w = scalex(pt->display->scrnWidth);
  316         h = scaley(pt->display->scrnHeight);
  317         len = pt->display->name ? strlen(pt->display->name) : 0;
  318         if (x > dmxConfigWidgetWidth - 1)
  319             x = dmxConfigWidgetWidth - 1;
  320         if (y > dmxConfigWidgetHeight - 1)
  321             y = dmxConfigWidgetHeight - 1;
  322         XDrawRectangle(dpy, win, gc, x, y, w, h);
  323         if (fs && len) {
  324             int xo = 3, yo = fs->ascent + fs->descent + 2;
  325 
  326             while (len && XTextWidth(fs, pt->display->name, len) >= w - 2 * xo)
  327                 --len;
  328             if (len)
  329                 XDrawString(dpy, win, gc, x + xo, y + yo, pt->display->name,
  330                             len);
  331         }
  332     }
  333     if (fs)
  334         XFreeFontInfo(NULL, fs, 0);
  335 }
  336 
  337 static void
  338 dmxConfigCanvasDraw(Region region)
  339 {
  340     Display *dpy = XtDisplay(canvas);
  341     int maxWidth, maxHeight;
  342 
  343     dmxConfigCanvasGCs();
  344     if (region) {
  345         XSetRegion(dpy, dmxConfigGC, region);
  346         XSetRegion(dpy, dmxConfigGCRev, region);
  347         XSetRegion(dpy, dmxConfigGCHL, region);
  348     }
  349     XtVaGetValues(canvas,
  350                   XtNwidth, &dmxConfigWidgetWidth,
  351                   XtNheight, &dmxConfigWidgetHeight, NULL);
  352     dmxConfigGetDims(&maxWidth, &maxHeight);
  353     dmxConfigScaleX = (double) dmxConfigWidgetWidth / maxWidth;
  354     dmxConfigScaleY = (double) dmxConfigWidgetHeight / maxHeight;
  355     if (dmxConfigScaleX > dmxConfigScaleY)
  356         dmxConfigScaleX = dmxConfigScaleY;
  357     if (dmxConfigScaleY > dmxConfigScaleX)
  358         dmxConfigScaleY = dmxConfigScaleX;
  359     dmxConfigCanvasUpdate();
  360     if (region) {
  361         XSetClipMask(dpy, dmxConfigGC, None);
  362         XSetClipMask(dpy, dmxConfigGCRev, None);
  363         XSetClipMask(dpy, dmxConfigGCHL, None);
  364     }
  365 }
  366 
  367 static void
  368 dmxConfigSelectCallback(Widget w, XtPointer closure, XtPointer callData)
  369 {
  370     dmxConfigCurrent = closure;
  371     dmxConfigVirtualPrint(stdout, dmxConfigCurrent);
  372     dmxConfigCanvasDraw(NULL);
  373 }
  374 
  375 static void
  376 dmxConfigCopystrings(void)
  377 {
  378     DMXConfigEntryPtr pt;
  379     DMXConfigSubPtr sub;
  380 
  381     if (!dmxConfigCurrent)
  382         return;
  383 
  384     /* FIXME: this is all a per-config file
  385      * memory leak */
  386     for (pt = dmxConfigEntry; pt; pt = pt->next) {
  387         if (pt->type == dmxConfigVirtual) {
  388             pt->virtual->name = XtNewString(pt->virtual->name
  389                                             ? pt->virtual->name : "");
  390 
  391             for (sub = pt->virtual->subentry; sub; sub = sub->next) {
  392                 if (sub->type != dmxConfigDisplay)
  393                     continue;
  394                 sub->display->name = XtNewString(sub->display->name
  395                                                  ? sub->display->name : "");
  396             }
  397         }
  398     }
  399 }
  400 
  401 static void
  402 dmxConfigGetValueString(char **d, Widget w)
  403 {
  404     const char *tmp = XawDialogGetValueString(w);
  405 
  406     if (*d)
  407         XtFree(*d);
  408     *d = XtNewString(tmp);
  409 }
  410 
  411 static void
  412 dmxConfigSetupCnamemenu(void)
  413 {
  414     static Widget cnamemenu = NULL;
  415     Widget w;
  416     DMXConfigEntryPtr pt;
  417 
  418     if (cnamemenu)
  419         XtDestroyWidget(cnamemenu);
  420     cnamemenu = NULL;
  421 
  422     if (!dmxConfigCurrent)
  423         return;
  424     cnamemenu = XtVaCreatePopupShell("cnamemenu", simpleMenuWidgetClass,
  425                                      cnamebox, NULL);
  426 
  427     for (pt = dmxConfigEntry; pt; pt = pt->next) {
  428         if (pt->type == dmxConfigVirtual) {
  429             w = XtVaCreateManagedWidget(pt->virtual->name
  430                                         ? pt->virtual->name
  431                                         : "",
  432                                         smeBSBObjectClass, cnamemenu, NULL);
  433             XtAddCallback(w, XtNcallback, dmxConfigSelectCallback, pt->virtual);
  434         }
  435     }
  436 }
  437 
  438 static void
  439 dmxConfigReadFile(void)
  440 {
  441     FILE *str;
  442     DMXConfigEntryPtr pt;
  443 
  444     if (!(str = fopen(dmxConfigFilename, "r"))) {
  445         dmxLog(dmxWarning, "Unable to read configuration file %s\n",
  446                dmxConfigFilename);
  447         return;
  448     }
  449     yyin = str;
  450     yydebug = 0;
  451     yyparse();
  452     fclose(str);
  453     dmxLog(dmxInfo, "Read configuration file %s\n", dmxConfigFilename);
  454 
  455     for (pt = dmxConfigEntry; pt; pt = pt->next) {
  456         if (pt->type == dmxConfigVirtual) {
  457             dmxConfigCurrent = pt->virtual;
  458             break;
  459         }
  460     }
  461 
  462     if (XtIsRealized(canvas)) {
  463         dmxConfigCopystrings();
  464         dmxConfigSetupCnamemenu();
  465         dmxConfigCanvasDraw(NULL);
  466     }
  467     dmxConfigVirtualPrint(stdout, dmxConfigCurrent);
  468 }
  469 
  470 static void
  471 dmxConfigWriteFile(void)
  472 {
  473     FILE *str;
  474 
  475     if (!(str = fopen(dmxConfigFilename, "w"))) {
  476         dmxLog(dmxWarning, "Unable to write configuration file %s\n",
  477                dmxConfigFilename);
  478         return;
  479     }
  480     dmxConfigPrint(str, dmxConfigEntry);
  481     fclose(str);
  482 }
  483 
  484 static DMXConfigDisplayPtr
  485 dmxConfigFindDisplay(int x, int y)
  486 {
  487     DMXConfigSubPtr pt;
  488 
  489     if (!dmxConfigCurrent)
  490         return NULL;
  491     for (pt = dmxConfigCurrent->subentry; pt; pt = pt->next) {
  492         DMXConfigDisplayPtr d = pt->display;
  493 
  494         if (pt->type != dmxConfigDisplay)
  495             continue;
  496         if (x >= scalex(d->rootXOrigin)
  497             && x <= scalex(d->rootXOrigin + d->scrnWidth)
  498             && y >= scaley(d->rootYOrigin)
  499             && y <= scaley(d->rootYOrigin + d->scrnHeight))
  500             return d;
  501     }
  502     return NULL;
  503 }
  504 
  505 static void
  506 dmxConfigSetPopupPosition(Widget popup)
  507 {
  508     Position x, y;
  509     Window t1, t2;
  510     int root_x, root_y;
  511     int temp_x, temp_y;
  512     unsigned int temp;
  513 
  514     XtRealizeWidget(popup);
  515     if (!XQueryPointer(XtDisplay(popup), XtWindow(popup), &t1, &t2,
  516                        &root_x, &root_y, &temp_x, &temp_y, &temp))
  517         root_x = root_y = 0;
  518 
  519     x = root_x - 5;
  520     y = root_y - 5;
  521     XtVaSetValues(popup, XtNx, x, XtNy, y, NULL);
  522 }
  523 
  524 static void
  525 dmxConfigPlaceMenu(Widget w, XEvent * event,
  526                    String * params, Cardinal * num_params)
  527 {
  528     dmxConfigSetPopupPosition(buttonpopup);
  529 }
  530 
  531 static void
  532 dmxConfigMove(int deltaX, int deltaY)
  533 {
  534     dmxConfigCurrentDisplay->rootXOrigin += deltaX;
  535     dmxConfigCurrentDisplay->rootYOrigin += deltaY;
  536     if (dmxConfigCurrentDisplay->rootXOrigin < 0)
  537         dmxConfigCurrentDisplay->rootXOrigin = 0;
  538     if (dmxConfigCurrentDisplay->rootYOrigin < 0)
  539         dmxConfigCurrentDisplay->rootYOrigin = 0;
  540     if (dmxConfigWallWidth && dmxConfigWallHeight) {
  541         if (dmxConfigCurrentDisplay->rootXOrigin >= dmxConfigWallWidth)
  542             dmxConfigCurrentDisplay->rootXOrigin = dmxConfigWallWidth - 1;
  543         if (dmxConfigCurrentDisplay->rootYOrigin >= dmxConfigWallHeight)
  544             dmxConfigCurrentDisplay->rootYOrigin = dmxConfigWallHeight - 1;
  545     }
  546     dmxConfigCanvasUpdate();
  547     dmxConfigNotSaved = 1;
  548 }
  549 
  550 static void
  551 dmxConfigCanvasInput(Widget w, XtPointer closure, XtPointer callData)
  552 {
  553     XEvent *e = (XEvent *) callData;
  554     DMXConfigDisplayPtr display = NULL;
  555 
  556     switch (e->type) {
  557     case ButtonPress:
  558         if (e->xbutton.button == Button1) {
  559             dmxConfigGrabbed = 1;
  560             dmxConfigGrabbedFine = 0;
  561             dmxConfigGrabbedX = e->xbutton.x;
  562             dmxConfigGrabbedY = e->xbutton.y;
  563         }
  564         if (e->xbutton.button == Button2) {
  565             dmxConfigGrabbed = 1;
  566             dmxConfigGrabbedFine = 1;
  567             dmxConfigGrabbedX = e->xbutton.x;
  568             dmxConfigGrabbedY = e->xbutton.y;
  569         }
  570         break;
  571     case ButtonRelease:
  572         if (e->xbutton.button == Button1)
  573             dmxConfigGrabbed = 0;
  574         if (e->xbutton.button == Button2)
  575             dmxConfigGrabbed = 0;
  576         break;
  577     case MotionNotify:
  578         if (dmxConfigGrabbed && dmxConfigCurrentDisplay) {
  579             int deltaX = e->xmotion.x - dmxConfigGrabbedX;
  580             int deltaY = e->xmotion.y - dmxConfigGrabbedY;
  581 
  582             dmxConfigMove(dmxConfigGrabbedFine ? deltaX : unscalex(deltaX),
  583                           dmxConfigGrabbedFine ? deltaY : unscaley(deltaY));
  584             dmxConfigGrabbedX = e->xmotion.x;
  585             dmxConfigGrabbedY = e->xmotion.y;
  586         }
  587         else {
  588             display = dmxConfigFindDisplay(e->xmotion.x, e->xmotion.y);
  589             if (display != dmxConfigCurrentDisplay) {
  590                 dmxConfigCurrentDisplay = display;
  591                 dmxConfigCanvasUpdate();
  592             }
  593         }
  594         break;
  595     case KeyPress:
  596         switch (XLookupKeysym(&e->xkey, 0)) {
  597         case XK_Right:
  598             dmxConfigMove(1, 0);
  599             break;
  600         case XK_Left:
  601             dmxConfigMove(-1, 0);
  602             break;
  603         case XK_Down:
  604             dmxConfigMove(0, 1);
  605             break;
  606         case XK_Up:
  607             dmxConfigMove(0, -1);
  608             break;
  609         }
  610         break;
  611     }
  612 }
  613 
  614 static void
  615 dmxConfigCanvasResize(Widget w, XtPointer closure, XtPointer callData)
  616 {
  617     dmxConfigCanvasDraw(NULL);
  618 }
  619 
  620 static void
  621 dmxConfigCanvasExpose(Widget w, XtPointer closure, XtPointer callData)
  622 {
  623     CanvasExposeDataPtr data = (CanvasExposeDataPtr) callData;
  624 
  625     dmxConfigCanvasDraw(data->region);
  626 }
  627 
  628 static void
  629 dmxConfigOpenCallback(Widget w, XtPointer closure, XtPointer callData)
  630 {
  631     dmxConfigState = dmxConfigStateOpen;
  632     XtVaSetValues(okbutton, XtNlabel, "Open", NULL);
  633     dmxConfigSetPopupPosition(openpopup);
  634     XtPopup(openpopup, XtGrabExclusive);
  635 }
  636 
  637 static void
  638 dmxConfigSaveCallback(Widget w, XtPointer closure, XtPointer callData)
  639 {
  640     dmxConfigState = dmxConfigStateSave;
  641     XtVaSetValues(okbutton, XtNlabel, "Save", NULL);
  642     dmxConfigSetPopupPosition(openpopup);
  643     XtPopup(openpopup, XtGrabExclusive);
  644 }
  645 
  646 static void
  647 dmxConfigOkCallback(Widget w, XtPointer closure, XtPointer callData)
  648 {
  649     dmxConfigGetValueString(&dmxConfigFilename, opendialog);
  650     XtPopdown(openpopup);
  651     if (dmxConfigState == dmxConfigStateOpen)
  652         dmxConfigReadFile();
  653     else
  654         dmxConfigWriteFile();
  655     dmxConfigNotSaved = 0;
  656 }
  657 
  658 static void
  659 dmxConfigCanCallback(Widget w, XtPointer closure, XtPointer callData)
  660 {
  661     XtPopdown(openpopup);
  662 }
  663 
  664 static void
  665 dmxConfigECCallback(Widget w, XtPointer closure, XtPointer callData)
  666 {
  667     char buf[256];              /* RATS: Only used in snprintf */
  668 
  669     if (!dmxConfigCurrent)
  670         return;
  671     dmxConfigSetPopupPosition(ecpopup);
  672     XtVaSetValues(ecdialog0, XtNvalue,
  673                   dmxConfigCurrent->name ? dmxConfigCurrent->name : "", NULL);
  674     snprintf(buf, sizeof(buf), "%dx%d",
  675              dmxConfigCurrent->width, dmxConfigCurrent->height);
  676     XtVaSetValues(ecdialog1, XtNvalue, buf, NULL);
  677     XtPopup(ecpopup, XtGrabExclusive);
  678 }
  679 
  680 static void
  681 dmxConfigNCCallback(Widget w, XtPointer closure, XtPointer callData)
  682 {
  683     int width = 1280 * 2, height = 1024 * 2;
  684 
  685     if (dmxConfigCurrent) {
  686         width = dmxConfigCurrent->width;
  687         height = dmxConfigCurrent->height;
  688     }
  689 
  690     dmxConfigCurrent = dmxConfigCreateVirtual(NULL, NULL, NULL,
  691                                               NULL, NULL, NULL);
  692     dmxConfigNewVirtual = dmxConfigCurrent;
  693     dmxConfigCurrent->width = width;
  694     dmxConfigCurrent->height = height;
  695     dmxConfigEntry = dmxConfigAddEntry(dmxConfigEntry, dmxConfigVirtual, NULL,
  696                                        dmxConfigCurrent);
  697     dmxConfigECCallback(w, closure, callData);
  698 }
  699 
  700 static void
  701 dmxConfigDCCallback(Widget w, XtPointer closure, XtPointer callData)
  702 {
  703     DMXConfigEntryPtr pt;
  704 
  705     if (!dmxConfigEntry)
  706         return;
  707     if (dmxConfigEntry
  708         && dmxConfigEntry->type == dmxConfigVirtual
  709         && dmxConfigEntry->virtual == dmxConfigCurrent) {
  710         dmxConfigEntry = dmxConfigEntry->next;
  711     }
  712     else {
  713         for (pt = dmxConfigEntry; pt && pt->next; pt = pt->next)
  714             if (pt->next->type == dmxConfigVirtual
  715                 && pt->next->virtual == dmxConfigCurrent) {
  716                 pt->next = pt->next->next;
  717                 break;
  718             }
  719     }
  720     dmxConfigFreeVirtual(dmxConfigCurrent);
  721     dmxConfigCurrent = NULL;
  722     dmxConfigCurrentDisplay = NULL;
  723 
  724     /* Make the first entry current */
  725     for (pt = dmxConfigEntry; pt; pt = pt->next) {
  726         if (pt->type == dmxConfigVirtual) {
  727             dmxConfigCurrent = pt->virtual;
  728             break;
  729         }
  730     }
  731 
  732     dmxConfigSetupCnamemenu();
  733     dmxConfigCanvasDraw(NULL);
  734 }
  735 
  736 static void
  737 dmxConfigECOkCallback(Widget w, XtPointer closure, XtPointer callData)
  738 {
  739     const char *value;
  740     char *endpt;
  741 
  742     dmxConfigGetValueString((char **) &dmxConfigCurrent->name, ecdialog0);
  743     value = XawDialogGetValueString(ecdialog1);
  744     dmxConfigCurrent->width = strtol(value, &endpt, 10);
  745     dmxConfigCurrent->height = strtol(endpt + 1, NULL, 10);
  746     XtPopdown(ecpopup);
  747     dmxConfigCurrentDisplay = NULL;
  748     dmxConfigNewVirtual = NULL;
  749     dmxConfigSetupCnamemenu();
  750     dmxConfigCanvasDraw(NULL);
  751     dmxConfigNotSaved = 1;
  752 }
  753 
  754 static void
  755 dmxConfigECCanCallback(Widget w, XtPointer closure, XtPointer callData)
  756 {
  757     if (dmxConfigNewVirtual)
  758         dmxConfigDCCallback(w, closure, callData);
  759     dmxConfigNewVirtual = NULL;
  760     XtPopdown(ecpopup);
  761 }
  762 
  763 static void
  764 dmxConfigEDCallback(Widget w, XtPointer closure, XtPointer callData)
  765 {
  766     char buf[256];              /* RATS: Only used in snprintf */
  767 
  768     if (!dmxConfigCurrent || !dmxConfigCurrentDisplay)
  769         return;
  770     dmxConfigSetPopupPosition(edpopup);
  771     XtVaSetValues(eddialog0, XtNvalue,
  772                   dmxConfigCurrentDisplay->name
  773                   ? dmxConfigCurrentDisplay->name : "", NULL);
  774     snprintf(buf, sizeof(buf), "%dx%d%c%d%c%d",
  775              dmxConfigCurrentDisplay->scrnWidth,
  776              dmxConfigCurrentDisplay->scrnHeight,
  777              dmxConfigCurrentDisplay->scrnXSign < 0 ? '-' : '+',
  778              dmxConfigCurrentDisplay->scrnY,
  779              dmxConfigCurrentDisplay->scrnYSign < 0 ? '-' : '+',
  780              dmxConfigCurrentDisplay->scrnY);
  781     XtVaSetValues(eddialog1, XtNvalue, buf, NULL);
  782     snprintf(buf, sizeof(buf), "@%dx%d",
  783              dmxConfigCurrentDisplay->rootXOrigin,
  784              dmxConfigCurrentDisplay->rootYOrigin);
  785     XtVaSetValues(eddialog2, XtNvalue, buf, NULL);
  786     XtPopup(edpopup, XtGrabExclusive);
  787 }
  788 
  789 static void
  790 dmxConfigNDCallback(Widget w, XtPointer closure, XtPointer callData)
  791 {
  792     int width = 1280, height = 1024;
  793 
  794     if (!dmxConfigCurrent)
  795         return;
  796     if (dmxConfigCurrentDisplay) {
  797         width = dmxConfigCurrentDisplay->scrnWidth;
  798         height = dmxConfigCurrentDisplay->scrnHeight;
  799     }
  800     dmxConfigCurrentDisplay = dmxConfigCreateDisplay(NULL, NULL, NULL,
  801                                                      NULL, NULL);
  802     dmxConfigNewDisplay = dmxConfigCurrentDisplay;
  803     dmxConfigCurrentDisplay->scrnWidth = width;
  804     dmxConfigCurrentDisplay->scrnHeight = height;
  805 
  806     dmxConfigCurrent->subentry
  807         = dmxConfigAddSub(dmxConfigCurrent->subentry,
  808                           dmxConfigSubDisplay(dmxConfigCurrentDisplay));
  809     dmxConfigEDCallback(w, closure, callData);
  810 }
  811 
  812 static void
  813 dmxConfigDDCallback(Widget w, XtPointer closure, XtPointer callData)
  814 {
  815     DMXConfigSubPtr pt;
  816 
  817     if (!dmxConfigCurrent || !dmxConfigCurrentDisplay)
  818         return;
  819     /* First */
  820     if (dmxConfigCurrent->subentry
  821         && dmxConfigCurrent->subentry->type == dmxConfigDisplay
  822         && dmxConfigCurrent->subentry->display == dmxConfigCurrentDisplay) {
  823         dmxConfigCurrent->subentry = dmxConfigCurrent->subentry->next;
  824     }
  825     else {
  826         for (pt = dmxConfigCurrent->subentry; pt && pt->next; pt = pt->next)
  827             if (pt->next->type == dmxConfigDisplay
  828                 && pt->next->display == dmxConfigCurrentDisplay) {
  829                 pt->next = pt->next->next;
  830                 break;
  831             }
  832     }
  833     dmxConfigFreeDisplay(dmxConfigCurrentDisplay);
  834     dmxConfigCurrentDisplay = NULL;
  835     dmxConfigSetupCnamemenu();
  836     dmxConfigCanvasDraw(NULL);
  837 }
  838 
  839 static void
  840 dmxConfigAboutCallback(Widget w, XtPointer closure, XtPointer callData)
  841 {
  842     dmxConfigSetPopupPosition(aboutpopup);
  843     XtPopup(aboutpopup, XtGrabExclusive);
  844 }
  845 
  846 static void
  847 dmxConfigAboutOkCallback(Widget w, XtPointer closure, XtPointer CallData)
  848 {
  849     XtPopdown(aboutpopup);
  850 }
  851 
  852 static void
  853 dmxConfigQuitCallback(Widget w, XtPointer closure, XtPointer callData)
  854 {
  855     if (dmxConfigNotSaved) {
  856         dmxConfigSetPopupPosition(quitpopup);
  857         XtPopup(quitpopup, XtGrabExclusive);
  858         return;
  859     }
  860     exit(0);
  861 }
  862 
  863 static void
  864 dmxConfigQuitOkCallback(Widget w, XtPointer closure, XtPointer callData)
  865 {
  866     XtPopdown(quitpopup);
  867     exit(0);
  868 }
  869 
  870 static void
  871 dmxConfigQuitCanCallback(Widget w, XtPointer closure, XtPointer callData)
  872 {
  873     XtPopdown(quitpopup);
  874 }
  875 
  876 static void
  877 dmxConfigEDOkCallback(Widget w, XtPointer closure, XtPointer callData)
  878 {
  879     char *value;
  880     char *endpt;
  881 
  882     dmxConfigNewDisplay = NULL;
  883     dmxConfigGetValueString((char **) &dmxConfigCurrentDisplay->name,
  884                             eddialog0);
  885     value = XawDialogGetValueString(eddialog1);
  886     if (*value == '-' || *value == '+') {
  887         dmxConfigCurrentDisplay->scrnWidth = 0;
  888         dmxConfigCurrentDisplay->scrnHeight = 0;
  889         endpt = value;
  890     }
  891     else {
  892         dmxConfigCurrentDisplay->scrnWidth = strtol(value, &endpt, 10);
  893         dmxConfigCurrentDisplay->scrnHeight = strtol(endpt + 1, &endpt, 10);
  894     }
  895     if (*endpt) {
  896         dmxConfigCurrentDisplay->scrnXSign = (*endpt == '-') ? -1 : 1;
  897         dmxConfigCurrentDisplay->scrnX = strtol(endpt + 1, &endpt, 10);
  898         dmxConfigCurrentDisplay->scrnYSign = (*endpt == '-') ? -1 : 1;
  899         dmxConfigCurrentDisplay->scrnY = strtol(endpt + 1, NULL, 10);
  900     }
  901     if (dmxConfigCurrentDisplay->scrnX < 0)
  902         dmxConfigCurrentDisplay->scrnX = -dmxConfigCurrentDisplay->scrnX;
  903     if (dmxConfigCurrentDisplay->scrnY < 0)
  904         dmxConfigCurrentDisplay->scrnY = -dmxConfigCurrentDisplay->scrnY;
  905     value = XawDialogGetValueString(eddialog2);
  906     dmxConfigCurrentDisplay->rootXOrigin = strtol(value + 1, &endpt, 10);
  907     dmxConfigCurrentDisplay->rootYOrigin = strtol(endpt + 1, NULL, 10);
  908     XtPopdown(edpopup);
  909     dmxConfigSetupCnamemenu();
  910     dmxConfigCanvasDraw(NULL);
  911     dmxConfigNotSaved = 1;
  912 }
  913 
  914 static void
  915 dmxConfigEDCanCallback(Widget w, XtPointer closure, XtPointer callData)
  916 {
  917     if (dmxConfigNewDisplay)
  918         dmxConfigDDCallback(w, closure, callData);
  919     dmxConfigNewDisplay = NULL;
  920     XtPopdown(edpopup);
  921 }
  922 
  923 static void
  924 dmxConfigOkAction(Widget w, XEvent * event,
  925                   String * params, Cardinal * num_params)
  926 {
  927     Widget p = XtParent(w);
  928     Widget t;
  929 
  930     if (p == opendialog)
  931         dmxConfigOkCallback(w, NULL, NULL);
  932 
  933     if (p == ecdialog0) {
  934         t = XtNameToWidget(ecdialog1, "value");
  935         XWarpPointer(XtDisplay(t), None, XtWindow(t), 0, 0, 0, 0, 0, 10);
  936     }
  937     if (p == ecdialog1)
  938         dmxConfigECOkCallback(w, NULL, NULL);
  939 
  940     if (p == eddialog0) {
  941         t = XtNameToWidget(eddialog1, "value");
  942         XWarpPointer(XtDisplay(t), None, XtWindow(t), 0, 0, 0, 0, 0, 10);
  943     }
  944     if (p == eddialog1) {
  945         t = XtNameToWidget(eddialog2, "value");
  946         XWarpPointer(XtDisplay(t), None, XtWindow(t), 0, 0, 0, 0, 0, 10);
  947     }
  948     if (p == eddialog2)
  949         dmxConfigEDOkCallback(w, NULL, NULL);
  950 }
  951 
  952 int
  953 main(int argc, char **argv)
  954 {
  955     XtAppContext appContext;
  956     Widget toplevel;
  957     Widget parent, menubox, bottombox, databox, canvasbox;
  958     Widget filebutton, helpbutton;
  959     Widget filemenu, openbutton, savebutton, quitbutton;
  960     Widget helpmenu, aboutbutton, aboutbox, aboutok;
  961     Widget quitbox, quitok, quitcan;
  962     Widget ncbutton;
  963     Widget canbutton;
  964     Widget ecbox, ecokbutton, eccanbutton;
  965     Widget edbox, edokbutton;
  966     Widget edcanbutton;
  967 
  968     /* FIXME: add meta-i, ctrl,meta-z,v? */
  969     const char *opentrans = "<Key>Return: openOk()\n\
  970                                  <Key>Linefeed: openOk()\n\
  971                                  Ctrl<Key>M: openOk()\n\
  972                                  Ctrl<Key>J: openOk()\n\
  973                                  Ctrl<Key>O: noop()\n\
  974                                  Ctrl<Key>N: noop()\n\
  975                                  Ctrl<Key>P: noop()";
  976     const char *canvastrans =
  977         "<Btn3Down>: placeMenu() XtMenuPopup(buttonpopup)";
  978     XtActionsRec actiontable[] = {
  979         {(char *) "openOk", dmxConfigOkAction},
  980         {(char *) "placeMenu", dmxConfigPlaceMenu},
  981         {(char *) "noop", NULL}
  982     };
  983 
  984     dmxConfigFilename = XtNewString((argc >= 2) ? argv[1] : "");
  985 
  986     toplevel = XtVaAppInitialize(&appContext, "XDmxconfig",
  987                                  NULL, 0, &argc, argv, NULL, NULL);
  988 
  989     /* Main boxes */
  990     parent = XtVaCreateManagedWidget("parent", formWidgetClass, toplevel,
  991                                      XtNorientation, XtorientVertical,
  992                                      XtNwidth, DMX_MAIN_WIDTH,
  993                                      XtNheight, DMX_MAIN_HEIGHT, NULL);
  994     menubox = XtVaCreateManagedWidget("menubox", boxWidgetClass, parent,
  995                                       XtNborderWidth, 0,
  996                                       XtNorientation, XtorientHorizontal,
  997                                       XtNtop, XtChainTop, NULL);
  998     bottombox = XtVaCreateManagedWidget("bottombox", formWidgetClass, parent,
  999                                         XtNborderWidth, 0,
 1000                                         XtNfromVert, menubox,
 1001                                         XtNorientation, XtorientHorizontal,
 1002                                         NULL);
 1003     databox = XtVaCreateManagedWidget("databox", formWidgetClass,
 1004                                       bottombox,
 1005                                       XtNborderWidth, 0,
 1006                                       XtNhorizDistance, 0,
 1007                                       XtNwidth, DMX_DATA_WIDTH,
 1008                                       XtNheight, DMX_DATA_HEIGHT,
 1009                                       XtNleft, XtChainLeft,
 1010                                       XtNorientation, XtorientVertical, NULL);
 1011 
 1012     /* Data */
 1013     cnamebox = XtVaCreateManagedWidget("cnamebox", menuButtonWidgetClass,
 1014                                        databox,
 1015                                        XtNtop, XtChainTop,
 1016                                        XtNjustify, XtJustifyLeft,
 1017                                        XtNwidth, DMX_DATA_WIDTH,
 1018                                        XtNlabel, "",
 1019                                        XtNmenuName, "cnamemenu", NULL);
 1020     cdimbox = XtVaCreateManagedWidget("cdimbox", labelWidgetClass,
 1021                                       databox,
 1022                                       XtNfromVert, cnamebox,
 1023                                       XtNjustify, XtJustifyLeft,
 1024                                       XtNwidth, DMX_DATA_WIDTH,
 1025                                       XtNlabel, "", NULL);
 1026     namebox = XtVaCreateManagedWidget("namebox", labelWidgetClass, databox,
 1027                                       XtNfromVert, cdimbox,
 1028                                       XtNjustify, XtJustifyLeft,
 1029                                       XtNwidth, DMX_DATA_WIDTH,
 1030                                       XtNlabel, "", NULL);
 1031     dimbox = XtVaCreateManagedWidget("dimbox", labelWidgetClass,
 1032                                      databox,
 1033                                      XtNfromVert, namebox,
 1034                                      XtNjustify, XtJustifyLeft,
 1035                                      XtNwidth, DMX_DATA_WIDTH,
 1036                                      XtNlabel, "", NULL);
 1037     rtbox = XtVaCreateManagedWidget("rtbox", labelWidgetClass,
 1038                                     databox,
 1039                                     XtNfromVert, dimbox,
 1040                                     XtNjustify, XtJustifyLeft,
 1041                                     XtNwidth, DMX_DATA_WIDTH,
 1042                                     XtNlabel, "", NULL);
 1043     origbox = XtVaCreateManagedWidget("origbox", labelWidgetClass,
 1044                                       databox,
 1045                                       XtNfromVert, rtbox,
 1046                                       XtNjustify, XtJustifyLeft,
 1047                                       XtNwidth, DMX_DATA_WIDTH,
 1048                                       XtNlabel, "", NULL);
 1049 
 1050     /* Canvas */
 1051     canvasbox = XtVaCreateManagedWidget("canvasbox", boxWidgetClass,
 1052                                         bottombox,
 1053                                         XtNborderWidth, 0,
 1054                                         XtNwidth, DMX_CANVAS_WIDTH,
 1055                                         XtNheight, DMX_CANVAS_HEIGHT,
 1056                                         XtNfromHoriz, databox, NULL);
 1057 
 1058     canvas = XtVaCreateManagedWidget("canvas", canvasWidgetClass,
 1059                                      canvasbox,
 1060                                      XtNwidth, DMX_CANVAS_WIDTH,
 1061                                      XtNheight, DMX_CANVAS_HEIGHT, NULL);
 1062 
 1063     /* Main menu buttons */
 1064     filebutton = XtVaCreateManagedWidget("File", menuButtonWidgetClass,
 1065                                          menubox,
 1066                                          XtNmenuName, "filemenu", NULL);
 1067     helpbutton = XtVaCreateManagedWidget("Help", menuButtonWidgetClass,
 1068                                          menubox,
 1069                                          XtNmenuName, "helpmenu", NULL);
 1070 
 1071     /* File submenu buttons */
 1072     filemenu = XtVaCreatePopupShell("filemenu", simpleMenuWidgetClass,
 1073                                     filebutton, NULL);
 1074     openbutton = XtVaCreateManagedWidget("Open File", smeBSBObjectClass,
 1075                                          filemenu, NULL);
 1076     savebutton = XtVaCreateManagedWidget("Save File", smeBSBObjectClass,
 1077                                          filemenu, NULL);
 1078     ncbutton = XtVaCreateManagedWidget("New Global", smeBSBObjectClass,
 1079                                        filemenu, NULL);
 1080     ecbutton = XtVaCreateManagedWidget("Edit Global", smeBSBObjectClass,
 1081                                        filemenu, NULL);
 1082     dcbutton = XtVaCreateManagedWidget("Delete Global", smeBSBObjectClass,
 1083                                        filemenu, NULL);
 1084     ndbutton0 = XtVaCreateManagedWidget("New Display", smeBSBObjectClass,
 1085                                         filemenu, NULL);
 1086     quitbutton = XtVaCreateManagedWidget("Quit", smeBSBObjectClass,
 1087                                          filemenu, NULL);
 1088 
 1089     /* Help submenu button */
 1090     helpmenu = XtVaCreatePopupShell("helpmenu", simpleMenuWidgetClass,
 1091                                     helpbutton, NULL);
 1092     aboutbutton = XtVaCreateManagedWidget("About", smeBSBObjectClass,
 1093                                           helpmenu, NULL);
 1094 
 1095     /* Open popup */
 1096     openpopup = XtVaCreatePopupShell("openpopup", transientShellWidgetClass,
 1097                                      toplevel, NULL);
 1098     opendialog = XtVaCreateManagedWidget("opendialog", dialogWidgetClass,
 1099                                          openpopup,
 1100                                          XtNlabel, "Filename: ",
 1101                                          XtNvalue, dmxConfigFilename, NULL);
 1102     okbutton = XtVaCreateManagedWidget("Open", commandWidgetClass,
 1103                                        opendialog, NULL);
 1104     canbutton = XtVaCreateManagedWidget("Cancel", commandWidgetClass,
 1105                                         opendialog, NULL);
 1106 
 1107     /* EC popup */
 1108     ecpopup = XtVaCreatePopupShell("ecpopup", transientShellWidgetClass,
 1109                                    toplevel, NULL);
 1110     ecbox = XtVaCreateManagedWidget("ecbox", boxWidgetClass, ecpopup, NULL);
 1111     ecdialog0 = XtVaCreateManagedWidget("ecdialog0", dialogWidgetClass,
 1112                                         ecbox,
 1113                                         XtNlabel, "Name:              ",
 1114                                         XtNvalue, "", NULL);
 1115     ecdialog1 = XtVaCreateManagedWidget("ecdialog1", dialogWidgetClass,
 1116                                         ecbox,
 1117                                         XtNlabel, "Dimension:         ",
 1118                                         XtNvalue, "", NULL);
 1119     ecokbutton = XtVaCreateManagedWidget("OK", commandWidgetClass, ecbox, NULL);
 1120     eccanbutton = XtVaCreateManagedWidget("Cancel", commandWidgetClass,
 1121                                           ecbox, NULL);
 1122 
 1123     /* ED popup */
 1124     edpopup = XtVaCreatePopupShell("edpopup", transientShellWidgetClass,
 1125                                    toplevel, NULL);
 1126     edbox = XtVaCreateManagedWidget("edbox", boxWidgetClass, edpopup, NULL);
 1127     eddialog0 = XtVaCreateManagedWidget("eddialog0", dialogWidgetClass,
 1128                                         edbox,
 1129                                         XtNlabel, "Display Name:      ",
 1130                                         XtNvalue, "", NULL);
 1131     eddialog1 = XtVaCreateManagedWidget("eddialog1", dialogWidgetClass,
 1132                                         edbox,
 1133                                         XtNlabel, "Geometry:          ",
 1134                                         XtNvalue, "", NULL);
 1135     eddialog2 = XtVaCreateManagedWidget("eddialog2", dialogWidgetClass,
 1136                                         edbox,
 1137                                         XtNlabel, "Offset:            ",
 1138                                         XtNvalue, "", NULL);
 1139     edokbutton = XtVaCreateManagedWidget("OK", commandWidgetClass, edbox, NULL);
 1140     edcanbutton = XtVaCreateManagedWidget("Cancel", commandWidgetClass,
 1141                                           edbox, NULL);
 1142 
 1143     /* About popup */
 1144     aboutpopup = XtVaCreatePopupShell("aboutpopup", transientShellWidgetClass,
 1145                                       toplevel, NULL);
 1146     aboutbox = XtVaCreateManagedWidget("aboutbox", boxWidgetClass,
 1147                                        aboutpopup, NULL);
 1148     XtVaCreateManagedWidget("abouttext", labelWidgetClass,
 1149                             aboutbox, XtNlabel, DMX_INFO, NULL);
 1150     aboutok = XtVaCreateManagedWidget("OK", commandWidgetClass, aboutbox, NULL);
 1151 
 1152     /* Quit popup */
 1153     quitpopup = XtVaCreatePopupShell("quitpopup", transientShellWidgetClass,
 1154                                      toplevel, NULL);
 1155     quitbox = XtVaCreateManagedWidget("quitbox", boxWidgetClass,
 1156                                       quitpopup, NULL);
 1157     XtVaCreateManagedWidget("quittext", labelWidgetClass,
 1158                             quitbox,
 1159                             XtNlabel,
 1160                             "Changes to the configuration\n"
 1161                             "been made that have not yet\n"
 1162                             "been saved.  Do you want to\n"
 1163                             "quit without saving?", NULL);
 1164     quitok = XtVaCreateManagedWidget("Quit WITHOUT Saving",
 1165                                      commandWidgetClass, quitbox, NULL);
 1166     quitcan = XtVaCreateManagedWidget("Continue Editing",
 1167                                       commandWidgetClass, quitbox, NULL);
 1168 
 1169     /* Button popup */
 1170     buttonpopup = XtVaCreatePopupShell("buttonpopup", simpleMenuWidgetClass,
 1171                                        toplevel, NULL);
 1172     ndbutton1 = XtVaCreateManagedWidget("New Display", smeBSBObjectClass,
 1173                                         buttonpopup, NULL);
 1174     edbutton = XtVaCreateManagedWidget("Edit Display", smeBSBObjectClass,
 1175                                        buttonpopup, NULL);
 1176     ddbutton = XtVaCreateManagedWidget("Delete Display", smeBSBObjectClass,
 1177                                        buttonpopup, NULL);
 1178 
 1179     /* Callbacks */
 1180     XtAddCallback(openbutton, XtNcallback, dmxConfigOpenCallback, NULL);
 1181     XtAddCallback(savebutton, XtNcallback, dmxConfigSaveCallback, NULL);
 1182     XtAddCallback(okbutton, XtNcallback, dmxConfigOkCallback, NULL);
 1183     XtAddCallback(canbutton, XtNcallback, dmxConfigCanCallback, NULL);
 1184 
 1185     XtAppAddActions(appContext, actiontable, XtNumber(actiontable));
 1186     XtOverrideTranslations(canvas, XtParseTranslationTable(canvastrans));
 1187     XtOverrideTranslations(XtNameToWidget(opendialog, "value"),
 1188                            XtParseTranslationTable(opentrans));
 1189     XtOverrideTranslations(XtNameToWidget(ecdialog0, "value"),
 1190                            XtParseTranslationTable(opentrans));
 1191     XtOverrideTranslations(XtNameToWidget(ecdialog1, "value"),
 1192                            XtParseTranslationTable(opentrans));
 1193     XtOverrideTranslations(XtNameToWidget(eddialog0, "value"),
 1194                            XtParseTranslationTable(opentrans));
 1195     XtOverrideTranslations(XtNameToWidget(eddialog1, "value"),
 1196                            XtParseTranslationTable(opentrans));
 1197     XtOverrideTranslations(XtNameToWidget(eddialog2, "value"),
 1198                            XtParseTranslationTable(opentrans));
 1199 
 1200     XtAddCallback(ncbutton, XtNcallback, dmxConfigNCCallback, NULL);
 1201     XtAddCallback(ecbutton, XtNcallback, dmxConfigECCallback, NULL);
 1202     XtAddCallback(ecokbutton, XtNcallback, dmxConfigECOkCallback, NULL);
 1203     XtAddCallback(eccanbutton, XtNcallback, dmxConfigECCanCallback, NULL);
 1204     XtAddCallback(dcbutton, XtNcallback, dmxConfigDCCallback, NULL);
 1205 
 1206     XtAddCallback(ndbutton0, XtNcallback, dmxConfigNDCallback, NULL);
 1207     XtAddCallback(ndbutton1, XtNcallback, dmxConfigNDCallback, NULL);
 1208     XtAddCallback(edbutton, XtNcallback, dmxConfigEDCallback, NULL);
 1209     XtAddCallback(ddbutton, XtNcallback, dmxConfigDDCallback, NULL);
 1210     XtAddCallback(edokbutton, XtNcallback, dmxConfigEDOkCallback, NULL);
 1211     XtAddCallback(edcanbutton, XtNcallback, dmxConfigEDCanCallback, NULL);
 1212 
 1213     XtAddCallback(aboutbutton, XtNcallback, dmxConfigAboutCallback, NULL);
 1214     XtAddCallback(aboutok, XtNcallback, dmxConfigAboutOkCallback, NULL);
 1215     XtAddCallback(quitok, XtNcallback, dmxConfigQuitOkCallback, NULL);
 1216     XtAddCallback(quitcan, XtNcallback, dmxConfigQuitCanCallback, NULL);
 1217 
 1218     XtAddCallback(quitbutton, XtNcallback, dmxConfigQuitCallback, NULL);
 1219 
 1220     XtAddCallback(canvas, XtNcallback, dmxConfigCanvasInput, NULL);
 1221     XtAddCallback(canvas, XtNcanvasExposeCallback, dmxConfigCanvasExpose, NULL);
 1222     XtAddCallback(canvas, XtNcanvasResizeCallback, dmxConfigCanvasResize, NULL);
 1223 
 1224     if (dmxConfigFilename)
 1225         dmxConfigReadFile();
 1226 
 1227     XtRealizeWidget(toplevel);
 1228     dmxConfigCopystrings();
 1229     dmxConfigSetupCnamemenu();
 1230     XtAppMainLoop(appContext);
 1231     return 0;
 1232 }