1 /* 2 3 Copyright 1989, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 /* 30 * Author: Davor Matic, MIT X Consortium 31 */ 32 33 #ifdef HAVE_CONFIG_H 34 # include "config.h" 35 #endif 36 37 #include <X11/IntrinsicP.h> 38 #include <X11/StringDefs.h> 39 #include <X11/Xaw/XawInit.h> 40 #include <X11/Xmu/CharSet.h> 41 #include <X11/Xmu/Drawing.h> 42 #include <X11/Xatom.h> 43 #include <X11/Xfuncs.h> 44 #include <X11/Xos.h> 45 #include "BitmapP.h" 46 #include "Bitmap.h" 47 48 #include <assert.h> 49 #include <stdio.h> 50 #include <math.h> 51 52 #define min(x, y) ((((int)(x)) < (int)(y)) ? (x) : (y)) 53 #define max(x, y) ((((int)(x)) > (int)(y)) ? (x) : (y)) 54 55 Boolean DEBUG; 56 57 #define DefaultGridTolerance 8 58 #define DefaultBitmapSize "16x16" 59 #define FallbackBitmapWidth 16 60 #define FallbackBitmapHeight 16 61 #define DefaultGrid TRUE 62 #define DefaultDashed TRUE 63 #define DefaultStippled TRUE 64 #define DefaultProportional TRUE 65 #define DefaultAxes FALSE 66 #define DefaultMargin 16 67 #define DefaultSquareWidth 16 68 #define DefaultSquareHeight 16 69 #define DefaultFilename "" 70 71 #define Offset(field) XtOffsetOf(BitmapRec, bitmap.field) 72 73 static XtResource resources[] = { 74 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 75 Offset(foreground_pixel), XtRString, XtDefaultForeground}, 76 {XtNhighlight, XtCHighlight, XtRPixel, sizeof(Pixel), 77 Offset(highlight_pixel), XtRString, XtDefaultForeground}, 78 {XtNframe, XtCFrame, XtRPixel, sizeof(Pixel), 79 Offset(frame_pixel), XtRString, XtDefaultForeground}, 80 {XtNgridTolerance, XtCGridTolerance, XtRDimension, sizeof(Dimension), 81 Offset(grid_tolerance), XtRImmediate, (XtPointer) DefaultGridTolerance}, 82 {XtNsize, XtCSize, XtRString, sizeof(String), 83 Offset(size), XtRImmediate, (XtPointer) DefaultBitmapSize}, 84 {XtNdashed, XtCDashed, XtRBoolean, sizeof(Boolean), 85 Offset(dashed), XtRImmediate, (XtPointer) DefaultDashed}, 86 {XtNgrid, XtCGrid, XtRBoolean, sizeof(Boolean), 87 Offset(grid), XtRImmediate, (XtPointer) DefaultGrid}, 88 {XtNstippled, XtCStippled, XtRBoolean, sizeof(Boolean), 89 Offset(stippled), XtRImmediate, (XtPointer) DefaultStippled}, 90 {XtNproportional, XtCProportional, XtRBoolean, sizeof(Boolean), 91 Offset(proportional), XtRImmediate, (XtPointer) DefaultProportional}, 92 {XtNaxes, XtCAxes, XtRBoolean, sizeof(Boolean), 93 Offset(axes), XtRImmediate, (XtPointer) DefaultAxes}, 94 {XtNsquareWidth, XtCSquareWidth, XtRDimension, sizeof(Dimension), 95 Offset(squareW), XtRImmediate, (XtPointer) DefaultSquareWidth}, 96 {XtNsquareHeight, XtCSquareHeight, XtRDimension, sizeof(Dimension), 97 Offset(squareH), XtRImmediate, (XtPointer) DefaultSquareHeight}, 98 {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension), 99 Offset(margin), XtRImmediate, (XtPointer) DefaultMargin}, 100 {XtNxHot, XtCXHot, XtRPosition, sizeof(Position), 101 Offset(hot.x), XtRImmediate, (XtPointer) NotSet}, 102 {XtNyHot, XtCYHot, XtRPosition, sizeof(Position), 103 Offset(hot.y), XtRImmediate, (XtPointer) NotSet}, 104 {XtNbutton1Function, XtCButton1Function, XtRButtonFunction, sizeof(int), 105 Offset(button_function[0]), XtRImmediate, (XtPointer) Set}, 106 {XtNbutton2Function, XtCButton2Function, XtRButtonFunction, sizeof(int), 107 Offset(button_function[1]), XtRImmediate, (XtPointer) Invert}, 108 {XtNbutton3Function, XtCButton3Function, XtRButtonFunction, sizeof(int), 109 Offset(button_function[2]), XtRImmediate, (XtPointer) Clear}, 110 {XtNbutton4Function, XtCButton4Function, XtRButtonFunction, sizeof(int), 111 Offset(button_function[3]), XtRImmediate, (XtPointer) Clear}, 112 {XtNbutton5Function, XtCButton5Function, XtRButtonFunction, sizeof(int), 113 Offset(button_function[4]), XtRImmediate, (XtPointer) Clear}, 114 {XtNfilename, XtCFilename, XtRString, sizeof(String), 115 Offset(filename), XtRImmediate, (XtPointer) DefaultFilename}, 116 {XtNbasename, XtCBasename, XtRString, sizeof(String), 117 Offset(basename), XtRImmediate, (XtPointer) DefaultFilename}, 118 {XtNdashes, XtCDashes, XtRBitmap, sizeof(Pixmap), 119 Offset(dashes), XtRImmediate, (XtPointer) XtUnspecifiedPixmap}, 120 {XtNstipple, XtCStipple, XtRBitmap, sizeof(Pixmap), 121 Offset(stipple), XtRImmediate, (XtPointer) XtUnspecifiedPixmap}, 122 }; 123 #undef Offset 124 125 126 static XtActionsRec actions[] = 127 { 128 {"mark", (XtActionProc)BWTMark}, 129 {"mark-all", (XtActionProc)BWTMarkAll}, 130 {"unmark", (XtActionProc)BWTUnmark}, 131 {"paste", (XtActionProc)BWTPaste}, 132 {"bw-debug", (XtActionProc)BWDebug}, 133 {"abort", (XtActionProc)BWAbort}, 134 {"store-to-buffer", (XtActionProc)BWStoreToBuffer}, 135 {"change-notify", (XtActionProc)BWChangeNotify}, 136 {"set-changed", (XtActionProc)BWSetChanged}, 137 {"up", (XtActionProc)BWUp}, 138 {"down", (XtActionProc)BWDown}, 139 {"left", (XtActionProc)BWLeft}, 140 {"right", (XtActionProc)BWRight}, 141 {"fold", (XtActionProc)BWFold}, 142 {"flip-horiz", (XtActionProc)BWFlipHoriz}, 143 {"flip-vert", (XtActionProc)BWFlipVert}, 144 {"rotate-right", (XtActionProc)BWRotateRight}, 145 {"rotate-left", (XtActionProc)BWRotateLeft}, 146 {"set", (XtActionProc)BWSet}, 147 {"clear", (XtActionProc)BWClear}, 148 {"invert", (XtActionProc)BWInvert}, 149 {"undo", (XtActionProc)BWUndo}, 150 {"redraw", (XtActionProc)BWRedraw}, 151 }; 152 153 static char translations1[] = 154 "\ 155 Shift<Btn1Down>: mark()\n\ 156 Shift<Btn2Down>: mark-all()\n\ 157 Shift<Btn3Down>: unmark()\n\ 158 Ctrl<BtnDown>: paste()\n\ 159 Ctrl<Key>l: redraw()\n\ 160 <Key>d: bw-debug()\n\ 161 <Key>a: abort()\n\ 162 <Key>Up: store-to-buffer()\ 163 up()\ 164 change-notify()\ 165 set-changed()\n\ 166 <Key>KP_Up: store-to-buffer()\ 167 up()\ 168 change-notify()\ 169 set-changed()\n\ 170 <Key>Down: store-to-buffer()\ 171 down()\ 172 change-notify()\ 173 set-changed()\n\ 174 <Key>KP_Down: store-to-buffer()\ 175 down()\ 176 change-notify()\ 177 set-changed()\n\ 178 <Key>Left: store-to-buffer()\ 179 left()\ 180 change-notify()\ 181 set-changed()\n\ 182 <Key>KP_Left: store-to-buffer()\ 183 left()\ 184 change-notify()\ 185 set-changed()\n\ 186 <Key>Right: store-to-buffer()\ 187 right()\ 188 change-notify()\ 189 set-changed()\n\ 190 <Key>KP_Right: store-to-buffer()\ 191 right()\ 192 change-notify()\ 193 set-changed()\n\ 194 <Key>f: store-to-buffer()\ 195 fold()\ 196 change-notify()\ 197 set-changed()\n\ 198 <Key>h: store-to-buffer()\ 199 flip-horiz()\ 200 change-notify()\ 201 set-changed()\n\ 202 "; 203 204 static char translations2[] = 205 "<Key>v: store-to-buffer()\ 206 flip-vert()\ 207 change-notify()\ 208 set-changed()\n\ 209 <Key>r: store-to-buffer()\ 210 rotate-right()\ 211 change-notify()\ 212 set-changed()\n\ 213 <Key>l: store-to-buffer()\ 214 rotate-left()\ 215 change-notify()\ 216 set-changed()\n\ 217 <Key>s: store-to-buffer()\ 218 set()\ 219 change-notify()\ 220 set-changed()\n\ 221 <Key>c: store-to-buffer()\ 222 clear()\ 223 change-notify()\ 224 set-changed()\n\ 225 <Key>i: store-to-buffer()\ 226 invert()\ 227 change-notify()\ 228 set-changed()\n\ 229 <Key>u: undo()\ 230 change-notify()\ 231 set-changed()\n\ 232 "; 233 234 static Atom targets[] = { 235 XA_BITMAP, 236 XA_PIXMAP 237 }; 238 239 #include "Requests.h" 240 241 242 static BWRequestRec requests[] = 243 { 244 {MarkRequest, sizeof(BWStatus), 245 TwoPointsEngage, (XtPointer) BWDrawRectangle, 246 TwoPointsTerminateTimed, (XtPointer) BWSelect, 247 NULL, (XtPointer) NULL}, 248 {RestoreRequest, sizeof(BWStatus), 249 OnePointEngage, (XtPointer) BWDragStored, 250 OnePointTerminate, (XtPointer) BWRestore, 251 NULL, (XtPointer) NULL}, 252 {ImmediateCopyRequest, sizeof(BWStatus), 253 OnePointEngage, (XtPointer) BWDragMarked, 254 OnePointTerminate, (XtPointer) BWCopy, 255 NULL, (XtPointer) NULL}, 256 {ImmediateMoveRequest, sizeof(BWStatus), 257 OnePointEngage, (XtPointer) BWDragMarked, 258 OnePointTerminate, (XtPointer) BWMove, 259 NULL, (XtPointer) NULL}, 260 {CopyRequest, sizeof(BWStatus), 261 DragOnePointEngage, (XtPointer) Paste, 262 DragOnePointTerminate, (XtPointer) ImmediateCopyRequest, 263 Interface, (XtPointer) BWUnmark}, 264 {MoveRequest, sizeof(BWStatus), 265 DragOnePointEngage, (XtPointer) Paste, 266 DragOnePointTerminate, (XtPointer) ImmediateMoveRequest, 267 Interface, (XtPointer) BWUnmark}, 268 {PointRequest, sizeof(BWStatus), 269 DragOnePointEngage, (XtPointer) BWDrawPoint, 270 DragOnePointTerminate, (XtPointer) BWDrawPoint, 271 NULL, (XtPointer) NULL}, 272 {CurveRequest, sizeof(BWStatus), 273 DragTwoPointsEngage, (XtPointer) BWBlindLine, 274 DragTwoPointsTerminate, (XtPointer) BWBlindLine, 275 NULL, (XtPointer) NULL}, 276 {LineRequest, sizeof(BWStatus), 277 TwoPointsEngage, (XtPointer) BWDrawLine, 278 TwoPointsTerminate, (XtPointer) BWDrawLine, 279 NULL, (XtPointer) NULL}, 280 {RectangleRequest, sizeof(BWStatus), 281 TwoPointsEngage, (XtPointer) BWDrawRectangle, 282 TwoPointsTerminate, (XtPointer) BWDrawRectangle, 283 NULL, (XtPointer) NULL}, 284 {FilledRectangleRequest, sizeof(BWStatus), 285 TwoPointsEngage, (XtPointer) BWDrawRectangle, 286 TwoPointsTerminate, (XtPointer) BWDrawFilledRectangle, 287 NULL, (XtPointer) NULL}, 288 {CircleRequest, sizeof(BWStatus), 289 TwoPointsEngage, (XtPointer) BWDrawCircle, 290 TwoPointsTerminate, (XtPointer) BWDrawCircle, 291 NULL, (XtPointer) NULL}, 292 {FilledCircleRequest, sizeof(BWStatus), 293 TwoPointsEngage, (XtPointer) BWDrawCircle, 294 TwoPointsTerminate, (XtPointer) BWDrawFilledCircle, 295 NULL, (XtPointer) NULL}, 296 {FloodFillRequest, sizeof(BWStatus), 297 OnePointEngage, (XtPointer) NULL, 298 OnePointTerminate, (XtPointer) BWFloodFill, 299 NULL, (XtPointer) NULL}, 300 {HotSpotRequest, sizeof(BWStatus), 301 OnePointEngage, (XtPointer) BWDrawHotSpot, 302 OnePointTerminate, (XtPointer) BWDrawHotSpot, 303 NULL, (XtPointer) NULL}, 304 {ZoomInRequest, sizeof(BWStatus), 305 TwoPointsEngage, (XtPointer) BWDrawRectangle, 306 TwoPointsTerminate, (XtPointer) BWZoomIn, 307 NULL, (XtPointer) NULL}, 308 }; 309 310 static void ClassInitialize(void); 311 static void Initialize(Widget wrequest, Widget wnew, 312 ArgList argv, Cardinal *argc); 313 static void Redisplay(Widget w, XEvent *event, Region region); 314 static void Resize(Widget w); 315 static void Destroy(Widget w); 316 static void Refresh(BitmapWidget BW, Position x, Position y, 317 Dimension width, Dimension height); 318 static Boolean SetValues(Widget old, Widget request, Widget new, 319 ArgList args, Cardinal *num_args); 320 321 BitmapClassRec bitmapClassRec = { 322 { /* core fields */ 323 /* superclass */ (WidgetClass) &simpleClassRec, 324 /* class_name */ "Bitmap", 325 /* widget_size */ sizeof(BitmapRec), 326 /* class_initialize */ ClassInitialize, 327 /* class_part_initialize */ NULL, 328 /* class_inited */ FALSE, 329 /* initialize */ Initialize, 330 /* initialize_hook */ NULL, 331 /* realize */ XtInheritRealize, 332 /* actions */ actions, 333 /* num_actions */ XtNumber(actions), 334 /* resources */ resources, 335 /* num_resources */ XtNumber(resources), 336 /* xrm_class */ NULLQUARK, 337 /* compress_motion */ TRUE, 338 /* compress_exposure */ FALSE, 339 /* compress_enterleave */ TRUE, 340 /* visible_interest */ TRUE, 341 /* destroy */ Destroy, 342 /* resize */ Resize, 343 /* expose */ Redisplay, 344 /* set_values */ SetValues, 345 /* set_values_hook */ NULL, 346 /* set_values_almost */ XtInheritSetValuesAlmost, 347 /* get_values_hook */ NULL, 348 /* accept_focus */ NULL, 349 /* version */ XtVersion, 350 /* callback_private */ NULL, 351 /* tm_table */ NULL , /* set in code */ 352 /* query_geometry */ XtInheritQueryGeometry, 353 /* display_accelerator */ XtInheritDisplayAccelerator, 354 /* extension */ NULL, 355 }, 356 { 357 /* empty */ XtInheritChangeSensitive, 358 }, 359 { 360 /* targets */ targets, 361 /* num_trets */ XtNumber(targets), 362 /* requests */ requests, 363 /* num_requests */ XtNumber(requests), 364 } 365 }; 366 367 WidgetClass bitmapWidgetClass = (WidgetClass) &bitmapClassRec; 368 369 /* ARGSUSED */ 370 371 void 372 BWDebug(Widget w, XEvent *event, String *params, Cardinal *num_params) 373 { 374 DEBUG ^= True; 375 } 376 377 Pixmap 378 BWGetPixmap(Widget w) 379 { 380 BitmapWidget BW = (BitmapWidget) w; 381 382 return GetPixmap(BW, BW->bitmap.zoom.image); 383 } 384 385 Pixmap 386 BWGetUnzoomedPixmap(Widget w) 387 { 388 BitmapWidget BW = (BitmapWidget) w; 389 GC gc; 390 Pixmap pix; 391 392 if (BW->bitmap.zooming) { 393 pix = XCreatePixmap(XtDisplay(w), XtWindow(w), 394 BW->bitmap.zoom.image->width, 395 BW->bitmap.zoom.image->height, 1); 396 if (!(gc = XCreateGC(XtDisplay(w), pix, 397 (unsigned long) 0, (XGCValues *) 0))) { 398 XFreePixmap(XtDisplay(w), pix); 399 return (Pixmap) None; 400 } 401 402 XPutImage(XtDisplay(w), pix, gc, 403 BW->bitmap.zoom.image, 404 0, 0, 0, 0, 405 BW->bitmap.zoom.image->width, 406 BW->bitmap.zoom.image->height); 407 XPutImage(XtDisplay(w), pix, gc, 408 BW->bitmap.image, 409 0, 0, 410 BW->bitmap.zoom.at_x, 411 BW->bitmap.zoom.at_y, 412 BW->bitmap.image->width, 413 BW->bitmap.image->height); 414 } 415 else { 416 pix = XCreatePixmap(XtDisplay(w), XtWindow(w), 417 BW->bitmap.image->width, 418 BW->bitmap.image->height, 1); 419 if (! (gc = XCreateGC(XtDisplay(w), pix, 420 (unsigned long) 0, (XGCValues *) 0))){ 421 XFreePixmap(XtDisplay(w), pix); 422 return (Pixmap) None; 423 } 424 425 XPutImage(XtDisplay(w), pix, gc, 426 BW->bitmap.image, 427 0, 0, 0, 0, 428 BW->bitmap.image->width, 429 BW->bitmap.image->height); 430 } 431 XFreeGC(XtDisplay(w), gc); 432 return(pix); 433 } 434 435 436 XImage * 437 GetImage(BitmapWidget BW, Pixmap pixmap) 438 { 439 Window root; 440 int x, y; 441 unsigned int width, height, border_width, depth; 442 XImage *source, *image; 443 444 XGetGeometry(XtDisplay(BW), pixmap, &root, &x, &y, 445 &width, &height, &border_width, &depth); 446 447 source = XGetImage(XtDisplay(BW), pixmap, x, y, width, height, 448 1, XYPixmap); 449 450 image = ConvertToBitmapImage(BW, source); 451 452 return image; 453 } 454 455 XImage * 456 CreateBitmapImage(BitmapWidget BW, char *data, 457 Dimension width, Dimension height) 458 { 459 XImage *image = XCreateImage(XtDisplay(BW), 460 DefaultVisual(XtDisplay(BW), 461 DefaultScreen(XtDisplay(BW))), 462 1, XYBitmap, 0, 463 data, width, height, 464 8, ((int)width + 7) / 8); 465 466 image->height = height; 467 image->width = width; 468 image->depth = 1; 469 image->xoffset = 0; 470 image->format = XYBitmap; 471 image->data = (char *)data; 472 image->byte_order = LSBFirst; 473 image->bitmap_unit = 8; 474 image->bitmap_bit_order = LSBFirst; 475 image->bitmap_pad = 8; 476 image->bytes_per_line = ((int)width + 7) / 8; 477 478 return image; 479 } 480 481 void 482 DestroyBitmapImage(XImage **image) 483 { 484 /*XDestroyImage(*image);*/ 485 if (image) { 486 if (*image) { 487 if ((*image)->data) 488 XtFree((*image)->data); 489 XtFree((char *)*image); 490 } 491 *image = NULL; 492 } 493 } 494 495 #if 0 496 XImage * 497 BWGetImage(Widget w, XEvent *event, String *params, Cardinal *num_params) 498 { 499 BitmapWidget BW = (BitmapWidget) w; 500 501 return BW->bitmap.image; 502 } 503 #endif 504 505 void 506 BWChangeNotify(Widget w) 507 { 508 BitmapWidget BW = (BitmapWidget) w; 509 510 if (BW->bitmap.notify) 511 (*BW->bitmap.notify)(w, NULL, NULL, NULL); 512 } 513 514 void 515 BWNotify(Widget w, XtActionProc proc) 516 { 517 BitmapWidget BW = (BitmapWidget) w; 518 519 BW->bitmap.notify = proc; 520 } 521 522 void 523 BWSetChanged(Widget w) 524 { 525 BitmapWidget BW = (BitmapWidget) w; 526 527 BW->bitmap.changed = True; 528 } 529 530 Boolean 531 BWQueryChanged(Widget w) 532 { 533 BitmapWidget BW = (BitmapWidget) w; 534 535 return BW->bitmap.changed; 536 } 537 538 void 539 BWClearChanged(Widget w) 540 { 541 BitmapWidget BW = (BitmapWidget) w; 542 543 BW->bitmap.changed = False; 544 } 545 546 Boolean 547 BWQueryStored(Widget w) 548 { 549 BitmapWidget BW = (BitmapWidget) w; 550 551 return (BW->bitmap.storage != NULL); 552 } 553 554 Boolean 555 BWQueryStippled(Widget w) 556 { 557 BitmapWidget BW = (BitmapWidget) w; 558 559 return BW->bitmap.stippled; 560 } 561 562 static void 563 RedrawStippled(BitmapWidget BW) 564 { 565 XExposeEvent event; 566 567 event.type = Expose; 568 event.display = XtDisplay((Widget)BW); 569 event.window = XtWindow((Widget)BW); 570 event.x = 0; 571 event.y = 0; 572 event.width = BW->core.width; 573 event.height = BW->core.height; 574 event.count = 0; 575 576 BWRedrawMark((Widget)BW); 577 578 BW->bitmap.stipple_change_expose_event = True; 579 580 XtDispatchEvent((XEvent *)&event); 581 582 BW->bitmap.stipple_change_expose_event = False; 583 } 584 585 void 586 BWSwitchStippled(Widget w) 587 { 588 BitmapWidget BW = (BitmapWidget) w; 589 590 RedrawStippled(BW); 591 592 BW->bitmap.stippled ^= True; 593 XSetFillStyle(XtDisplay(BW), BW->bitmap.highlighting_gc, 594 (BW->bitmap.stippled ? FillStippled : FillSolid)); 595 596 RedrawStippled(BW); 597 } 598 599 void 600 BWSelect(Widget w, Position from_x, Position from_y, 601 Position to_x, Position to_y, Time btime) 602 { 603 BWMark(w, from_x, from_y, to_x, to_y); 604 605 BWGrabSelection(w, btime); 606 } 607 608 Boolean 609 BWQueryAxes(Widget w) 610 { 611 BitmapWidget BW = (BitmapWidget) w; 612 613 return BW->bitmap.axes; 614 } 615 616 void 617 BWSwitchAxes(Widget w) 618 { 619 BitmapWidget BW = (BitmapWidget) w; 620 621 BW->bitmap.axes ^= True; 622 BWHighlightAxes(w); 623 } 624 625 void 626 BWAxes(Widget w, Boolean _switch) 627 { 628 BitmapWidget BW = (BitmapWidget) w; 629 630 if (BW->bitmap.axes != _switch) 631 BWSwitchAxes(w); 632 } 633 634 void 635 BWRedrawAxes(Widget w) 636 { 637 BitmapWidget BW = (BitmapWidget) w; 638 639 if (BW->bitmap.axes) 640 BWHighlightAxes(w); 641 } 642 643 #if 0 644 void 645 BWPutImage(BitmapWidget w, Display *display, Drawable drawable, GC gc, 646 Position x, Position y) 647 { 648 BitmapWidget BW = (BitmapWidget) w; 649 650 XPutImage(display, drawable, gc, BW->bitmap.image, 651 0, 0, x, y, BW->bitmap.image->width, BW->bitmap.image->height); 652 } 653 #endif 654 655 static char * 656 StripFilename(_Xconst _XtString filename) 657 { 658 const char *begin = strrchr(filename, '/'); 659 const char *end; 660 char *result; 661 int length; 662 663 if (filename) { 664 begin = (begin ? begin + 1 : filename); 665 end = strchr(begin, '.'); /* change to strrchr to allow longer names */ 666 length = (end ? (end - begin) : strlen (begin)); 667 result = (char *) XtMalloc (length + 1); 668 strncpy (result, begin, length); 669 result [length] = '\0'; 670 return (result); 671 } 672 else 673 return (NULL); 674 } 675 676 static int 677 XmuWriteBitmapDataToFile(_Xconst _XtString filename, 678 _Xconst _XtString basename, 679 int width, int height, char *datap, 680 int x_hot, int y_hot) 681 { 682 FILE *file; 683 int i, data_length; 684 685 data_length = Length(width, height); 686 687 if(!filename || !strcmp(filename, "") || !strcmp(filename, "-")) { 688 file = stdout; 689 filename = "dummy"; 690 } 691 else 692 file = fopen(filename, "w+"); 693 694 if (file) { 695 char *new_basename; 696 697 if (!basename || !strcmp(basename, "") || !strcmp(basename, "-")) 698 basename = new_basename = StripFilename(filename); 699 else 700 new_basename = NULL; 701 702 fprintf(file, "#define %s_width %d\n", basename, width); 703 fprintf(file, "#define %s_height %d\n", basename, height); 704 if (QuerySet(x_hot, y_hot)) { 705 fprintf(file, "#define %s_x_hot %d\n", basename, x_hot); 706 fprintf(file, "#define %s_y_hot %d\n", basename, y_hot); 707 } 708 fprintf(file, "static unsigned char %s_bits[] = {\n 0x%02x", 709 basename, (unsigned char) datap[0]); 710 for(i = 1; i < data_length; i++) { 711 fprintf(file, ","); 712 fprintf(file, (i % 12) ? " " : "\n "); 713 fprintf(file, "0x%02x", (unsigned char) datap[i]); 714 } 715 fprintf(file, "};\n"); 716 717 if (file != stdout) 718 fclose(file); 719 720 XtFree(new_basename); 721 return BitmapSuccess; 722 } 723 724 return 1; 725 } 726 727 /* 728 * 729 */ 730 731 /* ARGSUSED */ 732 static void 733 CvtStringToButtonFunction(XrmValuePtr args, /* not used */ 734 Cardinal *num_args, /* not used */ 735 XrmValuePtr from_val, 736 XrmValuePtr to_val) 737 { 738 static int button_function; 739 char lower_name[80]; 740 741 XmuCopyISOLatin1Lowered (lower_name, (char*)from_val->addr); 742 743 if (!strcmp(lower_name, XtClear)) { 744 button_function = Clear; 745 to_val->addr = (XPointer) &button_function; 746 to_val->size = sizeof(button_function); 747 return; 748 } 749 750 if (!strcmp(lower_name, XtSet)) { 751 button_function = Set; 752 to_val->addr = (XPointer) &button_function; 753 to_val->size = sizeof(button_function); 754 return; 755 } 756 757 if (!strcmp(lower_name, XtInvert)) { 758 button_function = Invert; 759 to_val->addr = (XPointer) &button_function; 760 to_val->size = sizeof(button_function); 761 return; 762 } 763 764 XtStringConversionWarning(from_val->addr, XtRButtonFunction); 765 button_function = Clear; 766 to_val->addr = (XPointer) &button_function; 767 to_val->size = sizeof(button_function); 768 769 } 770 771 static void 772 ClassInitialize(void) 773 { 774 char *tm_table = XtMalloc(strlen(translations1) + strlen(translations2) + 1); 775 strcpy(tm_table, translations1); 776 strcat(tm_table, translations2); 777 bitmapClassRec.core_class.tm_table = tm_table; 778 779 XawInitializeWidgetSet(); 780 XtAddConverter(XtRString, XtRButtonFunction, CvtStringToButtonFunction, 781 NULL, 0); 782 DEBUG = False; 783 } 784 785 static void 786 SetSizeFromSizeResource(BitmapWidget bw) 787 { 788 if (BWParseSize(bw->bitmap.size, 789 &bw->bitmap.width, 790 &bw->bitmap.height) 791 == 792 False) { 793 bw->bitmap.width = FallbackBitmapWidth; 794 bw->bitmap.height = FallbackBitmapHeight; 795 XtWarning("Cannot parse the size resource. BitmapWidget"); 796 } 797 } 798 799 800 /* ARGSUSED */ 801 static void 802 Initialize(Widget wrequest, Widget wnew, ArgList argv, Cardinal *argc) 803 { 804 BitmapWidget new = (BitmapWidget) wnew; 805 806 XGCValues values; 807 XtGCMask mask; 808 char *image_data, *buffer_data; 809 810 new->bitmap.stipple_change_expose_event = False; 811 new->bitmap.notify = NULL; 812 new->bitmap.cardinal = 0; 813 new->bitmap.current = 0; 814 new->bitmap.fold = False; 815 new->bitmap.changed = False; 816 new->bitmap.zooming = False; 817 new->bitmap.selection.own = False; 818 new->bitmap.selection.limbo = False; 819 820 new->bitmap.request_stack = (BWRequestStack *) 821 XtMalloc(sizeof(BWRequestStack)); 822 823 new->bitmap.request_stack[0].request = NULL; 824 new->bitmap.request_stack[0].call_data = NULL; 825 new->bitmap.request_stack[0].trap = False; 826 827 SetSizeFromSizeResource(new); 828 829 new->core.width = new->bitmap.width * new->bitmap.squareW + 830 2 * new->bitmap.margin; 831 new->core.height = new->bitmap.height * new->bitmap.squareH + 832 2 * new->bitmap.margin; 833 834 new->bitmap.hot.x = new->bitmap.hot.y = NotSet; 835 new->bitmap.buffer_hot.x = new->bitmap.buffer_hot.y = NotSet; 836 837 new->bitmap.mark.from_x = new->bitmap.mark.from_y = NotSet; 838 new->bitmap.mark.to_x = new->bitmap.mark.to_y = NotSet; 839 new->bitmap.buffer_mark.from_x = new->bitmap.buffer_mark.from_y = NotSet; 840 new->bitmap.buffer_mark.to_x = new->bitmap.buffer_mark.to_y = NotSet; 841 842 values.foreground = new->bitmap.foreground_pixel; 843 values.background = new->core.background_pixel; 844 values.foreground ^= values.background; 845 values.function = GXxor; 846 mask = GCForeground | GCBackground | GCFunction; 847 new->bitmap.drawing_gc = XCreateGC(XtDisplay(new), 848 RootWindow(XtDisplay(new), 849 DefaultScreen(XtDisplay(new))), 850 mask, &values); 851 852 values.foreground = new->bitmap.highlight_pixel; 853 values.background = new->core.background_pixel; 854 values.foreground ^= values.background; 855 values.function = GXxor; 856 mask = GCForeground | GCBackground | GCFunction; 857 if (new->bitmap.stipple != XtUnspecifiedPixmap) 858 { 859 values.stipple = new->bitmap.stipple; 860 mask |= GCStipple | GCFillStyle; 861 } 862 values.fill_style = (new->bitmap.stippled ? FillStippled : FillSolid); 863 864 new->bitmap.highlighting_gc = XCreateGC(XtDisplay(new), 865 RootWindow(XtDisplay(new), 866 DefaultScreen(XtDisplay(new))), 867 mask, &values); 868 869 870 values.foreground = new->bitmap.frame_pixel; 871 values.background = new->core.background_pixel; 872 values.foreground ^= values.background; 873 mask = GCForeground | GCBackground | GCFunction; 874 if (new->bitmap.dashes != XtUnspecifiedPixmap) 875 { 876 values.stipple = new->bitmap.dashes; 877 mask |= GCStipple | GCFillStyle; 878 } 879 values.fill_style = (new->bitmap.dashed ? FillStippled : FillSolid); 880 881 new->bitmap.frame_gc = XCreateGC(XtDisplay(new), 882 RootWindow(XtDisplay(new), 883 DefaultScreen(XtDisplay(new))), 884 mask, &values); 885 886 values.foreground = new->bitmap.highlight_pixel; 887 values.background = new->core.background_pixel; 888 values.foreground ^= values.background; 889 mask = GCForeground | GCBackground | GCFunction; 890 new->bitmap.axes_gc = XCreateGC(XtDisplay(new), 891 RootWindow(XtDisplay(new), 892 DefaultScreen(XtDisplay(new))), 893 mask, &values); 894 895 image_data = CreateCleanData(Length(new->bitmap.width, 896 new->bitmap.height)); 897 buffer_data = CreateCleanData(Length(new->bitmap.width, 898 new->bitmap.height)); 899 900 new->bitmap.storage = NULL; 901 902 new->bitmap.image = CreateBitmapImage(new, 903 image_data, 904 new->bitmap.width, 905 new->bitmap.height); 906 new->bitmap.buffer = CreateBitmapImage(new, 907 buffer_data, 908 new->bitmap.width, 909 new->bitmap.height); 910 911 /* Read file */ 912 { 913 int status; 914 XImage *image, *buffer; 915 unsigned char *image_data2; 916 char *buffer_data2; 917 unsigned int width, height; 918 int x_hot, y_hot; 919 920 status = XmuReadBitmapDataFromFile(new->bitmap.filename, 921 &width, &height, &image_data2, 922 &x_hot, &y_hot); 923 if (status == BitmapSuccess) { 924 925 buffer_data2 = CreateCleanData(Length(width, height)); 926 927 image = CreateBitmapImage(new, (char *)image_data2, width, height); 928 buffer = CreateBitmapImage(new, buffer_data2, width, height); 929 930 TransferImageData(new->bitmap.image, buffer); 931 932 DestroyBitmapImage(&new->bitmap.image); 933 DestroyBitmapImage(&new->bitmap.buffer); 934 935 new->bitmap.image = image; 936 new->bitmap.buffer = buffer; 937 new->bitmap.width = width; 938 new->bitmap.height = height; 939 940 new->bitmap.hot.x = x_hot; 941 new->bitmap.hot.y = y_hot; 942 943 new->bitmap.changed = False; 944 new->bitmap.zooming = False; 945 } 946 947 new->bitmap.filename = XtNewString(new->bitmap.filename); 948 949 if (!strcmp(new->bitmap.basename, "")) { 950 new->bitmap.basename = StripFilename(new->bitmap.filename); 951 } 952 else 953 new->bitmap.basename = XtNewString(new->bitmap.basename); 954 } 955 956 Resize((Widget)new); 957 } 958 959 960 /* returns False if the format is wrong */ 961 Boolean 962 BWParseSize(String size, Dimension *width, Dimension *height) 963 { 964 int x, y; 965 unsigned int w, h; 966 int status; 967 968 status = XParseGeometry(size, &x, &y, &w, &h); 969 970 if (status & WidthValue) { 971 *width = (Dimension) w; 972 if (status & HeightValue) { 973 *height = (Dimension) h; 974 return True; 975 } 976 } 977 return False; 978 979 } 980 981 982 Boolean 983 BWQueryMarked(Widget w) 984 { 985 BitmapWidget BW = (BitmapWidget) w; 986 987 return QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y); 988 } 989 990 static void 991 FixMark(BitmapWidget BW) 992 { 993 if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 994 BW->bitmap.mark.from_x = min(BW->bitmap.mark.from_x, 995 BW->bitmap.image->width); 996 BW->bitmap.mark.from_y = min(BW->bitmap.mark.from_y, 997 BW->bitmap.image->height); 998 BW->bitmap.mark.to_x = min(BW->bitmap.mark.to_x, 999 BW->bitmap.image->width); 1000 BW->bitmap.mark.to_y = min(BW->bitmap.mark.to_y, 1001 BW->bitmap.image->height); 1002 1003 if((BW->bitmap.mark.from_x == BW->bitmap.mark.from_y) && 1004 (BW->bitmap.mark.to_x == BW->bitmap.mark.to_y)) 1005 BW->bitmap.mark.from_x = 1006 BW->bitmap.mark.from_y = 1007 BW->bitmap.mark.to_x = 1008 BW->bitmap.mark.to_y = NotSet; 1009 } 1010 } 1011 1012 /* ARGSUSED */ 1013 int 1014 BWStoreFile(Widget w, _Xconst _XtString filename, _Xconst _XtString *basename) 1015 { 1016 BitmapWidget BW = (BitmapWidget) w; 1017 int status; 1018 unsigned char *storage_data; 1019 unsigned int width, height; 1020 int x_hot, y_hot; 1021 1022 status = XmuReadBitmapDataFromFile(filename, &width, &height, 1023 &storage_data, &x_hot, &y_hot); 1024 if (status == BitmapSuccess) { 1025 1026 DestroyBitmapImage(&BW->bitmap.storage); 1027 1028 BW->bitmap.storage = CreateBitmapImage(BW, (char *)storage_data, width, height); 1029 1030 return BitmapSuccess; 1031 } 1032 else 1033 XtWarning(" read file failed. BitmapWidget"); 1034 1035 return status; 1036 } 1037 1038 String 1039 BWUnparseStatus(Widget w) 1040 { 1041 BitmapWidget BW = (BitmapWidget) w; 1042 1043 snprintf(BW->bitmap.status, sizeof(BW->bitmap.status), 1044 "Filename: %s Basename: %s Size: %dx%d", 1045 (strcmp(BW->bitmap.filename, "") ? BW->bitmap.filename : "<none>"), 1046 (strcmp(BW->bitmap.basename, "") ? BW->bitmap.basename : "<none>"), 1047 BW->bitmap.width, BW->bitmap.height); 1048 1049 return BW->bitmap.status; 1050 } 1051 1052 void 1053 BWChangeFilename(Widget w, _Xconst _XtString str) 1054 { 1055 BitmapWidget BW = (BitmapWidget) w; 1056 1057 if (str) { 1058 XtFree(BW->bitmap.filename); 1059 BW->bitmap.filename = XtNewString( str); 1060 } 1061 } 1062 1063 void 1064 BWChangeBasename(Widget w, _Xconst _XtString str) 1065 { 1066 BitmapWidget BW = (BitmapWidget) w; 1067 1068 if (str) { 1069 XtFree(BW->bitmap.basename); 1070 BW->bitmap.basename = XtNewString(str); 1071 } 1072 } 1073 1074 1075 int 1076 BWReadFile(Widget w, _Xconst _XtString filename, _Xconst _XtString basename) /* ARGSUSED */ 1077 { 1078 BitmapWidget BW = (BitmapWidget) w; 1079 int status; 1080 XImage *image, *buffer; 1081 unsigned char *image_data; 1082 char *buffer_data; 1083 unsigned int width, height; 1084 int x_hot, y_hot; 1085 1086 if (!filename) 1087 filename = BW->bitmap.filename; 1088 1089 status = XmuReadBitmapDataFromFile(filename, &width, &height, &image_data, 1090 &x_hot, &y_hot); 1091 if (status == BitmapSuccess) { 1092 1093 buffer_data = CreateCleanData(Length(width, height)); 1094 1095 image = CreateBitmapImage(BW, (char *)image_data, width, height); 1096 buffer = CreateBitmapImage(BW, buffer_data, width, height); 1097 1098 TransferImageData(BW->bitmap.image, buffer); 1099 1100 DestroyBitmapImage(&BW->bitmap.image); 1101 DestroyBitmapImage(&BW->bitmap.buffer); 1102 1103 BW->bitmap.image = image; 1104 BW->bitmap.buffer = buffer; 1105 BW->bitmap.width = width; 1106 BW->bitmap.height = height; 1107 1108 BW->bitmap.hot.x = x_hot; 1109 BW->bitmap.hot.y = y_hot; 1110 1111 BW->bitmap.changed = False; 1112 BW->bitmap.zooming = False; 1113 1114 XtFree(BW->bitmap.filename); 1115 BW->bitmap.filename = XtNewString(filename); 1116 XtFree(BW->bitmap.basename); 1117 BW->bitmap.basename = StripFilename(filename); 1118 1119 BWUnmark(w); 1120 1121 Resize((Widget)BW); 1122 1123 if (BW->core.visible) { 1124 XClearArea(XtDisplay(BW), XtWindow(BW), 1125 0, 0, 1126 BW->core.width, BW->core.height, 1127 True); 1128 } 1129 1130 return BitmapSuccess; 1131 } 1132 else 1133 XtWarning(" read file failed. BitmapWidget"); 1134 1135 return status; 1136 } 1137 1138 #if 0 1139 void 1140 BWSetImage(Widget w, XImage *image) 1141 { 1142 BitmapWidget BW = (BitmapWidget) w; 1143 XImage *buffer; 1144 char *buffer_data; 1145 1146 buffer_data = CreateCleanData(Length(image->width, image->height)); 1147 buffer = CreateBitmapImage(BW, buffer_data, 1148 (Dimension) image->width, 1149 (Dimension) image->height); 1150 1151 TransferImageData(BW->bitmap.image, buffer); 1152 1153 DestroyBitmapImage(&BW->bitmap.image); 1154 DestroyBitmapImage(&BW->bitmap.buffer); 1155 1156 BW->bitmap.image = image; 1157 BW->bitmap.buffer = buffer; 1158 BW->bitmap.width = image->width; 1159 BW->bitmap.height = image->height; 1160 1161 Resize((Widget)BW); 1162 1163 if (BW->core.visible) { 1164 XClearArea(XtDisplay(BW), XtWindow(BW), 1165 0, 0, 1166 BW->core.width, BW->core.height, 1167 True); 1168 } 1169 } 1170 #endif 1171 1172 int 1173 BWWriteFile(Widget w, _Xconst _XtString filename, _Xconst _XtString basename) 1174 { 1175 BitmapWidget BW = (BitmapWidget) w; 1176 char *data; 1177 XImage *image; 1178 XPoint hot; 1179 int status; 1180 1181 if (BW->bitmap.zooming) { 1182 data = XtMalloc(Length(BW->bitmap.zoom.image->width, 1183 BW->bitmap.zoom.image->height)); 1184 memmove( data, BW->bitmap.zoom.image->data, 1185 Length(BW->bitmap.zoom.image->width, 1186 BW->bitmap.zoom.image->height)); 1187 image = CreateBitmapImage(BW, data, 1188 (Dimension) BW->bitmap.zoom.image->width, 1189 (Dimension) BW->bitmap.zoom.image->height); 1190 CopyImageData(BW->bitmap.image, image, 1191 0, 0, 1192 BW->bitmap.image->width - 1, 1193 BW->bitmap.image->height - 1, 1194 BW->bitmap.zoom.at_x, BW->bitmap.zoom.at_y); 1195 1196 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) { 1197 hot.x = BW->bitmap.hot.x + BW->bitmap.zoom.at_x; 1198 hot.y = BW->bitmap.hot.y + BW->bitmap.zoom.at_y; 1199 } 1200 else 1201 hot = BW->bitmap.zoom.hot; 1202 } 1203 else { 1204 image = BW->bitmap.image; 1205 hot = BW->bitmap.hot; 1206 } 1207 1208 if (!filename) filename = BW->bitmap.filename; 1209 else { 1210 XtFree(BW->bitmap.filename); 1211 BW->bitmap.filename = XtNewString(filename); 1212 XtFree(BW->bitmap.basename); 1213 BW->bitmap.basename = StripFilename(filename); 1214 } 1215 if (!basename) basename = BW->bitmap.basename; 1216 else { 1217 XtFree(BW->bitmap.basename); 1218 BW->bitmap.basename = XtNewString(basename); 1219 } 1220 1221 if (DEBUG) 1222 fprintf(stderr, "Saving filename: %s %s\n", filename, basename); 1223 1224 status = XmuWriteBitmapDataToFile(filename, basename, 1225 image->width, image->height, image->data, 1226 hot.x, hot.y); 1227 if (BW->bitmap.zooming) 1228 DestroyBitmapImage(&image); 1229 1230 if (status == BitmapSuccess) 1231 BW->bitmap.changed = False; 1232 1233 return status; 1234 } 1235 1236 _XtString 1237 BWGetFilename(Widget w, _XtString *str) 1238 { 1239 BitmapWidget BW = (BitmapWidget) w; 1240 1241 *str = XtNewString(BW->bitmap.filename); 1242 1243 return *str; 1244 } 1245 1246 _XtString 1247 BWGetFilepath(Widget w, _XtString *str) 1248 { 1249 BitmapWidget BW = (BitmapWidget) w; 1250 _XtString end; 1251 1252 *str = XtNewString(BW->bitmap.filename); 1253 assert(*str); 1254 1255 end = strrchr(*str, '/'); 1256 1257 if (end) 1258 *(end + 1) = '\0'; 1259 else 1260 **str = '\0'; 1261 1262 return *str; 1263 } 1264 1265 1266 _XtString 1267 BWGetBasename(Widget w, _XtString *str) 1268 { 1269 BitmapWidget BW = (BitmapWidget) w; 1270 1271 *str = XtNewString(BW->bitmap.basename); 1272 1273 return *str; 1274 } 1275 1276 static void 1277 FixHotSpot(BitmapWidget BW) 1278 { 1279 if (!QueryInBitmap(BW, BW->bitmap.hot.x, BW->bitmap.hot.y)) 1280 BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet; 1281 } 1282 1283 static void 1284 ZoomOut(BitmapWidget BW) 1285 { 1286 CopyImageData(BW->bitmap.image, BW->bitmap.zoom.image, 1287 0, 0, 1288 BW->bitmap.image->width - 1, 1289 BW->bitmap.image->height - 1, 1290 BW->bitmap.zoom.at_x, BW->bitmap.zoom.at_y); 1291 1292 DestroyBitmapImage(&BW->bitmap.image); 1293 DestroyBitmapImage(&BW->bitmap.buffer); 1294 1295 BW->bitmap.image = BW->bitmap.zoom.image; 1296 BW->bitmap.buffer = BW->bitmap.zoom.buffer; 1297 BW->bitmap.width = BW->bitmap.image->width; 1298 BW->bitmap.height = BW->bitmap.image->height; 1299 BW->bitmap.fold = BW->bitmap.zoom.fold; 1300 BW->bitmap.changed |= BW->bitmap.zoom.changed; 1301 BW->bitmap.grid = BW->bitmap.zoom.grid; 1302 1303 if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) { 1304 BW->bitmap.hot.x += BW->bitmap.zoom.at_x; 1305 BW->bitmap.hot.y += BW->bitmap.zoom.at_y; 1306 } 1307 else 1308 BW->bitmap.hot = BW->bitmap.zoom.hot; 1309 1310 BW->bitmap.mark.from_x = NotSet; 1311 BW->bitmap.mark.from_y = NotSet; 1312 BW->bitmap.mark.to_x = NotSet; 1313 BW->bitmap.mark.to_y = NotSet; 1314 BW->bitmap.zooming = False; 1315 } 1316 1317 void 1318 BWZoomOut(Widget w) 1319 { 1320 BitmapWidget BW = (BitmapWidget) w; 1321 1322 if (BW->bitmap.zooming) { 1323 ZoomOut(BW); 1324 1325 Resize((Widget)BW); 1326 if (BW->core.visible) 1327 XClearArea(XtDisplay(BW), XtWindow(BW), 1328 0, 0, 1329 BW->core.width, BW->core.height, 1330 True); 1331 } 1332 } 1333 1334 1335 void 1336 BWZoomMarked(Widget w) 1337 { 1338 BitmapWidget BW = (BitmapWidget) w; 1339 1340 BWZoomIn(w, 1341 BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1342 BW->bitmap.mark.to_x, BW->bitmap.mark.to_y); 1343 } 1344 1345 void 1346 BWZoomIn(Widget w, 1347 Position from_x, Position from_y, 1348 Position to_x, Position to_y) 1349 { 1350 BitmapWidget BW = (BitmapWidget) w; 1351 XImage *image, *buffer; 1352 Dimension width, height; 1353 char *image_data, *buffer_data; 1354 1355 if (BW->bitmap.zooming) 1356 ZoomOut(BW); 1357 1358 QuerySwap(from_x, to_x); 1359 QuerySwap(from_y, to_y); 1360 from_x = max(0, from_x); 1361 from_y = max(0, from_y); 1362 to_x = min(BW->bitmap.width - 1, to_x); 1363 to_y = min(BW->bitmap.height - 1, to_y); 1364 1365 width = to_x - from_x + 1; 1366 height = to_y - from_y + 1; 1367 1368 image_data = CreateCleanData(Length(width, height)); 1369 buffer_data = CreateCleanData(Length(width, height)); 1370 1371 image = CreateBitmapImage(BW, image_data, width, height); 1372 buffer = CreateBitmapImage(BW, buffer_data, width, height); 1373 1374 CopyImageData(BW->bitmap.image, image, from_x, from_y, to_x, to_y, 0, 0); 1375 CopyImageData(BW->bitmap.buffer, buffer, from_x, from_y, to_x, to_y, 0, 0); 1376 1377 BW->bitmap.zoom.image = BW->bitmap.image; 1378 BW->bitmap.zoom.buffer = BW->bitmap.buffer; 1379 BW->bitmap.zoom.at_x = from_x; 1380 BW->bitmap.zoom.at_y = from_y; 1381 BW->bitmap.zoom.fold = BW->bitmap.fold; 1382 BW->bitmap.zoom.changed = BW->bitmap.changed; 1383 BW->bitmap.zoom.hot = BW->bitmap.hot; 1384 BW->bitmap.zoom.grid = BW->bitmap.grid; 1385 1386 BW->bitmap.image = image; 1387 BW->bitmap.buffer = buffer; 1388 BW->bitmap.width = width; 1389 BW->bitmap.height = height; 1390 BW->bitmap.changed = False; 1391 BW->bitmap.hot.x -= from_x; 1392 BW->bitmap.hot.y -= from_y; 1393 BW->bitmap.mark.from_x = NotSet; 1394 BW->bitmap.mark.from_y = NotSet; 1395 BW->bitmap.mark.to_x = NotSet; 1396 BW->bitmap.mark.to_y = NotSet; 1397 BW->bitmap.zooming = True; 1398 BW->bitmap.grid = True; /* potentially true, could use a resource here */ 1399 1400 FixHotSpot(BW); 1401 1402 Resize((Widget)BW); 1403 if (BW->core.visible) 1404 XClearArea(XtDisplay(BW), XtWindow(BW), 1405 0, 0, 1406 BW->core.width, BW->core.height, 1407 True); 1408 } 1409 1410 1411 void 1412 BWRescale(Widget w, Dimension width, Dimension height) 1413 { 1414 BitmapWidget BW = (BitmapWidget) w; 1415 XImage *image, *buffer; 1416 char *buffer_data; 1417 1418 if (BW->bitmap.zooming) 1419 ZoomOut(BW); 1420 1421 image = ScaleBitmapImage(BW, BW->bitmap.image, 1422 (double) width / (double) BW->bitmap.image->width, 1423 (double) height / (double) BW->bitmap.image->height); 1424 1425 buffer_data = CreateCleanData(Length(image->width, image->height)); 1426 buffer = CreateBitmapImage(BW, buffer_data, 1427 (Dimension) image->width, 1428 (Dimension) image->height); 1429 1430 TransferImageData(BW->bitmap.buffer, buffer); 1431 1432 DestroyBitmapImage(&BW->bitmap.image); 1433 DestroyBitmapImage(&BW->bitmap.buffer); 1434 1435 BW->bitmap.image = image; 1436 BW->bitmap.buffer = buffer; 1437 BW->bitmap.width = image->width; 1438 BW->bitmap.height = image->height; 1439 1440 FixHotSpot(BW); 1441 FixMark(BW); 1442 1443 Resize((Widget)BW); 1444 if (BW->core.visible) 1445 XClearArea(XtDisplay(BW), XtWindow(BW), 1446 0, 0, 1447 BW->core.width, BW->core.height, 1448 True); 1449 } 1450 1451 Boolean 1452 BWQueryZooming(Widget w) 1453 { 1454 BitmapWidget BW = (BitmapWidget) w; 1455 1456 return BW->bitmap.zooming; 1457 } 1458 1459 1460 static void 1461 ResizeGrid(BitmapWidget BW, Dimension width, Dimension height) 1462 { 1463 XImage *image, *buffer; 1464 char *image_data, *buffer_data; 1465 1466 if (BW->bitmap.zooming) 1467 ZoomOut(BW); 1468 1469 image_data = CreateCleanData(Length(width, height)); 1470 buffer_data = CreateCleanData(Length(width, height)); 1471 1472 image = CreateBitmapImage(BW, image_data, width, height); 1473 buffer = CreateBitmapImage(BW, buffer_data, width, height); 1474 1475 TransferImageData(BW->bitmap.image, image); 1476 TransferImageData(BW->bitmap.buffer, buffer); 1477 1478 DestroyBitmapImage(&BW->bitmap.image); 1479 DestroyBitmapImage(&BW->bitmap.buffer); 1480 1481 BW->bitmap.image = image; 1482 BW->bitmap.buffer = buffer; 1483 BW->bitmap.width = width; 1484 BW->bitmap.height = height; 1485 1486 FixHotSpot(BW); 1487 FixMark(BW); 1488 } 1489 1490 void 1491 BWResize(Widget w, Dimension width, Dimension height) 1492 { 1493 BitmapWidget BW = (BitmapWidget) w; 1494 1495 ResizeGrid(BW, width, height); 1496 1497 Resize((Widget)BW); 1498 if (BW->core.visible) 1499 XClearArea(XtDisplay(BW), XtWindow(BW), 1500 0, 0, 1501 BW->core.width, BW->core.height, 1502 True); 1503 } 1504 1505 static void 1506 Destroy(Widget w) 1507 { 1508 BitmapWidget BW = (BitmapWidget) w; 1509 1510 XFreeGC(XtDisplay(w), BW->bitmap.drawing_gc); 1511 XFreeGC(XtDisplay(w), BW->bitmap.highlighting_gc); 1512 XFreeGC(XtDisplay(w), BW->bitmap.frame_gc); 1513 XFreeGC(XtDisplay(w), BW->bitmap.axes_gc); 1514 BWRemoveAllRequests(w); 1515 1516 XtFree(BW->bitmap.filename); 1517 XtFree(BW->bitmap.basename); 1518 } 1519 1520 1521 static void 1522 Resize(Widget w) 1523 { 1524 BitmapWidget BW = (BitmapWidget) w; 1525 1526 Dimension squareW, squareH; 1527 1528 squareW = max(1, ((int)BW->core.width - 2 * (int)BW->bitmap.margin) / 1529 (int)BW->bitmap.width); 1530 squareH = max(1, ((int)BW->core.height - 2 * (int)BW->bitmap.margin) / 1531 (int)BW->bitmap.height); 1532 1533 if (BW->bitmap.proportional) 1534 BW->bitmap.squareW = BW->bitmap.squareH = min(squareW, squareH); 1535 else { 1536 BW->bitmap.squareW = squareW; 1537 BW->bitmap.squareH = squareH; 1538 } 1539 1540 BW->bitmap.horizOffset = max((Position)BW->bitmap.margin, 1541 (Position)(BW->core.width - 1542 BW->bitmap.width * 1543 BW->bitmap.squareW) / 2); 1544 BW->bitmap.vertOffset = max((Position)BW->bitmap.margin, 1545 (Position)(BW->core.height - 1546 BW->bitmap.height * 1547 BW->bitmap.squareH) / 2); 1548 1549 BW->bitmap.grid &= ((BW->bitmap.squareW > BW->bitmap.grid_tolerance) && 1550 (BW->bitmap.squareH > BW->bitmap.grid_tolerance)); 1551 } 1552 1553 /* ARGSUSED */ 1554 static void 1555 Redisplay(Widget w, XEvent *event, Region region) 1556 { 1557 BitmapWidget BW = (BitmapWidget) w; 1558 1559 if(event->type == Expose 1560 && 1561 BW->core.visible) 1562 if (BW->bitmap.stipple_change_expose_event == False) 1563 Refresh(BW, 1564 event->xexpose.x, event->xexpose.y, 1565 event->xexpose.width, event->xexpose.height); 1566 } 1567 1568 void 1569 BWClip(Widget w, Position x, Position y, Dimension width, Dimension height) 1570 { 1571 Position from_x, from_y, 1572 to_x, to_y; 1573 BitmapWidget BW = (BitmapWidget) w; 1574 XRectangle rectangle; 1575 1576 from_x = InBitmapX(BW, x); 1577 from_y = InBitmapY(BW, y); 1578 to_x = InBitmapX(BW, x + width); 1579 to_y = InBitmapY(BW, y + height); 1580 QuerySwap(from_x, to_x); 1581 QuerySwap(from_y, to_y); 1582 from_x = max(0, from_x); 1583 from_y = max(0, from_y); 1584 to_x = min(BW->bitmap.width - 1, to_x); 1585 to_y = min(BW->bitmap.height - 1, to_y); 1586 1587 rectangle.x = InWindowX(BW, from_x); 1588 rectangle.y = InWindowY(BW, from_y); 1589 rectangle.width = InWindowX(BW, to_x + 1) - InWindowX(BW, from_x); 1590 rectangle.height = InWindowY(BW, to_y + 1) - InWindowY(BW, from_y); 1591 XSetClipRectangles(XtDisplay(BW), 1592 BW->bitmap.highlighting_gc, 1593 0, 0, 1594 &rectangle, 1, 1595 Unsorted); 1596 XSetClipRectangles(XtDisplay(BW), 1597 BW->bitmap.drawing_gc, 1598 0, 0, 1599 &rectangle, 1, 1600 Unsorted); 1601 XSetClipRectangles(XtDisplay(BW), 1602 BW->bitmap.frame_gc, 1603 0, 0, 1604 &rectangle, 1, 1605 Unsorted); 1606 XSetClipRectangles(XtDisplay(BW), 1607 BW->bitmap.axes_gc, 1608 0, 0, 1609 &rectangle, 1, 1610 Unsorted); 1611 } 1612 1613 void 1614 BWUnclip(Widget w) 1615 { 1616 BitmapWidget BW = (BitmapWidget) w; 1617 XRectangle rectangle; 1618 1619 rectangle.x = InWindowX(BW, 0); 1620 rectangle.y = InWindowY(BW, 0); 1621 rectangle.width = InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0); 1622 rectangle.height = InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0); 1623 XSetClipRectangles(XtDisplay(BW), 1624 BW->bitmap.highlighting_gc, 1625 0, 0, 1626 &rectangle, 1, 1627 Unsorted); 1628 XSetClipRectangles(XtDisplay(BW), 1629 BW->bitmap.drawing_gc, 1630 0, 0, 1631 &rectangle, 1, 1632 Unsorted); 1633 XSetClipRectangles(XtDisplay(BW), 1634 BW->bitmap.frame_gc, 1635 0, 0, 1636 &rectangle, 1, 1637 Unsorted); 1638 XSetClipRectangles(XtDisplay(BW), 1639 BW->bitmap.axes_gc, 1640 0, 0, 1641 &rectangle, 1, 1642 Unsorted); 1643 } 1644 1645 static void 1646 Refresh(BitmapWidget BW, Position x, Position y, 1647 Dimension width, Dimension height) 1648 { 1649 XRectangle rectangle; 1650 1651 rectangle.x = min(x, InWindowX(BW, InBitmapX(BW, x))); 1652 rectangle.y = min(y, InWindowY(BW, InBitmapY(BW, y))); 1653 rectangle.width = max(x + width, 1654 InWindowX(BW, InBitmapX(BW, x + width)+1)) - rectangle.x; 1655 rectangle.height = max(y + height, 1656 InWindowY(BW, InBitmapY(BW, y + height)+1)) - rectangle.y; 1657 1658 XClearArea(XtDisplay(BW), XtWindow(BW), 1659 rectangle.x, rectangle.y, 1660 rectangle.width, rectangle.height, 1661 False); 1662 1663 XSetClipRectangles(XtDisplay(BW), 1664 BW->bitmap.frame_gc, 1665 0, 0, 1666 &rectangle, 1, 1667 Unsorted); 1668 1669 XDrawRectangle(XtDisplay(BW), XtWindow(BW), 1670 BW->bitmap.frame_gc, 1671 InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1, 1672 InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1, 1673 InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1); 1674 1675 BWClip((Widget) BW, x, y, width, height); 1676 1677 BWRedrawGrid((Widget) BW, x, y, width, height); 1678 1679 BWRedrawSquares((Widget) BW, x, y, width, height); 1680 1681 BWRedrawMark((Widget) BW); 1682 BWRedrawHotSpot((Widget) BW); 1683 BWRedrawAxes((Widget) BW); 1684 BWUnclip((Widget) BW); 1685 } 1686 1687 Boolean 1688 BWQueryGrid(Widget w) 1689 { 1690 BitmapWidget BW = (BitmapWidget) w; 1691 1692 return BW->bitmap.grid; 1693 } 1694 1695 void 1696 BWSwitchGrid(Widget w) 1697 { 1698 BitmapWidget BW = (BitmapWidget) w; 1699 BW->bitmap.grid ^= TRUE; 1700 BWDrawGrid(w, 1701 0, 0, 1702 BW->bitmap.image->width - 1, BW->bitmap.image->height - 1); 1703 } 1704 1705 void 1706 BWGrid(Widget w, Boolean _switch) 1707 { 1708 BitmapWidget BW = (BitmapWidget) w; 1709 1710 if (BW->bitmap.grid != _switch) 1711 BWSwitchGrid(w); 1712 } 1713 1714 Boolean 1715 BWQueryDashed(Widget w) 1716 { 1717 BitmapWidget BW = (BitmapWidget) w; 1718 1719 return (BW->bitmap.dashed); 1720 } 1721 1722 void 1723 BWSwitchDashed(Widget w) 1724 { 1725 BitmapWidget BW = (BitmapWidget) w; 1726 XRectangle rectangle; 1727 1728 BWRedrawGrid(w, 0, 0, BW->bitmap.width - 1, BW->bitmap.height - 1); 1729 1730 rectangle.x = 0; 1731 rectangle.y = 0; 1732 rectangle.width = BW->core.width; 1733 rectangle.height = BW->core.height; 1734 1735 XSetClipRectangles(XtDisplay(BW), 1736 BW->bitmap.frame_gc, 1737 0, 0, 1738 &rectangle, 1, 1739 Unsorted); 1740 1741 XDrawRectangle(XtDisplay(BW), XtWindow(BW), 1742 BW->bitmap.frame_gc, 1743 InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1, 1744 InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1, 1745 InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1); 1746 1747 BW->bitmap.dashed ^= True; 1748 XSetFillStyle(XtDisplay(BW), BW->bitmap.frame_gc, 1749 (BW->bitmap.dashed ? FillStippled : FillSolid)); 1750 1751 XDrawRectangle(XtDisplay(BW), XtWindow(BW), 1752 BW->bitmap.frame_gc, 1753 InWindowX(BW, 0) - 1, InWindowY(BW, 0) - 1, 1754 InWindowX(BW, BW->bitmap.width) - InWindowX(BW, 0) + 1, 1755 InWindowY(BW, BW->bitmap.height) - InWindowY(BW, 0) + 1); 1756 1757 BWUnclip(w); 1758 1759 BWRedrawGrid(w, 0, 0, BW->bitmap.width - 1, BW->bitmap.height - 1); 1760 } 1761 1762 void 1763 BWDashed(Widget w, Boolean _switch) 1764 { 1765 BitmapWidget BW = (BitmapWidget) w; 1766 1767 if (BW->bitmap.dashed != _switch) 1768 BWSwitchDashed(w); 1769 } 1770 1771 static Boolean 1772 SetValues(Widget old, Widget request, Widget new, 1773 ArgList args, Cardinal *num_args) /* ARGSUSED */ 1774 { 1775 BitmapWidget oldbw = (BitmapWidget) old; 1776 BitmapWidget newbw = (BitmapWidget) new; 1777 Boolean resize = False; 1778 Boolean redisplay = False; 1779 1780 #define NE(field) (oldbw->field != newbw->field) 1781 1782 if (NE(bitmap.grid)) 1783 BWSwitchGrid(old); 1784 1785 if (NE(bitmap.dashed)) 1786 BWSwitchDashed(old); 1787 1788 if (NE(bitmap.axes)) 1789 BWSwitchAxes(old); 1790 1791 if (NE(bitmap.stippled)) 1792 BWSwitchStippled(old); 1793 1794 if (NE(bitmap.proportional)) 1795 resize = True; 1796 1797 if (NE(bitmap.filename) || NE(bitmap.basename) || NE(bitmap.size)) 1798 BWChangeNotify(old); 1799 1800 if (NE(bitmap.filename)) { 1801 if (newbw->bitmap.filename) { 1802 XtFree(oldbw->bitmap.filename); 1803 newbw->bitmap.filename = XtNewString(newbw->bitmap.filename); 1804 } 1805 else 1806 newbw->bitmap.filename = oldbw->bitmap.filename; 1807 } 1808 1809 if (NE(bitmap.basename)) { 1810 if (newbw->bitmap.basename) { 1811 XtFree(oldbw->bitmap.basename); 1812 newbw->bitmap.basename = XtNewString(newbw->bitmap.basename); 1813 } 1814 else 1815 newbw->bitmap.basename = oldbw->bitmap.basename; 1816 } 1817 1818 if (NE(bitmap.size)) { 1819 Dimension width, height; 1820 1821 if (BWParseSize(newbw->bitmap.size, &width, &height)) { 1822 ResizeGrid(newbw, width, height); 1823 resize = True; 1824 } 1825 } 1826 1827 if (NE(bitmap.margin) || 1828 NE(bitmap.grid_tolerance) || 1829 NE(bitmap.squareW) || 1830 NE(bitmap.squareH) || 1831 NE(core.height) || 1832 NE(core.width)) 1833 resize = True; 1834 1835 if (NE(bitmap.hot.x) || NE(bitmap.hot.y)) 1836 BWSetHotSpot(old, newbw->bitmap.hot.x, newbw->bitmap.hot.y); 1837 1838 if (NE(bitmap.foreground_pixel) || NE(core.background_pixel)) { 1839 XSetForeground(XtDisplay(new), 1840 newbw->bitmap.drawing_gc, 1841 newbw->bitmap.foreground_pixel 1842 ^ 1843 newbw->core.background_pixel); 1844 redisplay = True; 1845 } 1846 1847 if (NE(bitmap.frame_pixel) || NE(core.background_pixel)) { 1848 XSetForeground(XtDisplay(new), 1849 newbw->bitmap.frame_gc, 1850 newbw->bitmap.frame_pixel 1851 ^ 1852 newbw->core.background_pixel); 1853 redisplay = True; 1854 } 1855 1856 if (NE(bitmap.dashes)) { 1857 XSetStipple(XtDisplay(new), 1858 newbw->bitmap.frame_gc, 1859 newbw->bitmap.dashes); 1860 redisplay = True; 1861 } 1862 1863 if (NE(bitmap.highlight_pixel) || NE(core.background_pixel)) { 1864 RedrawStippled(newbw); 1865 XSetForeground(XtDisplay(new), 1866 newbw->bitmap.highlighting_gc, 1867 newbw->bitmap.highlight_pixel 1868 ^ 1869 newbw->core.background_pixel); 1870 RedrawStippled(newbw); 1871 } 1872 1873 if (NE(bitmap.stipple)) { 1874 RedrawStippled(newbw); 1875 XSetStipple(XtDisplay(new), 1876 newbw->bitmap.highlighting_gc, 1877 newbw->bitmap.stipple); 1878 RedrawStippled(newbw); 1879 } 1880 1881 if (resize) Resize((Widget)newbw); 1882 1883 return (redisplay || resize); 1884 1885 #undef NE 1886 } 1887 1888 Boolean 1889 BWQueryProportional(Widget w) 1890 { 1891 BitmapWidget BW = (BitmapWidget) w; 1892 1893 return (BW->bitmap.proportional); 1894 } 1895 1896 void 1897 BWSwitchProportional(Widget w) 1898 { 1899 BitmapWidget BW = (BitmapWidget) w; 1900 1901 BW->bitmap.proportional ^= True; 1902 1903 Resize((Widget)BW); 1904 if (BW->core.visible) 1905 XClearArea(XtDisplay(BW), XtWindow(BW), 1906 0, 0, 1907 BW->core.width, BW->core.height, 1908 True); 1909 } 1910 1911 #if 0 1912 void 1913 BWProportional(Widget w, Boolean _switch) 1914 { 1915 BitmapWidget BW = (BitmapWidget) w; 1916 1917 if (BW->bitmap.proportional != _switch) 1918 BWSwitchProportional(w); 1919 } 1920 #endif 1921 1922 void 1923 BWTPaste(Widget w, XEvent *event, String *params, Cardinal *num_params) 1924 { 1925 BitmapWidget BW = (BitmapWidget) w; 1926 1927 BWRequestSelection(w, event->xbutton.time, TRUE); 1928 1929 if (!BWQueryStored(w)) 1930 return; 1931 1932 BWEngageRequest(w, RestoreRequest, False, 1933 (char *)&(event->xbutton.state), sizeof(int)); 1934 1935 OnePointHandler(w, 1936 (BWStatus*) BW->bitmap.request_stack[BW->bitmap.current].status, 1937 event, NULL); 1938 } 1939 1940 void 1941 BWTMark(Widget w, XEvent *event, String *params, Cardinal *num_params) 1942 { 1943 BitmapWidget BW = (BitmapWidget) w; 1944 1945 BWEngageRequest(w, MarkRequest, False, 1946 (char *)&(event->xbutton.state), sizeof(int)); 1947 TwoPointsHandler(w, 1948 (BWStatus*) BW->bitmap.request_stack[BW->bitmap.current].status, 1949 event, NULL); 1950 1951 } 1952 1953 void 1954 BWTMarkAll(Widget w, XEvent *event, String *params, Cardinal *num_params) 1955 { 1956 BWMarkAll(w); 1957 1958 BWGrabSelection(w, event->xkey.time); 1959 } 1960 1961 void 1962 BWTUnmark(Widget w, XEvent *event, String *params, Cardinal *num_params) 1963 { 1964 BWUnmark(w); 1965 } 1966 1967 /*****************************************************************************/ 1968