home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / motifpg2.zip / ch04 / xbitmap5.c < prev   
C/C++ Source or Header  |  1992-07-08  |  15KB  |  475 lines

  1. /*
  2.  * Copyright 1989, 1992 O'Reilly and Associates, Inc.
  3.  * See ../Copyright for complete rights and liability information.
  4.  */
  5.  
  6. /* 
  7.  *  xbitmap5.c - bitmap in main window with small pixmaps
  8.  */
  9.  
  10. /*
  11.  *  So that we can use fprintf:
  12.  */
  13. #include <stdio.h>
  14.  
  15. /* 
  16.  * Standard Toolkit include files:
  17.  */
  18. #include <X11/Intrinsic.h>
  19. #include <Xm/Xm.h>
  20.  
  21. /*
  22.  * Public include files for widgets used in this file.
  23.  */
  24. #include <Xm/PanedW.h>    /* paned window */
  25. #include <Xm/PushB.h>     /* push button */
  26. #include <Xm/MessageB.h>  /* message box */
  27. #include <Xm/CascadeB.h>  /* cascade button */
  28. #include <Xm/RowColumn.h> /* row column (for menus) */
  29. #include <Xm/DrawingA.h>  /* drawing area */
  30. #include <Xm/Form.h>      /* pixmap box */
  31. #include <Xm/Frame.h>     /* frame */
  32. #include <Xm/ScrolledW.h> /* scrolled window */
  33.  
  34. #include "BitmapEdit.h"
  35.  
  36. #define DRAWN 1
  37. #define UNDRAWN 0
  38.  
  39. struct {
  40.     GC draw_gc, undraw_gc, invert_gc;
  41.     Pixmap normal_bitmap, reverse_bitmap;
  42.     Widget showNormalBitmap, showReverseBitmap;
  43.     String filename;    /* filename to read and write */
  44.     Dimension pixmap_width_in_cells, pixmap_height_in_cells;
  45. } bitmap_stuff;
  46.  
  47. static Boolean file_contained_good_data = False;
  48.  
  49. static void CellToggled(), SetUpThings();
  50.  
  51. /*ARGSUSED*/
  52. static void
  53. RedrawSmallPicture(w, client_data, call_data)
  54. Widget w;
  55. XtPointer client_data;
  56. XtPointer call_data;
  57. {
  58.     Pixmap pixmap;
  59.  
  60.     if (w == bitmap_stuff.showNormalBitmap)
  61.         pixmap = bitmap_stuff.normal_bitmap;
  62.     else
  63.         pixmap = bitmap_stuff.reverse_bitmap;
  64.  
  65.     if (DefaultDepthOfScreen(XtScreen(w)) == 1)
  66.         XCopyArea(XtDisplay(w), pixmap, XtWindow(w),
  67.                 DefaultGCOfScreen(XtScreen(w)), 0, 0,
  68.                 bitmap_stuff.pixmap_width_in_cells, 
  69.         bitmap_stuff.pixmap_height_in_cells, 
  70.                 0, 0);
  71.     else
  72.         XCopyPlane(XtDisplay(w), pixmap, XtWindow(w),
  73.                 DefaultGCOfScreen(XtScreen(w)), 0, 0,
  74.                 bitmap_stuff.pixmap_width_in_cells, 
  75.         bitmap_stuff.pixmap_height_in_cells, 
  76.                 0, 0, 1);
  77. }
  78.  
  79. /*
  80.  * The printout routine writes the data into a standard X11 bitmap file.
  81.  */
  82. /* ARGSUSED */
  83. static void 
  84. PrintOut(widget, client_data, call_data)
  85. Widget widget;
  86. XtPointer client_data;   /* unused */
  87. XtPointer call_data;    /* unused */
  88. {
  89.     XWriteBitmapFile(XtDisplay(widget), bitmap_stuff.filename, 
  90.             bitmap_stuff.normal_bitmap,
  91.             bitmap_stuff.pixmap_width_in_cells, 
  92.             bitmap_stuff.pixmap_height_in_cells, 0, 0);
  93. }
  94.  
  95. String
  96. FillCell(w)
  97. Widget w;
  98. {
  99.     String cell;
  100.     int x, y;
  101.     XImage *image;
  102.  
  103.     cell = XtCalloc(bitmap_stuff.pixmap_width_in_cells 
  104.             * bitmap_stuff.pixmap_height_in_cells, sizeof(char));
  105.  
  106.     /* Convert pixmap into image, so that we can 
  107.      * read individual pixels */
  108.     image = XGetImage(XtDisplay(w), bitmap_stuff.normal_bitmap, 0, 0, 
  109.               bitmap_stuff.pixmap_width_in_cells, 
  110.               bitmap_stuff.pixmap_height_in_cells,
  111.               AllPlanes, XYPixmap);
  112.  
  113.     for (x = 0; x < bitmap_stuff.pixmap_width_in_cells; x++) {
  114.         for (y = 0; y < bitmap_stuff.pixmap_height_in_cells; y++) {
  115.             cell[x + (y * bitmap_stuff.pixmap_width_in_cells)] = 
  116.           XGetPixel(image, x, y);
  117.         }
  118.     }
  119.     return(cell);
  120. }
  121.  
  122. /* 
  123.  * callback to pop up help dialog widget 
  124.  */
  125. /*ARGSUSED*/
  126. void ShowHelp(w, client_data, call_data)
  127. Widget w;
  128. XtPointer client_data;
  129. XtPointer call_data;
  130. {
  131.     Widget dialog = (Widget) client_data;
  132.     XtManageChild(dialog);
  133. }
  134.  
  135. /*
  136.  * quit button callback function
  137.  */
  138. /*ARGSUSED*/
  139. void Quit(w, client_data, call_data)
  140. Widget w;
  141. XtPointer client_data, call_data;
  142.     exit(0); 
  143. }
  144.  
  145. main(argc, argv)
  146. int argc;
  147. char **argv;
  148. {
  149.     XtAppContext app_context;
  150.     Widget topLevel, mainWindow, menuBar;
  151.     Widget fileButton, fileMenu, quit, helpButton, helpMenu, help, helpBox;
  152.     Widget temp;
  153.     Widget bigBitmap, output, smallPixmapBox;
  154.     Widget scrolledWin, frame1, frame2;
  155.     Arg args[5];
  156.     int i;
  157.     unsigned int width, height;
  158.     int junk;
  159.     String cell;
  160.  
  161.     /* never call a Widget variable "exit"! */
  162.     extern exit();
  163.  
  164.     static XrmOptionDescRec table[] = {
  165.         {"-pw",            "*pixmapWidthInCells",        XrmoptionSepArg, NULL},
  166.         {"-pixmapwidth",   "*pixmapWidthInCells",        XrmoptionSepArg, NULL},
  167.         {"-ph",            "*pixmapHeightInCells",       XrmoptionSepArg, NULL},
  168.         {"-pixmapheight",  "*pixmapHeightInCells",       XrmoptionSepArg, NULL},
  169.         {"-cellsize",      "*cellSizeInPixels",           XrmoptionSepArg, NULL},
  170.  
  171.     };
  172.     
  173.     XtSetLanguageProc(NULL, (XtLanguageProc)NULL, NULL);
  174.  
  175.     topLevel = XtVaAppInitialize(
  176.             &app_context,       /* Application context */
  177.             "XBitmap5",     /* Application class */
  178.             table, XtNumber(table),   /* command line option list */
  179.             &argc, argv,        /* command line args */
  180.             NULL,               /* for missing app-defaults file */
  181.             NULL);              /* terminate varargs list */
  182.  
  183.     if (argv[1] != NULL)
  184.         bitmap_stuff.filename = argv[1];
  185.     else {
  186.         fprintf(stderr, "xbitmap: must specify filename on command line\n");
  187.         exit(1);
  188.     }
  189.  
  190.     /* create main window */
  191.     mainWindow = XtVaCreateManagedWidget(
  192.             "mainWindow",           /* widget name */
  193.             xmPanedWindowWidgetClass,   /* widget class */
  194.             topLevel,           /* parent widget*/
  195.             NULL);                  /* terminate varargs list */
  196.  
  197.     /* create menu bar along top inside of main window */
  198.     menuBar = XmCreateMenuBar(
  199.             mainWindow, /* parent widget*/
  200.             "menuBar",  /* widget name */
  201.             NULL,       /* no arguments needed */
  202.             0);         /* no arguments needed */
  203.     XtManageChild(menuBar);
  204.  
  205.     scrolledWin = XtVaCreateManagedWidget("scrolledWin", 
  206.             xmScrolledWindowWidgetClass, mainWindow, 
  207.             NULL);
  208.  
  209.     switch (XReadBitmapFile(XtDisplay(topLevel),
  210.         RootWindowOfScreen(XtScreen(topLevel)), bitmap_stuff.filename,
  211.             &width, &height, &bitmap_stuff.normal_bitmap, &junk, &junk)) {
  212.     case BitmapSuccess:
  213.       file_contained_good_data = True;
  214.       if ((bitmap_stuff.pixmap_width_in_cells != width) || 
  215.       (bitmap_stuff.pixmap_height_in_cells != height)) {
  216.     i = 0;
  217.     XtSetArg(args[i], XtNpixmapWidthInCells, width);   i++;
  218.     XtSetArg(args[i], XtNpixmapHeightInCells, height);   i++;
  219.     bitmap_stuff.pixmap_width_in_cells = width;
  220.     bitmap_stuff.pixmap_height_in_cells = height;
  221.     cell = FillCell(topLevel);
  222.     XtSetArg(args[i], XtNcellArray, cell);   i++;
  223.       }
  224.       break;
  225.     case BitmapOpenFailed:
  226.       fprintf(stderr, 
  227.           "xbitmap: could not open bitmap file, using fresh bitmap.\n");
  228.       i = 0;
  229.       file_contained_good_data = False;
  230.       break;
  231.     case BitmapFileInvalid:
  232.       fprintf(stderr, "xbitmap: bitmap file invalid.\n");
  233.       exit(1);
  234.     case BitmapNoMemory:
  235.       fprintf(stderr, 
  236.           "xbitmap: insufficient server memory to create bitmap.\n");
  237.       exit(1);
  238.     default:
  239.       fprintf(stderr, "xbitmap: programming error.\n");
  240.       exit(1);
  241.     }
  242.  
  243.     bigBitmap = XtCreateManagedWidget("bigBitmap", 
  244.             bitmapEditWidgetClass, scrolledWin, args, i);
  245.  
  246.     XtAddCallback(bigBitmap, XtNtoggleCallback, CellToggled, NULL);
  247.  
  248.     if (!file_contained_good_data) {
  249.       XtVaGetValues(bigBitmap,
  250.         XtNpixmapWidthInCells, &bitmap_stuff.pixmap_width_in_cells,
  251.         XtNpixmapHeightInCells, &bitmap_stuff.pixmap_height_in_cells,
  252.         NULL);
  253.     }
  254.  
  255.     /*
  256.      *  CREATE FILE MENU AND CHILDREN
  257.      */
  258.  
  259.     /* create button that will pop up the menu */
  260.     fileButton = XtVaCreateManagedWidget(
  261.             "fileButton",           /* widget name */
  262.             xmCascadeButtonWidgetClass, /* widget class */
  263.             menuBar,            /* parent widget*/
  264.             NULL);                  /* terminate varargs list */
  265.  
  266.     /* create menu (really a Shell widget and RowColumn widget combo) */
  267.     fileMenu = XmCreatePulldownMenu(
  268.             menuBar,    /* parent widget*/
  269.             "fileMenu", /* widget name */
  270.             NULL,       /* no argument list needed */
  271.             0);         /* no argument list needed */
  272.  
  273.     /*
  274.      *  CREATE BUTTON TO OUTPUT BITMAP
  275.      */
  276.  
  277.     /* create button that will pop up the menu */
  278.     output = XtVaCreateManagedWidget(
  279.             "output",           /* widget name */
  280.             xmPushButtonWidgetClass,    /* widget class */
  281.             fileMenu,           /* parent widget*/
  282.             NULL);                  /* terminate varargs list */
  283.  
  284.     XtAddCallback(output, XmNactivateCallback, PrintOut, 0);
  285.  
  286.     /* create the quit button up in the menu */
  287.     quit = XtVaCreateManagedWidget(
  288.             "quit",             /* widget name */
  289.             xmPushButtonWidgetClass,    /* widget class */
  290.             fileMenu,           /* parent widget*/
  291.             NULL);                  /* terminate varargs list */
  292.  
  293.     /* 
  294.      * Specify which menu fileButton will pop up.
  295.      */
  296.     XtVaSetValues(fileButton,
  297.             XmNsubMenuId, fileMenu,
  298.             NULL);
  299.  
  300.     /* arrange for quit button to call function that exits. */
  301.     XtAddCallback(quit, XmNactivateCallback, Quit, 0);
  302.  
  303.     /*
  304.      *  CREATE HELP BUTTON AND BOX
  305.      */
  306.  
  307.     /* create button that will bring up help menu */
  308.     helpButton = XtVaCreateManagedWidget( "helpButton",
  309.         xmCascadeButtonWidgetClass, menuBar, NULL);
  310.  
  311.     /* tell menuBar which is the help button (will be specially positioned) */
  312.     XtVaSetValues(menuBar,
  313.           XmNmenuHelpWidget, helpButton,
  314.           NULL);
  315.  
  316.     /* create menu (really a Shell widget and RowColumn widget combo) */
  317.     helpMenu = XmCreatePulldownMenu( menuBar,
  318.             "helpMenu", NULL, 0);
  319.  
  320.     /* create the help button up in the menu */
  321.     help = XtVaCreateManagedWidget( "help",
  322.             xmPushButtonWidgetClass, helpMenu, NULL);
  323.  
  324.     /* 
  325.      * Specify which menu helpButton will pop up.
  326.      */
  327.     XtVaSetValues(helpButton,
  328.           XmNsubMenuId, helpMenu,
  329.           NULL);
  330.  
  331.     /* create popup that will contain help */
  332.     helpBox = XmCreateMessageDialog(
  333.             help,    /* parent widget*/
  334.             "helpBox",  /* widget name   */
  335.             NULL,       /* no arguments needed */
  336.             0);         /* no arguments needed */
  337.  
  338.     temp = XmMessageBoxGetChild (helpBox, XmDIALOG_CANCEL_BUTTON);
  339.     XtUnmanageChild (temp);
  340.     temp = XmMessageBoxGetChild (helpBox, XmDIALOG_HELP_BUTTON);
  341.     XtUnmanageChild (temp);
  342.  
  343.  
  344.     /* arrange for getHelp button to pop up helpBox */
  345.     XtAddCallback(help, XmNactivateCallback, ShowHelp, helpBox);
  346.  
  347.     smallPixmapBox = XtVaCreateManagedWidget("smallPixmapBox", 
  348.             xmFormWidgetClass, mainWindow, 
  349.             NULL);
  350.  
  351.     frame1 = XtVaCreateManagedWidget("frameNormal", 
  352.             xmFrameWidgetClass, smallPixmapBox, 
  353.             XmNleftAttachment, XmATTACH_FORM,
  354.             NULL);
  355.  
  356.     SetUpThings(topLevel);
  357.  
  358.     bitmap_stuff.showNormalBitmap = XtVaCreateManagedWidget("showNormalBitmap", 
  359.             xmDrawingAreaWidgetClass, frame1, 
  360.             XmNwidth, bitmap_stuff.pixmap_width_in_cells,
  361.             XmNheight, bitmap_stuff.pixmap_height_in_cells,
  362.             NULL);
  363.     
  364.     frame2 = XtVaCreateManagedWidget("frameReverse", 
  365.             xmFrameWidgetClass, smallPixmapBox, 
  366.             XmNleftAttachment, XmATTACH_WIDGET,
  367.             XmNleftWidget, frame1,
  368.             NULL);
  369.  
  370.     bitmap_stuff.showReverseBitmap = XtVaCreateManagedWidget("showReverseBitmap", 
  371.             xmDrawingAreaWidgetClass, frame2, 
  372.             XmNwidth, bitmap_stuff.pixmap_width_in_cells,
  373.             XmNheight, bitmap_stuff.pixmap_height_in_cells,
  374.             NULL);
  375.  
  376.     XtAddCallback(bitmap_stuff.showNormalBitmap, XmNexposeCallback,
  377.             RedrawSmallPicture, NULL);
  378.  
  379.     XtAddCallback(bitmap_stuff.showReverseBitmap, XmNexposeCallback,
  380.             RedrawSmallPicture, NULL);
  381.  
  382.     XtRealizeWidget(topLevel);
  383.  
  384.     XtAppMainLoop(app_context);
  385. }
  386.  
  387. static void
  388. SetUpThings(w)
  389. Widget w;
  390. {
  391.     XGCValues values;
  392.  
  393.     if (!file_contained_good_data) {
  394.       bitmap_stuff.normal_bitmap = XCreatePixmap(XtDisplay(w), 
  395.             RootWindowOfScreen(XtScreen(w)),
  396.             bitmap_stuff.pixmap_width_in_cells, 
  397.             bitmap_stuff.pixmap_height_in_cells, 1);
  398.     }
  399.  
  400.     values.foreground = 1;
  401.     values.background = 0;
  402.     /* note that normal_bitmap is used as the drawable because it
  403.      * is one bit deep.  The root window may not be one bit deep */
  404.     bitmap_stuff.draw_gc = XCreateGC(XtDisplay(w),  
  405.             bitmap_stuff.normal_bitmap,
  406.             GCForeground | GCBackground, &values);
  407.  
  408.     values.foreground = 0;
  409.     values.background = 1;
  410.     bitmap_stuff.undraw_gc = XCreateGC(XtDisplay(w), 
  411.             bitmap_stuff.normal_bitmap,
  412.             GCForeground | GCBackground, &values);
  413.  
  414.     bitmap_stuff.reverse_bitmap = XCreatePixmap(XtDisplay(w), 
  415.             RootWindowOfScreen(XtScreen(w)),
  416.             bitmap_stuff.pixmap_width_in_cells, 
  417.             bitmap_stuff.pixmap_height_in_cells, 1);
  418.     
  419.     if (file_contained_good_data) {
  420.       XImage *image;
  421.       int x, y;
  422.  
  423.       image = XGetImage (XtDisplay(w), bitmap_stuff.normal_bitmap, 0, 0,
  424.              bitmap_stuff.pixmap_width_in_cells,
  425.              bitmap_stuff.pixmap_height_in_cells,
  426.              AllPlanes, XYPixmap);
  427.  
  428.       for (x = 0; x < bitmap_stuff.pixmap_width_in_cells; x++) {
  429.         for (y = 0; y < bitmap_stuff.pixmap_height_in_cells; y++) {
  430.       XDrawPoint(XtDisplay(w), bitmap_stuff.reverse_bitmap,
  431.           ((XGetPixel(image, x, y) == DRAWN) ? bitmap_stuff.undraw_gc :
  432.           bitmap_stuff.draw_gc), x, y);
  433.         }
  434.       }
  435.     }
  436.     else {
  437.     /* pixmaps must be cleared - may contain garbage */
  438.       XFillRectangle(XtDisplay(w), 
  439.             bitmap_stuff.reverse_bitmap, bitmap_stuff.draw_gc,
  440.             0, 0, bitmap_stuff.pixmap_width_in_cells + 1, 
  441.             bitmap_stuff.pixmap_height_in_cells + 1);
  442.       XFillRectangle(XtDisplay(w), 
  443.             bitmap_stuff.normal_bitmap, bitmap_stuff.undraw_gc,
  444.             0, 0, bitmap_stuff.pixmap_width_in_cells + 1, 
  445.             bitmap_stuff.pixmap_height_in_cells + 1);
  446.     }
  447. }
  448.  
  449. /* ARGSUSED */
  450. static void
  451. CellToggled(w, client_data, call_data)
  452. Widget w;
  453. XtPointer client_data;  /* unused */
  454. XtPointer call_data;    /* will be cast to cur_info */
  455. {
  456.     /* cast pointer to needed type: */
  457.     BitmapEditPointInfo *cur_info = (BitmapEditPointInfo *) call_data;
  458.     /* 
  459.      * Note, BitmapEditPointInfo is defined in BitmapEdit.h 
  460.      */
  461.  
  462.     XDrawPoint(XtDisplay(w), bitmap_stuff.normal_bitmap, 
  463.             ((cur_info->mode == DRAWN) ? bitmap_stuff.draw_gc : 
  464.             bitmap_stuff.undraw_gc), cur_info->newx, cur_info->newy);
  465.     XDrawPoint(XtDisplay(w), bitmap_stuff.reverse_bitmap, 
  466.             ((cur_info->mode == DRAWN) ? bitmap_stuff.undraw_gc : 
  467.             bitmap_stuff.draw_gc), cur_info->newx, cur_info->newy); 
  468.  
  469.     RedrawSmallPicture(bitmap_stuff.showNormalBitmap, 
  470.             cur_info->newx, cur_info->newy);
  471.     RedrawSmallPicture(bitmap_stuff.showReverseBitmap, 
  472.             cur_info->newx, cur_info->newy);
  473. }
  474.