home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / bitmap / Graphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-24  |  40.4 KB  |  1,596 lines

  1. /*
  2.  * $XConsortium: Graphics.c,v 1.15 91/07/24 15:24:24 converse Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Davor Matic, MIT X Consortium
  24.  */
  25.  
  26. #include <X11/StringDefs.h>
  27. #include <X11/IntrinsicP.h>
  28. #include <X11/Xfuncs.h>
  29. #include "BitmapP.h"
  30.     
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <math.h>
  34.  
  35. #ifndef abs
  36. #define abs(x)                        (((x) > 0) ? (x) : -(x))
  37. #endif
  38. #define min(x, y)                     (((int)(x) < (int)(y)) ? (x) : (y))
  39. #define max(x, y)                     (((int)(x) > (int)(y)) ? (x) : (y))
  40. #ifndef rint
  41. #define rint(x)                       floor(x + 0.5)
  42. #endif
  43.  
  44. /*****************************************************************************\
  45.  *                                   Graphics                                *
  46. \*****************************************************************************/
  47.  
  48. #define GetBit(image, x, y)\
  49.     ((bit)((*(image->data + (x) / 8 + (y) * image->bytes_per_line) &\
  50.         (1 << ((x) % 8))) ? 1 : 0))
  51.  
  52.  
  53. bit BWGetBit(w, x, y)
  54.     Widget  w;
  55.      Position      x, y;
  56. {
  57.     BitmapWidget BW = (BitmapWidget) w;
  58.     
  59.     if (QueryInBitmap(BW, x, y))
  60.     return GetBit(BW->bitmap.image, x, y);
  61.     else
  62.     return NotSet;
  63. }
  64.  
  65.  
  66. #define InvertBit(image, x, y)\
  67.     (*(image->data + (x) / 8 + (y) * image->bytes_per_line) ^=\
  68.      (bit) (1 << ((x) % 8)))
  69.  
  70.  
  71. #define SetBit(image, x, y)\
  72.     (*(image->data + (x) / 8 + (y) * image->bytes_per_line) |=\
  73.      (bit) (1 << ((x) % 8)))
  74.  
  75. #define ClearBit(image, x, y)\
  76.     (*(image->data + (x) / 8 + (y) * image->bytes_per_line) &=\
  77.      (bit)~(1 << ((x) % 8)))
  78.  
  79.  
  80. #define HighlightSquare(BW, x, y)\
  81.     XFillRectangle(XtDisplay(BW), XtWindow(BW),\
  82.                    BW->bitmap.highlighting_gc,\
  83.            InWindowX(BW, x), InWindowY(BW, y),\
  84.                    BW->bitmap.squareW, BW->bitmap.squareH)
  85. /*
  86. void HighlightSquare(BW, x, y)
  87.     BitmapWidget BW;
  88.     Position x, y;
  89. {
  90.     XFillRectangle(XtDisplay(BW), XtWindow(BW),
  91.                    BW->bitmap.highlighting_gc,
  92.            InWindowX(BW, x), InWindowY(BW, y),
  93.                    BW->bitmap.squareW, BW->bitmap.squareH);
  94. }
  95. */
  96.  
  97. #define DrawSquare(BW, x, y)\
  98.     XFillRectangle(XtDisplay(BW), XtWindow(BW),\
  99.                    BW->bitmap.drawing_gc,\
  100.            InWindowX(BW, x), InWindowY(BW, y),\
  101.                    BW->bitmap.squareW, BW->bitmap.squareH) 
  102.  
  103. /*
  104. void DrawSquare(BW, x, y)
  105.     BitmapWidget BW;
  106.     Position x, y;
  107. {
  108.     XFillRectangle(XtDisplay(BW), XtWindow(BW),
  109.                    BW->bitmap.drawing_gc,
  110.            InWindowX(BW, x), InWindowY(BW, y),
  111.                    BW->bitmap.squareW, BW->bitmap.squareH);
  112. }
  113. */
  114.  
  115. #define InvertPoint(BW, x, y)\
  116.     {InvertBit(BW->bitmap.image, x, y); DrawSquare(BW, x, y);}
  117.  
  118. #define DrawPoint(BW, x, y, value)\
  119.     if (GetBit(BW->bitmap.image, x, y) != value)\
  120.        InvertPoint(BW, x, y)
  121.  
  122. void BWDrawPoint(w, x, y, value)
  123.     Widget  w;
  124.     Position      x, y;
  125.     bit           value;
  126. {
  127.     BitmapWidget BW = (BitmapWidget) w;
  128.     
  129.     if (QueryInBitmap(BW, x, y)) {
  130.     if (value == Highlight)
  131.         HighlightSquare(BW, x, y);
  132.     else
  133.         DrawPoint(BW, x, y, value);
  134.     }
  135. }
  136.  
  137. XPoint *HotSpotShape(BW, x ,y)
  138.     BitmapWidget BW;
  139.     Position     x, y;
  140. {
  141.     static XPoint points[5];
  142.   
  143.     points[0].x = InWindowX(BW, x);
  144.     points[0].y = InWindowY(BW, y + 1.0/2);
  145.     points[1].x = InWindowX(BW, x + 1.0/2);
  146.     points[1].y = InWindowY(BW, y + 1);
  147.     points[2].x = InWindowX(BW, x + 1);
  148.     points[2].y = InWindowY(BW, y + 1.0/2);
  149.     points[3].x = InWindowX(BW, x + 1.0/2);
  150.     points[3].y = InWindowY(BW, y);
  151.     points[4].x = InWindowX(BW, x);
  152.     points[4].y = InWindowY(BW, y + 1.0/2);
  153.     
  154.     return points;
  155. }
  156.  
  157. #define DrawHotSpot(BW, x, y)\
  158.   XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.drawing_gc,\
  159.            HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin)
  160.  
  161. #define HighlightHotSpot(BW, x, y)\
  162.   XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,\
  163.            HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin)
  164.  
  165. XImage *CreateBitmapImage();
  166. void DestroyBitmapImage();
  167.  
  168. void BWRedrawHotSpot(w)
  169.     Widget w;
  170. {
  171.     BitmapWidget BW = (BitmapWidget) w;
  172.  
  173.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y))
  174.     DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y);
  175. }
  176.  
  177. void BWClearHotSpot(w)
  178.     Widget w;
  179. {
  180.     BitmapWidget BW = (BitmapWidget) w;
  181.     
  182.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) {
  183.       DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y);
  184.       BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet;
  185.     }
  186. }
  187.  
  188. void BWDrawHotSpot(w, x, y, value)
  189.     Widget w;
  190.     Position x, y;
  191.     int  value;
  192. {
  193.     BitmapWidget BW = (BitmapWidget) w;
  194.     
  195.     if (QueryInBitmap(BW, x, y)) {
  196.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) &&
  197.         ((BW->bitmap.hot.x == x) && (BW->bitmap.hot.y == y))) {
  198.         if ((value == Clear) || (value == Invert)) {
  199.         BWClearHotSpot(w);
  200.         }
  201.     }
  202.     else
  203.         if ((value == Set) || (value == Invert)) {
  204.         BWClearHotSpot(w);
  205.         DrawHotSpot(BW, x, y);
  206.         BW->bitmap.hot.x = x;
  207.         BW->bitmap.hot.y = y;
  208.         }
  209.     
  210.     if (value == Highlight)
  211.         HighlightHotSpot(BW, x, y); 
  212.     }
  213. }
  214.  
  215. void BWSetHotSpot(w, x, y)
  216.     Widget w;
  217.     Position x, y;
  218. {
  219.     if (QuerySet(x, y))
  220.     BWDrawHotSpot(w, x, y, Set);
  221.     else
  222.     BWClearHotSpot(w);
  223. }
  224.  
  225. /* high level procedures */
  226.  
  227. void BWRedrawSquares(w, x, y, width, height)
  228.     Widget  w;
  229.     register Position x, y;
  230.     Dimension width, height;
  231. {
  232.     BitmapWidget BW = (BitmapWidget) w;
  233.     Position from_x = InBitmapX(BW, x);
  234.     Position from_y = InBitmapY(BW, y);
  235.     Position to_x = InBitmapX(BW, x + width);
  236.     Position to_y = InBitmapY(BW, y + height);
  237.  
  238.     QuerySwap(from_x, to_x);
  239.     QuerySwap(from_y, to_y);
  240.     from_x = max(0, from_x);
  241.     from_y = max(0, from_y);
  242.     to_x = min(BW->bitmap.image->width - 1, to_x);
  243.     to_y = min(BW->bitmap.image->height - 1, to_y);
  244.   
  245.     for (x = from_x; x <= to_x; x++)
  246.     for (y = from_y; y <= to_y; y++)
  247.         if (GetBit(BW->bitmap.image, x, y)) DrawSquare(BW, x, y);
  248. }
  249.  
  250. void BWDrawGrid(w, from_x, from_y, to_x, to_y)
  251.      Widget w;
  252.      Position from_x, from_y,
  253.               to_x, to_y;
  254. {
  255.     BitmapWidget BW = (BitmapWidget) w;
  256.     int i;
  257.   
  258.     QuerySwap(from_x, to_x);
  259.     QuerySwap(from_y, to_y);
  260.     from_x = max(0, from_x);
  261.     from_y = max(0, from_y);
  262.     to_x = min(BW->bitmap.image->width - 1, to_x);
  263.     to_y = min(BW->bitmap.image->height - 1, to_y);
  264.   
  265.     for(i = from_x + (from_x == 0); i <= to_x; i++)
  266.     XDrawLine(XtDisplay(BW), XtWindow(BW), 
  267.           BW->bitmap.frame_gc,
  268.           InWindowX(BW, i), InWindowY(BW, from_y),
  269.           InWindowX(BW, i), InWindowY(BW, to_y + 1));
  270.   
  271.     for(i = from_y + (from_y == 0); i <= to_y; i++)
  272.     XDrawLine(XtDisplay(BW), XtWindow(BW), 
  273.           BW->bitmap.frame_gc,
  274.           InWindowX(BW, from_x), InWindowY(BW, i),
  275.           InWindowX(BW, to_x + 1), InWindowY(BW, i));
  276. }
  277.  
  278.  
  279. void BWRedrawGrid(w, x, y, width, height)
  280.     Widget w;
  281.     Position x, y;
  282.     Dimension width, height;
  283. {
  284.     BitmapWidget BW = (BitmapWidget) w;
  285.     Position from_x = InBitmapX(BW, x);
  286.     Position from_y = InBitmapY(BW, y);
  287.     Position to_x = InBitmapX(BW, x + width);
  288.     Position to_y = InBitmapY(BW, y + height);
  289.  
  290.     if (BW->bitmap.grid)
  291.     BWDrawGrid(w, from_x, from_y, to_x, to_y);
  292. }
  293.  
  294. void BWDrawLine(w, from_x, from_y, to_x, to_y, value)
  295.     Widget  w;
  296.     Position      from_x, from_y,
  297.                   to_x, to_y;
  298.     int           value;
  299. {
  300.     Position i;
  301.     register double x, y;
  302.     double dx, dy, delta;
  303.  
  304.     dx = to_x - from_x;
  305.     dy = to_y - from_y;
  306.     x = from_x + 0.5;
  307.     y = from_y + 0.5;
  308.     delta = max(abs(dx), abs(dy));
  309.     if (delta > 0) {
  310.     dx /= delta;
  311.     dy /= delta;
  312.     for(i = 0; i <= delta; i++) {
  313.         BWDrawPoint(w, (Position) x, (Position) y, value);
  314.         x += dx;
  315.         y += dy;
  316.     }
  317.     }
  318.     else
  319.     BWDrawPoint(w, from_x, from_y, value);
  320. }
  321.  
  322. void BWBlindLine(w, from_x, from_y, to_x, to_y, value)
  323.     Widget  w;
  324.     Position      from_x, from_y,
  325.                   to_x, to_y;
  326.     int           value;
  327. {
  328.     Position i;
  329.     register double x, y;
  330.     double dx, dy, delta;
  331.  
  332.     dx = to_x - from_x;
  333.     dy = to_y - from_y;
  334.     x = from_x + 0.5;
  335.     y = from_y + 0.5;
  336.     delta = max(abs(dx), abs(dy));
  337.     if (delta > 0) {
  338.     dx /= delta;
  339.     dy /= delta;
  340.     x += dx;
  341.     y += dy;
  342.     for(i = 1; i <= delta; i++) {
  343.         BWDrawPoint(w, (Position) x, (Position) y, value);
  344.         x += dx;
  345.         y += dy;
  346.     }
  347.     }
  348.     else
  349.     BWDrawPoint(w, from_x, from_y, value);
  350. }
  351.  
  352. void BWDrawRectangle(w, from_x, from_y, to_x, to_y, value)
  353.     Widget w;
  354.     Position     from_x, from_y,
  355.     to_x, to_y;
  356.     int          value;
  357. {
  358.     register Position i;
  359.     Dimension delta, width, height;
  360.     
  361.     QuerySwap(from_x, to_x);
  362.     QuerySwap(from_y, to_y);
  363.     
  364.     width = to_x - from_x;
  365.     height = to_y - from_y;
  366.  
  367.     delta = max(width, height);
  368.     
  369.     if (!QueryZero(width, height)) {
  370.     for (i = 0; (int)i < (int)delta; i++) {
  371.         if ((int)i < (int)width) {
  372.         BWDrawPoint(w, from_x + i, from_y, value);
  373.         BWDrawPoint(w, to_x - i, to_y, value);
  374.         }
  375.         if ((int)i < (int)height) {
  376.         BWDrawPoint(w, from_x, to_y - i, value);
  377.         BWDrawPoint(w, to_x, from_y + i, value);
  378.         }
  379.     }
  380.     }
  381.     else
  382.     BWDrawLine(w, 
  383.            from_x, from_y, 
  384.            to_x, to_y, value);
  385. }
  386.   
  387. void BWDrawFilledRectangle(w, from_x, from_y, to_x, to_y, value)
  388.     Widget   w;
  389.     Position from_x, from_y,
  390.          to_x, to_y;
  391.     int      value;
  392. {
  393.     register Position x, y;
  394.  
  395.     QuerySwap(from_x, to_x);
  396.     QuerySwap(from_y, to_y);
  397.     
  398.     for (x = from_x; x <= to_x; x++)
  399.     for (y = from_y; y <= to_y; y++)
  400.         BWDrawPoint(w, x, y, value);
  401. }
  402.  
  403. void BWDrawCircle(w, origin_x, origin_y, point_x, point_y, value)
  404.     Widget  w;
  405.     Position      origin_x, origin_y,
  406.     point_x, point_y;
  407.     int           value;
  408. {
  409.     register Position i, delta;
  410.     Dimension dx, dy, half;
  411.     double radius;
  412.     
  413.     dx = abs(point_x - origin_x);
  414.     dy = abs(point_y - origin_y);
  415.     radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy));
  416.     if (radius < 1.0) {
  417.     BWDrawPoint(w, origin_x, origin_y, value);
  418.     }
  419.     else {
  420.     BWDrawPoint(w, origin_x - (Position) floor(radius), origin_y, value);
  421.     BWDrawPoint(w, origin_x + (Position) floor(radius), origin_y, value);
  422.     BWDrawPoint(w, origin_x, origin_y - (Position) floor(radius), value);
  423.     BWDrawPoint(w, origin_x, origin_y + (Position) floor(radius), value);
  424.     }
  425.     half = radius / sqrt(2.0);
  426.     for(i = 1; (int)i <= (int)half; i++) {
  427.     delta = sqrt(radius * radius - i * i);
  428.     BWDrawPoint(w, origin_x - delta, origin_y - i, value);
  429.     BWDrawPoint(w, origin_x - delta, origin_y + i, value);
  430.     BWDrawPoint(w, origin_x + delta, origin_y - i, value);
  431.     BWDrawPoint(w, origin_x + delta, origin_y + i, value);
  432.     if (i != delta) {
  433.         BWDrawPoint(w, origin_x - i, origin_y - delta, value);
  434.         BWDrawPoint(w, origin_x - i, origin_y + delta, value);
  435.         BWDrawPoint(w, origin_x + i, origin_y - delta, value);
  436.         BWDrawPoint(w, origin_x + i, origin_y + delta, value);
  437.     }
  438.     }
  439. }
  440.  
  441. void BWDrawFilledCircle(w, origin_x, origin_y, point_x, point_y, value)
  442.     Widget  w;
  443.     Position      origin_x, origin_y,
  444.               point_x, point_y;
  445.     int           value;
  446. {
  447.     register Position i, j, delta;
  448.     Dimension dx, dy;
  449.     double radius;
  450.     
  451.     dx = abs(point_x - origin_x);
  452.     dy = abs(point_y - origin_y);
  453.     radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy));
  454.     for(j = origin_x - (Position) floor(radius); 
  455.     j <= origin_x + (Position) floor(radius); j++)
  456.     BWDrawPoint(w, j, origin_y, value);
  457.     for(i = 1; i <= (Position) floor(radius); i++) {
  458.     delta = sqrt(radius * radius - i * i);
  459.     for(j = origin_x - delta; j <= origin_x + delta; j++) {
  460.         BWDrawPoint(w, j, origin_y - i, value);
  461.         BWDrawPoint(w, j, origin_y + i, value);
  462.     }
  463.     }
  464. }
  465.  
  466. #define QueryFlood(BW, x, y, value)\
  467.     ((GetBit(BW->bitmap.image, x, y) !=\
  468.       (value & 1)) && QueryInBitmap(BW, x, y))
  469.  
  470. #define Flood(BW, x, y, value)\
  471.     {if (value == Highlight) HighlightSquare(BW, x, y);\
  472.      else InvertPoint(BW, x, y);}
  473.  
  474. /*
  475. void FloodLoop(BW, x, y, value)
  476.     BitmapWidget  BW;
  477.     Position      x, y;
  478.     int           value;
  479. {
  480.     if (QueryFlood(BW, x, y, value)) {
  481.     Flood(BW, x, y, value);
  482.     FloodLoop(BW, x, y - 1, value);
  483.     FloodLoop(BW, x - 1, y, value);
  484.     FloodLoop(BW, x, y + 1, value);
  485.     FloodLoop(BW, x + 1, y, value);
  486.     }
  487. }
  488. */
  489.  
  490. void FloodLoop(BW, x, y, value)
  491.     BitmapWidget BW;
  492.     Position     x, y;
  493.     int          value;
  494. {
  495.     Position save_x, save_y, x_left, x_right;
  496.     
  497.     if (QueryFlood(BW, x, y, value)) 
  498.     Flood(BW, x, y, value)
  499.  
  500.  
  501.     save_x = x;
  502.     save_y = y;
  503.  
  504.     x++;
  505.     while (QueryFlood(BW, x, y, value)) {
  506.     Flood(BW, x, y, value);
  507.     x++;
  508.     }
  509.     x_right = --x;
  510.  
  511.     x = save_x;
  512.     x--;
  513.     while (QueryFlood(BW, x, y, value)) {
  514.     Flood(BW, x, y, value);
  515.     x--;
  516.     }
  517.     x_left = ++x;
  518.  
  519.  
  520.     x = x_left;
  521.     y = save_y;
  522.     y++;
  523.     
  524.     while (x <= x_right) {
  525.     Boolean flag = False;
  526.     Position x_enter;
  527.     
  528.     while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
  529.         flag = True;
  530.         x++;
  531.     }
  532.     
  533.     if (flag) {
  534.         if ((x == x_right) && QueryFlood(BW, x, y, value))
  535.         FloodLoop(BW, x, y, value);
  536.         else
  537.         FloodLoop(BW, x - 1, y, value);
  538.     }
  539.     
  540.     x_enter = x;
  541.     
  542.     while (!QueryFlood(BW, x, y, value) && (x < x_right))
  543.         x++;
  544.     
  545.     if (x == x_enter) x++;
  546.     }
  547.  
  548.     x = x_left;
  549.     y = save_y;
  550.     y--;
  551.  
  552.     while (x <= x_right) {
  553.     Boolean flag = False;
  554.     Position x_enter;
  555.     
  556.     while (QueryFlood(BW, x, y, value) && (x <= x_right)) {
  557.         flag = True;
  558.         x++;
  559.     }
  560.     
  561.     if (flag) {
  562.         if ((x == x_right) && QueryFlood(BW, x, y, value))
  563.         FloodLoop(BW, x, y, value);
  564.         else
  565.         FloodLoop(BW, x - 1, y, value);
  566.     }
  567.     
  568.     x_enter = x;
  569.     
  570.     while (!QueryFlood(BW, x, y, value) && (x < x_right))
  571.         x++;
  572.     
  573.     if (x == x_enter) x++;
  574.     }
  575. }
  576.  
  577. void BWFloodFill(w, x, y, value)
  578.     Widget  w;
  579.     Position      x, y;
  580.     int           value;
  581. {
  582.     BitmapWidget BW = (BitmapWidget) w;
  583.     int pixel;
  584.  
  585.     pixel = GetBit(BW->bitmap.image, x, y);
  586.  
  587.     if (value == Invert)
  588.     FloodLoop(BW, x, y, (pixel ? Clear : Set));
  589.     else if (value != pixel)
  590.     FloodLoop(BW, x, y, value); 
  591. }
  592.  
  593. #define QueryHotInMark(BW)\
  594.     ((BW->bitmap.hot.x == max(BW->bitmap.mark.from_x,\
  595.                   min(BW->bitmap.hot.x, BW->bitmap.mark.to_x)))\
  596.      &&\
  597.      (BW->bitmap.hot.y == max(BW->bitmap.mark.from_y,\
  598.                   min(BW->bitmap.hot.y, BW->bitmap.mark.to_y))))
  599.  
  600. void BWUp(w)
  601.     Widget w;
  602. {
  603.     BitmapWidget BW = (BitmapWidget) w;
  604.     register Position x, y;
  605.     bit first, up, down;
  606.     Position from_x, from_y, to_x, to_y;
  607.  
  608.     if (BWQueryMarked(w)) {
  609.     from_x = BW->bitmap.mark.from_x;
  610.     from_y = BW->bitmap.mark.from_y;
  611.     to_x = BW->bitmap.mark.to_x;
  612.     to_y = BW->bitmap.mark.to_y;
  613.     }
  614.     else {
  615.     from_x = 0;
  616.     from_y = 0;
  617.     to_x = BW->bitmap.width - 1;
  618.     to_y = BW->bitmap.height - 1;
  619.     }
  620.  
  621.     if ((to_y - from_y) == 0)
  622.     return;
  623.     
  624.     for(x = from_x; x <= to_x; x++) {
  625.     first = up = GetBit(BW->bitmap.image, x, to_y);
  626.     for(y = to_y - 1; y >= from_y; y--) {
  627.         down = GetBit(BW->bitmap.image, x, y);
  628.         if (up != down) 
  629.         InvertPoint(BW, x, y);
  630.         up =down;
  631.     }
  632.     if(first != down)
  633.         InvertPoint(BW, x, to_y);
  634.     }
  635.  
  636.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  637.     &&
  638.     !BWQueryMarked(w))
  639.     BWSetHotSpot(w,
  640.              BW->bitmap.hot.x,
  641.              (BW->bitmap.hot.y - 1 + BW->bitmap.image->height) % 
  642.              BW->bitmap.image->height);
  643.  
  644. }
  645.  
  646. void BWDown(w)
  647.     Widget w;
  648. {
  649.     BitmapWidget BW = (BitmapWidget) w;
  650.     register Position x, y;
  651.     bit first, down, up;
  652.     Position from_x, from_y, to_x, to_y;
  653.  
  654.     if (BWQueryMarked(w)) {
  655.     from_x = BW->bitmap.mark.from_x;
  656.     from_y = BW->bitmap.mark.from_y;
  657.     to_x = BW->bitmap.mark.to_x;
  658.     to_y = BW->bitmap.mark.to_y;
  659.     }
  660.     else {
  661.     from_x = 0;
  662.     from_y = 0;
  663.     to_x = BW->bitmap.width - 1;
  664.     to_y = BW->bitmap.height - 1;
  665.     }
  666.  
  667.     if ((to_y - from_y) == 0)
  668.     return;
  669.  
  670.     for(x = from_x; x <= to_x; x++) {
  671.     first = down = GetBit(BW->bitmap.image, x, from_y);
  672.     for(y = from_y + 1; y <= to_y; y++) {
  673.         up = GetBit(BW->bitmap.image, x, y);
  674.         if (down != up)
  675.         InvertPoint(BW, x, y);
  676.         down = up;
  677.     }
  678.     if(first != up) 
  679.         InvertPoint(BW, x, from_y);
  680.     }
  681.     
  682.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  683.     &&
  684.     !BWQueryMarked(w))
  685.     BWSetHotSpot(w,
  686.              BW->bitmap.hot.x,
  687.              (BW->bitmap.hot.y + 1) % BW->bitmap.image->height);
  688. }
  689.  
  690. void BWLeft(w)
  691.     Widget w;
  692. {
  693.     BitmapWidget BW = (BitmapWidget) w;
  694.     register Position x, y;
  695.     bit first, left, right;
  696.     Position from_x, from_y, to_x, to_y;
  697.     
  698.     if (BWQueryMarked(w)) {
  699.     from_x = BW->bitmap.mark.from_x;
  700.     from_y = BW->bitmap.mark.from_y;
  701.     to_x = BW->bitmap.mark.to_x;
  702.     to_y = BW->bitmap.mark.to_y;
  703.     }
  704.     else {
  705.     from_x = 0;
  706.     from_y = 0;
  707.     to_x = BW->bitmap.width - 1;
  708.     to_y = BW->bitmap.height - 1;
  709.     }
  710.  
  711.     if ((to_x - from_x) == 0)
  712.     return;
  713.     
  714.     for(y = from_y; y <= to_y; y++) {
  715.     first = left = GetBit(BW->bitmap.image, to_x, y);
  716.     for(x = to_x - 1; x >= from_x; x--) {
  717.         right = GetBit(BW->bitmap.image, x, y);
  718.         if (left != right)
  719.         InvertPoint(BW, x, y);
  720.         left = right;
  721.     }
  722.     if(first != right)
  723.         InvertPoint(BW, to_x, y);
  724.     }
  725.     
  726.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  727.     &&
  728.     !BWQueryMarked(w))
  729.     BWSetHotSpot(w,
  730.              (BW->bitmap.hot.x - 1 + BW->bitmap.image->width) % 
  731.              BW->bitmap.image->width,
  732.              BW->bitmap.hot.y);
  733. }
  734.  
  735. void BWRight(w)
  736.     Widget w;
  737. {
  738.     BitmapWidget BW = (BitmapWidget) w;
  739.     register Position x, y;
  740.     bit first, right, left;
  741.     Position from_x, from_y, to_x, to_y;
  742.     
  743.     if (BWQueryMarked(w)) {
  744.     from_x = BW->bitmap.mark.from_x;
  745.     from_y = BW->bitmap.mark.from_y;
  746.     to_x = BW->bitmap.mark.to_x;
  747.     to_y = BW->bitmap.mark.to_y;
  748.     }
  749.     else {
  750.     from_x = 0;
  751.     from_y = 0;
  752.     to_x = BW->bitmap.width - 1;
  753.     to_y = BW->bitmap.height - 1;
  754.     }
  755.     
  756.     if ((to_x - from_x) == 0)
  757.     return;
  758.     
  759.     for(y = from_y; y <= to_y; y++) {
  760.     first = right = GetBit(BW->bitmap.image, from_x, y);
  761.     for(x = from_x + 1; x <= to_x; x++) {
  762.         left = GetBit(BW->bitmap.image, x, y);
  763.         if (right != left)
  764.         InvertPoint(BW, x, y);
  765.         right = left;
  766.     }
  767.     if(first != left)
  768.         InvertPoint(BW, from_x, y);
  769.     }
  770.  
  771.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  772.     &&
  773.     !BWQueryMarked(w))
  774.     BWSetHotSpot(w,
  775.              (BW->bitmap.hot.x + 1) % BW->bitmap.image->width,
  776.              BW->bitmap.hot.y);
  777. }
  778.  
  779. void TransferImageData();
  780.  
  781. void BWFold(w)
  782.     Widget w;
  783. {
  784.     BitmapWidget BW = (BitmapWidget) w;
  785.     Position x, y, new_x, new_y;
  786.     Dimension horiz, vert;
  787.     char *storage_data;
  788.     XImage *storage;
  789.     
  790.     storage_data = CreateCleanData(Length(BW->bitmap.image->width, 
  791.                       BW->bitmap.image->height));
  792.  
  793.     storage = CreateBitmapImage(BW, storage_data, 
  794.                 (Dimension) BW->bitmap.image->width, 
  795.                 (Dimension) BW->bitmap.image->height);
  796.  
  797.     TransferImageData(BW->bitmap.image, storage);
  798.  
  799.     BW->bitmap.fold ^= True;
  800.     horiz = (BW->bitmap.image->width + BW->bitmap.fold) / 2;
  801.     vert = (BW->bitmap.image->height + BW->bitmap.fold) / 2;
  802.     
  803.     for (x = 0; x < BW->bitmap.image->width; x++)
  804.     for (y = 0; y < BW->bitmap.image->height; y++) {
  805.         new_x = (int)(x + horiz) % (int)BW->bitmap.image->width;
  806.         new_y = (int)(y + vert) % (int)BW->bitmap.image->height;
  807.         if(GetBit(BW->bitmap.image, new_x, new_y) != 
  808.            GetBit(storage, x, y))
  809.         InvertPoint(BW, new_x, new_y);
  810.     }
  811.     
  812.     DestroyBitmapImage(&storage);
  813.  
  814.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y))
  815.       BWSetHotSpot(w, 
  816.            (Position) 
  817.            ((int)(BW->bitmap.hot.x+horiz)
  818.             %(int)BW->bitmap.image->width),
  819.            (Position)
  820.            ((int)(BW->bitmap.hot.y+vert)
  821.             %(int)BW->bitmap.image->height)
  822.            );
  823. }
  824.  
  825.  
  826. void BWClear(w)
  827.     Widget w;
  828. {
  829.     BitmapWidget BW = (BitmapWidget) w;
  830.     register Position x, y;
  831.     int i, length;
  832.  
  833.     length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
  834.  
  835.     for (x = 0; x < BW->bitmap.image->width; x++)
  836.     for (y = 0; y < BW->bitmap.image->height; y++)
  837.         if (GetBit(BW->bitmap.image, x, y))
  838.         DrawSquare(BW, x, y);
  839.     
  840.     for (i = 0; i < length; i++)
  841.     BW->bitmap.image->data[i] = 0;
  842.  
  843. }
  844.  
  845. void BWSet(w)
  846.     Widget w;
  847. {
  848.     BitmapWidget BW = (BitmapWidget) w;
  849.     register Position x, y;
  850.     int i, length;
  851.     
  852.     length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
  853.     
  854.     for (x = 0; x < BW->bitmap.image->width; x++)
  855.     for (y = 0; y < BW->bitmap.image->height; y++)
  856.         if (!GetBit(BW->bitmap.image, x, y))
  857.         DrawSquare(BW, x, y);
  858.     
  859.     for (i = 0; i < length; i++)
  860.     BW->bitmap.image->data[i] = 255;
  861.  
  862. }
  863.  
  864. void BWRedraw(w)
  865.     Widget w;
  866. {
  867.     BitmapWidget BW = (BitmapWidget) w;
  868.  
  869.     XClearArea(XtDisplay(BW), XtWindow(BW),
  870.            0, 0, BW->core.width, BW->core.height,
  871.            True);
  872. }
  873.  
  874. void BWInvert(w)
  875.     Widget w;
  876. {
  877.     BitmapWidget BW = (BitmapWidget) w;
  878.     int i, length;
  879.  
  880.     length = Length(BW->bitmap.image->width, BW->bitmap.image->height);
  881.  
  882.     XFillRectangle(XtDisplay(BW), XtWindow(BW),
  883.            BW->bitmap.drawing_gc,
  884.            InWindowX(BW, 0), InWindowY(BW, 0),
  885.            InWindowX(BW, BW->bitmap.image->width) - InWindowX(BW, 0),
  886.            InWindowY(BW, BW->bitmap.image->height) - InWindowY(BW, 0));
  887.     
  888.     for (i = 0; i < length; i++)
  889.     BW->bitmap.image->data[i] ^= 255;
  890. }
  891.  
  892. void BWFlipHoriz(w)
  893.     Widget w;
  894. {
  895.     BitmapWidget BW = (BitmapWidget) w;
  896.     register Position x, y;
  897.     Position from_x, from_y, to_x, to_y;
  898.     float half;
  899.     
  900.     if (BWQueryMarked(w)) {
  901.     from_x = BW->bitmap.mark.from_x;
  902.     from_y = BW->bitmap.mark.from_y;
  903.     to_x = BW->bitmap.mark.to_x;
  904.     to_y = BW->bitmap.mark.to_y;
  905.     }
  906.     else {
  907.     from_x = 0;
  908.     from_y = 0;
  909.     to_x = BW->bitmap.width - 1;
  910.     to_y = BW->bitmap.height - 1;
  911.     }
  912.     half = (float) (to_y - from_y) / 2.0 + 0.5;
  913.     
  914.     if (half == 0.0)
  915.     return;
  916.     
  917.     for (x = from_x; x <= to_x; x++) 
  918.     for (y = 0; y <  half; y++)
  919.         if (GetBit(BW->bitmap.image, x, from_y + y) != 
  920.         GetBit(BW->bitmap.image, x, to_y - y)) {
  921.         InvertPoint(BW, x, from_y + y);
  922.         InvertPoint(BW, x, to_y - y);
  923.         }
  924.     
  925.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  926.     &&
  927.     !BWQueryMarked(w))
  928.     BWSetHotSpot(w,
  929.              BW->bitmap.hot.x,
  930.              BW->bitmap.image->height - 1 - BW->bitmap.hot.y);
  931. }
  932.  
  933. void BWFlipVert(w)
  934.     Widget w;
  935. {
  936.     BitmapWidget BW = (BitmapWidget) w;
  937.     register Position x, y;
  938.     Position from_x, from_y, to_x, to_y;
  939.     float half;
  940.     
  941.     if (BWQueryMarked(w)) {
  942.     from_x = BW->bitmap.mark.from_x;
  943.     from_y = BW->bitmap.mark.from_y;
  944.     to_x = BW->bitmap.mark.to_x;
  945.     to_y = BW->bitmap.mark.to_y;
  946.     }
  947.     else {
  948.     from_x = 0;
  949.     from_y = 0;
  950.     to_x = BW->bitmap.width - 1;
  951.     to_y = BW->bitmap.height - 1;
  952.     }
  953.     half = (float) (to_x - from_x) / 2.0 + 0.5;
  954.  
  955.     if (half == 0)
  956.     return;
  957.  
  958.     for (y = from_y; y <= to_y; y++)
  959.     for (x = 0; x < half; x++)
  960.         if (GetBit(BW->bitmap.image, from_x + x, y) != 
  961.         GetBit(BW->bitmap.image, to_x - x, y)) {
  962.         InvertPoint(BW, from_x + x, y);
  963.         InvertPoint(BW, to_x - x, y);
  964.         }
  965.     
  966.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  967.     &&
  968.     !BWQueryMarked(w))
  969.     BWSetHotSpot(w,
  970.              BW->bitmap.image->width - 1 - BW->bitmap.hot.x,
  971.              BW->bitmap.hot.y);
  972. }
  973.  
  974.  
  975. void BWRotateRight(w)
  976.     Widget w;
  977. {
  978.     BitmapWidget BW = (BitmapWidget) w;
  979.     Position x, y, delta, shift, tmp;
  980.     Position half_width, half_height;
  981.     XPoint hot;
  982.     bit quad1, quad2, quad3, quad4;
  983.     Position from_x, from_y, to_x, to_y;
  984.     
  985.     if (BWQueryMarked(w)) {
  986.     from_x = BW->bitmap.mark.from_x;
  987.     from_y = BW->bitmap.mark.from_y;
  988.     to_x = BW->bitmap.mark.to_x;
  989.     to_y = BW->bitmap.mark.to_y;
  990.     }
  991.     else {
  992.     from_x = 0;
  993.     from_y = 0;
  994.     to_x = BW->bitmap.width - 1;
  995.     to_y = BW->bitmap.height - 1;
  996.     }
  997.  
  998.     half_width = floor((to_x - from_x) / 2.0 + 0.5);
  999.     half_height = floor((to_y - from_y ) / 2.0 + 0.5);
  1000.     shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
  1001.     delta = min((Position) half_width, (Position) half_height) - shift;
  1002.     
  1003.     for (x = 0; x <= delta; x++) {
  1004.     for (y = 1 - shift; y <= delta; y++) {
  1005.         quad1 = GetBit(BW->bitmap.image, 
  1006.                from_x + (Position)half_width + x, 
  1007.                from_y + (Position)half_height + y);
  1008.         quad2 = GetBit(BW->bitmap.image, 
  1009.                from_x + (Position)half_width + y, 
  1010.                from_y + (Position)half_height - shift - x);
  1011.         quad3 = GetBit(BW->bitmap.image, 
  1012.                from_x + (Position)half_width - shift - x, 
  1013.                from_y + (Position)half_height - shift - y);
  1014.         quad4 = GetBit(BW->bitmap.image, 
  1015.                from_x + (Position)half_width - shift - y, 
  1016.                from_y + (Position)half_height + x);
  1017.  
  1018.         if (quad1 != quad2)
  1019.         InvertPoint(BW, 
  1020.                 from_x + (Position)half_width + x, 
  1021.                 from_y + (Position)half_height + y);
  1022.         if (quad2 != quad3)
  1023.         InvertPoint(BW, 
  1024.                 from_x + (Position)half_width + y, 
  1025.                 from_y + (Position)half_height - shift - x);
  1026.         if (quad3 != quad4)
  1027.         InvertPoint(BW, 
  1028.                 from_x + (Position)half_width - shift - x,
  1029.                 from_y + (Position)half_height - shift - y);
  1030.         if (quad4 != quad1)
  1031.         InvertPoint(BW, 
  1032.                 from_x + (Position)half_width - shift - y, 
  1033.                 from_y + (Position)half_height + x);
  1034.     }
  1035.     }
  1036.     
  1037.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  1038.     &&
  1039.     !BWQueryMarked(w)) {
  1040.     hot.x = BW->bitmap.hot.x - half_width;
  1041.     hot.y = BW->bitmap.hot.y - half_height;
  1042.     if (hot.x >= 0) hot.x += shift;
  1043.     if (hot.y >= 0) hot.y += shift;
  1044.     tmp = hot.x;
  1045.     hot.x = - hot.y;
  1046.     hot.y = tmp;
  1047.     if (hot.x > 0) hot.x -= shift;
  1048.     if (hot.y > 0) hot.y -= shift;
  1049.     hot.x += half_width;
  1050.     hot.y += half_height;
  1051.     if (QueryInBitmap(BW, hot.x, hot.y))
  1052.         BWSetHotSpot(w, hot.x, hot.y);
  1053.     }
  1054.     
  1055. }
  1056.  
  1057. void BWRotateLeft(w)
  1058.     Widget w;
  1059. {
  1060.     BitmapWidget BW = (BitmapWidget) w;
  1061.     Position x, y,delta, shift, tmp;
  1062.     Position half_width, half_height;
  1063.     XPoint hot;
  1064.     bit quad1, quad2, quad3, quad4;
  1065.     Position from_x, from_y, to_x, to_y;
  1066.     
  1067.     if (BWQueryMarked(w)) {
  1068.     from_x = BW->bitmap.mark.from_x;
  1069.     from_y = BW->bitmap.mark.from_y;
  1070.     to_x = BW->bitmap.mark.to_x;
  1071.     to_y = BW->bitmap.mark.to_y;
  1072.     }
  1073.     else {
  1074.     from_x = 0;
  1075.     from_y = 0;
  1076.     to_x = BW->bitmap.width - 1;
  1077.     to_y = BW->bitmap.height - 1;
  1078.     }
  1079.  
  1080.     half_width = floor((to_x - from_x) / 2.0 + 0.5);
  1081.     half_height = floor((to_y - from_y ) / 2.0 + 0.5);
  1082.     shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
  1083.     delta = min((Position) half_width, (Position) half_height) - shift;
  1084.     
  1085.     for (x = 0; x <= delta; x++) {
  1086.     for (y = 1 - shift; y <= delta; y++) {
  1087.         quad1 = GetBit(BW->bitmap.image, 
  1088.                from_x + (Position)half_width + x, 
  1089.                from_y + (Position)half_height + y);
  1090.         quad2 = GetBit(BW->bitmap.image, 
  1091.                from_x + (Position)half_width + y, 
  1092.                from_y + (Position)half_height - shift - x);
  1093.         quad3 = GetBit(BW->bitmap.image, 
  1094.                from_x + (Position)half_width - shift - x, 
  1095.                from_y + (Position)half_height - shift - y);
  1096.         quad4 = GetBit(BW->bitmap.image, 
  1097.                from_x + (Position)half_width - shift - y, 
  1098.                from_y + (Position)half_height + x);
  1099.  
  1100.         if (quad1 != quad4)
  1101.         InvertPoint(BW, 
  1102.                 from_x + (Position)half_width + x, 
  1103.                 from_y + (Position)half_height + y);
  1104.         if (quad2 != quad1)
  1105.         InvertPoint(BW, 
  1106.                 from_x + (Position)half_width + y, 
  1107.                 from_y + (Position)half_height - shift - x);
  1108.         if (quad3 != quad2)
  1109.         InvertPoint(BW, 
  1110.                 from_x + (Position)half_width - shift - x,
  1111.                 from_y + (Position)half_height - shift - y);
  1112.         if (quad4 != quad3)
  1113.         InvertPoint(BW, 
  1114.                 from_x + (Position)half_width - shift - y, 
  1115.                 from_y + (Position)half_height + x);
  1116.     }
  1117.     }
  1118.     
  1119.     if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)
  1120.     &&
  1121.     !BWQueryMarked(w)) {
  1122.     hot.x = BW->bitmap.hot.x - half_width;
  1123.     hot.y = BW->bitmap.hot.y - half_height;
  1124.     if (hot.x >= 0) hot.x += shift;
  1125.     if (hot.y >= 0) hot.y += shift;
  1126.     tmp = hot.x;
  1127.     hot.x = hot.y;
  1128.     hot.y = - tmp;
  1129.     if (hot.x > 0) hot.x -= shift;
  1130.     if (hot.y > 0) hot.y -= shift;
  1131.     hot.x += half_width;
  1132.     hot.y += half_height;
  1133.     if (QueryInBitmap(BW, hot.x, hot.y))
  1134.         BWSetHotSpot(w, hot.x, hot.y);
  1135.     }
  1136. }
  1137.  
  1138.  
  1139. void CopyImageData(source, destination, from_x, from_y, to_x, to_y, at_x, at_y)
  1140.     XImage *source, *destination;
  1141.     Position  from_x, from_y, to_x, to_y, at_x, at_y;
  1142. {
  1143.     Position x, y, delta_x, delta_y;
  1144.     
  1145.     delta_x = to_x - from_x + 1;
  1146.     delta_y = to_y - from_y + 1;
  1147.     
  1148.     for (x = 0; x < delta_x; x++)
  1149.     for (y = 0; y < delta_y; y++)
  1150.         if (GetBit(source, from_x + x, from_y + y))
  1151.         SetBit(destination, at_x + x, at_y + y);
  1152.         else
  1153.         ClearBit(destination, at_x + x, at_y + y);
  1154. }
  1155.       
  1156. XImage *ConvertToBitmapImage(BW, image)
  1157.     BitmapWidget BW;
  1158.     XImage *image;
  1159. {
  1160.     XImage *bitmap_image;
  1161.     char   *data;
  1162.     Position x, y;
  1163.     
  1164.     data = CreateCleanData(Length(image->width, image->height));
  1165.     bitmap_image = CreateBitmapImage(BW, data, 
  1166.                      (Dimension) image->width, 
  1167.                      (Dimension) image->height);
  1168.  
  1169.     for (x = 0; x < min(image->width, bitmap_image->width); x++)
  1170.     for (y = 0; y < min(image->height, bitmap_image->height); y++)
  1171.         if ((XGetPixel(image, x, y) != 0) != GetBit(bitmap_image, x, y))
  1172.         InvertBit(bitmap_image, x, y);
  1173.  
  1174.     return bitmap_image;
  1175. }
  1176.  
  1177. void TransferImageData(source, destination)
  1178.     XImage *source, *destination;
  1179. {
  1180.     Position x, y;
  1181.     
  1182.     for (x = 0; x < min(source->width, destination->width); x++)
  1183.     for (y = 0; y < min(source->height, destination->height); y++)
  1184.         if (GetBit(source, x, y) != GetBit(destination, x, y))
  1185.         InvertBit(destination, x, y);
  1186. }
  1187.  
  1188. void BWStore(w)
  1189.     Widget w;
  1190. {
  1191.     BitmapWidget BW = (BitmapWidget) w;
  1192.     Dimension width, height;
  1193.     char *storage_data;
  1194.  
  1195.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1196.  
  1197.     DestroyBitmapImage(&BW->bitmap.storage);
  1198.  
  1199.     width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
  1200.     height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
  1201.     
  1202.     storage_data = CreateCleanData(Length(width, height));
  1203.  
  1204.     BW->bitmap.storage = CreateBitmapImage(BW,
  1205.                            storage_data,
  1206.                            width, height);
  1207.  
  1208.     CopyImageData(BW->bitmap.image, BW->bitmap.storage,
  1209.               BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
  1210.               BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
  1211.               0, 0);
  1212.     }
  1213. }
  1214.  
  1215. void BWClearMarked(w)
  1216.     Widget w;
  1217. {
  1218.     BitmapWidget BW = (BitmapWidget) w;
  1219.     
  1220.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
  1221.     BWDrawFilledRectangle(w,
  1222.                   BW->bitmap.mark.from_x,
  1223.                   BW->bitmap.mark.from_y,
  1224.                   BW->bitmap.mark.to_x,
  1225.                   BW->bitmap.mark.to_y,
  1226.                   Clear);
  1227. }
  1228.  
  1229.  
  1230. void BWDragMarked(w, at_x, at_y)
  1231.     Widget w;
  1232.     Position     at_x, at_y;
  1233. {
  1234.     BitmapWidget BW = (BitmapWidget) w;
  1235.  
  1236.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y))
  1237.     BWDrawRectangle(w, 
  1238.             at_x, at_y, 
  1239.             at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
  1240.             at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y,
  1241.             Highlight);
  1242. }
  1243.  
  1244. void BWDragStored(w, at_x, at_y)
  1245.     Widget       w;
  1246.     Position     at_x, at_y;
  1247. {
  1248.     BitmapWidget BW = (BitmapWidget) w;
  1249.     
  1250.     if (BW->bitmap.storage)
  1251.     BWDrawRectangle(w, 
  1252.             at_x, at_y,
  1253.             at_x + BW->bitmap.storage->width - 1,
  1254.             at_y + BW->bitmap.storage->height - 1,
  1255.             Highlight);
  1256. }
  1257.  
  1258. void DrawImageData(BW, image, at_x, at_y, value)
  1259.     BitmapWidget BW;
  1260.     XImage       *image;
  1261.     Position     at_x, at_y;
  1262.     int          value;
  1263. {
  1264.     Position x, y;
  1265.     Boolean  C, S, I, H;
  1266.     bit      A, B;
  1267.  
  1268.     C = value == Clear;
  1269.     S = value == Set;
  1270.     I = value == Invert;
  1271.     H = value == Highlight;
  1272.  
  1273.     for (x = 0; x < image->width; x++) 
  1274.     for (y = 0; y < image->height; y++) {
  1275.         A = GetBit(image, x, y);
  1276.         B = GetBit(BW->bitmap.image, at_x + x, at_y + y);
  1277.         if (A & C | (A | B) & S | (A ^ B) & I | (A | B) & H)
  1278.         value = (A & H) ? Highlight : Set;
  1279.         else
  1280.         value = Clear;
  1281.         BWDrawPoint((Widget) BW, 
  1282.              at_x + x, at_y + y, 
  1283.              value);
  1284.     }
  1285. }
  1286.  
  1287. void BWRestore(w, at_x, at_y, value)
  1288.     Widget       w;
  1289.     Position     at_x, at_y;
  1290.     int          value;
  1291. {
  1292.     BitmapWidget BW = (BitmapWidget) w;
  1293.     
  1294.     if (BW->bitmap.storage) {
  1295.       DrawImageData(BW, BW->bitmap.storage, at_x, at_y, value);
  1296.       /*DestroyBitmapImage(&BW->bitmap.storage);*/
  1297.     }
  1298. }
  1299.  
  1300. void BWCopy(w, at_x, at_y, value)
  1301.     Widget       w;
  1302.     Position     at_x, at_y;
  1303.     int          value;
  1304. {
  1305.     BitmapWidget BW = (BitmapWidget) w;
  1306.     XImage *storage;
  1307.     char *storage_data;
  1308.     Dimension width, height;
  1309.  
  1310.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1311.  
  1312.     width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
  1313.     height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
  1314.     
  1315.     storage_data = CreateCleanData(Length(width, height));
  1316.  
  1317.     storage = CreateBitmapImage(BW, storage_data, width, height);
  1318.  
  1319.     CopyImageData(BW->bitmap.image, storage,
  1320.               BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
  1321.               BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
  1322.               0, 0);
  1323.  
  1324.     DrawImageData(BW, storage, at_x, at_y, value);
  1325.  
  1326.     DestroyBitmapImage(&storage);
  1327.     }
  1328. }
  1329.  
  1330. void BWMark();
  1331.  
  1332. void BWMove(w, at_x, at_y, value)
  1333.     Widget   w;
  1334.     Position at_x, at_y;
  1335.     int      value;
  1336. {
  1337.     BitmapWidget BW = (BitmapWidget) w;
  1338.     XImage *storage;
  1339.     char *storage_data;
  1340.     Dimension width, height;
  1341.  
  1342.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1343.  
  1344.     width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1;
  1345.     height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1;
  1346.     
  1347.     storage_data = CreateCleanData(Length(width, height));
  1348.  
  1349.     storage = CreateBitmapImage(BW, storage_data, width, height);
  1350.  
  1351.     CopyImageData(BW->bitmap.image, storage,
  1352.               BW->bitmap.mark.from_x,  BW->bitmap.mark.from_y,
  1353.               BW->bitmap.mark.to_x,  BW->bitmap.mark.to_y,
  1354.               0, 0);
  1355.  
  1356.     BWDrawFilledRectangle(w,
  1357.                   BW->bitmap.mark.from_x, BW->bitmap.mark.from_y,
  1358.                   BW->bitmap.mark.to_x, BW->bitmap.mark.to_y,
  1359.                   Clear);
  1360.  
  1361.     DrawImageData(BW, storage, at_x, at_y, value);
  1362.  
  1363.     BWMark(w, at_x, at_y,
  1364.          at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x,
  1365.          at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y);
  1366.  
  1367.     DestroyBitmapImage(&storage);
  1368.     }
  1369. }
  1370.  
  1371. void BWRedrawMark(w)
  1372.     Widget w;
  1373. {
  1374.     BitmapWidget BW = (BitmapWidget) w;
  1375.     
  1376.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 
  1377.     XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
  1378.                InWindowX(BW, BW->bitmap.mark.from_x), 
  1379.                InWindowY(BW, BW->bitmap.mark.from_y), 
  1380.                InWindowX(BW, BW->bitmap.mark.to_x + 1) - 
  1381.                InWindowX(BW, BW->bitmap.mark.from_x),
  1382.                InWindowY(BW, BW->bitmap.mark.to_y + 1) -
  1383.                InWindowY(BW, BW->bitmap.mark.from_y));
  1384. }
  1385.  
  1386. void BWStoreToBuffer(w)
  1387.      Widget w;
  1388. {
  1389.     BitmapWidget BW = (BitmapWidget) w;
  1390.     
  1391.     bcopy(BW->bitmap.image->data, BW->bitmap.buffer->data,
  1392.       Length(BW->bitmap.image->width, BW->bitmap.image->height));
  1393.  
  1394.     BW->bitmap.buffer_hot = BW->bitmap.hot;
  1395.     BW->bitmap.buffer_mark = BW->bitmap.mark;
  1396. }
  1397.  
  1398. void BWUnmark(w)
  1399.      Widget w;
  1400. {
  1401.     BitmapWidget BW = (BitmapWidget) w;
  1402.  
  1403.     BW->bitmap.buffer_mark = BW->bitmap.mark;
  1404.  
  1405.     if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) {
  1406.     XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
  1407.                InWindowX(BW, BW->bitmap.mark.from_x), 
  1408.                InWindowY(BW, BW->bitmap.mark.from_y), 
  1409.                InWindowX(BW, BW->bitmap.mark.to_x + 1) - 
  1410.                InWindowX(BW, BW->bitmap.mark.from_x),
  1411.                InWindowY(BW, BW->bitmap.mark.to_y + 1) -
  1412.                InWindowY(BW, BW->bitmap.mark.from_y));
  1413.     
  1414.     BW->bitmap.mark.from_x = BW->bitmap.mark.from_y = NotSet;
  1415.     BW->bitmap.mark.to_x = BW->bitmap.mark.to_y = NotSet;
  1416.     }
  1417. }
  1418.  
  1419. void BWMark(w, from_x, from_y, to_x, to_y)
  1420.     Widget w;
  1421.     Position from_x, from_y,
  1422.          to_x, to_y;
  1423. {
  1424.     BitmapWidget BW = (BitmapWidget) w;
  1425.  
  1426.     BWUnmark(w);
  1427.     
  1428.     if (QuerySet(from_x, from_y)) {
  1429.     if ((from_x == to_x) && (from_y == to_y)) {
  1430.         /*
  1431.           BW->bitmap.mark.from_x = 0;
  1432.           BW->bitmap.mark.from_y = 0;
  1433.           BW->bitmap.mark.to_x = BW->bitmap.image->width - 1;
  1434.           BW->bitmap.mark.to_y = BW->bitmap.image->height - 1;
  1435.           */
  1436.         return;
  1437.     }
  1438.     else {
  1439.         QuerySwap(from_x, to_x);
  1440.         QuerySwap(from_y, to_y);
  1441.         from_x = max(0, from_x);
  1442.         from_y = max(0, from_y);
  1443.         to_x = min(BW->bitmap.image->width - 1, to_x);
  1444.         to_y = min(BW->bitmap.image->height - 1, to_y);
  1445.         
  1446.         BW->bitmap.mark.from_x = from_x;
  1447.         BW->bitmap.mark.from_y = from_y;
  1448.         BW->bitmap.mark.to_x = to_x;
  1449.         BW->bitmap.mark.to_y = to_y;
  1450.     }
  1451.     
  1452.     XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,
  1453.                InWindowX(BW, BW->bitmap.mark.from_x),
  1454.                InWindowY(BW, BW->bitmap.mark.from_y), 
  1455.                InWindowX(BW, BW->bitmap.mark.to_x + 1) -
  1456.                InWindowX(BW, BW->bitmap.mark.from_x),
  1457.                InWindowY(BW, BW->bitmap.mark.to_y +1) - 
  1458.                InWindowY(BW, BW->bitmap.mark.from_y));
  1459.     }
  1460. }
  1461.  
  1462. void BWMarkAll(w)
  1463.     Widget w;
  1464. {
  1465.   BitmapWidget BW = (BitmapWidget) w;
  1466.  
  1467.   BWMark(w, 0, 0, BW->bitmap.image->width - 1, BW->bitmap.image->height - 1);
  1468. }
  1469.  
  1470. void BWUndo(w)
  1471.     Widget w;
  1472. {
  1473.     BitmapWidget BW = (BitmapWidget) w;
  1474.     Position x, y;
  1475.     char *tmp_data;
  1476.     XPoint tmp_hot;
  1477.     BWArea tmp_mark;
  1478.     
  1479.     tmp_data = BW->bitmap.image->data;
  1480.     BW->bitmap.image->data = BW->bitmap.buffer->data;
  1481.     BW->bitmap.buffer->data = tmp_data;
  1482.  
  1483.     tmp_hot = BW->bitmap.hot;
  1484.     tmp_mark = BW->bitmap.mark;
  1485.     
  1486.     for (x = 0; x < BW->bitmap.image->width; x++)
  1487.     for (y = 0; y < BW->bitmap.image->height; y++)
  1488.      if (GetBit(BW->bitmap.image, x, y) != GetBit(BW->bitmap.buffer, x, y))
  1489.          DrawSquare(BW, x, y);
  1490.  
  1491.     BWSetHotSpot(w, BW->bitmap.buffer_hot.x, BW->bitmap.buffer_hot.y);
  1492. /*    
  1493.     BWMark(w, BW->bitmap.buffer_mark.from_x, BW->bitmap.buffer_mark.from_y,
  1494.        BW->bitmap.buffer_mark.to_x, BW->bitmap.buffer_mark.to_y);
  1495. */
  1496.     BW->bitmap.buffer_hot = tmp_hot;
  1497.     BW->bitmap.buffer_mark= tmp_mark;
  1498.  
  1499. }
  1500.  
  1501. void BWHighlightAxes(w)
  1502.     Widget w;
  1503. {
  1504.     BitmapWidget BW = (BitmapWidget) w;
  1505.  
  1506.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1507.           BW->bitmap.axes_gc,
  1508.           InWindowX(BW, 0), 
  1509.           InWindowY(BW, 0),
  1510.           InWindowX(BW, BW->bitmap.width),
  1511.           InWindowY(BW, BW->bitmap.height));
  1512.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1513.           BW->bitmap.axes_gc,
  1514.           InWindowX(BW, BW->bitmap.width),
  1515.           InWindowY(BW, 0), 
  1516.           InWindowX(BW, 0),
  1517.           InWindowY(BW, BW->bitmap.height));
  1518.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1519.           BW->bitmap.axes_gc,
  1520.           InWindowX(BW, 0),
  1521.           InWindowY(BW, (float)BW->bitmap.height / 2.0),
  1522.           InWindowX(BW, BW->bitmap.width),
  1523.           InWindowY(BW, (float)BW->bitmap.height / 2.0));
  1524.     XDrawLine(XtDisplay(BW), XtWindow(BW),
  1525.           BW->bitmap.axes_gc,
  1526.           InWindowX(BW, (float)BW->bitmap.width / 2.0),
  1527.           InWindowY(BW, 0),
  1528.           InWindowX(BW, (float)BW->bitmap.width / 2.0),
  1529.           InWindowY(BW, BW->bitmap.height));
  1530. }
  1531.     
  1532. typedef struct {
  1533.     Position *x, *y;
  1534.     Dimension *width, *height;
  1535. } Table;
  1536.  
  1537. XImage *ScaleBitmapImage(BW, src, scale_x, scale_y)
  1538.     BitmapWidget BW;
  1539.     XImage *src;
  1540.     double scale_x, scale_y;
  1541. {
  1542.     char *data;
  1543.     XImage *dst;
  1544.     Table table;    
  1545.     Position x, y, w, h;
  1546.     Dimension width, height;
  1547.     bit pixel;
  1548.  
  1549.     width = max(rint(scale_x * src->width), 1);
  1550.     height = max(rint(scale_y * src->height), 1);
  1551.  
  1552.     data = CreateCleanData(Length(width, height));
  1553.     dst = CreateBitmapImage(BW, data, width, height);
  1554.  
  1555.     /*
  1556.      * It would be nice to check if width or height < 1.0 and
  1557.      * average the skipped pixels. But, it is slow as it is now.
  1558.      */
  1559.     if (scale_x == 1.0 && scale_y == 1.0)
  1560.     bcopy (src->data, dst->data, Length(width, height));
  1561.     else {
  1562.     table.x = (Position *) XtMalloc(sizeof(Position) * src->width);
  1563.     table.y = (Position *) XtMalloc(sizeof(Position) * src->height);
  1564.     table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width);
  1565.     table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height);
  1566.     
  1567.     for (x = 0; x < src->width; x++) {
  1568.         table.x[x] = rint(scale_x * x);
  1569.         table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x);
  1570.     }
  1571.     for (y = 0; y < src->height; y++) {
  1572.         table.y[y] = rint(scale_y * y);
  1573.         table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y);
  1574.     }
  1575.     
  1576.     for (x = 0; x < src->width; x++)
  1577.         for (y = 0; y < src->height; y++) {
  1578.             pixel = GetBit(src, x, y);
  1579.         for (w = 0; (int)w < (int)table.width[x]; w++)
  1580.             for (h = 0; (int)h < (int)table.height[y]; h++)
  1581.             if (pixel) SetBit(dst, 
  1582.                     table.x[x] + w, 
  1583.                     table.y[y] + h);
  1584.         }
  1585.  
  1586.     XtFree((char *)table.x);
  1587.     XtFree((char *)table.y);
  1588.     XtFree((char *)table.width);
  1589.     XtFree((char *)table.height);
  1590.     }
  1591.     
  1592.     return (dst);
  1593. }
  1594.  
  1595. /*****************************************************************************/
  1596.