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