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