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