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 / xbitmap4.c < prev    next >
C/C++ Source or Header  |  1992-07-08  |  19KB  |  613 lines

  1. /*
  2.  * Copyright 1989, 1992 O'Reilly and Associates, Inc.
  3.  * See ../Copyright for complete rights and liability information.
  4.  */
  5.  
  6. /*
  7.  * xbitmap4.c
  8.  */
  9. #include <X11/Intrinsic.h>
  10. #include <Xm/Xm.h>
  11.  
  12. #include <Xm/MainW.h>
  13. #include <Xm/RowColumn.h>
  14. #include <Xm/PushB.h>
  15. #include <Xm/MessageB.h> 
  16. #include <Xm/CascadeB.h> 
  17. #include <Xm/RowColumn.h>
  18. /* we use XmPrimitive, but no header file needed (in Xm.h) */
  19.  
  20. #include <stdio.h>
  21.  
  22. /* 
  23.  * The following could be placed in an "xbitmap.h" file.
  24.  */
  25. #define XtNdebug "debug"
  26. #define XtCDebug "Debug"
  27. #define XtNpixmapWidthInCells "pixmapWidthInCells"
  28. #define XtCPixmapWidthInCells "PixmapWidthInCells"
  29. #define XtNpixmapHeightInCells "pixmapHeightInCells"
  30. #define XtCPixmapHeightInCells "PixmapHeightInCells"
  31. #define XtNcellSizeInPixels "cellSizeInPixels"
  32. #define XtCCellSizeInPixels "CellSizeInPixels"
  33.  
  34. #define DRAWN 1
  35. #define UNDRAWN 0
  36.  
  37. #define DRAW 1
  38. #define UNDRAW 0
  39.  
  40. #define MAXLINES  1000
  41.  
  42. #define MINBITMAPWIDTH  2
  43. #define MAXBITMAPWIDTH  1000
  44. #define MINBITMAPHEIGHT  2
  45. #define MAXBITMAPHEIGHT  1000
  46. #define MINCELLSIZE  4
  47. #define MAXCELLSIZE  100
  48.  
  49. #define SCROLLBARWIDTH 15
  50.  
  51. /* 
  52.  * Data structure for private data.
  53.  * (This avoids lots of global variables.)
  54.  */
  55. typedef struct {
  56.     Pixmap big_picture;
  57.     GC draw_gc, undraw_gc; /* for drawing into the big_picture, 1-bit deep */
  58.     GC copy_gc; /* for copying from pixmap into window, screen depth */
  59.     Widget bitmap;  /* this is the drawing surface */
  60.     char *cell;  /* this is the array for printing output 
  61.                   * and keeping track of cells drawn */
  62.     int cur_x, cur_y;
  63.     Dimension pixmap_width_in_pixels, pixmap_height_in_pixels;
  64. } PrivateAppData;
  65.  
  66. /* data structure for application resources */
  67. typedef struct {
  68.     Pixel copy_fg;
  69.     Pixel copy_bg;
  70.     int pixmap_width_in_cells;
  71.     int pixmap_height_in_cells;
  72.     int cell_size_in_pixels;
  73.     Boolean debug;
  74. } AppData;
  75.  
  76. AppData app_data;
  77. PrivateAppData private_app_data;
  78.  
  79. /* resource list */
  80. static XtResource resources[] = {
  81.     {
  82.         XmNforeground,
  83.         XmCForeground,
  84.         XmRPixel,
  85.         sizeof(Pixel),
  86.         XtOffsetOf(AppData, copy_fg),
  87.         XmRString,
  88.         XtDefaultForeground
  89.     },
  90.     {
  91.         XmNbackground,
  92.         XmCBackground,
  93.         XmRPixel,
  94.         sizeof(Pixel),
  95.         XtOffsetOf(AppData, copy_bg),
  96.         XmRString,
  97.         XtDefaultBackground
  98.     },
  99.     {
  100.         XtNpixmapWidthInCells,
  101.         XtCPixmapWidthInCells,
  102.         XmRInt,
  103.         sizeof(int),
  104.         XtOffsetOf(AppData, pixmap_width_in_cells),
  105.         XmRImmediate,
  106.         (XtPointer) 32,
  107.     },
  108.     {
  109.         XtNpixmapHeightInCells,
  110.         XtCPixmapHeightInCells,
  111.         XmRInt,
  112.         sizeof(int),
  113.         XtOffsetOf(AppData, pixmap_height_in_cells),
  114.         XmRImmediate,
  115.         (XtPointer) 32,
  116.     },
  117.     {
  118.         XtNcellSizeInPixels,
  119.         XtCCellSizeInPixels,
  120.         XmRInt,
  121.         sizeof(int),
  122.         XtOffsetOf(AppData, cell_size_in_pixels),
  123.         XmRImmediate,
  124.         (XtPointer) 30,
  125.     },
  126.     {
  127.         XtNdebug,
  128.         XtCDebug,
  129.         XmRBoolean,
  130.         sizeof(Boolean),
  131.         XtOffsetOf(AppData, debug),
  132.         XmRImmediate,
  133.         (XtPointer) FALSE,
  134.     },
  135. };
  136.  
  137. /* Command-line options table */
  138. static XrmOptionDescRec options[] = {
  139.     {"-pw",            "*pixmapWidthInCells",        XrmoptionSepArg, NULL},
  140.     {"-pixmapwidth",   "*pixmapWidthInCells",        XrmoptionSepArg, NULL},
  141.     {"-ph",            "*pixmapHeightInCells",       XrmoptionSepArg, NULL},
  142.     {"-pixmapheight",  "*pixmapHeightInCells",       XrmoptionSepArg, NULL},
  143.     {"-cellsize",      "*cellSizeInPixels",           XrmoptionSepArg, NULL},
  144.     {"-fg",            "*foreground",           XrmoptionSepArg, NULL},
  145.     {"-foreground",    "*foreground",           XrmoptionSepArg, NULL},
  146.     {"-debug",    "*debug",           XrmoptionNoArg, "True"},
  147. };
  148.  
  149. /* callback function to print cell array to stdout */
  150. /* ARGSUSED */
  151. static void 
  152. PrintOut(w, event, params, num_params)
  153. Widget w;
  154. XEvent *event;
  155. String *params;
  156. Cardinal *num_params;
  157. {
  158.     /*
  159.      * The absense of the small pixmaps in this version makes it
  160.      * more difficult to call XWriteBitmapFile.  Therefore, we will
  161.      * stick with the printed output for this version.
  162.      */
  163.     int x, y;
  164.     putchar('\n');
  165.     for (y = 0; y < app_data.pixmap_height_in_cells; y++) {
  166.         for (x = 0; x < app_data.pixmap_width_in_cells; x++)
  167.             putchar(private_app_data.cell[x + y * 
  168.                     app_data.pixmap_width_in_cells] ? '1' : '0');
  169.         putchar('\n');
  170.     }
  171.     putchar('\n');
  172. }
  173.  
  174. static void RedrawPicture(), DrawCell(), UndrawCell(), ToggleCell(), DrawPixmaps();
  175.  
  176. static void Syntax(argc, argv)
  177. int argc;
  178. char * argv[];
  179. {
  180.     int i;
  181.     static int errs = False;
  182.  
  183.     /* first argument is program name - skip that */
  184.     for (i = 1; i < argc; i++) {
  185.         if (!errs++) /* do first time through */
  186.             fprintf(stderr, "xbitmap4: command line option not understood:\n");
  187.         fprintf(stderr, "option: %s\n", argv[i]);
  188.     }
  189.  
  190.     fprintf(stderr, "xbitmap understands all standard Xt command line options.\n");
  191.  
  192.     fprintf(stderr, "Additional options are as follows:\n");
  193.     fprintf(stderr, "Option             Valid Range\n");
  194.     fprintf(stderr, "-pw                MINBITMAPWIDTH to MAXBITMAPWIDTH\n");
  195.     fprintf(stderr, "-pixmapwidth       MINBITMAPWIDTH to MAXBITMAPWIDTH\n");
  196.     fprintf(stderr, "-ph                MINBITMAPHEIGHT to MAXBITMAPHEIGHT\n");
  197.     fprintf(stderr, "-pixmapheight      MINBITMAPHEIGHT to MAXBITMAPHEIGHT\n");
  198.     fprintf(stderr, "-cellsize          MINCELLSIZE to MAXCELLSIZE\n");
  199.     fprintf(stderr, "-fg                color name\n");
  200.     fprintf(stderr, "-foreground        color name\n");
  201.     fprintf(stderr, "-debug             no value necessary\n");
  202. }
  203.  
  204. /* 
  205.  * callback to pop up help dialog widget 
  206.  */
  207. /*ARGSUSED*/
  208. void ShowHelp(w, client_data, call_data)
  209. Widget w;
  210. XtPointer client_data;
  211. XtPointer call_data;
  212. {
  213.     Widget dialog = (Widget) client_data;
  214.     XtManageChild(dialog);
  215. }
  216.  
  217. /*
  218.  * quit button callback function
  219.  */
  220. /*ARGSUSED*/
  221. void Quit(w, client_data, call_data)
  222. Widget w;
  223. XtPointer client_data, call_data;
  224.     exit(0); 
  225. }
  226.  
  227. main(argc, argv)
  228. int argc;
  229. char *argv[];
  230. {
  231.     XtAppContext app_context;
  232.     Widget topLevel, mainWindow, menuBar;
  233.     Widget fileButton, fileMenu, quit, output, helpButton, helpMenu, help;
  234.     Widget helpBox, temp;
  235.     extern exit();
  236.  
  237.     /* translation table for bitmap core widget */
  238.     String trans =
  239.     "<Expose>:  RedrawPicture()         \n\
  240.          <Btn1Down>:    DrawCell()              \n\
  241.          <Btn2Down>:    UndrawCell()            \n\
  242.          <Btn3Down>:    ToggleCell()            \n\
  243.          <Btn1Motion>:  DrawCell()              \n\
  244.          <Btn2Motion>:  UndrawCell()            \n\
  245.          <Btn3Motion>:  ToggleCell()";
  246.  
  247.     static XtActionsRec window_actions[] = {
  248.         {"RedrawPicture",   RedrawPicture},
  249.         {"DrawCell",    DrawCell},
  250.         {"UndrawCell",  UndrawCell},
  251.         {"ToggleCell",  ToggleCell},
  252.     };
  253.  
  254.     XtSetLanguageProc(NULL, (XtLanguageProc)NULL, NULL);
  255.  
  256.     topLevel = XtVaAppInitialize(
  257.             &app_context,       /* Application context */
  258.             "XBitmap4", 
  259.             options, XtNumber(options), 
  260.             &argc, argv,        /* command line args */
  261.             NULL,               /* for missing app-defaults file */
  262.             NULL);              /* terminate varargs list */
  263.  
  264.     /* XtInitialize leaves program name in args */
  265.     if (argc > 1)
  266.         Syntax(argc, argv);
  267.  
  268.     XtGetApplicationResources(topLevel, 
  269.             &app_data, 
  270.             resources, 
  271.             XtNumber(resources), 
  272.             NULL, 
  273.             0);
  274.  
  275.     /*
  276.      * We must check the application resource values here.
  277.      * Otherwise, user could supply out of range values and crash program.
  278.      * Conversion routines do this automatically, so colors are already checked.
  279.      */
  280.     if ((app_data.pixmap_width_in_cells > MAXBITMAPWIDTH) || 
  281.             (app_data.pixmap_width_in_cells < MINBITMAPWIDTH) ||
  282.             (app_data.pixmap_height_in_cells > MAXBITMAPWIDTH) || 
  283.             (app_data.pixmap_height_in_cells < MINBITMAPWIDTH)) {
  284.         fprintf(stderr, "xbitmap: error in resource settings:\
  285.                 dimension must be between %d and %d cells\n", 
  286.                 MINBITMAPWIDTH, MAXBITMAPWIDTH);
  287.         exit(1);
  288.     }
  289.     if ((app_data.cell_size_in_pixels < MINCELLSIZE) || 
  290.             (app_data.cell_size_in_pixels > MAXCELLSIZE)) {
  291.         fprintf(stderr, "xbitmap: error in resource settings:\
  292.                 cell size must be between %d and %d pixels\n", 
  293.                 MINCELLSIZE, MAXCELLSIZE);
  294.         exit(1);
  295.     }
  296.  
  297.     /* begin application code */
  298.  
  299.     set_up_things(topLevel);
  300.  
  301.     private_app_data.cell = XtCalloc(app_data.pixmap_width_in_cells * 
  302.             app_data.pixmap_height_in_cells, sizeof(char));
  303.  
  304.     if (app_data.debug)
  305.         fprintf(stderr, "xbitmap: pixmap dimensions are %d by %d\n", 
  306.                 app_data.pixmap_width_in_cells, 
  307.                 app_data.pixmap_height_in_cells);
  308.  
  309.     /* create main window */
  310.     mainWindow = XtVaCreateManagedWidget( "mainWindow",
  311.             xmMainWindowWidgetClass, topLevel, 
  312.             NULL);
  313.  
  314.     /* create menu bar along top inside of main window */
  315.     menuBar = XmCreateMenuBar( mainWindow, "menuBar",
  316.             (ArgList) NULL, (Cardinal) 0);
  317.     XtManageChild(menuBar);
  318.  
  319.     /* note: no header file needed to create xmPrimitive */
  320.     private_app_data.bitmap = XtVaCreateManagedWidget("bitmap", 
  321.             xmPrimitiveWidgetClass, mainWindow, 
  322.             XmNtranslations, XtParseTranslationTable(trans),
  323.             XmNwidth, private_app_data.pixmap_width_in_pixels,
  324.             XmNheight, private_app_data.pixmap_height_in_pixels,
  325.             NULL);
  326.  
  327.     /*  Set MainWindow areas */
  328.     XmMainWindowSetAreas (mainWindow, menuBar, NULL, NULL, NULL,
  329.             private_app_data.bitmap);
  330.  
  331.     /*
  332.      *  CREATE FILE MENU AND CHILDREN
  333.      */
  334.  
  335.     /* create button that will pop up the menu */
  336.     fileButton = XtVaCreateManagedWidget("fileButton",
  337.             xmCascadeButtonWidgetClass, menuBar, NULL);
  338.  
  339.     /* create menu (really a Shell widget and RowColumn widget combo) */
  340.     fileMenu = XmCreatePulldownMenu( menuBar,
  341.             "fileMenu", NULL, 0);
  342.  
  343.     /*
  344.      *  CREATE BUTTON TO OUTPUT BITMAP
  345.      */
  346.  
  347.     /* create button that will pop up the menu */
  348.     output = XtVaCreateManagedWidget( "output",
  349.             xmPushButtonWidgetClass, fileMenu, NULL);
  350.  
  351.     XtAddCallback(output, XmNactivateCallback, PrintOut, NULL);
  352.  
  353.     /* create the quit button up in the menu */
  354.     quit = XtVaCreateManagedWidget( "quit",
  355.             xmPushButtonWidgetClass, fileMenu, NULL);
  356.  
  357.     /* 
  358.      * Specify which menu fileButton will pop up.
  359.      */
  360.     XtVaSetValues(fileButton,
  361.             XmNsubMenuId, fileMenu,
  362.             NULL);
  363.  
  364.     /* arrange for quit button to call function that exits. */
  365.     XtAddCallback(quit, XmNactivateCallback, Quit, NULL);
  366.  
  367.     /*
  368.      *  CREATE HELP BUTTON AND BOX
  369.      */
  370.  
  371.     /* create button that will bring up help menu */
  372.     helpButton = XtVaCreateManagedWidget( "helpButton",
  373.         xmCascadeButtonWidgetClass, menuBar, NULL);
  374.  
  375.     /* tell menuBar which is the help button (will be specially positioned) */
  376.     XtVaSetValues(menuBar,
  377.           XmNmenuHelpWidget, helpButton,
  378.           NULL);
  379.  
  380.     /* create menu (really a Shell widget and RowColumn widget combo) */
  381.     helpMenu = XmCreatePulldownMenu( menuBar,
  382.             "helpMenu", NULL, 0);
  383.  
  384.     /* create the help button up in the menu */
  385.     help = XtVaCreateManagedWidget( "help",
  386.             xmPushButtonWidgetClass, helpMenu, NULL);
  387.  
  388.     /* 
  389.      * Specify which menu helpButton will pop up.
  390.      */
  391.     XtVaSetValues(helpButton,
  392.           XmNsubMenuId, helpMenu,
  393.           NULL);
  394.  
  395.     /* create popup that will contain help */
  396.     helpBox = XmCreateMessageDialog( help,
  397.             "helpBox", NULL, 0);
  398.  
  399.     temp = XmMessageBoxGetChild (helpBox, XmDIALOG_CANCEL_BUTTON);
  400.     XtUnmanageChild (temp);
  401.     temp = XmMessageBoxGetChild (helpBox, XmDIALOG_HELP_BUTTON);
  402.     XtUnmanageChild (temp);
  403.  
  404.     /* arrange for getHelp button to pop up helpBox */
  405.     XtAddCallback(help, XmNactivateCallback, ShowHelp, helpBox);
  406.  
  407.     XtAppAddActions(app_context, window_actions, XtNumber(window_actions));
  408.  
  409.     XtRealizeWidget(topLevel);
  410.  
  411.     XtAppMainLoop(app_context);
  412. }
  413.  
  414. set_up_things(w)
  415. Widget w;
  416. {
  417.     XGCValues values;
  418.     int x, y;
  419.     XSegment segment[MAXLINES];
  420.     int n_horiz_segments, n_vert_segments;
  421.  
  422.     private_app_data.pixmap_width_in_pixels = 
  423.             app_data.pixmap_width_in_cells * 
  424.             app_data.cell_size_in_pixels;
  425.     private_app_data.pixmap_height_in_pixels = 
  426.             app_data.pixmap_height_in_cells * 
  427.             app_data.cell_size_in_pixels;
  428.  
  429.     private_app_data.big_picture = XCreatePixmap(XtDisplay(w),
  430.             RootWindowOfScreen(XtScreen(w)),
  431.             private_app_data.pixmap_width_in_pixels, 
  432.             private_app_data.pixmap_height_in_pixels, 1);
  433.  
  434.     values.foreground = 1;
  435.     values.background = 0;
  436.     values.dashes = 1;
  437.     values.dash_offset = 0;
  438.     values.line_style = LineOnOffDash;
  439.  
  440.     private_app_data.draw_gc = XCreateGC(XtDisplay(w), 
  441.             private_app_data.big_picture, GCForeground | GCBackground 
  442.             | GCDashOffset | GCDashList | GCLineStyle, &values);
  443.  
  444.     values.foreground = 0;
  445.     values.background = 1;
  446.     private_app_data.undraw_gc = XCreateGC(XtDisplay(w), 
  447.             private_app_data.big_picture, GCForeground | GCBackground 
  448.             | GCDashOffset | GCDashList | GCLineStyle, &values);
  449.  
  450.     values.foreground = app_data.copy_fg;
  451.     values.background = app_data.copy_bg;
  452.     private_app_data.copy_gc = XCreateGC(XtDisplay(w), 
  453.             RootWindowOfScreen(XtScreen(w)),
  454.             GCForeground | GCBackground, &values);
  455.  
  456.     XFillRectangle(XtDisplay(w), private_app_data.big_picture, 
  457.             private_app_data.undraw_gc, 0, 0, 
  458.             private_app_data.pixmap_width_in_pixels, 
  459.             private_app_data.pixmap_height_in_pixels);
  460.  
  461.     /* draw permanent grid into pixmap */
  462.     n_horiz_segments = app_data.pixmap_height_in_cells + 1;
  463.     n_vert_segments = app_data.pixmap_width_in_cells + 1;
  464.  
  465.     for (x = 0; x < n_horiz_segments; x += 1) {
  466.         segment[x].x1 = 0;
  467.         segment[x].x2 = private_app_data.pixmap_width_in_pixels;
  468.         segment[x].y1 = app_data.cell_size_in_pixels * x;
  469.         segment[x].y2 = app_data.cell_size_in_pixels * x;
  470.     }
  471.  
  472.     /* drawn only once into pixmap */
  473.     XDrawSegments(XtDisplay(w), private_app_data.big_picture, 
  474.             private_app_data.draw_gc, segment, n_horiz_segments);
  475.  
  476.     for (y = 0; y < n_vert_segments; y += 1) {
  477.         segment[y].x1 = y * app_data.cell_size_in_pixels;
  478.         segment[y].x2 = y * app_data.cell_size_in_pixels;
  479.         segment[y].y1 = 0;
  480.         segment[y].y2 = private_app_data.pixmap_height_in_pixels;
  481.     }
  482.  
  483.     /* drawn only once into pixmap */
  484.     XDrawSegments(XtDisplay(w), private_app_data.big_picture, 
  485.             private_app_data.draw_gc, segment, n_vert_segments);
  486. }
  487.  
  488. /* ARGSUSED */
  489. static void
  490. RedrawPicture(w, event, params, num_params)
  491. Widget w;
  492. XExposeEvent *event;
  493. String *params;
  494. Cardinal *num_params;
  495. {
  496.     register int x, y;
  497.     unsigned int width, height;
  498.  
  499.     if (event) {    /* drawing because of expose or button press */
  500.         x = event->x;
  501.         y = event->y; 
  502.         width = event->width;
  503.         height =  event->height;
  504.     } 
  505.     else {  /* drawing because of scrolling */
  506.         x = 0;
  507.         y = 0; 
  508.         width =  10000;  /* always the whole window! */
  509.         height =  10000;
  510.     }
  511.  
  512.     if (DefaultDepthOfScreen(XtScreen(w)) == 1)
  513.         XCopyArea(XtDisplay(w), private_app_data.big_picture, XtWindow(w),
  514.                private_app_data.copy_gc, x + private_app_data.cur_x, 
  515.                y + private_app_data.cur_y, width, height, x, y);
  516.     else
  517.         XCopyPlane(XtDisplay(w), private_app_data.big_picture, XtWindow(w),
  518.                private_app_data.copy_gc, x + private_app_data.cur_x, 
  519.                y + private_app_data.cur_y, width, height, x, y, 1);
  520. }
  521.  
  522. /* ARGSUSED */
  523. static void
  524. DrawCell(w, event, params, num_params)
  525. Widget w;
  526. XButtonEvent *event;
  527. String *params;
  528. Cardinal *num_params;
  529. {
  530.     DrawPixmaps(private_app_data.draw_gc, DRAW, w, event);
  531. }
  532.  
  533. /* ARGSUSED */
  534. static void
  535. UndrawCell(w, event, params, num_params)
  536. Widget w;
  537. XButtonEvent *event;
  538. String *params;
  539. Cardinal *num_params;
  540. {
  541.     DrawPixmaps(private_app_data.undraw_gc, UNDRAW, w, event);
  542. }
  543.  
  544. /* ARGSUSED */
  545. static void
  546. ToggleCell(w, event, params, num_params)
  547. Widget w;
  548. XButtonEvent *event;
  549. String *params;
  550. Cardinal *num_params;
  551. {
  552.     static int oldx = -1, oldy = -1;
  553.     GC gc;
  554.     int mode;
  555.     int newx = (private_app_data.cur_x + event->x) / app_data.cell_size_in_pixels;
  556.     int newy = (private_app_data.cur_y + event->y) / app_data.cell_size_in_pixels;
  557.  
  558.     if ((mode = private_app_data.cell[newx + newy * 
  559.             app_data.pixmap_width_in_cells]) == DRAWN) {
  560.         gc = private_app_data.undraw_gc;
  561.         mode = UNDRAW;
  562.     }
  563.     else {
  564.         gc = private_app_data.draw_gc;
  565.         mode = DRAW;
  566.     }
  567.  
  568.     if (oldx != newx || oldy != newy) {
  569.         oldx = newx;
  570.         oldy = newy;
  571.         DrawPixmaps(gc, mode, w, event);
  572.     }
  573. }
  574.  
  575. /* Private Function */
  576. static void
  577. DrawPixmaps(gc, mode, w, event)
  578. GC gc;
  579. int mode;
  580. Widget w;
  581. XButtonEvent *event;
  582. {
  583.     int newx = (private_app_data.cur_x + event->x) / 
  584.             app_data.cell_size_in_pixels;
  585.     int newy = (private_app_data.cur_y + event->y) / 
  586.             app_data.cell_size_in_pixels;
  587.     XExposeEvent fake_event;
  588.  
  589.     /* if already done, return */
  590.     if (private_app_data.cell[newx + newy * 
  591.             app_data.pixmap_width_in_cells] == mode) 
  592.         return;
  593.  
  594.     XFillRectangle(XtDisplay(w), private_app_data.big_picture, gc,
  595.             app_data.cell_size_in_pixels*newx + 2, 
  596.             app_data.cell_size_in_pixels*newy + 2, 
  597.             (unsigned int) app_data.cell_size_in_pixels - 3, 
  598.             (unsigned int) app_data.cell_size_in_pixels - 3);
  599.  
  600.     private_app_data.cell[newx + newy * 
  601.             app_data.pixmap_width_in_cells] = mode;
  602.  
  603.     fake_event.x = app_data.cell_size_in_pixels * newx - 
  604.             private_app_data.cur_x;
  605.     fake_event.y = app_data.cell_size_in_pixels * newy - 
  606.             private_app_data.cur_y;
  607.     fake_event.width = app_data.cell_size_in_pixels;
  608.     fake_event.height = app_data.cell_size_in_pixels;
  609.  
  610.     RedrawPicture(private_app_data.bitmap, &fake_event);
  611. }
  612.