Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2 
      3 Copyright 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included
     12 in all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall
     23 not be used in advertising or otherwise to promote the sale, use or
     24 other dealings in this Software without prior written authorization
     25 from The Open Group.
     26 
     27 */
     28 
     29 /*
     30  * Author:  Davor Matic, MIT X Consortium
     31  */
     32 
     33 #ifdef HAVE_CONFIG_H
     34 # include "config.h"
     35 #endif
     36 
     37 #include <stdio.h>
     38 #include <stdlib.h>
     39 #include <X11/Intrinsic.h>
     40 #include <X11/StringDefs.h>
     41 #include <X11/Xaw/Paned.h>
     42 #include <X11/Xaw/Form.h>
     43 #include <X11/Xaw/Box.h>
     44 #include <X11/Xaw/Command.h>
     45 #include <X11/Xaw/Toggle.h>
     46 #include <X11/Xaw/MenuButton.h>
     47 #include <X11/Xaw/SimpleMenu.h>
     48 #include <X11/Xaw/SmeLine.h>
     49 #include <X11/Xaw/SmeBSB.h>
     50 #include "Bitmap.h"
     51 
     52 #include <X11/bitmaps/xlogo16>
     53 
     54 static const char *usage = "[-options ...] filename\n\
     55 \n\
     56 where options include all standard toolkit options plus:\n\
     57      -size WIDTHxHEIGHT\n\
     58      -sw dimension\n\
     59      -sh dimension\n\
     60      -gt dimension\n\
     61      -grid, +grid\n\
     62      -axes, +axes\n\
     63      -dashed, +dashed\n\
     64      -stippled, +stippled\n\
     65      -proportional, +proportional\n\
     66      -basename basename\n\
     67      -dashes filename\n\
     68      -stipple filename\n\
     69      -hl color\n\
     70      -fr color\n\
     71      -help\n\
     72      -version\n\
     73 \n\
     74 The default WIDTHxHEIGHT is 16x16.\n";
     75 
     76 #define __C(A,B,C,D)   {(char *)A,(char *)B,C,(XPointer)D}
     77 
     78 static XrmOptionDescRec options[] = {
     79   __C( "-axes",	    "*bitmap.axes",	    XrmoptionNoArg,	"True"),
     80   __C( "+axes",	    "*bitmap.axes",	    XrmoptionNoArg,	"False"),
     81   __C( "-basename",    "*bitmap.basename",	    XrmoptionSepArg,	NULL),
     82   __C( "-dashed",	    "*bitmap.dashed",	    XrmoptionNoArg,	"True"),
     83   __C( "+dashed",	    "*bitmap.dashed",	    XrmoptionNoArg,	"False"),
     84   __C( "-dashes",	    "*bitmap.dashes",	    XrmoptionSepArg,	NULL),
     85   __C( "-fr",	    "*bitmap.frame",	    XrmoptionSepArg,	NULL),
     86   __C( "-gt",	    "*bitmap.gridTolerance",XrmoptionSepArg,	NULL),
     87   __C( "-grid",	    "*bitmap.grid",	    XrmoptionNoArg,	"True"),
     88   __C( "+grid",	    "*bitmap.grid",	    XrmoptionNoArg,	"False"),
     89   __C( "-hl",	    "*bitmap.highlight",    XrmoptionSepArg,	NULL),
     90   __C( "-proportional","*bitmap.proportional", XrmoptionNoArg,	"True"),
     91   __C( "+proportional","*bitmap.proportional", XrmoptionNoArg,	"False"),
     92   __C( "-size",	    "*bitmap.size",	    XrmoptionSepArg,	NULL),
     93   __C( "-sh",	    "*bitmap.squareHeight", XrmoptionSepArg,	NULL),
     94   __C( "-sw",	    "*bitmap.squareWidth",  XrmoptionSepArg,	NULL),
     95   __C( "-stipple",	    "*bitmap.stipple",	    XrmoptionSepArg,	NULL),
     96   __C( "-stippled",    "*bitmap.stippled",	    XrmoptionNoArg,	"True"),
     97   __C( "+stippled",    "*bitmap.stippled",	    XrmoptionNoArg,	"False"),
     98 };
     99 
    100 #undef   __C
    101 
    102 typedef struct {
    103   int             id;
    104   String          name;
    105   Boolean         trap;
    106   Widget          widget;
    107   } ButtonRec;
    108 
    109 static ButtonRec file_menu[] = {
    110 #define New 101
    111   {New, "new", True},
    112 #define Load 102
    113   {Load, "load", True},
    114 #define Insert 103
    115   {Insert, "insert", True},
    116 #define Save 104
    117   {Save, "save", True},
    118 #define SaveAs 105
    119   {SaveAs, "saveAs", True},
    120 #define Resize 106
    121   {Resize, "resize", True},
    122 #define Rescale 107
    123   {Rescale, "rescale", True},
    124 #define Filename 108
    125   {Filename, "filename", True},
    126 #define Basename 109
    127   {Basename, "basename", True},
    128 #define Dummy -1
    129   {Dummy, "line", False},
    130 #define Quit 110
    131   {Quit, "quit", True},
    132 };
    133 
    134 static ButtonRec edit_menu[] = {
    135 #define Image 201
    136   {Image, "image", True},
    137 #define Grid 203
    138   {Grid, "grid", True},
    139 #define Dashed 204
    140   {Dashed, "dashed", True},
    141 #define Axes 205
    142   {Axes, "axes", True},
    143 #define Stippled 206
    144   {Stippled, "stippled", True},
    145 #define Proportional 207
    146   {Proportional, "proportional", True},
    147 #define Zoom 208
    148   {Zoom, "zoom", True},
    149 /* Dummy */
    150   {Dummy, "line", False},
    151 #define Cut 209
    152   {Cut, "cut", True},
    153 #define Copy 210
    154   {Copy, "copy", True},
    155 #define Paste 211
    156   {Paste, "paste", True},
    157 };
    158 
    159 static ButtonRec buttons[] = {
    160 /*#define Clear 1*/
    161   {Clear, "clear", False},
    162 /*#define Set 2*/
    163   {Set, "set", False},
    164 /*#define Invert 3*/
    165   {Invert, "invert", False},
    166 #define Mark 26
    167   {Mark, "mark", True},
    168 #define Unmark 27
    169   {Unmark, "unmark", False},
    170 #define CopyImm 4
    171   {CopyImm, "copy", True},
    172 #define MoveImm 5
    173   {MoveImm, "move", True},
    174 #define FlipHoriz 6
    175   {FlipHoriz, "flipHoriz", False},
    176 #define Up 7
    177   {Up, "up", False},
    178 #define FlipVert 8
    179   {FlipVert, "flipVert", False},
    180 #define Left 9
    181   {Left, "left", False},
    182 #define Fold 10
    183   {Fold, "fold", False},
    184 #define Right 11
    185   {Right, "right", False},
    186 #define RotateLeft 12
    187   {RotateLeft, "rotateLeft", False},
    188 #define Down 13
    189   {Down, "down", False},
    190 #define RotateRight 14
    191   {RotateRight, "rotateRight", False},
    192 #define Point 15
    193   {Point, "point", True},
    194 #define Curve 16
    195   {Curve, "curve", True},
    196 #define Line 17
    197   {Line, "line", True},
    198 #define Rectangle 18
    199   {Rectangle, "rectangle", True},
    200 #define FilledRectangle 19
    201   {FilledRectangle, "filledRectangle", True},
    202 #define Circle 20
    203   {Circle, "circle", True},
    204 #define FilledCircle 21
    205   {FilledCircle, "filledCircle", True},
    206 #define FloodFill 22
    207   {FloodFill, "floodFill", True},
    208 #define SetHotSpot 23
    209   {SetHotSpot, "setHotSpot", True},
    210 #define ClearHotSpot 24
    211   {ClearHotSpot, "clearHotSpot", False},
    212 #define Undo 25
    213   {Undo, "undo", False},
    214 };
    215 
    216 #include "Dialog.h"
    217 
    218 static Widget
    219     top_widget,
    220     parent_widget,
    221     formy_widget,
    222     fileMenu_widget,
    223     editMenu_widget,
    224     status_widget,
    225     pane_widget,
    226     form_widget,
    227     bitmap_widget,
    228     image_shell,
    229     box_widget,
    230     normal_image_widget,
    231     inverted_image_widget;
    232 static Boolean image_visible = False;
    233 static Pixmap check_mark;
    234 static Dialog input_dialog, error_dialog, qsave_dialog;
    235 static Time btime;
    236 static char *filename = NULL, *base_name = NULL;
    237 static char  *format;
    238 static char message[80];
    239 
    240 
    241 void FixMenu ( Widget w, XEvent *event, String *params, Cardinal *num_params );
    242 void SwitchImage ( void );
    243 void SwitchGrid( void );
    244 void SwitchDashed( void );
    245 void SwitchAxes( void );
    246 void SwitchStippled( void );
    247 void SwitchProportional( void );
    248 void SwitchZoom( void );
    249 void DoCut( void );
    250 void DoCopy( void );
    251 void DoPaste( void );
    252 void DoNew( void );
    253 void DoLoad( void );
    254 void DoInsert( void );
    255 void DoSave( void );
    256 void DoSaveAs( void );
    257 void DoResize( void );
    258 void DoRescale( void );
    259 void DoFilename( void );
    260 void DoBasename( void );
    261 void DoQuit ( Widget w, XEvent *event, String *params, Cardinal *num_params );
    262 
    263 static XtActionsRec actions_table[] = {
    264   {"fix-menu", FixMenu},
    265   {"switch-image", (XtActionProc)SwitchImage},
    266   {"switch-grid", (XtActionProc)SwitchGrid},
    267   {"switch-dashed", (XtActionProc)SwitchDashed},
    268   {"switch-axes", (XtActionProc)SwitchAxes},
    269   {"switch-stippled", (XtActionProc)SwitchStippled},
    270   {"switch-proportional", (XtActionProc)SwitchProportional},
    271   {"switch-zoom", (XtActionProc)SwitchZoom},
    272   {"do-cut", (XtActionProc)DoCut},
    273   {"do-copy", (XtActionProc)DoCopy},
    274   {"do-paste", (XtActionProc)DoPaste},
    275   {"do-new", (XtActionProc)DoNew},
    276   {"do-load", (XtActionProc)DoLoad},
    277   {"do-insert", (XtActionProc)DoInsert},
    278   {"do-save", (XtActionProc)DoSave},
    279   {"do-save-as", (XtActionProc)DoSaveAs},
    280   {"do-resize", (XtActionProc)DoResize},
    281   {"do-rescale", (XtActionProc)DoRescale},
    282   {"do-filename", (XtActionProc)DoFilename},
    283   {"do-basename", (XtActionProc)DoBasename},
    284   {"do-quit", DoQuit}
    285 };
    286 
    287 static Atom wm_delete_window;
    288 
    289 static void
    290 FixImage(void)
    291 {
    292     Pixmap old_image, image;
    293     int n;
    294     Arg wargs[2];
    295 
    296     if (!image_visible) return;
    297 
    298     n=0;
    299     XtSetArg(wargs[n], XtNbitmap, &old_image); n++;
    300     XtGetValues(normal_image_widget, wargs, n);
    301 
    302 
    303     image = BWGetUnzoomedPixmap(bitmap_widget);
    304 
    305     n=0;
    306     XtSetArg(wargs[n], XtNbitmap, image); n++;
    307     XtSetValues(normal_image_widget, wargs, n);
    308     XtSetValues(inverted_image_widget, wargs, n);
    309 
    310     if (old_image != XtUnspecifiedPixmap)
    311 	XFreePixmap(XtDisplay(bitmap_widget), old_image);
    312 }
    313 
    314 static void
    315 FixStatus(void)
    316 {
    317     int n;
    318     Arg wargs[2];
    319     String str, label;
    320 
    321     str = BWUnparseStatus(bitmap_widget);
    322 
    323     n=0;
    324     XtSetArg(wargs[n], XtNlabel, &label); n++;
    325     XtGetValues(status_widget, wargs, n);
    326 
    327     if (strcmp(str, label)) {
    328       n = 0;
    329       XtSetArg(wargs[n], XtNlabel, str); n++;
    330       XtSetValues(status_widget, wargs, n);
    331     }
    332 
    333     /*XtFree(str); */
    334 }
    335 
    336 static void
    337 FixUp(void)
    338 {
    339   FixImage();
    340   FixStatus();
    341 }
    342 
    343 static void
    344 FixEntry(Widget w, int *id)
    345 {
    346     Time dummy = 0;
    347 
    348     switch (*id) {
    349 
    350     case Image:
    351       XtVaSetValues(w,  XtNleftBitmap,
    352 		    image_visible ? check_mark : None,NULL);
    353 	return;
    354 
    355     case Grid:
    356       XtVaSetValues(w,  XtNleftBitmap,
    357 		    BWQueryGrid(bitmap_widget) ? check_mark : None,NULL);
    358 	return;
    359 
    360     case Dashed:
    361     XtVaSetValues(w,  XtNleftBitmap,
    362 		 BWQueryDashed(bitmap_widget) ? check_mark : None,NULL);
    363 	return;
    364 
    365     case Axes:
    366     XtVaSetValues(w,  XtNleftBitmap,
    367 		 BWQueryAxes(bitmap_widget) ? check_mark : None,NULL);
    368 	return;
    369 
    370     case Stippled:
    371         XtVaSetValues(w,  XtNleftBitmap,
    372 		 BWQueryStippled(bitmap_widget) ? check_mark : None,NULL);
    373 	return;
    374 
    375     case Proportional:
    376         XtVaSetValues(w,  XtNleftBitmap,
    377 		      BWQueryProportional(bitmap_widget) ? check_mark : None,NULL);
    378 	return;
    379 
    380     case Zoom:
    381         XtVaSetValues(w,  XtNleftBitmap,
    382 		 BWQueryZooming(bitmap_widget) ? check_mark : None,NULL);
    383 	return;
    384 
    385     case Copy:
    386     case Cut:
    387       XtVaSetValues(w,  XtNsensitive, BWQueryMarked(bitmap_widget),NULL );
    388 	return;
    389 
    390     case Paste:
    391       XtVaSetValues(w,  XtNsensitive, BWQuerySelection(bitmap_widget, dummy),NULL );
    392 	return;
    393 
    394     default:
    395 	return;
    396     }
    397 }
    398 
    399 /* ARGSUSED */
    400 void FixMenu(Widget w,
    401 	     XEvent *event,
    402 	     String *params,
    403 	     Cardinal *num_params)
    404 {
    405     btime = event->xbutton.time;
    406 
    407     for (Cardinal i = 0; i < XtNumber(edit_menu); i++)
    408 	FixEntry(edit_menu[i].widget, &edit_menu[i].id);
    409 }
    410 
    411 static int zero = 0;
    412 #define Plain  (char *)&zero,sizeof(int)
    413 /* ARGSUSED */
    414 static void
    415 TheCallback(Widget w,	/* not used */
    416 	    XtPointer clientData,
    417 	    XtPointer callData)
    418 {
    419     int *id = (int *)clientData;
    420     switch (*id) {
    421 
    422     case New:
    423       DoNew();
    424       break;
    425 
    426     case Load:
    427       DoLoad();
    428       break;
    429 
    430     case Insert:
    431       DoInsert();
    432       break;
    433 
    434     case Save:
    435       DoSave();
    436       break;
    437 
    438     case SaveAs:
    439       DoSaveAs();
    440       break;
    441 
    442     case Resize:
    443       DoResize();
    444       break;
    445 
    446     case Rescale:
    447       DoRescale();
    448       break;
    449 
    450     case Filename:
    451       DoFilename();
    452       break;
    453 
    454     case Basename:
    455       DoBasename();
    456       break;
    457 
    458     case Image:
    459       SwitchImage();
    460       break;
    461 
    462     case Grid:
    463       SwitchGrid();
    464       break;
    465 
    466     case Dashed:
    467       SwitchDashed();
    468       break;
    469 
    470     case Axes:
    471       SwitchAxes();
    472       break;
    473 
    474     case Stippled:
    475       SwitchStippled();
    476       break;
    477 
    478     case Proportional:
    479       SwitchProportional();
    480       break;
    481 
    482     case Zoom:
    483       SwitchZoom();
    484       break;
    485 
    486     case Cut:
    487       DoCut();
    488       break;
    489 
    490     case Copy:
    491       DoCopy();
    492       break;
    493 
    494     case Paste:
    495       DoPaste();
    496       break;
    497 
    498     case Clear:
    499 	BWStoreToBuffer(bitmap_widget);
    500 	BWClear(bitmap_widget);
    501 	BWChangeNotify(bitmap_widget);
    502 	BWSetChanged(bitmap_widget);
    503 	break;
    504 
    505     case Set:
    506 	BWStoreToBuffer(bitmap_widget);
    507 	BWSet(bitmap_widget);
    508 	BWChangeNotify(bitmap_widget);
    509 	BWSetChanged(bitmap_widget);
    510 break;
    511 
    512     case Invert:
    513 	BWStoreToBuffer(bitmap_widget);
    514 	BWInvert(bitmap_widget);
    515 	BWChangeNotify(bitmap_widget);
    516 	BWSetChanged(bitmap_widget);
    517 	break;
    518 
    519     case Mark:
    520         BWRemoveAllRequests(bitmap_widget);
    521         BWEngageRequest(bitmap_widget, MarkRequest, True, Plain);
    522         break;
    523 
    524     case Unmark:
    525         BWUnmark(bitmap_widget);
    526         break;
    527 
    528     case CopyImm:
    529 	BWRemoveAllRequests(bitmap_widget);
    530 	if (BWQueryMarked(bitmap_widget)) {
    531 	    BWAddRequest(bitmap_widget, MarkRequest, False, Plain);
    532 	    BWEngageRequest(bitmap_widget, CopyRequest, True, Plain);
    533 	}
    534 	else {
    535 	    BWEngageRequest(bitmap_widget, MarkRequest, False, Plain);
    536 	    BWAddRequest(bitmap_widget, CopyRequest, True, Plain);
    537 	}
    538 	break;
    539 
    540     case MoveImm:
    541 	BWRemoveAllRequests(bitmap_widget);
    542 	if (BWQueryMarked(bitmap_widget)) {
    543 	    BWAddRequest(bitmap_widget, MarkRequest, False, Plain);
    544 	    BWEngageRequest(bitmap_widget, MoveRequest, True, Plain);
    545 	}
    546 	else {
    547 	    BWEngageRequest(bitmap_widget, MarkRequest, False, Plain);
    548 	    BWAddRequest(bitmap_widget, MoveRequest, True, Plain);
    549 	}
    550 	break;
    551 
    552     case Up:
    553 	BWStoreToBuffer(bitmap_widget);
    554 	BWUp(bitmap_widget);
    555 	BWChangeNotify(bitmap_widget);
    556 	BWSetChanged(bitmap_widget);
    557 	break;
    558 
    559     case Down:
    560 	BWStoreToBuffer(bitmap_widget);
    561 	BWDown(bitmap_widget);
    562 	BWChangeNotify(bitmap_widget);
    563 	BWSetChanged(bitmap_widget);
    564 	break;
    565 
    566     case Left:
    567 	BWStoreToBuffer(bitmap_widget);
    568 	BWLeft(bitmap_widget);
    569 	BWChangeNotify(bitmap_widget);
    570 	BWSetChanged(bitmap_widget);
    571 	break;
    572 
    573     case Right:
    574 	BWStoreToBuffer(bitmap_widget);
    575 	BWRight(bitmap_widget);
    576 	BWChangeNotify(bitmap_widget);
    577 	BWSetChanged(bitmap_widget);
    578 	break;
    579 
    580     case Fold:
    581 	BWStoreToBuffer(bitmap_widget);
    582 	BWFold(bitmap_widget);
    583 	BWChangeNotify(bitmap_widget);
    584 	BWSetChanged(bitmap_widget);
    585 	break;
    586 
    587     case FlipHoriz:
    588 	BWStoreToBuffer(bitmap_widget);
    589 	BWFlipHoriz(bitmap_widget);
    590 	BWChangeNotify(bitmap_widget);
    591 	BWSetChanged(bitmap_widget);
    592 	break;
    593 
    594     case FlipVert:
    595 	BWStoreToBuffer(bitmap_widget);
    596 	BWFlipVert(bitmap_widget);
    597 	BWChangeNotify(bitmap_widget);
    598 	BWSetChanged(bitmap_widget);
    599 	break;
    600 
    601     case RotateRight:
    602 	BWStoreToBuffer(bitmap_widget);
    603 	BWRotateRight(bitmap_widget);
    604 	BWChangeNotify(bitmap_widget);
    605 	BWSetChanged(bitmap_widget);
    606 	break;
    607 
    608     case RotateLeft:
    609 	BWStoreToBuffer(bitmap_widget);
    610 	BWRotateLeft(bitmap_widget);
    611 	BWChangeNotify(bitmap_widget);
    612 	BWSetChanged(bitmap_widget);
    613 	break;
    614 
    615     case Point:
    616 	BWRemoveAllRequests(bitmap_widget);
    617 	BWEngageRequest(bitmap_widget, PointRequest, True, Plain);
    618 	break;
    619 
    620     case Curve:
    621 	BWRemoveAllRequests(bitmap_widget);
    622 	BWEngageRequest(bitmap_widget, CurveRequest, True, Plain);
    623 	break;
    624 
    625     case Line:
    626 	BWRemoveAllRequests(bitmap_widget);
    627 	BWEngageRequest(bitmap_widget, LineRequest, True, Plain);
    628 	break;
    629 
    630     case Rectangle:
    631 	BWRemoveAllRequests(bitmap_widget);
    632 	BWEngageRequest(bitmap_widget, RectangleRequest, True, Plain);
    633 	break;
    634 
    635     case FilledRectangle:
    636 	BWRemoveAllRequests(bitmap_widget);
    637 	BWEngageRequest(bitmap_widget, FilledRectangleRequest, True, Plain);
    638 	break;
    639 
    640     case Circle:
    641 	BWRemoveAllRequests(bitmap_widget);
    642 	BWEngageRequest(bitmap_widget, CircleRequest, True, Plain);
    643 	break;
    644 
    645     case FilledCircle:
    646 	BWRemoveAllRequests(bitmap_widget);
    647 	BWEngageRequest(bitmap_widget, FilledCircleRequest, True, Plain);
    648 	break;
    649 
    650     case FloodFill:
    651 	BWRemoveAllRequests(bitmap_widget);
    652 	BWEngageRequest(bitmap_widget, FloodFillRequest, True, Plain);
    653 	break;
    654 
    655     case SetHotSpot:
    656 	BWRemoveAllRequests(bitmap_widget);
    657 	BWEngageRequest(bitmap_widget, HotSpotRequest, True, Plain);
    658 	break;
    659 
    660     case ClearHotSpot:
    661 	BWStoreToBuffer(bitmap_widget);
    662 	BWClearHotSpot(bitmap_widget);
    663 	BWChangeNotify(bitmap_widget);
    664 	BWSetChanged(bitmap_widget);
    665 	break;
    666 
    667     case Undo:
    668 	BWUndo(bitmap_widget);
    669 	BWChangeNotify(bitmap_widget);
    670 	BWSetChanged(bitmap_widget);
    671 	break;
    672 
    673     case Quit:
    674       DoQuit(bitmap_widget, NULL, NULL, NULL);
    675       break;
    676     } /* don't add anything below this line */
    677 }
    678 
    679 /* ARGSUSED */
    680 
    681 void SwitchImage(void)
    682 {
    683   if (image_visible) {
    684     XtPopdown(image_shell);
    685     image_visible = False;
    686   }
    687   else {
    688     Position image_x, image_y;
    689     int n;
    690     Arg wargs[3];
    691 
    692     XtTranslateCoords(bitmap_widget,
    693 		      10, 10, &image_x, &image_y);
    694 
    695     n = 0;
    696     XtSetArg(wargs[n], XtNx, image_x); n++;
    697     XtSetArg(wargs[n], XtNy, image_y); n++;
    698     XtSetValues(image_shell, wargs, n);
    699 
    700     image_visible = True;
    701 
    702     FixImage();
    703     XtPopup(image_shell, XtGrabNone);
    704     FixImage();
    705   }
    706 }
    707 
    708 void SwitchGrid(void)
    709 {
    710   BWSwitchGrid(bitmap_widget);
    711 }
    712 
    713 void SwitchDashed(void)
    714 {
    715   BWSwitchDashed(bitmap_widget);
    716 }
    717 
    718 void SwitchAxes(void)
    719 {
    720   BWSwitchAxes(bitmap_widget);
    721 }
    722 
    723 void SwitchStippled(void)
    724 {
    725   BWSwitchStippled(bitmap_widget);
    726 }
    727 
    728 void SwitchProportional(void)
    729 {
    730   BWSwitchProportional(bitmap_widget);
    731 }
    732 
    733 void SwitchZoom(void)
    734 {
    735   if (BWQueryZooming(bitmap_widget)) {
    736     BWZoomOut(bitmap_widget);
    737     BWChangeNotify(bitmap_widget);
    738   }
    739   else {
    740     if (BWQueryMarked(bitmap_widget)) {
    741       BWStoreToBuffer(bitmap_widget);
    742       BWZoomMarked(bitmap_widget);
    743       BWChangeNotify(bitmap_widget);
    744     }
    745     else {
    746       BWEngageRequest(bitmap_widget, ZoomInRequest, False, Plain);
    747     }
    748   }
    749 }
    750 
    751 void DoCut(void)
    752 {
    753   BWStore(bitmap_widget);
    754   BWStoreToBuffer(bitmap_widget);
    755   BWClearMarked(bitmap_widget);
    756   BWUnmark(bitmap_widget);
    757   BWChangeNotify(bitmap_widget);
    758   BWSetChanged(bitmap_widget);
    759 }
    760 
    761 void DoCopy(void)
    762 {
    763   BWStore(bitmap_widget);
    764   BWUnmark(bitmap_widget);
    765 }
    766 
    767 void DoPaste(void)
    768 {
    769   BWRequestSelection(bitmap_widget, btime, TRUE);
    770   BWEngageRequest(bitmap_widget, RestoreRequest, False, Plain);
    771 }
    772 
    773 void DoNew(void)
    774 {
    775   BWGetFilename(bitmap_widget, &filename);
    776   if (PopupDialog(input_dialog, "New file:",
    777 		  filename, &filename, XtGrabExclusive) == Okay) {
    778     BWChangeFilename(bitmap_widget, filename);
    779     BWChangeBasename(bitmap_widget, filename);
    780     BWStoreToBuffer(bitmap_widget);
    781     BWClear(bitmap_widget);
    782     BWClearHotSpot(bitmap_widget);
    783     BWChangeNotify(bitmap_widget);
    784     BWClearChanged(bitmap_widget);
    785     BWUnmark(bitmap_widget);
    786     FixStatus();
    787   }
    788 }
    789 
    790 void DoLoad(void)
    791 {
    792   if (BWQueryChanged(bitmap_widget)) {
    793     BWGetFilename(bitmap_widget, &filename);
    794   RetryLoadSave:
    795     switch (PopupDialog(qsave_dialog, "Save file before loading?",
    796 			filename, &filename, XtGrabExclusive)) {
    797     case Yes:
    798       if (BWWriteFile(bitmap_widget, filename, NULL)
    799 	  != BitmapSuccess) {
    800 	snprintf(message, sizeof(message), "Can't write file: %s", filename);
    801 	if (PopupDialog(error_dialog, message,
    802 			NULL, NULL, XtGrabExclusive) == Retry)
    803 	  goto RetryLoadSave;
    804       }
    805       break;
    806 
    807     case Cancel:
    808       return;
    809     }
    810   }
    811   BWGetFilepath(bitmap_widget, &filename);
    812  RetryLoad:
    813   if (PopupDialog(input_dialog, "Load file:",
    814 		  filename, &filename, XtGrabExclusive) == Okay) {
    815     if (BWReadFile(bitmap_widget, filename, NULL) != BitmapSuccess) {
    816       snprintf(message, sizeof(message), "Can't read file: %s", filename);
    817       if (PopupDialog(error_dialog, message,
    818 		      NULL, NULL, XtGrabExclusive) == Retry)
    819 	goto RetryLoad;
    820     }
    821     else {
    822       BWChangeNotify(bitmap_widget);
    823       BWClearChanged(bitmap_widget);
    824       FixStatus();
    825     }
    826   }
    827 }
    828 
    829 void DoInsert(void)
    830 {
    831   BWGetFilepath(bitmap_widget, &filename);
    832  RetryInsert:
    833   if (PopupDialog(input_dialog, "Insert file:",
    834 		  filename, &filename, XtGrabExclusive) == Okay) {
    835     if (BWStoreFile(bitmap_widget, filename, NULL) != BitmapSuccess) {
    836       snprintf(message, sizeof(message), "Can't read file: %s", filename);
    837       if (PopupDialog(error_dialog, message,
    838 		      NULL, NULL, XtGrabExclusive) == Retry)
    839 	goto RetryInsert;
    840     }
    841     else {
    842       BWEngageRequest(bitmap_widget, RestoreRequest, False, Plain);
    843     }
    844   }
    845 }
    846 
    847 void DoSave(void)
    848 {
    849   BWGetFilename(bitmap_widget, &filename);
    850   if (!strcmp(filename, ""))
    851     DoSaveAs();
    852   else if (BWWriteFile(bitmap_widget, NULL, NULL) != BitmapSuccess) {
    853     snprintf(message, sizeof(message), "Can't write file: %s", filename);
    854     if (PopupDialog(error_dialog, message,
    855 		    NULL, NULL, XtGrabExclusive) == Retry)
    856       DoSaveAs();
    857   }
    858   else {
    859     BWClearChanged(bitmap_widget);
    860   }
    861 }
    862 
    863 void DoSaveAs(void)
    864 {
    865   BWGetFilename(bitmap_widget, &filename);
    866  RetrySave:
    867   if (PopupDialog(input_dialog, "Save file:",
    868 		  filename, &filename, XtGrabExclusive) == Okay) {
    869     if (BWWriteFile(bitmap_widget, filename, NULL) != BitmapSuccess) {
    870       snprintf(message, sizeof(message), "Can't write file: %s", filename);
    871       if (PopupDialog(error_dialog, message,
    872 		      NULL, NULL, XtGrabExclusive) == Retry)
    873 	goto RetrySave;
    874     }
    875     else {
    876       BWClearChanged(bitmap_widget);
    877       FixStatus();
    878     }
    879   }
    880 }
    881 
    882 void DoResize(void)
    883 {
    884   Dimension width, height;
    885   format = (char *)"";
    886  RetryResize:
    887   if (PopupDialog(input_dialog, "Resize to WIDTHxHEIGHT:",
    888 		  format, &format, XtGrabExclusive) == Okay) {
    889     if (BWParseSize(format, &width, &height)) {
    890       BWResize(bitmap_widget, width, height);
    891       BWChangeNotify(bitmap_widget);
    892       BWSetChanged(bitmap_widget);
    893       FixStatus();
    894     }
    895     else {
    896       snprintf(message, sizeof(message), "Wrong format: %s", format);
    897       if (PopupDialog(error_dialog, message,
    898 		      NULL, NULL, XtGrabExclusive) == Retry)
    899 	goto RetryResize;
    900     }
    901   }
    902 }
    903 
    904 void DoRescale(void)
    905 {
    906   Dimension width, height;
    907 
    908   format = (char *)"";
    909  RetryRescale:
    910   if (PopupDialog(input_dialog, "Rescale to WIDTHxHEIGHT:",
    911 		  format, &format, XtGrabExclusive) == Okay) {
    912     if (BWParseSize(format, &width, &height)) {
    913       BWRescale(bitmap_widget, width, height);
    914       BWChangeNotify(bitmap_widget);
    915       BWSetChanged(bitmap_widget);
    916       FixStatus();
    917     }
    918     else {
    919       snprintf(message, sizeof(message), "Wrong format: %s", format);
    920       if (PopupDialog(error_dialog, message,
    921 		      NULL, NULL, XtGrabExclusive) == Retry)
    922 	goto RetryRescale;
    923     }
    924   }
    925 }
    926 
    927 void DoFilename(void)
    928 {
    929   BWGetFilename(bitmap_widget, &filename);
    930   if (PopupDialog(input_dialog, "Change filename:",
    931 		  filename, &filename, XtGrabExclusive) == Okay) {
    932     BWChangeFilename(bitmap_widget, filename);
    933     FixStatus();
    934   }
    935 }
    936 
    937 void DoBasename(void)
    938 {
    939   BWGetBasename(bitmap_widget, &base_name);
    940   if (PopupDialog(input_dialog, "Change basename:",
    941 		  base_name, &base_name, XtGrabExclusive) == Okay) {
    942     BWChangeBasename(bitmap_widget, base_name);
    943     FixStatus();
    944   }
    945 }
    946 
    947 void DoQuit(Widget w, XEvent *event, String *params, Cardinal *num_params)
    948 {
    949   if (BWQueryChanged(bitmap_widget)) {
    950     BWGetFilename(bitmap_widget, &filename);
    951   RetryQuit:
    952     switch (PopupDialog(qsave_dialog, "Save file before quitting?",
    953 			filename, &filename, XtGrabExclusive)) {
    954     case Yes:
    955       if (BWWriteFile(bitmap_widget, filename, NULL)
    956 	  != BitmapSuccess) {
    957 	snprintf(message, sizeof(message), "Can't write file: %s", filename);
    958 	if (PopupDialog(error_dialog, message,
    959 			NULL, NULL, XtGrabExclusive) == Retry)
    960 	  goto RetryQuit;
    961 	else return;
    962       }
    963       break;
    964 
    965     case Cancel:
    966       return;
    967     }
    968   }
    969   exit(0);
    970 }
    971 
    972 int main(int argc, char *argv[])
    973 {
    974     Cardinal i, n;
    975     Arg wargs[2];
    976     Widget w;
    977     Widget radio_group = NULL;
    978     XtPointer radio_data = NULL;
    979     const char *myfilename = NULL;
    980 
    981     /* Handle args that don't require opening a display */
    982     for (int a = 1; a < argc; a++) {
    983 	const char *argn = argv[a];
    984 	/* accept single or double dash for -help & -version */
    985 	if (argn[0] == '-' && argn[1] == '-') {
    986 	    argn++;
    987 	}
    988 	if (strcmp(argn, "-help") == 0) {
    989 	    fprintf(stderr, "usage: %s %s", argv[0], usage);
    990 	    exit(0);
    991 	}
    992 	if (strcmp(argn, "-version") == 0) {
    993 	    puts(PACKAGE_STRING);
    994 	    exit(0);
    995 	}
    996     }
    997 
    998     top_widget = XtInitialize(NULL, "Bitmap",
    999 			      options, XtNumber(options), &argc, argv);
   1000 
   1001     if (argc > 1) {
   1002 	if ((argv[argc - 1][0] != '-') && (argv[argc - 1][0] != '+')) {
   1003 	    myfilename = argv[--argc];
   1004 	}
   1005 	if (argc > 1) {
   1006 	    fputs("Unknown argument(s):", stderr);
   1007 	    for (int a = 1; a < argc; a++) {
   1008 		fprintf(stderr, " %s", argv[a]);
   1009 	    }
   1010 	    fputs("\n\n", stderr);
   1011 	    fprintf(stderr, "usage: %s %s", argv[0], usage);
   1012 	    exit (1);
   1013 	}
   1014     }
   1015 
   1016     check_mark = XCreateBitmapFromData(XtDisplay(top_widget),
   1017 				      RootWindowOfScreen(XtScreen(top_widget)),
   1018 				      (char *) xlogo16_bits,
   1019 				      xlogo16_width,
   1020 				      xlogo16_height);
   1021 
   1022     XtAddActions(actions_table, XtNumber(actions_table));
   1023     XtOverrideTranslations
   1024       (top_widget,
   1025        XtParseTranslationTable("<Message>WM_PROTOCOLS: do-quit()"));
   1026 
   1027     parent_widget = XtCreateManagedWidget("parent", panedWidgetClass,
   1028 					 top_widget, NULL, 0);
   1029 
   1030     formy_widget = XtCreateManagedWidget("formy", formWidgetClass,
   1031 				       parent_widget, NULL, 0);
   1032 
   1033     fileMenu_widget = XtCreatePopupShell("fileMenu",
   1034 					 simpleMenuWidgetClass,
   1035 					 formy_widget, NULL, 0);
   1036 
   1037     (void) XtCreateManagedWidget("fileButton",
   1038 				 menuButtonWidgetClass,
   1039 				 formy_widget, NULL, 0);
   1040 
   1041     for (i = 0; i < XtNumber(file_menu); i++) {
   1042 	w = XtCreateManagedWidget(file_menu[i].name,
   1043 				  (file_menu[i].trap ?
   1044 				   smeBSBObjectClass : smeLineObjectClass),
   1045 				  fileMenu_widget, NULL, 0),
   1046 	XtAddCallback(w,
   1047 		      XtNcallback,
   1048 		      TheCallback,
   1049 		      (XtPointer)&file_menu[i].id);
   1050 
   1051 	file_menu[i].widget = w;
   1052     }
   1053 
   1054     editMenu_widget = XtCreatePopupShell("editMenu",
   1055 					 simpleMenuWidgetClass,
   1056 					 formy_widget, NULL, 0);
   1057 
   1058     (void) XtCreateManagedWidget("editButton",
   1059 				 menuButtonWidgetClass,
   1060 				 formy_widget, NULL, 0);
   1061 
   1062     for (i = 0; i < XtNumber(edit_menu); i++) {
   1063 	w = XtCreateManagedWidget(edit_menu[i].name,
   1064 				  (edit_menu[i].trap ?
   1065 				   smeBSBObjectClass : smeLineObjectClass),
   1066 				  editMenu_widget, NULL, 0),
   1067 	XtAddCallback(w,
   1068 		      XtNcallback,
   1069 		      TheCallback,
   1070 		      (XtPointer)&edit_menu[i].id);
   1071 
   1072 	edit_menu[i].widget = w;
   1073     }
   1074 
   1075     status_widget = XtCreateManagedWidget("status", labelWidgetClass,
   1076 					  formy_widget, NULL, 0);
   1077 
   1078     pane_widget = XtCreateManagedWidget("pane", panedWidgetClass,
   1079 					parent_widget, NULL, 0);
   1080 
   1081     form_widget = XtCreateManagedWidget("form", formWidgetClass,
   1082 					pane_widget, NULL, 0);
   1083 
   1084     for (i = 0; i < XtNumber(buttons); i++) {
   1085 	w = XtCreateManagedWidget(buttons[i].name,
   1086 				  (buttons[i].trap ?
   1087 				   toggleWidgetClass : commandWidgetClass),
   1088 				  form_widget, NULL, 0);
   1089 
   1090 	XtAddCallback(w,
   1091 		      XtNcallback,
   1092 		      TheCallback,
   1093 		      (XtPointer)&buttons[i].id);
   1094 
   1095 	buttons[i].widget = w;
   1096 
   1097 	if (buttons[i].id == Point) {
   1098 	    radio_group = buttons[i].widget;
   1099 	    radio_data  = (char *)buttons[i].name;
   1100 	}
   1101     }
   1102     bitmap_widget = XtCreateManagedWidget("bitmap", bitmapWidgetClass,
   1103 					  pane_widget, NULL, 0);
   1104     XtRealizeWidget(top_widget);
   1105     if (myfilename != NULL)
   1106         BWReadFile(bitmap_widget, myfilename, NULL);
   1107 
   1108     wm_delete_window = XInternAtom(XtDisplay(top_widget), "WM_DELETE_WINDOW",
   1109 				   False);
   1110     (void) XSetWMProtocols (XtDisplay(top_widget), XtWindow(top_widget),
   1111                             &wm_delete_window, 1);
   1112 
   1113 
   1114     image_shell = XtCreatePopupShell("image", transientShellWidgetClass,
   1115 				     top_widget, NULL, 0);
   1116 
   1117     box_widget = XtCreateManagedWidget("box", boxWidgetClass,
   1118 				       image_shell, NULL, 0);
   1119 
   1120     normal_image_widget = XtCreateManagedWidget("normalImage",
   1121 						labelWidgetClass,
   1122 						box_widget, NULL, 0);
   1123 
   1124     inverted_image_widget = XtCreateManagedWidget("invertedImage",
   1125 						  labelWidgetClass,
   1126 						  box_widget, NULL, 0);
   1127 
   1128     n=0;
   1129     XtSetArg(wargs[n], XtNbitmap, BWGetUnzoomedPixmap(bitmap_widget)); n++;
   1130     XtSetValues(normal_image_widget, wargs, n);
   1131     XtSetValues(inverted_image_widget, wargs, n);
   1132 
   1133     XtRealizeWidget(image_shell);
   1134 
   1135     BWNotify(bitmap_widget, (XtActionProc)FixUp);
   1136 
   1137     FixStatus();
   1138 
   1139     input_dialog = CreateDialog(top_widget, "input", Okay | Cancel);
   1140     error_dialog = CreateDialog(top_widget, "error", Abort | Retry);
   1141     qsave_dialog = CreateDialog(top_widget, "qsave", Yes | No | Cancel);
   1142 
   1143     XawToggleSetCurrent(radio_group, radio_data);
   1144     BWEngageRequest(bitmap_widget, PointRequest, True, Plain);
   1145 
   1146     XtMainLoop();
   1147     exit(0);
   1148 }
   1149