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