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