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