widget.c revision cbda611068350bf4459f2dda1951f8823702e129
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% % 7% W W IIIII DDDD GGGG EEEEE TTTTT % 8% W W I D D G E T % 9% W W W I D D G GG EEE T % 10% WW WW I D D G G E T % 11% W W IIIII DDDD GGGG EEEEE T % 12% % 13% % 14% MagickCore X11 User Interface Methods % 15% % 16% Software Design % 17% John Cristy % 18% September 1993 % 19% % 20% % 21% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 22% dedicated to making software imaging solutions freely available. % 23% % 24% You may not use this file except in compliance with the License. You may % 25% obtain a copy of the License at % 26% % 27% http://www.imagemagick.org/script/license.php % 28% % 29% Unless required by applicable law or agreed to in writing, software % 30% distributed under the License is distributed on an "AS IS" BASIS, % 31% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 32% See the License for the specific language governing permissions and % 33% limitations under the License. % 34% % 35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36% 37% 38*/ 39 40/* 41 Include declarations. 42*/ 43#include "MagickCore/studio.h" 44#include "MagickCore/color.h" 45#include "MagickCore/color-private.h" 46#include "MagickCore/exception.h" 47#include "MagickCore/exception-private.h" 48#include "MagickCore/image.h" 49#include "MagickCore/magick.h" 50#include "MagickCore/memory_.h" 51#include "MagickCore/PreRvIcccm.h" 52#include "MagickCore/string_.h" 53#include "MagickCore/token.h" 54#include "MagickCore/token-private.h" 55#include "MagickCore/utility.h" 56#include "MagickCore/utility-private.h" 57#include "MagickCore/xwindow-private.h" 58#include "MagickCore/widget.h" 59#include "MagickCore/widget-private.h" 60 61#if defined(MAGICKCORE_X11_DELEGATE) 62 63/* 64 Define declarations. 65*/ 66#define AreaIsActive(matte_info,position) ( \ 67 ((position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \ 68 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \ 69 ? MagickTrue : MagickFalse) 70#define Extent(s) ((int) strlen(s)) 71#define MatteIsActive(matte_info,position) ( \ 72 ((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \ 73 (position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \ 74 (position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) && \ 75 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \ 76 ? MagickTrue : MagickFalse) 77#define MaxTextWidth ((unsigned int) (255*XTextWidth(font_info,"_",1))) 78#define MinTextWidth (26*XTextWidth(font_info,"_",1)) 79#define QuantumMargin MagickMax(font_info->max_bounds.width,12) 80#define WidgetTextWidth(font_info,text) \ 81 ((unsigned int) XTextWidth(font_info,text,Extent(text))) 82#define WindowIsActive(window_info,position) ( \ 83 ((position.x >= 0) && (position.y >= 0) && \ 84 (position.x < (int) window_info.width) && \ 85 (position.y < (int) window_info.height)) ? MagickTrue : MagickFalse) 86 87/* 88 Enum declarations. 89*/ 90typedef enum 91{ 92 ControlState = 0x0001, 93 InactiveWidgetState = 0x0004, 94 JumpListState = 0x0008, 95 RedrawActionState = 0x0010, 96 RedrawListState = 0x0020, 97 RedrawWidgetState = 0x0040, 98 UpdateListState = 0x0100 99} WidgetState; 100 101/* 102 Typedef declarations. 103*/ 104typedef struct _XWidgetInfo 105{ 106 char 107 *cursor, 108 *text, 109 *marker; 110 111 int 112 id; 113 114 unsigned int 115 bevel_width, 116 width, 117 height; 118 119 int 120 x, 121 y, 122 min_y, 123 max_y; 124 125 MagickStatusType 126 raised, 127 active, 128 center, 129 trough, 130 highlight; 131} XWidgetInfo; 132 133/* 134 Variable declarations. 135*/ 136static XWidgetInfo 137 monitor_info = 138 { 139 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0, 140 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse 141 }, 142 submenu_info = 143 { 144 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0, 145 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse 146 }, 147 *selection_info = (XWidgetInfo *) NULL, 148 toggle_info = 149 { 150 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0, 151 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse 152 }; 153 154/* 155 Constant declarations. 156*/ 157static const int 158 BorderOffset = 4, 159 DoubleClick = 250; 160 161/* 162 Method prototypes. 163*/ 164static void 165 XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *), 166 XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType), 167 XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType), 168 XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType); 169 170/* 171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 172% % 173% % 174% % 175% D e s t r o y X W i d g e t % 176% % 177% % 178% % 179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 180% 181% DestroyXWidget() destroys resources associated with the X widget. 182% 183% The format of the DestroyXWidget method is: 184% 185% void DestroyXWidget() 186% 187% A description of each parameter follows: 188% 189*/ 190MagickPrivate void DestroyXWidget(void) 191{ 192 if (selection_info != (XWidgetInfo *) NULL) 193 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info); 194} 195 196/* 197%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 198% % 199% % 200% % 201+ X D r a w B e v e l % 202% % 203% % 204% % 205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 206% 207% XDrawBevel() "sets off" an area with a highlighted upper and left bevel and 208% a shadowed lower and right bevel. The highlighted and shadowed bevels 209% create a 3-D effect. 210% 211% The format of the XDrawBevel function is: 212% 213% XDrawBevel(display,window_info,bevel_info) 214% 215% A description of each parameter follows: 216% 217% o display: Specifies a pointer to the Display structure; returned from 218% XOpenDisplay. 219% 220% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 221% 222% o bevel_info: Specifies a pointer to a XWidgetInfo structure. It 223% contains the extents of the bevel. 224% 225*/ 226static void XDrawBevel(Display *display,const XWindowInfo *window_info, 227 const XWidgetInfo *bevel_info) 228{ 229 int 230 x1, 231 x2, 232 y1, 233 y2; 234 235 unsigned int 236 bevel_width; 237 238 XPoint 239 points[6]; 240 241 /* 242 Draw upper and left beveled border. 243 */ 244 x1=bevel_info->x; 245 y1=bevel_info->y+bevel_info->height; 246 x2=bevel_info->x+bevel_info->width; 247 y2=bevel_info->y; 248 bevel_width=bevel_info->bevel_width; 249 points[0].x=x1; 250 points[0].y=y1; 251 points[1].x=x1; 252 points[1].y=y2; 253 points[2].x=x2; 254 points[2].y=y2; 255 points[3].x=x2+bevel_width; 256 points[3].y=y2-bevel_width; 257 points[4].x=x1-bevel_width; 258 points[4].y=y2-bevel_width; 259 points[5].x=x1-bevel_width; 260 points[5].y=y1+bevel_width; 261 XSetBevelColor(display,window_info,bevel_info->raised); 262 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 263 points,6,Complex,CoordModeOrigin); 264 /* 265 Draw lower and right beveled border. 266 */ 267 points[0].x=x1; 268 points[0].y=y1; 269 points[1].x=x2; 270 points[1].y=y1; 271 points[2].x=x2; 272 points[2].y=y2; 273 points[3].x=x2+bevel_width; 274 points[3].y=y2-bevel_width; 275 points[4].x=x2+bevel_width; 276 points[4].y=y1+bevel_width; 277 points[5].x=x1-bevel_width; 278 points[5].y=y1+bevel_width; 279 XSetBevelColor(display,window_info,!bevel_info->raised); 280 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 281 points,6,Complex,CoordModeOrigin); 282 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 283} 284 285/* 286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 287% % 288% % 289% % 290+ X D r a w B e v e l e d B u t t o n % 291% % 292% % 293% % 294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 295% 296% XDrawBeveledButton() draws a button with a highlighted upper and left bevel 297% and a shadowed lower and right bevel. The highlighted and shadowed bevels 298% create a 3-D effect. 299% 300% The format of the XDrawBeveledButton function is: 301% 302% XDrawBeveledButton(display,window_info,button_info) 303% 304% A description of each parameter follows: 305% 306% o display: Specifies a pointer to the Display structure; returned from 307% XOpenDisplay. 308% 309% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 310% 311% o button_info: Specifies a pointer to a XWidgetInfo structure. It 312% contains the extents of the button. 313% 314*/ 315 316static inline int MagickAbsoluteValue(const int x) 317{ 318 if (x < 0) 319 return(-x); 320 return(x); 321} 322 323static inline int MagickMax(const int x,const int y) 324{ 325 if (x > y) 326 return(x); 327 return(y); 328} 329 330static inline int MagickMin(const int x,const int y) 331{ 332 if (x < y) 333 return(x); 334 return(y); 335} 336 337static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info, 338 const XWidgetInfo *button_info) 339{ 340 int 341 x, 342 y; 343 344 unsigned int 345 width; 346 347 XFontStruct 348 *font_info; 349 350 XRectangle 351 crop_info; 352 353 /* 354 Draw matte. 355 */ 356 XDrawBevel(display,window_info,button_info); 357 XSetMatteColor(display,window_info,button_info->raised); 358 (void) XFillRectangle(display,window_info->id,window_info->widget_context, 359 button_info->x,button_info->y,button_info->width,button_info->height); 360 x=button_info->x-button_info->bevel_width-1; 361 y=button_info->y-button_info->bevel_width-1; 362 (void) XSetForeground(display,window_info->widget_context, 363 window_info->pixel_info->trough_color.pixel); 364 if (button_info->raised || (window_info->depth == 1)) 365 (void) XDrawRectangle(display,window_info->id,window_info->widget_context, 366 x,y,button_info->width+(button_info->bevel_width << 1)+1, 367 button_info->height+(button_info->bevel_width << 1)+1); 368 if (button_info->text == (char *) NULL) 369 return; 370 /* 371 Set cropping region. 372 */ 373 crop_info.width=(unsigned short) button_info->width; 374 crop_info.height=(unsigned short) button_info->height; 375 crop_info.x=button_info->x; 376 crop_info.y=button_info->y; 377 /* 378 Draw text. 379 */ 380 font_info=window_info->font_info; 381 width=WidgetTextWidth(font_info,button_info->text); 382 x=button_info->x+(QuantumMargin >> 1); 383 if (button_info->center) 384 x=button_info->x+(button_info->width >> 1)-(width >> 1); 385 y=button_info->y+((button_info->height- 386 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent; 387 if ((int) button_info->width == (QuantumMargin >> 1)) 388 { 389 /* 390 Option button-- write label to right of button. 391 */ 392 XSetTextColor(display,window_info,MagickTrue); 393 x=button_info->x+button_info->width+button_info->bevel_width+ 394 (QuantumMargin >> 1); 395 (void) XDrawString(display,window_info->id,window_info->widget_context, 396 x,y,button_info->text,Extent(button_info->text)); 397 return; 398 } 399 (void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info, 400 1,Unsorted); 401 XSetTextColor(display,window_info,button_info->raised); 402 (void) XDrawString(display,window_info->id,window_info->widget_context,x,y, 403 button_info->text,Extent(button_info->text)); 404 (void) XSetClipMask(display,window_info->widget_context,None); 405 if (button_info->raised == MagickFalse) 406 XDelay(display,SuspendTime << 2); 407} 408 409/* 410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 411% % 412% % 413% % 414+ X D r a w B e v e l e d M a t t e % 415% % 416% % 417% % 418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 419% 420% XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and 421% a highlighted lower and right bevel. The highlighted and shadowed bevels 422% create a 3-D effect. 423% 424% The format of the XDrawBeveledMatte function is: 425% 426% XDrawBeveledMatte(display,window_info,matte_info) 427% 428% A description of each parameter follows: 429% 430% o display: Specifies a pointer to the Display structure; returned from 431% XOpenDisplay. 432% 433% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 434% 435% o matte_info: Specifies a pointer to a XWidgetInfo structure. It 436% contains the extents of the matte. 437% 438*/ 439static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info, 440 const XWidgetInfo *matte_info) 441{ 442 /* 443 Draw matte. 444 */ 445 XDrawBevel(display,window_info,matte_info); 446 XDrawMatte(display,window_info,matte_info); 447} 448 449/* 450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 451% % 452% % 453% % 454+ X D r a w M a t t e % 455% % 456% % 457% % 458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 459% 460% XDrawMatte() fills a rectangular area with the matte color. 461% 462% The format of the XDrawMatte function is: 463% 464% XDrawMatte(display,window_info,matte_info) 465% 466% A description of each parameter follows: 467% 468% o display: Specifies a pointer to the Display structure; returned from 469% XOpenDisplay. 470% 471% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 472% 473% o matte_info: Specifies a pointer to a XWidgetInfo structure. It 474% contains the extents of the matte. 475% 476*/ 477static void XDrawMatte(Display *display,const XWindowInfo *window_info, 478 const XWidgetInfo *matte_info) 479{ 480 /* 481 Draw matte. 482 */ 483 if ((matte_info->trough == MagickFalse) || (window_info->depth == 1)) 484 (void) XFillRectangle(display,window_info->id, 485 window_info->highlight_context,matte_info->x,matte_info->y, 486 matte_info->width,matte_info->height); 487 else 488 { 489 (void) XSetForeground(display,window_info->widget_context, 490 window_info->pixel_info->trough_color.pixel); 491 (void) XFillRectangle(display,window_info->id,window_info->widget_context, 492 matte_info->x,matte_info->y,matte_info->width,matte_info->height); 493 } 494} 495 496/* 497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 498% % 499% % 500% % 501+ X D r a w M a t t e T e x t % 502% % 503% % 504% % 505%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 506% 507% XDrawMatteText() draws a matte with text. If the text exceeds the extents 508% of the text, a portion of the text relative to the cursor is displayed. 509% 510% The format of the XDrawMatteText function is: 511% 512% XDrawMatteText(display,window_info,text_info) 513% 514% A description of each parameter follows: 515% 516% o display: Specifies a pointer to the Display structure; returned from 517% XOpenDisplay. 518% 519% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 520% 521% o text_info: Specifies a pointer to a XWidgetInfo structure. It 522% contains the extents of the text. 523% 524*/ 525static void XDrawMatteText(Display *display,const XWindowInfo *window_info, 526 XWidgetInfo *text_info) 527{ 528 const char 529 *text; 530 531 int 532 n, 533 x, 534 y; 535 536 register int 537 i; 538 539 unsigned int 540 height, 541 width; 542 543 XFontStruct 544 *font_info; 545 546 XRectangle 547 crop_info; 548 549 /* 550 Clear the text area. 551 */ 552 XSetMatteColor(display,window_info,MagickFalse); 553 (void) XFillRectangle(display,window_info->id,window_info->widget_context, 554 text_info->x,text_info->y,text_info->width,text_info->height); 555 if (text_info->text == (char *) NULL) 556 return; 557 XSetTextColor(display,window_info,text_info->highlight); 558 font_info=window_info->font_info; 559 x=text_info->x+(QuantumMargin >> 2); 560 y=text_info->y+font_info->ascent+(text_info->height >> 2); 561 width=text_info->width-(QuantumMargin >> 1); 562 height=(unsigned int) (font_info->ascent+font_info->descent); 563 if (*text_info->text == '\0') 564 { 565 /* 566 No text-- just draw cursor. 567 */ 568 (void) XDrawLine(display,window_info->id,window_info->annotate_context, 569 x,y+3,x,y-height+3); 570 return; 571 } 572 /* 573 Set cropping region. 574 */ 575 crop_info.width=(unsigned short) text_info->width; 576 crop_info.height=(unsigned short) text_info->height; 577 crop_info.x=text_info->x; 578 crop_info.y=text_info->y; 579 /* 580 Determine beginning of the visible text. 581 */ 582 if (text_info->cursor < text_info->marker) 583 text_info->marker=text_info->cursor; 584 else 585 { 586 text=text_info->marker; 587 if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) > 588 (int) width) 589 { 590 text=text_info->text; 591 for (i=0; i < Extent(text); i++) 592 { 593 n=XTextWidth(font_info,(char *) text+i,(int) 594 (text_info->cursor-text-i)); 595 if (n <= (int) width) 596 break; 597 } 598 text_info->marker=(char *) text+i; 599 } 600 } 601 /* 602 Draw text and cursor. 603 */ 604 if (text_info->highlight == MagickFalse) 605 { 606 (void) XSetClipRectangles(display,window_info->widget_context,0,0, 607 &crop_info,1,Unsorted); 608 (void) XDrawString(display,window_info->id,window_info->widget_context, 609 x,y,text_info->marker,Extent(text_info->marker)); 610 (void) XSetClipMask(display,window_info->widget_context,None); 611 } 612 else 613 { 614 (void) XSetClipRectangles(display,window_info->annotate_context,0,0, 615 &crop_info,1,Unsorted); 616 width=WidgetTextWidth(font_info,text_info->marker); 617 (void) XFillRectangle(display,window_info->id, 618 window_info->annotate_context,x,y-font_info->ascent,width,height); 619 (void) XSetClipMask(display,window_info->annotate_context,None); 620 (void) XSetClipRectangles(display,window_info->highlight_context,0,0, 621 &crop_info,1,Unsorted); 622 (void) XDrawString(display,window_info->id, 623 window_info->highlight_context,x,y,text_info->marker, 624 Extent(text_info->marker)); 625 (void) XSetClipMask(display,window_info->highlight_context,None); 626 } 627 x+=XTextWidth(font_info,text_info->marker,(int) 628 (text_info->cursor-text_info->marker)); 629 (void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3, 630 x,y-height+3); 631} 632 633/* 634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 635% % 636% % 637% % 638+ X D r a w T r i a n g l e E a s t % 639% % 640% % 641% % 642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 643% 644% XDrawTriangleEast() draws a triangle with a highlighted left bevel and a 645% shadowed right and lower bevel. The highlighted and shadowed bevels create 646% a 3-D effect. 647% 648% The format of the XDrawTriangleEast function is: 649% 650% XDrawTriangleEast(display,window_info,triangle_info) 651% 652% A description of each parameter follows: 653% 654% o display: Specifies a pointer to the Display structure; returned from 655% XOpenDisplay. 656% 657% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 658% 659% o triangle_info: Specifies a pointer to a XWidgetInfo structure. It 660% contains the extents of the triangle. 661% 662*/ 663static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info, 664 const XWidgetInfo *triangle_info) 665{ 666 int 667 x1, 668 x2, 669 x3, 670 y1, 671 y2, 672 y3; 673 674 unsigned int 675 bevel_width; 676 677 XFontStruct 678 *font_info; 679 680 XPoint 681 points[4]; 682 683 /* 684 Draw triangle matte. 685 */ 686 x1=triangle_info->x; 687 y1=triangle_info->y; 688 x2=triangle_info->x+triangle_info->width; 689 y2=triangle_info->y+(triangle_info->height >> 1); 690 x3=triangle_info->x; 691 y3=triangle_info->y+triangle_info->height; 692 bevel_width=triangle_info->bevel_width; 693 points[0].x=x1; 694 points[0].y=y1; 695 points[1].x=x2; 696 points[1].y=y2; 697 points[2].x=x3; 698 points[2].y=y3; 699 XSetMatteColor(display,window_info,triangle_info->raised); 700 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 701 points,3,Complex,CoordModeOrigin); 702 /* 703 Draw bottom bevel. 704 */ 705 points[0].x=x2; 706 points[0].y=y2; 707 points[1].x=x3; 708 points[1].y=y3; 709 points[2].x=x3-bevel_width; 710 points[2].y=y3+bevel_width; 711 points[3].x=x2+bevel_width; 712 points[3].y=y2; 713 XSetBevelColor(display,window_info,!triangle_info->raised); 714 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 715 points,4,Complex,CoordModeOrigin); 716 /* 717 Draw Left bevel. 718 */ 719 points[0].x=x3; 720 points[0].y=y3; 721 points[1].x=x1; 722 points[1].y=y1; 723 points[2].x=x1-bevel_width+1; 724 points[2].y=y1-bevel_width; 725 points[3].x=x3-bevel_width+1; 726 points[3].y=y3+bevel_width; 727 XSetBevelColor(display,window_info,triangle_info->raised); 728 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 729 points,4,Complex,CoordModeOrigin); 730 /* 731 Draw top bevel. 732 */ 733 points[0].x=x1; 734 points[0].y=y1; 735 points[1].x=x2; 736 points[1].y=y2; 737 points[2].x=x2+bevel_width; 738 points[2].y=y2; 739 points[3].x=x1-bevel_width; 740 points[3].y=y1-bevel_width; 741 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 742 points,4,Complex,CoordModeOrigin); 743 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 744 if (triangle_info->text == (char *) NULL) 745 return; 746 /* 747 Write label to right of triangle. 748 */ 749 font_info=window_info->font_info; 750 XSetTextColor(display,window_info,MagickTrue); 751 x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+ 752 (QuantumMargin >> 1); 753 y1=triangle_info->y+((triangle_info->height- 754 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent; 755 (void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1, 756 triangle_info->text,Extent(triangle_info->text)); 757} 758 759/* 760%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 761% % 762% % 763% % 764+ X D r a w T r i a n g l e N o r t h % 765% % 766% % 767% % 768%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 769% 770% XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a 771% shadowed right and lower bevel. The highlighted and shadowed bevels create 772% a 3-D effect. 773% 774% The format of the XDrawTriangleNorth function is: 775% 776% XDrawTriangleNorth(display,window_info,triangle_info) 777% 778% A description of each parameter follows: 779% 780% o display: Specifies a pointer to the Display structure; returned from 781% XOpenDisplay. 782% 783% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 784% 785% o triangle_info: Specifies a pointer to a XWidgetInfo structure. It 786% contains the extents of the triangle. 787% 788*/ 789static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info, 790 const XWidgetInfo *triangle_info) 791{ 792 int 793 x1, 794 x2, 795 x3, 796 y1, 797 y2, 798 y3; 799 800 unsigned int 801 bevel_width; 802 803 XPoint 804 points[4]; 805 806 /* 807 Draw triangle matte. 808 */ 809 x1=triangle_info->x; 810 y1=triangle_info->y+triangle_info->height; 811 x2=triangle_info->x+(triangle_info->width >> 1); 812 y2=triangle_info->y; 813 x3=triangle_info->x+triangle_info->width; 814 y3=triangle_info->y+triangle_info->height; 815 bevel_width=triangle_info->bevel_width; 816 points[0].x=x1; 817 points[0].y=y1; 818 points[1].x=x2; 819 points[1].y=y2; 820 points[2].x=x3; 821 points[2].y=y3; 822 XSetMatteColor(display,window_info,triangle_info->raised); 823 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 824 points,3,Complex,CoordModeOrigin); 825 /* 826 Draw left bevel. 827 */ 828 points[0].x=x1; 829 points[0].y=y1; 830 points[1].x=x2; 831 points[1].y=y2; 832 points[2].x=x2; 833 points[2].y=y2-bevel_width-2; 834 points[3].x=x1-bevel_width-1; 835 points[3].y=y1+bevel_width; 836 XSetBevelColor(display,window_info,triangle_info->raised); 837 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 838 points,4,Complex,CoordModeOrigin); 839 /* 840 Draw right bevel. 841 */ 842 points[0].x=x2; 843 points[0].y=y2; 844 points[1].x=x3; 845 points[1].y=y3; 846 points[2].x=x3+bevel_width; 847 points[2].y=y3+bevel_width; 848 points[3].x=x2; 849 points[3].y=y2-bevel_width; 850 XSetBevelColor(display,window_info,!triangle_info->raised); 851 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 852 points,4,Complex,CoordModeOrigin); 853 /* 854 Draw lower bevel. 855 */ 856 points[0].x=x3; 857 points[0].y=y3; 858 points[1].x=x1; 859 points[1].y=y1; 860 points[2].x=x1-bevel_width; 861 points[2].y=y1+bevel_width; 862 points[3].x=x3+bevel_width; 863 points[3].y=y3+bevel_width; 864 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 865 points,4,Complex,CoordModeOrigin); 866 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 867} 868 869/* 870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 871% % 872% % 873% % 874+ X D r a w T r i a n g l e S o u t h % 875% % 876% % 877% % 878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 879% 880% XDrawTriangleSouth() draws a border with a highlighted left and right bevel 881% and a shadowed lower bevel. The highlighted and shadowed bevels create a 882% 3-D effect. 883% 884% The format of the XDrawTriangleSouth function is: 885% 886% XDrawTriangleSouth(display,window_info,triangle_info) 887% 888% A description of each parameter follows: 889% 890% o display: Specifies a pointer to the Display structure; returned from 891% XOpenDisplay. 892% 893% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 894% 895% o triangle_info: Specifies a pointer to a XWidgetInfo structure. It 896% contains the extents of the triangle. 897% 898*/ 899static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info, 900 const XWidgetInfo *triangle_info) 901{ 902 int 903 x1, 904 x2, 905 x3, 906 y1, 907 y2, 908 y3; 909 910 unsigned int 911 bevel_width; 912 913 XPoint 914 points[4]; 915 916 /* 917 Draw triangle matte. 918 */ 919 x1=triangle_info->x; 920 y1=triangle_info->y; 921 x2=triangle_info->x+(triangle_info->width >> 1); 922 y2=triangle_info->y+triangle_info->height; 923 x3=triangle_info->x+triangle_info->width; 924 y3=triangle_info->y; 925 bevel_width=triangle_info->bevel_width; 926 points[0].x=x1; 927 points[0].y=y1; 928 points[1].x=x2; 929 points[1].y=y2; 930 points[2].x=x3; 931 points[2].y=y3; 932 XSetMatteColor(display,window_info,triangle_info->raised); 933 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 934 points,3,Complex,CoordModeOrigin); 935 /* 936 Draw top bevel. 937 */ 938 points[0].x=x3; 939 points[0].y=y3; 940 points[1].x=x1; 941 points[1].y=y1; 942 points[2].x=x1-bevel_width; 943 points[2].y=y1-bevel_width; 944 points[3].x=x3+bevel_width; 945 points[3].y=y3-bevel_width; 946 XSetBevelColor(display,window_info,triangle_info->raised); 947 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 948 points,4,Complex,CoordModeOrigin); 949 /* 950 Draw right bevel. 951 */ 952 points[0].x=x2; 953 points[0].y=y2; 954 points[1].x=x3+1; 955 points[1].y=y3-bevel_width; 956 points[2].x=x3+bevel_width; 957 points[2].y=y3-bevel_width; 958 points[3].x=x2; 959 points[3].y=y2+bevel_width; 960 XSetBevelColor(display,window_info,!triangle_info->raised); 961 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 962 points,4,Complex,CoordModeOrigin); 963 /* 964 Draw left bevel. 965 */ 966 points[0].x=x1; 967 points[0].y=y1; 968 points[1].x=x2; 969 points[1].y=y2; 970 points[2].x=x2; 971 points[2].y=y2+bevel_width; 972 points[3].x=x1-bevel_width; 973 points[3].y=y1-bevel_width; 974 XSetBevelColor(display,window_info,triangle_info->raised); 975 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 976 points,4,Complex,CoordModeOrigin); 977 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 978} 979 980/* 981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 982% % 983% % 984% % 985+ X D r a w W i d g e t T e x t % 986% % 987% % 988% % 989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 990% 991% XDrawWidgetText() first clears the widget and draws a text string justifed 992% left (or center) in the x-direction and centered within the y-direction. 993% 994% The format of the XDrawWidgetText function is: 995% 996% XDrawWidgetText(display,window_info,text_info) 997% 998% A description of each parameter follows: 999% 1000% o display: Specifies a pointer to the Display structure; returned from 1001% XOpenDisplay. 1002% 1003% o window_info: Specifies a pointer to a XWindowText structure. 1004% 1005% o text_info: Specifies a pointer to XWidgetInfo structure. 1006% 1007*/ 1008static void XDrawWidgetText(Display *display,const XWindowInfo *window_info, 1009 XWidgetInfo *text_info) 1010{ 1011 GC 1012 widget_context; 1013 1014 int 1015 x, 1016 y; 1017 1018 unsigned int 1019 height, 1020 width; 1021 1022 XFontStruct 1023 *font_info; 1024 1025 XRectangle 1026 crop_info; 1027 1028 /* 1029 Clear the text area. 1030 */ 1031 widget_context=window_info->annotate_context; 1032 if (text_info->raised) 1033 (void) XClearArea(display,window_info->id,text_info->x,text_info->y, 1034 text_info->width,text_info->height,MagickFalse); 1035 else 1036 { 1037 (void) XFillRectangle(display,window_info->id,widget_context,text_info->x, 1038 text_info->y,text_info->width,text_info->height); 1039 widget_context=window_info->highlight_context; 1040 } 1041 if (text_info->text == (char *) NULL) 1042 return; 1043 if (*text_info->text == '\0') 1044 return; 1045 /* 1046 Set cropping region. 1047 */ 1048 font_info=window_info->font_info; 1049 crop_info.width=(unsigned short) text_info->width; 1050 crop_info.height=(unsigned short) text_info->height; 1051 crop_info.x=text_info->x; 1052 crop_info.y=text_info->y; 1053 /* 1054 Draw text. 1055 */ 1056 width=WidgetTextWidth(font_info,text_info->text); 1057 x=text_info->x+(QuantumMargin >> 1); 1058 if (text_info->center) 1059 x=text_info->x+(text_info->width >> 1)-(width >> 1); 1060 if (text_info->raised) 1061 if (width > (text_info->width-QuantumMargin)) 1062 x+=(text_info->width-QuantumMargin-width); 1063 height=(unsigned int) (font_info->ascent+font_info->descent); 1064 y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent; 1065 (void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted); 1066 (void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text, 1067 Extent(text_info->text)); 1068 (void) XSetClipMask(display,widget_context,None); 1069 if (x < text_info->x) 1070 (void) XDrawLine(display,window_info->id,window_info->annotate_context, 1071 text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1); 1072} 1073 1074/* 1075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1076% % 1077% % 1078% % 1079+ X E d i t T e x t % 1080% % 1081% % 1082% % 1083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1084% 1085% XEditText() edits a text string as indicated by the key symbol. 1086% 1087% The format of the XEditText function is: 1088% 1089% XEditText(display,text_info,key_symbol,text,state) 1090% 1091% A description of each parameter follows: 1092% 1093% o display: Specifies a connection to an X server; returned from 1094% XOpenDisplay. 1095% 1096% o text_info: Specifies a pointer to a XWidgetInfo structure. It 1097% contains the extents of the text. 1098% 1099% o key_symbol: A X11 KeySym that indicates what editing function to 1100% perform to the text. 1101% 1102% o text: A character string to insert into the text. 1103% 1104% o state: An size_t that indicates whether the key symbol is a 1105% control character or not. 1106% 1107*/ 1108static void XEditText(Display *display,XWidgetInfo *text_info, 1109 const KeySym key_symbol,char *text,const size_t state) 1110{ 1111 switch ((int) key_symbol) 1112 { 1113 case XK_BackSpace: 1114 case XK_Delete: 1115 { 1116 if (text_info->highlight) 1117 { 1118 /* 1119 Erase the entire line of text. 1120 */ 1121 *text_info->text='\0'; 1122 text_info->cursor=text_info->text; 1123 text_info->marker=text_info->text; 1124 text_info->highlight=MagickFalse; 1125 } 1126 /* 1127 Erase one character. 1128 */ 1129 if (text_info->cursor != text_info->text) 1130 { 1131 text_info->cursor--; 1132 (void) CopyMagickString(text_info->cursor,text_info->cursor+1, 1133 MaxTextExtent); 1134 text_info->highlight=MagickFalse; 1135 break; 1136 } 1137 } 1138 case XK_Left: 1139 case XK_KP_Left: 1140 { 1141 /* 1142 Move cursor one position left. 1143 */ 1144 if (text_info->cursor == text_info->text) 1145 break; 1146 text_info->cursor--; 1147 break; 1148 } 1149 case XK_Right: 1150 case XK_KP_Right: 1151 { 1152 /* 1153 Move cursor one position right. 1154 */ 1155 if (text_info->cursor == (text_info->text+Extent(text_info->text))) 1156 break; 1157 text_info->cursor++; 1158 break; 1159 } 1160 default: 1161 { 1162 register char 1163 *p, 1164 *q; 1165 1166 register int 1167 i; 1168 1169 if (state & ControlState) 1170 break; 1171 if (*text == '\0') 1172 break; 1173 if ((Extent(text_info->text)+1) >= (int) MaxTextExtent) 1174 (void) XBell(display,0); 1175 else 1176 { 1177 if (text_info->highlight) 1178 { 1179 /* 1180 Erase the entire line of text. 1181 */ 1182 *text_info->text='\0'; 1183 text_info->cursor=text_info->text; 1184 text_info->marker=text_info->text; 1185 text_info->highlight=MagickFalse; 1186 } 1187 /* 1188 Insert a string into the text. 1189 */ 1190 q=text_info->text+Extent(text_info->text)+strlen(text); 1191 for (i=0; i <= Extent(text_info->cursor); i++) 1192 { 1193 *q=(*(q-Extent(text))); 1194 q--; 1195 } 1196 p=text; 1197 for (i=0; i < Extent(text); i++) 1198 *text_info->cursor++=(*p++); 1199 } 1200 break; 1201 } 1202 } 1203} 1204 1205/* 1206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1207% % 1208% % 1209% % 1210+ X G e t W i d g e t I n f o % 1211% % 1212% % 1213% % 1214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1215% 1216% XGetWidgetInfo() initializes the XWidgetInfo structure. 1217% 1218% The format of the XGetWidgetInfo function is: 1219% 1220% XGetWidgetInfo(text,widget_info) 1221% 1222% A description of each parameter follows: 1223% 1224% o text: A string of characters associated with the widget. 1225% 1226% o widget_info: Specifies a pointer to a X11 XWidgetInfo structure. 1227% 1228*/ 1229static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info) 1230{ 1231 /* 1232 Initialize widget info. 1233 */ 1234 widget_info->id=(~0); 1235 widget_info->bevel_width=3; 1236 widget_info->width=1; 1237 widget_info->height=1; 1238 widget_info->x=0; 1239 widget_info->y=0; 1240 widget_info->min_y=0; 1241 widget_info->max_y=0; 1242 widget_info->raised=MagickTrue; 1243 widget_info->active=MagickFalse; 1244 widget_info->center=MagickTrue; 1245 widget_info->trough=MagickFalse; 1246 widget_info->highlight=MagickFalse; 1247 widget_info->text=(char *) text; 1248 widget_info->cursor=(char *) text; 1249 if (text != (char *) NULL) 1250 widget_info->cursor+=Extent(text); 1251 widget_info->marker=(char *) text; 1252} 1253 1254/* 1255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1256% % 1257% % 1258% % 1259+ X H i g h l i g h t W i d g e t % 1260% % 1261% % 1262% % 1263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1264% 1265% XHighlightWidget() draws a highlighted border around a window. 1266% 1267% The format of the XHighlightWidget function is: 1268% 1269% XHighlightWidget(display,window_info,x,y) 1270% 1271% A description of each parameter follows: 1272% 1273% o display: Specifies a pointer to the Display structure; returned from 1274% XOpenDisplay. 1275% 1276% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 1277% 1278% o x: Specifies an integer representing the rectangle offset in the 1279% x-direction. 1280% 1281% o y: Specifies an integer representing the rectangle offset in the 1282% y-direction. 1283% 1284*/ 1285static void XHighlightWidget(Display *display,const XWindowInfo *window_info, 1286 const int x,const int y) 1287{ 1288 /* 1289 Draw the widget highlighting rectangle. 1290 */ 1291 XSetBevelColor(display,window_info,MagickTrue); 1292 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y, 1293 window_info->width-(x << 1),window_info->height-(y << 1)); 1294 (void) XDrawRectangle(display,window_info->id,window_info->widget_context, 1295 x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1); 1296 XSetBevelColor(display,window_info,MagickFalse); 1297 (void) XDrawRectangle(display,window_info->id,window_info->widget_context, 1298 x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1)); 1299 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 1300} 1301 1302/* 1303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1304% % 1305% % 1306% % 1307+ X S c r e e n E v e n t % 1308% % 1309% % 1310% % 1311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1312% 1313% XScreenEvent() returns MagickTrue if the any event on the X server queue is 1314% associated with the widget window. 1315% 1316% The format of the XScreenEvent function is: 1317% 1318% int XScreenEvent(Display *display,XEvent *event,char *data) 1319% 1320% A description of each parameter follows: 1321% 1322% o display: Specifies a pointer to the Display structure; returned from 1323% XOpenDisplay. 1324% 1325% o event: Specifies a pointer to a X11 XEvent structure. 1326% 1327% o data: Specifies a pointer to a XWindows structure. 1328% 1329*/ 1330 1331#if defined(__cplusplus) || defined(c_plusplus) 1332extern "C" { 1333#endif 1334 1335static int XScreenEvent(Display *display,XEvent *event,char *data) 1336{ 1337 XWindows 1338 *windows; 1339 1340 windows=(XWindows *) data; 1341 if (event->xany.window == windows->popup.id) 1342 { 1343 if (event->type == MapNotify) 1344 windows->popup.mapped=MagickTrue; 1345 if (event->type == UnmapNotify) 1346 windows->popup.mapped=MagickFalse; 1347 return(MagickTrue); 1348 } 1349 if (event->xany.window == windows->widget.id) 1350 { 1351 if (event->type == MapNotify) 1352 windows->widget.mapped=MagickTrue; 1353 if (event->type == UnmapNotify) 1354 windows->widget.mapped=MagickFalse; 1355 return(MagickTrue); 1356 } 1357 switch (event->type) 1358 { 1359 case ButtonPress: 1360 { 1361 if ((event->xbutton.button == Button3) && 1362 (event->xbutton.state & Mod1Mask)) 1363 { 1364 /* 1365 Convert Alt-Button3 to Button2. 1366 */ 1367 event->xbutton.button=Button2; 1368 event->xbutton.state&=(~Mod1Mask); 1369 } 1370 return(MagickTrue); 1371 } 1372 case Expose: 1373 { 1374 if (event->xexpose.window == windows->image.id) 1375 { 1376 XRefreshWindow(display,&windows->image,event); 1377 break; 1378 } 1379 if (event->xexpose.window == windows->magnify.id) 1380 if (event->xexpose.count == 0) 1381 if (windows->magnify.mapped) 1382 { 1383 ExceptionInfo 1384 *exception; 1385 1386 exception=AcquireExceptionInfo(); 1387 XMakeMagnifyImage(display,windows,exception); 1388 exception=DestroyExceptionInfo(exception); 1389 break; 1390 } 1391 if (event->xexpose.window == windows->command.id) 1392 if (event->xexpose.count == 0) 1393 { 1394 (void) XCommandWidget(display,windows,(const char **) NULL,event); 1395 break; 1396 } 1397 break; 1398 } 1399 case FocusOut: 1400 { 1401 /* 1402 Set input focus for backdrop window. 1403 */ 1404 if (event->xfocus.window == windows->image.id) 1405 (void) XSetInputFocus(display,windows->image.id,RevertToNone, 1406 CurrentTime); 1407 return(MagickTrue); 1408 } 1409 case ButtonRelease: 1410 case KeyPress: 1411 case KeyRelease: 1412 case MotionNotify: 1413 case SelectionNotify: 1414 return(MagickTrue); 1415 default: 1416 break; 1417 } 1418 return(MagickFalse); 1419} 1420 1421#if defined(__cplusplus) || defined(c_plusplus) 1422} 1423#endif 1424 1425/* 1426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1427% % 1428% % 1429% % 1430+ X S e t B e v e l C o l o r % 1431% % 1432% % 1433% % 1434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1435% 1436% XSetBevelColor() sets the graphic context for drawing a beveled border. 1437% 1438% The format of the XSetBevelColor function is: 1439% 1440% XSetBevelColor(display,window_info,raised) 1441% 1442% A description of each parameter follows: 1443% 1444% o display: Specifies a pointer to the Display structure; returned from 1445% XOpenDisplay. 1446% 1447% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 1448% 1449% o raised: A value other than zero indicates the color show be a 1450% "highlight" color, otherwise the "shadow" color is set. 1451% 1452*/ 1453static void XSetBevelColor(Display *display,const XWindowInfo *window_info, 1454 const MagickStatusType raised) 1455{ 1456 if (window_info->depth == 1) 1457 { 1458 Pixmap 1459 stipple; 1460 1461 /* 1462 Monochrome window. 1463 */ 1464 (void) XSetBackground(display,window_info->widget_context, 1465 XBlackPixel(display,window_info->screen)); 1466 (void) XSetForeground(display,window_info->widget_context, 1467 XWhitePixel(display,window_info->screen)); 1468 (void) XSetFillStyle(display,window_info->widget_context, 1469 FillOpaqueStippled); 1470 stipple=window_info->highlight_stipple; 1471 if (raised == MagickFalse) 1472 stipple=window_info->shadow_stipple; 1473 (void) XSetStipple(display,window_info->widget_context,stipple); 1474 } 1475 else 1476 if (raised) 1477 (void) XSetForeground(display,window_info->widget_context, 1478 window_info->pixel_info->highlight_color.pixel); 1479 else 1480 (void) XSetForeground(display,window_info->widget_context, 1481 window_info->pixel_info->shadow_color.pixel); 1482} 1483 1484/* 1485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1486% % 1487% % 1488% % 1489+ X S e t M a t t e C o l o r % 1490% % 1491% % 1492% % 1493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1494% 1495% XSetMatteColor() sets the graphic context for drawing the matte. 1496% 1497% The format of the XSetMatteColor function is: 1498% 1499% XSetMatteColor(display,window_info,raised) 1500% 1501% A description of each parameter follows: 1502% 1503% o display: Specifies a pointer to the Display structure; returned from 1504% XOpenDisplay. 1505% 1506% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 1507% 1508% o raised: A value other than zero indicates the matte is active. 1509% 1510*/ 1511static void XSetMatteColor(Display *display,const XWindowInfo *window_info, 1512 const MagickStatusType raised) 1513{ 1514 if (window_info->depth == 1) 1515 { 1516 /* 1517 Monochrome window. 1518 */ 1519 if (raised) 1520 (void) XSetForeground(display,window_info->widget_context, 1521 XWhitePixel(display,window_info->screen)); 1522 else 1523 (void) XSetForeground(display,window_info->widget_context, 1524 XBlackPixel(display,window_info->screen)); 1525 } 1526 else 1527 if (raised) 1528 (void) XSetForeground(display,window_info->widget_context, 1529 window_info->pixel_info->matte_color.pixel); 1530 else 1531 (void) XSetForeground(display,window_info->widget_context, 1532 window_info->pixel_info->depth_color.pixel); 1533} 1534 1535/* 1536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1537% % 1538% % 1539% % 1540+ X S e t T e x t C o l o r % 1541% % 1542% % 1543% % 1544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1545% 1546% XSetTextColor() sets the graphic context for drawing text on a matte. 1547% 1548% The format of the XSetTextColor function is: 1549% 1550% XSetTextColor(display,window_info,raised) 1551% 1552% A description of each parameter follows: 1553% 1554% o display: Specifies a pointer to the Display structure; returned from 1555% XOpenDisplay. 1556% 1557% o window_info: Specifies a pointer to a X11 XWindowInfo structure. 1558% 1559% o raised: A value other than zero indicates the color show be a 1560% "highlight" color, otherwise the "shadow" color is set. 1561% 1562*/ 1563static void XSetTextColor(Display *display,const XWindowInfo *window_info, 1564 const MagickStatusType raised) 1565{ 1566 ssize_t 1567 foreground, 1568 matte; 1569 1570 if (window_info->depth == 1) 1571 { 1572 /* 1573 Monochrome window. 1574 */ 1575 if (raised) 1576 (void) XSetForeground(display,window_info->widget_context, 1577 XBlackPixel(display,window_info->screen)); 1578 else 1579 (void) XSetForeground(display,window_info->widget_context, 1580 XWhitePixel(display,window_info->screen)); 1581 return; 1582 } 1583 foreground=(ssize_t) XPixelIntensity( 1584 &window_info->pixel_info->foreground_color); 1585 matte=(ssize_t) XPixelIntensity(&window_info->pixel_info->matte_color); 1586 if (MagickAbsoluteValue((int) (foreground-matte)) > (65535L >> 3)) 1587 (void) XSetForeground(display,window_info->widget_context, 1588 window_info->pixel_info->foreground_color.pixel); 1589 else 1590 (void) XSetForeground(display,window_info->widget_context, 1591 window_info->pixel_info->background_color.pixel); 1592} 1593 1594/* 1595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1596% % 1597% % 1598% % 1599% X C o l o r B r o w s e r W i d g e t % 1600% % 1601% % 1602% % 1603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1604% 1605% XColorBrowserWidget() displays a Color Browser widget with a color query 1606% to the user. The user keys a reply and presses the Action or Cancel button 1607% to exit. The typed text is returned as the reply function parameter. 1608% 1609% The format of the XColorBrowserWidget method is: 1610% 1611% void XColorBrowserWidget(Display *display,XWindows *windows, 1612% const char *action,char *reply) 1613% 1614% A description of each parameter follows: 1615% 1616% o display: Specifies a connection to an X server; returned from 1617% XOpenDisplay. 1618% 1619% o window: Specifies a pointer to a XWindows structure. 1620% 1621% o action: Specifies a pointer to the action of this widget. 1622% 1623% o reply: the response from the user is returned in this parameter. 1624% 1625*/ 1626MagickPrivate void XColorBrowserWidget(Display *display,XWindows *windows, 1627 const char *action,char *reply) 1628{ 1629#define CancelButtonText "Cancel" 1630#define ColornameText "Name:" 1631#define ColorPatternText "Pattern:" 1632#define GrabButtonText "Grab" 1633#define ResetButtonText "Reset" 1634 1635 char 1636 **colorlist, 1637 primary_selection[MaxTextExtent], 1638 reset_pattern[MaxTextExtent], 1639 text[MaxTextExtent]; 1640 1641 ExceptionInfo 1642 *exception; 1643 1644 int 1645 x, 1646 y; 1647 1648 register int 1649 i; 1650 1651 static char 1652 glob_pattern[MaxTextExtent] = "*"; 1653 1654 static MagickStatusType 1655 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 1656 1657 Status 1658 status; 1659 1660 unsigned int 1661 height, 1662 text_width, 1663 visible_colors, 1664 width; 1665 1666 size_t 1667 colors, 1668 delay, 1669 state; 1670 1671 XColor 1672 color; 1673 1674 XEvent 1675 event; 1676 1677 XFontStruct 1678 *font_info; 1679 1680 XTextProperty 1681 window_name; 1682 1683 XWidgetInfo 1684 action_info, 1685 cancel_info, 1686 expose_info, 1687 grab_info, 1688 list_info, 1689 mode_info, 1690 north_info, 1691 reply_info, 1692 reset_info, 1693 scroll_info, 1694 selection_info, 1695 slider_info, 1696 south_info, 1697 text_info; 1698 1699 XWindowChanges 1700 window_changes; 1701 1702 /* 1703 Get color list and sort in ascending order. 1704 */ 1705 assert(display != (Display *) NULL); 1706 assert(windows != (XWindows *) NULL); 1707 assert(action != (char *) NULL); 1708 assert(reply != (char *) NULL); 1709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 1710 XSetCursorState(display,windows,MagickTrue); 1711 XCheckRefreshWindows(display,windows); 1712 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent); 1713 exception=AcquireExceptionInfo(); 1714 colorlist=GetColorList(glob_pattern,&colors,exception); 1715 if (colorlist == (char **) NULL) 1716 { 1717 /* 1718 Pattern failed, obtain all the colors. 1719 */ 1720 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent); 1721 colorlist=GetColorList(glob_pattern,&colors,exception); 1722 if (colorlist == (char **) NULL) 1723 { 1724 XNoticeWidget(display,windows,"Unable to obtain colors names:", 1725 glob_pattern); 1726 (void) XDialogWidget(display,windows,action,"Enter color name:", 1727 reply); 1728 return; 1729 } 1730 } 1731 /* 1732 Determine Color Browser widget attributes. 1733 */ 1734 font_info=windows->widget.font_info; 1735 text_width=0; 1736 for (i=0; i < (int) colors; i++) 1737 if (WidgetTextWidth(font_info,colorlist[i]) > text_width) 1738 text_width=WidgetTextWidth(font_info,colorlist[i]); 1739 width=WidgetTextWidth(font_info,(char *) action); 1740 if (WidgetTextWidth(font_info,CancelButtonText) > width) 1741 width=WidgetTextWidth(font_info,CancelButtonText); 1742 if (WidgetTextWidth(font_info,ResetButtonText) > width) 1743 width=WidgetTextWidth(font_info,ResetButtonText); 1744 if (WidgetTextWidth(font_info,GrabButtonText) > width) 1745 width=WidgetTextWidth(font_info,GrabButtonText); 1746 width+=QuantumMargin; 1747 if (WidgetTextWidth(font_info,ColorPatternText) > width) 1748 width=WidgetTextWidth(font_info,ColorPatternText); 1749 if (WidgetTextWidth(font_info,ColornameText) > width) 1750 width=WidgetTextWidth(font_info,ColornameText); 1751 height=(unsigned int) (font_info->ascent+font_info->descent); 1752 /* 1753 Position Color Browser widget. 1754 */ 1755 windows->widget.width=(unsigned int) 1756 (width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin); 1757 windows->widget.min_width=(unsigned int) 1758 (width+MinTextWidth+4*QuantumMargin); 1759 if (windows->widget.width < windows->widget.min_width) 1760 windows->widget.width=windows->widget.min_width; 1761 windows->widget.height=(unsigned int) 1762 ((81*height) >> 2)+((13*QuantumMargin) >> 1)+4; 1763 windows->widget.min_height=(unsigned int) 1764 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4); 1765 if (windows->widget.height < windows->widget.min_height) 1766 windows->widget.height=windows->widget.min_height; 1767 XConstrainWindowPosition(display,&windows->widget); 1768 /* 1769 Map Color Browser widget. 1770 */ 1771 (void) CopyMagickString(windows->widget.name,"Browse and Select a Color", 1772 MaxTextExtent); 1773 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 1774 if (status != False) 1775 { 1776 XSetWMName(display,windows->widget.id,&window_name); 1777 XSetWMIconName(display,windows->widget.id,&window_name); 1778 (void) XFree((void *) window_name.value); 1779 } 1780 window_changes.width=(int) windows->widget.width; 1781 window_changes.height=(int) windows->widget.height; 1782 window_changes.x=windows->widget.x; 1783 window_changes.y=windows->widget.y; 1784 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 1785 mask,&window_changes); 1786 (void) XMapRaised(display,windows->widget.id); 1787 windows->widget.mapped=MagickFalse; 1788 /* 1789 Respond to X events. 1790 */ 1791 XGetWidgetInfo((char *) NULL,&slider_info); 1792 XGetWidgetInfo((char *) NULL,&north_info); 1793 XGetWidgetInfo((char *) NULL,&south_info); 1794 XGetWidgetInfo((char *) NULL,&expose_info); 1795 visible_colors=0; 1796 delay=SuspendTime << 2; 1797 state=UpdateConfigurationState; 1798 do 1799 { 1800 if (state & UpdateConfigurationState) 1801 { 1802 int 1803 id; 1804 1805 /* 1806 Initialize button information. 1807 */ 1808 XGetWidgetInfo(CancelButtonText,&cancel_info); 1809 cancel_info.width=width; 1810 cancel_info.height=(unsigned int) ((3*height) >> 1); 1811 cancel_info.x=(int) 1812 (windows->widget.width-cancel_info.width-QuantumMargin-2); 1813 cancel_info.y=(int) 1814 (windows->widget.height-cancel_info.height-QuantumMargin); 1815 XGetWidgetInfo(action,&action_info); 1816 action_info.width=width; 1817 action_info.height=(unsigned int) ((3*height) >> 1); 1818 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+ 1819 (action_info.bevel_width << 1)); 1820 action_info.y=cancel_info.y; 1821 XGetWidgetInfo(GrabButtonText,&grab_info); 1822 grab_info.width=width; 1823 grab_info.height=(unsigned int) ((3*height) >> 1); 1824 grab_info.x=QuantumMargin; 1825 grab_info.y=((5*QuantumMargin) >> 1)+height; 1826 XGetWidgetInfo(ResetButtonText,&reset_info); 1827 reset_info.width=width; 1828 reset_info.height=(unsigned int) ((3*height) >> 1); 1829 reset_info.x=QuantumMargin; 1830 reset_info.y=grab_info.y+grab_info.height+QuantumMargin; 1831 /* 1832 Initialize reply information. 1833 */ 1834 XGetWidgetInfo(reply,&reply_info); 1835 reply_info.raised=MagickFalse; 1836 reply_info.bevel_width--; 1837 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1); 1838 reply_info.height=height << 1; 1839 reply_info.x=(int) (width+(QuantumMargin << 1)); 1840 reply_info.y=action_info.y-reply_info.height-QuantumMargin; 1841 /* 1842 Initialize mode information. 1843 */ 1844 XGetWidgetInfo((char *) NULL,&mode_info); 1845 mode_info.active=MagickTrue; 1846 mode_info.bevel_width=0; 1847 mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1)); 1848 mode_info.height=action_info.height; 1849 mode_info.x=QuantumMargin; 1850 mode_info.y=action_info.y; 1851 /* 1852 Initialize scroll information. 1853 */ 1854 XGetWidgetInfo((char *) NULL,&scroll_info); 1855 scroll_info.bevel_width--; 1856 scroll_info.width=height; 1857 scroll_info.height=(unsigned int) (reply_info.y-grab_info.y- 1858 (QuantumMargin >> 1)); 1859 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width); 1860 scroll_info.y=grab_info.y-reply_info.bevel_width; 1861 scroll_info.raised=MagickFalse; 1862 scroll_info.trough=MagickTrue; 1863 north_info=scroll_info; 1864 north_info.raised=MagickTrue; 1865 north_info.width-=(north_info.bevel_width << 1); 1866 north_info.height=north_info.width-1; 1867 north_info.x+=north_info.bevel_width; 1868 north_info.y+=north_info.bevel_width; 1869 south_info=north_info; 1870 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 1871 south_info.height; 1872 id=slider_info.id; 1873 slider_info=north_info; 1874 slider_info.id=id; 1875 slider_info.width-=2; 1876 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 1877 slider_info.bevel_width+2; 1878 slider_info.height=scroll_info.height-((slider_info.min_y- 1879 scroll_info.y+1) << 1)+4; 1880 visible_colors=scroll_info.height/(height+(height >> 3)); 1881 if (colors > visible_colors) 1882 slider_info.height=(unsigned int) 1883 ((visible_colors*slider_info.height)/colors); 1884 slider_info.max_y=south_info.y-south_info.bevel_width- 1885 slider_info.bevel_width-2; 1886 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 1887 slider_info.y=slider_info.min_y; 1888 expose_info=scroll_info; 1889 expose_info.y=slider_info.y; 1890 /* 1891 Initialize list information. 1892 */ 1893 XGetWidgetInfo((char *) NULL,&list_info); 1894 list_info.raised=MagickFalse; 1895 list_info.bevel_width--; 1896 list_info.width=(unsigned int) 1897 (scroll_info.x-reply_info.x-(QuantumMargin >> 1)); 1898 list_info.height=scroll_info.height; 1899 list_info.x=reply_info.x; 1900 list_info.y=scroll_info.y; 1901 if (windows->widget.mapped == MagickFalse) 1902 state|=JumpListState; 1903 /* 1904 Initialize text information. 1905 */ 1906 *text='\0'; 1907 XGetWidgetInfo(text,&text_info); 1908 text_info.center=MagickFalse; 1909 text_info.width=reply_info.width; 1910 text_info.height=height; 1911 text_info.x=list_info.x-(QuantumMargin >> 1); 1912 text_info.y=QuantumMargin; 1913 /* 1914 Initialize selection information. 1915 */ 1916 XGetWidgetInfo((char *) NULL,&selection_info); 1917 selection_info.center=MagickFalse; 1918 selection_info.width=list_info.width; 1919 selection_info.height=(unsigned int) ((9*height) >> 3); 1920 selection_info.x=list_info.x; 1921 state&=(~UpdateConfigurationState); 1922 } 1923 if (state & RedrawWidgetState) 1924 { 1925 /* 1926 Redraw Color Browser window. 1927 */ 1928 x=QuantumMargin; 1929 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent; 1930 (void) XDrawString(display,windows->widget.id, 1931 windows->widget.annotate_context,x,y,ColorPatternText, 1932 Extent(ColorPatternText)); 1933 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent); 1934 XDrawWidgetText(display,&windows->widget,&text_info); 1935 XDrawBeveledButton(display,&windows->widget,&grab_info); 1936 XDrawBeveledButton(display,&windows->widget,&reset_info); 1937 XDrawBeveledMatte(display,&windows->widget,&list_info); 1938 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 1939 XDrawTriangleNorth(display,&windows->widget,&north_info); 1940 XDrawBeveledButton(display,&windows->widget,&slider_info); 1941 XDrawTriangleSouth(display,&windows->widget,&south_info); 1942 x=QuantumMargin; 1943 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent; 1944 (void) XDrawString(display,windows->widget.id, 1945 windows->widget.annotate_context,x,y,ColornameText, 1946 Extent(ColornameText)); 1947 XDrawBeveledMatte(display,&windows->widget,&reply_info); 1948 XDrawMatteText(display,&windows->widget,&reply_info); 1949 XDrawBeveledButton(display,&windows->widget,&action_info); 1950 XDrawBeveledButton(display,&windows->widget,&cancel_info); 1951 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 1952 selection_info.id=(~0); 1953 state|=RedrawActionState; 1954 state|=RedrawListState; 1955 state&=(~RedrawWidgetState); 1956 } 1957 if (state & UpdateListState) 1958 { 1959 char 1960 **checklist; 1961 1962 size_t 1963 number_colors; 1964 1965 status=XParseColor(display,windows->widget.map_info->colormap, 1966 glob_pattern,&color); 1967 if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL)) 1968 { 1969 /* 1970 Reply is a single color name-- exit. 1971 */ 1972 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent); 1973 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent); 1974 action_info.raised=MagickFalse; 1975 XDrawBeveledButton(display,&windows->widget,&action_info); 1976 break; 1977 } 1978 /* 1979 Update color list. 1980 */ 1981 checklist=GetColorList(glob_pattern,&number_colors,exception); 1982 if (number_colors == 0) 1983 { 1984 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent); 1985 (void) XBell(display,0); 1986 } 1987 else 1988 { 1989 for (i=0; i < (int) colors; i++) 1990 colorlist[i]=DestroyString(colorlist[i]); 1991 if (colorlist != (char **) NULL) 1992 colorlist=(char **) RelinquishMagickMemory(colorlist); 1993 colorlist=checklist; 1994 colors=number_colors; 1995 } 1996 /* 1997 Sort color list in ascending order. 1998 */ 1999 slider_info.height= 2000 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1; 2001 if (colors > visible_colors) 2002 slider_info.height=(unsigned int) 2003 ((visible_colors*slider_info.height)/colors); 2004 slider_info.max_y=south_info.y-south_info.bevel_width- 2005 slider_info.bevel_width-2; 2006 slider_info.id=0; 2007 slider_info.y=slider_info.min_y; 2008 expose_info.y=slider_info.y; 2009 selection_info.id=(~0); 2010 list_info.id=(~0); 2011 state|=RedrawListState; 2012 /* 2013 Redraw color name & reply. 2014 */ 2015 *reply_info.text='\0'; 2016 reply_info.cursor=reply_info.text; 2017 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent); 2018 XDrawWidgetText(display,&windows->widget,&text_info); 2019 XDrawMatteText(display,&windows->widget,&reply_info); 2020 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 2021 XDrawTriangleNorth(display,&windows->widget,&north_info); 2022 XDrawBeveledButton(display,&windows->widget,&slider_info); 2023 XDrawTriangleSouth(display,&windows->widget,&south_info); 2024 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 2025 state&=(~UpdateListState); 2026 } 2027 if (state & JumpListState) 2028 { 2029 /* 2030 Jump scroll to match user color. 2031 */ 2032 list_info.id=(~0); 2033 for (i=0; i < (int) colors; i++) 2034 if (LocaleCompare(colorlist[i],reply) >= 0) 2035 { 2036 list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0; 2037 break; 2038 } 2039 if ((i < slider_info.id) || 2040 (i >= (int) (slider_info.id+visible_colors))) 2041 slider_info.id=i-(visible_colors >> 1); 2042 selection_info.id=(~0); 2043 state|=RedrawListState; 2044 state&=(~JumpListState); 2045 } 2046 if (state & RedrawListState) 2047 { 2048 /* 2049 Determine slider id and position. 2050 */ 2051 if (slider_info.id >= (int) (colors-visible_colors)) 2052 slider_info.id=(int) (colors-visible_colors); 2053 if ((slider_info.id < 0) || (colors <= visible_colors)) 2054 slider_info.id=0; 2055 slider_info.y=slider_info.min_y; 2056 if (colors != 0) 2057 slider_info.y+=(int) (slider_info.id*(slider_info.max_y- 2058 slider_info.min_y+1)/colors); 2059 if (slider_info.id != selection_info.id) 2060 { 2061 /* 2062 Redraw scroll bar and file names. 2063 */ 2064 selection_info.id=slider_info.id; 2065 selection_info.y=list_info.y+(height >> 3)+2; 2066 for (i=0; i < (int) visible_colors; i++) 2067 { 2068 selection_info.raised=(slider_info.id+i) != list_info.id ? 2069 MagickTrue : MagickFalse; 2070 selection_info.text=(char *) NULL; 2071 if ((slider_info.id+i) < (int) colors) 2072 selection_info.text=colorlist[slider_info.id+i]; 2073 XDrawWidgetText(display,&windows->widget,&selection_info); 2074 selection_info.y+=(int) selection_info.height; 2075 } 2076 /* 2077 Update slider. 2078 */ 2079 if (slider_info.y > expose_info.y) 2080 { 2081 expose_info.height=(unsigned int) slider_info.y-expose_info.y; 2082 expose_info.y=slider_info.y-expose_info.height- 2083 slider_info.bevel_width-1; 2084 } 2085 else 2086 { 2087 expose_info.height=(unsigned int) expose_info.y-slider_info.y; 2088 expose_info.y=slider_info.y+slider_info.height+ 2089 slider_info.bevel_width+1; 2090 } 2091 XDrawTriangleNorth(display,&windows->widget,&north_info); 2092 XDrawMatte(display,&windows->widget,&expose_info); 2093 XDrawBeveledButton(display,&windows->widget,&slider_info); 2094 XDrawTriangleSouth(display,&windows->widget,&south_info); 2095 expose_info.y=slider_info.y; 2096 } 2097 state&=(~RedrawListState); 2098 } 2099 if (state & RedrawActionState) 2100 { 2101 static char 2102 colorname[MaxTextExtent]; 2103 2104 /* 2105 Display the selected color in a drawing area. 2106 */ 2107 color=windows->widget.pixel_info->matte_color; 2108 (void) XParseColor(display,windows->widget.map_info->colormap, 2109 reply_info.text,&windows->widget.pixel_info->matte_color); 2110 XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL, 2111 (unsigned int) windows->widget.visual_info->colormap_size, 2112 &windows->widget.pixel_info->matte_color); 2113 mode_info.text=colorname; 2114 (void) FormatLocaleString(mode_info.text,MaxTextExtent,"#%02x%02x%02x", 2115 windows->widget.pixel_info->matte_color.red, 2116 windows->widget.pixel_info->matte_color.green, 2117 windows->widget.pixel_info->matte_color.blue); 2118 XDrawBeveledButton(display,&windows->widget,&mode_info); 2119 windows->widget.pixel_info->matte_color=color; 2120 state&=(~RedrawActionState); 2121 } 2122 /* 2123 Wait for next event. 2124 */ 2125 if (north_info.raised && south_info.raised) 2126 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 2127 else 2128 { 2129 /* 2130 Brief delay before advancing scroll bar. 2131 */ 2132 XDelay(display,delay); 2133 delay=SuspendTime; 2134 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows); 2135 if (north_info.raised == MagickFalse) 2136 if (slider_info.id > 0) 2137 { 2138 /* 2139 Move slider up. 2140 */ 2141 slider_info.id--; 2142 state|=RedrawListState; 2143 } 2144 if (south_info.raised == MagickFalse) 2145 if (slider_info.id < (int) colors) 2146 { 2147 /* 2148 Move slider down. 2149 */ 2150 slider_info.id++; 2151 state|=RedrawListState; 2152 } 2153 if (event.type != ButtonRelease) 2154 continue; 2155 } 2156 switch (event.type) 2157 { 2158 case ButtonPress: 2159 { 2160 if (MatteIsActive(slider_info,event.xbutton)) 2161 { 2162 /* 2163 Track slider. 2164 */ 2165 slider_info.active=MagickTrue; 2166 break; 2167 } 2168 if (MatteIsActive(north_info,event.xbutton)) 2169 if (slider_info.id > 0) 2170 { 2171 /* 2172 Move slider up. 2173 */ 2174 north_info.raised=MagickFalse; 2175 slider_info.id--; 2176 state|=RedrawListState; 2177 break; 2178 } 2179 if (MatteIsActive(south_info,event.xbutton)) 2180 if (slider_info.id < (int) colors) 2181 { 2182 /* 2183 Move slider down. 2184 */ 2185 south_info.raised=MagickFalse; 2186 slider_info.id++; 2187 state|=RedrawListState; 2188 break; 2189 } 2190 if (MatteIsActive(scroll_info,event.xbutton)) 2191 { 2192 /* 2193 Move slider. 2194 */ 2195 if (event.xbutton.y < slider_info.y) 2196 slider_info.id-=(visible_colors-1); 2197 else 2198 slider_info.id+=(visible_colors-1); 2199 state|=RedrawListState; 2200 break; 2201 } 2202 if (MatteIsActive(list_info,event.xbutton)) 2203 { 2204 int 2205 id; 2206 2207 /* 2208 User pressed list matte. 2209 */ 2210 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/ 2211 selection_info.height; 2212 if (id >= (int) colors) 2213 break; 2214 (void) CopyMagickString(reply_info.text,colorlist[id], 2215 MaxTextExtent); 2216 reply_info.highlight=MagickFalse; 2217 reply_info.marker=reply_info.text; 2218 reply_info.cursor=reply_info.text+Extent(reply_info.text); 2219 XDrawMatteText(display,&windows->widget,&reply_info); 2220 state|=RedrawActionState; 2221 if (id == list_info.id) 2222 { 2223 (void) CopyMagickString(glob_pattern,reply_info.text, 2224 MaxTextExtent); 2225 state|=UpdateListState; 2226 } 2227 selection_info.id=(~0); 2228 list_info.id=id; 2229 state|=RedrawListState; 2230 break; 2231 } 2232 if (MatteIsActive(grab_info,event.xbutton)) 2233 { 2234 /* 2235 User pressed Grab button. 2236 */ 2237 grab_info.raised=MagickFalse; 2238 XDrawBeveledButton(display,&windows->widget,&grab_info); 2239 break; 2240 } 2241 if (MatteIsActive(reset_info,event.xbutton)) 2242 { 2243 /* 2244 User pressed Reset button. 2245 */ 2246 reset_info.raised=MagickFalse; 2247 XDrawBeveledButton(display,&windows->widget,&reset_info); 2248 break; 2249 } 2250 if (MatteIsActive(mode_info,event.xbutton)) 2251 { 2252 /* 2253 User pressed mode button. 2254 */ 2255 (void) CopyMagickString(reply_info.text,mode_info.text, 2256 MaxTextExtent); 2257 (void) CopyMagickString(primary_selection,reply_info.text, 2258 MaxTextExtent); 2259 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 2260 event.xbutton.time); 2261 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 2262 windows->widget.id ? MagickTrue : MagickFalse; 2263 reply_info.marker=reply_info.text; 2264 reply_info.cursor=reply_info.text+Extent(reply_info.text); 2265 XDrawMatteText(display,&windows->widget,&reply_info); 2266 break; 2267 } 2268 if (MatteIsActive(action_info,event.xbutton)) 2269 { 2270 /* 2271 User pressed action button. 2272 */ 2273 action_info.raised=MagickFalse; 2274 XDrawBeveledButton(display,&windows->widget,&action_info); 2275 break; 2276 } 2277 if (MatteIsActive(cancel_info,event.xbutton)) 2278 { 2279 /* 2280 User pressed Cancel button. 2281 */ 2282 cancel_info.raised=MagickFalse; 2283 XDrawBeveledButton(display,&windows->widget,&cancel_info); 2284 break; 2285 } 2286 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 2287 break; 2288 if (event.xbutton.button != Button2) 2289 { 2290 static Time 2291 click_time; 2292 2293 /* 2294 Move text cursor to position of button press. 2295 */ 2296 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 2297 for (i=1; i <= Extent(reply_info.marker); i++) 2298 if (XTextWidth(font_info,reply_info.marker,i) > x) 2299 break; 2300 reply_info.cursor=reply_info.marker+i-1; 2301 if (event.xbutton.time > (click_time+DoubleClick)) 2302 reply_info.highlight=MagickFalse; 2303 else 2304 { 2305 /* 2306 Become the XA_PRIMARY selection owner. 2307 */ 2308 (void) CopyMagickString(primary_selection,reply_info.text, 2309 MaxTextExtent); 2310 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 2311 event.xbutton.time); 2312 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 2313 windows->widget.id ? MagickTrue : MagickFalse; 2314 } 2315 XDrawMatteText(display,&windows->widget,&reply_info); 2316 click_time=event.xbutton.time; 2317 break; 2318 } 2319 /* 2320 Request primary selection. 2321 */ 2322 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 2323 windows->widget.id,event.xbutton.time); 2324 break; 2325 } 2326 case ButtonRelease: 2327 { 2328 if (windows->widget.mapped == MagickFalse) 2329 break; 2330 if (north_info.raised == MagickFalse) 2331 { 2332 /* 2333 User released up button. 2334 */ 2335 delay=SuspendTime << 2; 2336 north_info.raised=MagickTrue; 2337 XDrawTriangleNorth(display,&windows->widget,&north_info); 2338 } 2339 if (south_info.raised == MagickFalse) 2340 { 2341 /* 2342 User released down button. 2343 */ 2344 delay=SuspendTime << 2; 2345 south_info.raised=MagickTrue; 2346 XDrawTriangleSouth(display,&windows->widget,&south_info); 2347 } 2348 if (slider_info.active) 2349 { 2350 /* 2351 Stop tracking slider. 2352 */ 2353 slider_info.active=MagickFalse; 2354 break; 2355 } 2356 if (grab_info.raised == MagickFalse) 2357 { 2358 if (event.xbutton.window == windows->widget.id) 2359 if (MatteIsActive(grab_info,event.xbutton)) 2360 { 2361 /* 2362 Select a fill color from the X server. 2363 */ 2364 (void) XGetWindowColor(display,windows,reply_info.text, 2365 exception); 2366 reply_info.marker=reply_info.text; 2367 reply_info.cursor=reply_info.text+Extent(reply_info.text); 2368 XDrawMatteText(display,&windows->widget,&reply_info); 2369 state|=RedrawActionState; 2370 } 2371 grab_info.raised=MagickTrue; 2372 XDrawBeveledButton(display,&windows->widget,&grab_info); 2373 } 2374 if (reset_info.raised == MagickFalse) 2375 { 2376 if (event.xbutton.window == windows->widget.id) 2377 if (MatteIsActive(reset_info,event.xbutton)) 2378 { 2379 (void) CopyMagickString(glob_pattern,reset_pattern, 2380 MaxTextExtent); 2381 state|=UpdateListState; 2382 } 2383 reset_info.raised=MagickTrue; 2384 XDrawBeveledButton(display,&windows->widget,&reset_info); 2385 } 2386 if (action_info.raised == MagickFalse) 2387 { 2388 if (event.xbutton.window == windows->widget.id) 2389 { 2390 if (MatteIsActive(action_info,event.xbutton)) 2391 { 2392 if (*reply_info.text == '\0') 2393 (void) XBell(display,0); 2394 else 2395 state|=ExitState; 2396 } 2397 } 2398 action_info.raised=MagickTrue; 2399 XDrawBeveledButton(display,&windows->widget,&action_info); 2400 } 2401 if (cancel_info.raised == MagickFalse) 2402 { 2403 if (event.xbutton.window == windows->widget.id) 2404 if (MatteIsActive(cancel_info,event.xbutton)) 2405 { 2406 *reply_info.text='\0'; 2407 state|=ExitState; 2408 } 2409 cancel_info.raised=MagickTrue; 2410 XDrawBeveledButton(display,&windows->widget,&cancel_info); 2411 } 2412 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 2413 break; 2414 break; 2415 } 2416 case ClientMessage: 2417 { 2418 /* 2419 If client window delete message, exit. 2420 */ 2421 if (event.xclient.message_type != windows->wm_protocols) 2422 break; 2423 if (*event.xclient.data.l == (int) windows->wm_take_focus) 2424 { 2425 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 2426 (Time) event.xclient.data.l[1]); 2427 break; 2428 } 2429 if (*event.xclient.data.l != (int) windows->wm_delete_window) 2430 break; 2431 if (event.xclient.window == windows->widget.id) 2432 { 2433 *reply_info.text='\0'; 2434 state|=ExitState; 2435 break; 2436 } 2437 break; 2438 } 2439 case ConfigureNotify: 2440 { 2441 /* 2442 Update widget configuration. 2443 */ 2444 if (event.xconfigure.window != windows->widget.id) 2445 break; 2446 if ((event.xconfigure.width == (int) windows->widget.width) && 2447 (event.xconfigure.height == (int) windows->widget.height)) 2448 break; 2449 windows->widget.width=(unsigned int) 2450 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 2451 windows->widget.height=(unsigned int) 2452 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 2453 state|=UpdateConfigurationState; 2454 break; 2455 } 2456 case EnterNotify: 2457 { 2458 if (event.xcrossing.window != windows->widget.id) 2459 break; 2460 state&=(~InactiveWidgetState); 2461 break; 2462 } 2463 case Expose: 2464 { 2465 if (event.xexpose.window != windows->widget.id) 2466 break; 2467 if (event.xexpose.count != 0) 2468 break; 2469 state|=RedrawWidgetState; 2470 break; 2471 } 2472 case KeyPress: 2473 { 2474 static char 2475 command[MaxTextExtent]; 2476 2477 static int 2478 length; 2479 2480 static KeySym 2481 key_symbol; 2482 2483 /* 2484 Respond to a user key press. 2485 */ 2486 if (event.xkey.window != windows->widget.id) 2487 break; 2488 length=XLookupString((XKeyEvent *) &event.xkey,command, 2489 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 2490 *(command+length)='\0'; 2491 if (AreaIsActive(scroll_info,event.xkey)) 2492 { 2493 /* 2494 Move slider. 2495 */ 2496 switch ((int) key_symbol) 2497 { 2498 case XK_Home: 2499 case XK_KP_Home: 2500 { 2501 slider_info.id=0; 2502 break; 2503 } 2504 case XK_Up: 2505 case XK_KP_Up: 2506 { 2507 slider_info.id--; 2508 break; 2509 } 2510 case XK_Down: 2511 case XK_KP_Down: 2512 { 2513 slider_info.id++; 2514 break; 2515 } 2516 case XK_Prior: 2517 case XK_KP_Prior: 2518 { 2519 slider_info.id-=visible_colors; 2520 break; 2521 } 2522 case XK_Next: 2523 case XK_KP_Next: 2524 { 2525 slider_info.id+=visible_colors; 2526 break; 2527 } 2528 case XK_End: 2529 case XK_KP_End: 2530 { 2531 slider_info.id=(int) colors; 2532 break; 2533 } 2534 } 2535 state|=RedrawListState; 2536 break; 2537 } 2538 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 2539 { 2540 /* 2541 Read new color or glob patterm. 2542 */ 2543 if (*reply_info.text == '\0') 2544 break; 2545 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent); 2546 state|=UpdateListState; 2547 break; 2548 } 2549 if (key_symbol == XK_Control_L) 2550 { 2551 state|=ControlState; 2552 break; 2553 } 2554 if (state & ControlState) 2555 switch ((int) key_symbol) 2556 { 2557 case XK_u: 2558 case XK_U: 2559 { 2560 /* 2561 Erase the entire line of text. 2562 */ 2563 *reply_info.text='\0'; 2564 reply_info.cursor=reply_info.text; 2565 reply_info.marker=reply_info.text; 2566 reply_info.highlight=MagickFalse; 2567 break; 2568 } 2569 default: 2570 break; 2571 } 2572 XEditText(display,&reply_info,key_symbol,command,state); 2573 XDrawMatteText(display,&windows->widget,&reply_info); 2574 state|=JumpListState; 2575 status=XParseColor(display,windows->widget.map_info->colormap, 2576 reply_info.text,&color); 2577 if (status != False) 2578 state|=RedrawActionState; 2579 break; 2580 } 2581 case KeyRelease: 2582 { 2583 static char 2584 command[MaxTextExtent]; 2585 2586 static KeySym 2587 key_symbol; 2588 2589 /* 2590 Respond to a user key release. 2591 */ 2592 if (event.xkey.window != windows->widget.id) 2593 break; 2594 (void) XLookupString((XKeyEvent *) &event.xkey,command, 2595 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 2596 if (key_symbol == XK_Control_L) 2597 state&=(~ControlState); 2598 break; 2599 } 2600 case LeaveNotify: 2601 { 2602 if (event.xcrossing.window != windows->widget.id) 2603 break; 2604 state|=InactiveWidgetState; 2605 break; 2606 } 2607 case MapNotify: 2608 { 2609 mask&=(~CWX); 2610 mask&=(~CWY); 2611 break; 2612 } 2613 case MotionNotify: 2614 { 2615 /* 2616 Discard pending button motion events. 2617 */ 2618 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 2619 if (slider_info.active) 2620 { 2621 /* 2622 Move slider matte. 2623 */ 2624 slider_info.y=event.xmotion.y- 2625 ((slider_info.height+slider_info.bevel_width) >> 1)+1; 2626 if (slider_info.y < slider_info.min_y) 2627 slider_info.y=slider_info.min_y; 2628 if (slider_info.y > slider_info.max_y) 2629 slider_info.y=slider_info.max_y; 2630 slider_info.id=0; 2631 if (slider_info.y != slider_info.min_y) 2632 slider_info.id=(int) ((colors*(slider_info.y- 2633 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1)); 2634 state|=RedrawListState; 2635 break; 2636 } 2637 if (state & InactiveWidgetState) 2638 break; 2639 if (grab_info.raised == MatteIsActive(grab_info,event.xmotion)) 2640 { 2641 /* 2642 Grab button status changed. 2643 */ 2644 grab_info.raised=!grab_info.raised; 2645 XDrawBeveledButton(display,&windows->widget,&grab_info); 2646 break; 2647 } 2648 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion)) 2649 { 2650 /* 2651 Reset button status changed. 2652 */ 2653 reset_info.raised=!reset_info.raised; 2654 XDrawBeveledButton(display,&windows->widget,&reset_info); 2655 break; 2656 } 2657 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 2658 { 2659 /* 2660 Action button status changed. 2661 */ 2662 action_info.raised=action_info.raised == MagickFalse ? 2663 MagickTrue : MagickFalse; 2664 XDrawBeveledButton(display,&windows->widget,&action_info); 2665 break; 2666 } 2667 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 2668 { 2669 /* 2670 Cancel button status changed. 2671 */ 2672 cancel_info.raised=cancel_info.raised == MagickFalse ? 2673 MagickTrue : MagickFalse; 2674 XDrawBeveledButton(display,&windows->widget,&cancel_info); 2675 break; 2676 } 2677 break; 2678 } 2679 case SelectionClear: 2680 { 2681 reply_info.highlight=MagickFalse; 2682 XDrawMatteText(display,&windows->widget,&reply_info); 2683 break; 2684 } 2685 case SelectionNotify: 2686 { 2687 Atom 2688 type; 2689 2690 int 2691 format; 2692 2693 unsigned char 2694 *data; 2695 2696 unsigned long 2697 after, 2698 length; 2699 2700 /* 2701 Obtain response from primary selection. 2702 */ 2703 if (event.xselection.property == (Atom) None) 2704 break; 2705 status=XGetWindowProperty(display,event.xselection.requestor, 2706 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type, 2707 &format,&length,&after,&data); 2708 if ((status != Success) || (type != XA_STRING) || (format == 32) || 2709 (length == 0)) 2710 break; 2711 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 2712 (void) XBell(display,0); 2713 else 2714 { 2715 /* 2716 Insert primary selection in reply text. 2717 */ 2718 *(data+length)='\0'; 2719 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 2720 state); 2721 XDrawMatteText(display,&windows->widget,&reply_info); 2722 state|=JumpListState; 2723 state|=RedrawActionState; 2724 } 2725 (void) XFree((void *) data); 2726 break; 2727 } 2728 case SelectionRequest: 2729 { 2730 XSelectionEvent 2731 notify; 2732 2733 XSelectionRequestEvent 2734 *request; 2735 2736 if (reply_info.highlight == MagickFalse) 2737 break; 2738 /* 2739 Set primary selection. 2740 */ 2741 request=(&(event.xselectionrequest)); 2742 (void) XChangeProperty(request->display,request->requestor, 2743 request->property,request->target,8,PropModeReplace, 2744 (unsigned char *) primary_selection,Extent(primary_selection)); 2745 notify.type=SelectionNotify; 2746 notify.send_event=MagickTrue; 2747 notify.display=request->display; 2748 notify.requestor=request->requestor; 2749 notify.selection=request->selection; 2750 notify.target=request->target; 2751 notify.time=request->time; 2752 if (request->property == None) 2753 notify.property=request->target; 2754 else 2755 notify.property=request->property; 2756 (void) XSendEvent(request->display,request->requestor,False, 2757 NoEventMask,(XEvent *) ¬ify); 2758 } 2759 default: 2760 break; 2761 } 2762 } while ((state & ExitState) == 0); 2763 XSetCursorState(display,windows,MagickFalse); 2764 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 2765 XCheckRefreshWindows(display,windows); 2766 /* 2767 Free color list. 2768 */ 2769 for (i=0; i < (int) colors; i++) 2770 colorlist[i]=DestroyString(colorlist[i]); 2771 if (colorlist != (char **) NULL) 2772 colorlist=(char **) RelinquishMagickMemory(colorlist); 2773 exception=DestroyExceptionInfo(exception); 2774 if ((*reply == '\0') || (strchr(reply,'-') != (char *) NULL)) 2775 return; 2776 status=XParseColor(display,windows->widget.map_info->colormap,reply,&color); 2777 if (status != False) 2778 return; 2779 XNoticeWidget(display,windows,"Color is unknown to X server:",reply); 2780 (void) CopyMagickString(reply,"gray",MaxTextExtent); 2781} 2782 2783/* 2784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2785% % 2786% % 2787% % 2788% X C o m m a n d W i d g e t % 2789% % 2790% % 2791% % 2792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2793% 2794% XCommandWidget() maps a menu and returns the command pointed to by the user 2795% when the button is released. 2796% 2797% The format of the XCommandWidget method is: 2798% 2799% int XCommandWidget(Display *display,XWindows *windows, 2800% const char **selections,XEvent *event) 2801% 2802% A description of each parameter follows: 2803% 2804% o selection_number: Specifies the number of the selection that the 2805% user choose. 2806% 2807% o display: Specifies a connection to an X server; returned from 2808% XOpenDisplay. 2809% 2810% o window: Specifies a pointer to a XWindows structure. 2811% 2812% o selections: Specifies a pointer to one or more strings that comprise 2813% the choices in the menu. 2814% 2815% o event: Specifies a pointer to a X11 XEvent structure. 2816% 2817*/ 2818MagickPrivate int XCommandWidget(Display *display,XWindows *windows, 2819 const char **selections,XEvent *event) 2820{ 2821#define tile_width 112 2822#define tile_height 70 2823 2824 static const unsigned char 2825 tile_bits[]= 2826 { 2827 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2828 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2829 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 2831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 2832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 2833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2834 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2835 0x00, 0x00, 0x1e, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2836 0x00, 0x00, 0x00, 0x00, 0x1e, 0xbc, 0x9f, 0x03, 0x00, 0x3e, 0x00, 0xc0, 2837 0x1f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x0f, 0x80, 0x3f, 2838 0x00, 0xf0, 0x1f, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x1f, 2839 0xe0, 0x3f, 0x00, 0xfc, 0x1f, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 2840 0xff, 0x1f, 0xf0, 0x3f, 0x00, 0xfe, 0x1f, 0xf8, 0x0f, 0x00, 0x00, 0x00, 2841 0x1e, 0xfc, 0xfc, 0x3f, 0xf8, 0x3f, 0x00, 0xff, 0x1e, 0xfc, 0x0f, 0x00, 2842 0x00, 0x00, 0x1e, 0x7c, 0xfc, 0x3e, 0xf8, 0x3c, 0x80, 0x1f, 0x1e, 0x7c, 2843 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 0xc0, 0x0f, 2844 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 2845 0xc0, 0x07, 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 2846 0x7c, 0x7c, 0xc0, 0x0f, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78, 2847 0x78, 0x3c, 0xfc, 0x7c, 0x80, 0x7f, 0x1e, 0x7c, 0x00, 0x00, 0x00, 0x00, 2848 0x1e, 0xf8, 0x78, 0x7c, 0xf8, 0xff, 0x00, 0xff, 0x1f, 0xf8, 0xff, 0x00, 2849 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xfe, 0x1f, 0xf8, 2850 0xff, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xf8, 2851 0x1f, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xc0, 0xef, 2852 0x07, 0xe0, 0x1f, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0x70, 0x40, 0x78, 2853 0x00, 0xc7, 0x07, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 2854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 2855 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 2856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 2857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 2858 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2859 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2860 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2861 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 2862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 2863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 2864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 2865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2866 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00, 2867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 2868 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2869 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2870 0x60, 0x00, 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2871 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 2872 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 2873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0x9f, 0x7f, 0x00, 2874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0xdf, 2875 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 2876 0xe0, 0xdf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0c, 2877 0x78, 0x30, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 2878 0x00, 0x0f, 0xf8, 0x70, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x1f, 0x00, 0xe0, 2879 0x0f, 0x1e, 0x80, 0x0f, 0xf8, 0x78, 0xf0, 0xfd, 0xf9, 0x00, 0xc0, 0x1f, 2880 0x00, 0xf8, 0x0f, 0x00, 0xe0, 0x1f, 0xf8, 0x7c, 0xf0, 0xfc, 0xf9, 0x00, 2881 0xf0, 0x1f, 0x00, 0xfe, 0x0f, 0x00, 0xf0, 0x07, 0xf8, 0x3e, 0xf8, 0xfc, 2882 0xf0, 0x01, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x1e, 0xf0, 0x03, 0xf8, 0x3f, 2883 0xf8, 0xf8, 0xf0, 0x01, 0xfc, 0x1f, 0x80, 0x7f, 0x0f, 0x1e, 0xf8, 0x00, 2884 0xf8, 0x1f, 0x78, 0x18, 0xf0, 0x01, 0x7c, 0x1e, 0xc0, 0x0f, 0x0f, 0x1e, 2885 0x7c, 0x00, 0xf0, 0x0f, 0x78, 0x00, 0xf0, 0x01, 0x3e, 0x1e, 0xe0, 0x07, 2886 0x0f, 0x1e, 0x7c, 0x00, 0xf0, 0x07, 0x7c, 0x00, 0xe0, 0x01, 0x3e, 0x1e, 2887 0xe0, 0x03, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x0f, 0x7c, 0x00, 0xe0, 0x03, 2888 0x3e, 0x3e, 0xe0, 0x07, 0x0f, 0x1e, 0x1e, 0x00, 0xf0, 0x1f, 0x3c, 0x00, 2889 0xe0, 0x03, 0x7e, 0x3e, 0xc0, 0x3f, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x1f, 2890 0x3e, 0x00, 0xe0, 0x03, 0xfc, 0x7f, 0x80, 0xff, 0x0f, 0x1e, 0xfc, 0x00, 2891 0xf0, 0x3e, 0x3e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xff, 0x0f, 0x1e, 2892 0xfc, 0x07, 0xf0, 0x7c, 0x1e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xfc, 2893 0x0f, 0x1e, 0xf8, 0x1f, 0xf0, 0xf8, 0x1e, 0x00, 0xc0, 0x03, 0xe0, 0xf7, 2894 0x03, 0xf0, 0x0f, 0x1e, 0xe0, 0x3f, 0xf0, 0x78, 0x1c, 0x00, 0x80, 0x03, 2895 0x80, 0xe3, 0x03, 0x00, 0x0f, 0x1e, 0xc0, 0x3f, 0xf0, 0x30, 0x00, 0x00, 2896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x3e, 0x00, 0x00, 2897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x10, 2898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 2899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 2900 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2901 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2902 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2903 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 2904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 2905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 2906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 2907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2908 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 2909 }; 2910 2911 int 2912 id, 2913 y; 2914 2915 register int 2916 i; 2917 2918 static unsigned int 2919 number_selections; 2920 2921 unsigned int 2922 height; 2923 2924 size_t 2925 state; 2926 2927 XFontStruct 2928 *font_info; 2929 2930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 2931 assert(display != (Display *) NULL); 2932 assert(windows != (XWindows *) NULL); 2933 font_info=windows->command.font_info; 2934 height=(unsigned int) (font_info->ascent+font_info->descent); 2935 id=(~0); 2936 state=DefaultState; 2937 if (event == (XEvent *) NULL) 2938 { 2939 unsigned int 2940 width; 2941 2942 XTextProperty 2943 window_name; 2944 2945 XWindowChanges 2946 window_changes; 2947 2948 /* 2949 Determine command window attributes. 2950 */ 2951 assert(selections != (const char **) NULL); 2952 windows->command.width=0; 2953 for (i=0; selections[i] != (char *) NULL; i++) 2954 { 2955 width=WidgetTextWidth(font_info,(char *) selections[i]); 2956 if (width > windows->command.width) 2957 windows->command.width=width; 2958 } 2959 number_selections=(unsigned int) i; 2960 windows->command.width+=3*QuantumMargin+10; 2961 if ((int) windows->command.width < (tile_width+QuantumMargin+10)) 2962 windows->command.width=(unsigned int) (tile_width+QuantumMargin+10); 2963 windows->command.height=(unsigned int) (number_selections* 2964 (((3*height) >> 1)+10)+tile_height+20); 2965 windows->command.min_width=windows->command.width; 2966 windows->command.min_height=windows->command.height; 2967 XConstrainWindowPosition(display,&windows->command); 2968 if (windows->command.id != (Window) NULL) 2969 { 2970 Status 2971 status; 2972 2973 /* 2974 Reconfigure command window. 2975 */ 2976 status=XStringListToTextProperty(&windows->command.name,1, 2977 &window_name); 2978 if (status != False) 2979 { 2980 XSetWMName(display,windows->command.id,&window_name); 2981 XSetWMIconName(display,windows->command.id,&window_name); 2982 (void) XFree((void *) window_name.value); 2983 } 2984 window_changes.width=(int) windows->command.width; 2985 window_changes.height=(int) windows->command.height; 2986 (void) XReconfigureWMWindow(display,windows->command.id, 2987 windows->command.screen,(unsigned int) (CWWidth | CWHeight), 2988 &window_changes); 2989 } 2990 /* 2991 Allocate selection info memory. 2992 */ 2993 if (selection_info != (XWidgetInfo *) NULL) 2994 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info); 2995 selection_info=(XWidgetInfo *) AcquireQuantumMemory(number_selections, 2996 sizeof(*selection_info)); 2997 if (selection_info == (XWidgetInfo *) NULL) 2998 { 2999 ThrowXWindowFatalException(ResourceLimitError, 3000 "MemoryAllocationFailed","..."); 3001 return(id); 3002 } 3003 state|=UpdateConfigurationState | RedrawWidgetState; 3004 } 3005 /* 3006 Wait for next event. 3007 */ 3008 if (event != (XEvent *) NULL) 3009 switch (event->type) 3010 { 3011 case ButtonPress: 3012 { 3013 for (i=0; i < (int) number_selections; i++) 3014 { 3015 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse) 3016 continue; 3017 if (i >= (int) windows->command.data) 3018 { 3019 selection_info[i].raised=MagickFalse; 3020 XDrawBeveledButton(display,&windows->command,&selection_info[i]); 3021 break; 3022 } 3023 submenu_info=selection_info[i]; 3024 submenu_info.active=MagickTrue; 3025 toggle_info.y= 3026 submenu_info.y+(submenu_info.height >> 1)-(toggle_info.height >> 1); 3027 id=i; 3028 (void) XCheckWindowEvent(display,windows->widget.id,LeaveWindowMask, 3029 event); 3030 break; 3031 } 3032 break; 3033 } 3034 case ButtonRelease: 3035 { 3036 for (i=0; i < (int) number_selections; i++) 3037 { 3038 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse) 3039 continue; 3040 id=i; 3041 if (id >= (int) windows->command.data) 3042 { 3043 selection_info[id].raised=MagickTrue; 3044 XDrawBeveledButton(display,&windows->command,&selection_info[id]); 3045 break; 3046 } 3047 break; 3048 } 3049 break; 3050 } 3051 case ClientMessage: 3052 { 3053 /* 3054 If client window delete message, withdraw command widget. 3055 */ 3056 if (event->xclient.message_type != windows->wm_protocols) 3057 break; 3058 if (*event->xclient.data.l != (int) windows->wm_delete_window) 3059 break; 3060 (void) XWithdrawWindow(display,windows->command.id, 3061 windows->command.screen); 3062 break; 3063 } 3064 case ConfigureNotify: 3065 { 3066 /* 3067 Update widget configuration. 3068 */ 3069 if (event->xconfigure.window != windows->command.id) 3070 break; 3071 if (event->xconfigure.send_event != 0) 3072 { 3073 windows->command.x=event->xconfigure.x; 3074 windows->command.y=event->xconfigure.y; 3075 } 3076 if ((event->xconfigure.width == (int) windows->command.width) && 3077 (event->xconfigure.height == (int) windows->command.height)) 3078 break; 3079 windows->command.width=(unsigned int) 3080 MagickMax(event->xconfigure.width,(int) windows->command.min_width); 3081 windows->command.height=(unsigned int) 3082 MagickMax(event->xconfigure.height,(int) windows->command.min_height); 3083 state|=UpdateConfigurationState; 3084 break; 3085 } 3086 case Expose: 3087 { 3088 if (event->xexpose.window != windows->command.id) 3089 break; 3090 if (event->xexpose.count != 0) 3091 break; 3092 state|=RedrawWidgetState; 3093 break; 3094 } 3095 case MotionNotify: 3096 { 3097 /* 3098 Return the ID of the highlighted menu entry. 3099 */ 3100 for ( ; ; ) 3101 { 3102 for (i=0; i < (int) number_selections; i++) 3103 { 3104 if (i >= (int) windows->command.data) 3105 { 3106 if (selection_info[i].raised == 3107 MatteIsActive(selection_info[i],event->xmotion)) 3108 { 3109 /* 3110 Button status changed. 3111 */ 3112 selection_info[i].raised=!selection_info[i].raised; 3113 XDrawBeveledButton(display,&windows->command, 3114 &selection_info[i]); 3115 } 3116 continue; 3117 } 3118 if (MatteIsActive(selection_info[i],event->xmotion) == MagickFalse) 3119 continue; 3120 submenu_info=selection_info[i]; 3121 submenu_info.active=MagickTrue; 3122 toggle_info.raised=MagickTrue; 3123 toggle_info.y=submenu_info.y+(submenu_info.height >> 1)- 3124 (toggle_info.height >> 1); 3125 XDrawTriangleEast(display,&windows->command,&toggle_info); 3126 id=i; 3127 } 3128 XDelay(display,SuspendTime); 3129 if (XCheckMaskEvent(display,ButtonMotionMask,event) == MagickFalse) 3130 break; 3131 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ; 3132 toggle_info.raised=MagickFalse; 3133 if (windows->command.data != 0) 3134 XDrawTriangleEast(display,&windows->command,&toggle_info); 3135 } 3136 break; 3137 } 3138 case MapNotify: 3139 { 3140 windows->command.mapped=MagickTrue; 3141 break; 3142 } 3143 case UnmapNotify: 3144 { 3145 windows->command.mapped=MagickFalse; 3146 break; 3147 } 3148 default: 3149 break; 3150 } 3151 if (state & UpdateConfigurationState) 3152 { 3153 /* 3154 Initialize button information. 3155 */ 3156 assert(selections != (const char **) NULL); 3157 y=tile_height+20; 3158 for (i=0; i < (int) number_selections; i++) 3159 { 3160 XGetWidgetInfo(selections[i],&selection_info[i]); 3161 selection_info[i].center=MagickFalse; 3162 selection_info[i].bevel_width--; 3163 selection_info[i].height=(unsigned int) ((3*height) >> 1); 3164 selection_info[i].x=(QuantumMargin >> 1)+4; 3165 selection_info[i].width=(unsigned int) 3166 (windows->command.width-(selection_info[i].x << 1)); 3167 selection_info[i].y=y; 3168 y+=selection_info[i].height+(selection_info[i].bevel_width << 1)+6; 3169 } 3170 XGetWidgetInfo((char *) NULL,&toggle_info); 3171 toggle_info.bevel_width--; 3172 toggle_info.width=(unsigned int) 3173 (((5*height) >> 3)-(toggle_info.bevel_width << 1)); 3174 toggle_info.height=toggle_info.width; 3175 toggle_info.x=selection_info[0].x+selection_info[0].width- 3176 toggle_info.width-(QuantumMargin >> 1); 3177 if (windows->command.mapped) 3178 (void) XClearWindow(display,windows->command.id); 3179 } 3180 if (state & RedrawWidgetState) 3181 { 3182 Pixmap 3183 tile_pixmap; 3184 3185 /* 3186 Draw command buttons. 3187 */ 3188 tile_pixmap=XCreatePixmapFromBitmapData(display,windows->command.id, 3189 (char *) tile_bits,tile_width,tile_height,1L,0L,1); 3190 if (tile_pixmap != (Pixmap) NULL) 3191 { 3192 (void) XCopyPlane(display,tile_pixmap,windows->command.id, 3193 windows->command.annotate_context,0,0,tile_width,tile_height, 3194 (int) ((windows->command.width-tile_width) >> 1),10,1L); 3195 (void) XFreePixmap(display,tile_pixmap); 3196 } 3197 for (i=0; i < (int) number_selections; i++) 3198 { 3199 XDrawBeveledButton(display,&windows->command,&selection_info[i]); 3200 if (i >= (int) windows->command.data) 3201 continue; 3202 toggle_info.raised=i == id ? MagickTrue : MagickFalse; 3203 toggle_info.y=selection_info[i].y+ 3204 (selection_info[i].height >> 1)-(toggle_info.height >> 1); 3205 XDrawTriangleEast(display,&windows->command,&toggle_info); 3206 } 3207 XHighlightWidget(display,&windows->command,BorderOffset,BorderOffset); 3208 } 3209 return(id); 3210} 3211 3212/* 3213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3214% % 3215% % 3216% % 3217% X C o n f i r m W i d g e t % 3218% % 3219% % 3220% % 3221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3222% 3223% XConfirmWidget() displays a Confirm widget with a notice to the user. The 3224% function returns -1 if Dismiss is pressed, 0 for Cancel, and 1 for Yes. 3225% 3226% The format of the XConfirmWidget method is: 3227% 3228% int XConfirmWidget(Display *display,XWindows *windows, 3229% const char *reason,const char *description) 3230% 3231% A description of each parameter follows: 3232% 3233% o display: Specifies a connection to an X server; returned from 3234% XOpenDisplay. 3235% 3236% o window: Specifies a pointer to a XWindows structure. 3237% 3238% o reason: Specifies the message to display before terminating the 3239% program. 3240% 3241% o description: Specifies any description to the message. 3242% 3243*/ 3244MagickPrivate int XConfirmWidget(Display *display,XWindows *windows, 3245 const char *reason,const char *description) 3246{ 3247#define CancelButtonText "Cancel" 3248#define DismissButtonText "Dismiss" 3249#define YesButtonText "Yes" 3250 3251 int 3252 confirm, 3253 x, 3254 y; 3255 3256 Status 3257 status; 3258 3259 unsigned int 3260 height, 3261 width; 3262 3263 size_t 3264 state; 3265 3266 XEvent 3267 event; 3268 3269 XFontStruct 3270 *font_info; 3271 3272 XTextProperty 3273 window_name; 3274 3275 XWidgetInfo 3276 cancel_info, 3277 dismiss_info, 3278 yes_info; 3279 3280 XWindowChanges 3281 window_changes; 3282 3283 /* 3284 Determine Confirm widget attributes. 3285 */ 3286 assert(display != (Display *) NULL); 3287 assert(windows != (XWindows *) NULL); 3288 assert(reason != (char *) NULL); 3289 assert(description != (char *) NULL); 3290 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason); 3291 XCheckRefreshWindows(display,windows); 3292 font_info=windows->widget.font_info; 3293 width=WidgetTextWidth(font_info,CancelButtonText); 3294 if (WidgetTextWidth(font_info,DismissButtonText) > width) 3295 width=WidgetTextWidth(font_info,DismissButtonText); 3296 if (WidgetTextWidth(font_info,YesButtonText) > width) 3297 width=WidgetTextWidth(font_info,YesButtonText); 3298 width<<=1; 3299 if (description != (char *) NULL) 3300 if (WidgetTextWidth(font_info,(char *) description) > width) 3301 width=WidgetTextWidth(font_info,(char *) description); 3302 height=(unsigned int) (font_info->ascent+font_info->descent); 3303 /* 3304 Position Confirm widget. 3305 */ 3306 windows->widget.width=(unsigned int) (width+9*QuantumMargin); 3307 windows->widget.min_width=(unsigned int) (9*QuantumMargin+ 3308 WidgetTextWidth(font_info,CancelButtonText)+ 3309 WidgetTextWidth(font_info,DismissButtonText)+ 3310 WidgetTextWidth(font_info,YesButtonText)); 3311 if (windows->widget.width < windows->widget.min_width) 3312 windows->widget.width=windows->widget.min_width; 3313 windows->widget.height=(unsigned int) (12*height); 3314 windows->widget.min_height=(unsigned int) (7*height); 3315 if (windows->widget.height < windows->widget.min_height) 3316 windows->widget.height=windows->widget.min_height; 3317 XConstrainWindowPosition(display,&windows->widget); 3318 /* 3319 Map Confirm widget. 3320 */ 3321 (void) CopyMagickString(windows->widget.name,"Confirm",MaxTextExtent); 3322 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 3323 if (status != False) 3324 { 3325 XSetWMName(display,windows->widget.id,&window_name); 3326 XSetWMIconName(display,windows->widget.id,&window_name); 3327 (void) XFree((void *) window_name.value); 3328 } 3329 window_changes.width=(int) windows->widget.width; 3330 window_changes.height=(int) windows->widget.height; 3331 window_changes.x=windows->widget.x; 3332 window_changes.y=windows->widget.y; 3333 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 3334 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes); 3335 (void) XMapRaised(display,windows->widget.id); 3336 windows->widget.mapped=MagickFalse; 3337 /* 3338 Respond to X events. 3339 */ 3340 confirm=0; 3341 state=UpdateConfigurationState; 3342 XSetCursorState(display,windows,MagickTrue); 3343 do 3344 { 3345 if (state & UpdateConfigurationState) 3346 { 3347 /* 3348 Initialize button information. 3349 */ 3350 XGetWidgetInfo(CancelButtonText,&cancel_info); 3351 cancel_info.width=(unsigned int) QuantumMargin+ 3352 WidgetTextWidth(font_info,CancelButtonText); 3353 cancel_info.height=(unsigned int) ((3*height) >> 1); 3354 cancel_info.x=(int) (windows->widget.width-cancel_info.width- 3355 QuantumMargin); 3356 cancel_info.y=(int) (windows->widget.height-(cancel_info.height << 1)); 3357 dismiss_info=cancel_info; 3358 dismiss_info.text=(char *) DismissButtonText; 3359 if (LocaleCompare(description,"Do you want to save it") == 0) 3360 dismiss_info.text=(char *) "Don't Save"; 3361 dismiss_info.width=(unsigned int) QuantumMargin+ 3362 WidgetTextWidth(font_info,dismiss_info.text); 3363 dismiss_info.x=(int) 3364 ((windows->widget.width >> 1)-(dismiss_info.width >> 1)); 3365 yes_info=cancel_info; 3366 yes_info.text=(char *) YesButtonText; 3367 if (LocaleCompare(description,"Do you want to save it") == 0) 3368 yes_info.text=(char *) "Save"; 3369 yes_info.width=(unsigned int) QuantumMargin+ 3370 WidgetTextWidth(font_info,yes_info.text); 3371 if (yes_info.width < cancel_info.width) 3372 yes_info.width=cancel_info.width; 3373 yes_info.x=QuantumMargin; 3374 state&=(~UpdateConfigurationState); 3375 } 3376 if (state & RedrawWidgetState) 3377 { 3378 /* 3379 Redraw Confirm widget. 3380 */ 3381 width=WidgetTextWidth(font_info,(char *) reason); 3382 x=(int) ((windows->widget.width >> 1)-(width >> 1)); 3383 y=(int) ((windows->widget.height >> 1)-(height << 1)); 3384 (void) XDrawString(display,windows->widget.id, 3385 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason)); 3386 if (description != (char *) NULL) 3387 { 3388 char 3389 question[MaxTextExtent]; 3390 3391 (void) CopyMagickString(question,description,MaxTextExtent); 3392 (void) ConcatenateMagickString(question,"?",MaxTextExtent); 3393 width=WidgetTextWidth(font_info,question); 3394 x=(int) ((windows->widget.width >> 1)-(width >> 1)); 3395 y+=height; 3396 (void) XDrawString(display,windows->widget.id, 3397 windows->widget.annotate_context,x,y,question,Extent(question)); 3398 } 3399 XDrawBeveledButton(display,&windows->widget,&cancel_info); 3400 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 3401 XDrawBeveledButton(display,&windows->widget,&yes_info); 3402 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 3403 state&=(~RedrawWidgetState); 3404 } 3405 /* 3406 Wait for next event. 3407 */ 3408 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 3409 switch (event.type) 3410 { 3411 case ButtonPress: 3412 { 3413 if (MatteIsActive(cancel_info,event.xbutton)) 3414 { 3415 /* 3416 User pressed No button. 3417 */ 3418 cancel_info.raised=MagickFalse; 3419 XDrawBeveledButton(display,&windows->widget,&cancel_info); 3420 break; 3421 } 3422 if (MatteIsActive(dismiss_info,event.xbutton)) 3423 { 3424 /* 3425 User pressed Dismiss button. 3426 */ 3427 dismiss_info.raised=MagickFalse; 3428 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 3429 break; 3430 } 3431 if (MatteIsActive(yes_info,event.xbutton)) 3432 { 3433 /* 3434 User pressed Yes button. 3435 */ 3436 yes_info.raised=MagickFalse; 3437 XDrawBeveledButton(display,&windows->widget,&yes_info); 3438 break; 3439 } 3440 break; 3441 } 3442 case ButtonRelease: 3443 { 3444 if (windows->widget.mapped == MagickFalse) 3445 break; 3446 if (cancel_info.raised == MagickFalse) 3447 { 3448 if (event.xbutton.window == windows->widget.id) 3449 if (MatteIsActive(cancel_info,event.xbutton)) 3450 { 3451 confirm=0; 3452 state|=ExitState; 3453 } 3454 cancel_info.raised=MagickTrue; 3455 XDrawBeveledButton(display,&windows->widget,&cancel_info); 3456 } 3457 if (dismiss_info.raised == MagickFalse) 3458 { 3459 if (event.xbutton.window == windows->widget.id) 3460 if (MatteIsActive(dismiss_info,event.xbutton)) 3461 { 3462 confirm=(-1); 3463 state|=ExitState; 3464 } 3465 dismiss_info.raised=MagickTrue; 3466 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 3467 } 3468 if (yes_info.raised == MagickFalse) 3469 { 3470 if (event.xbutton.window == windows->widget.id) 3471 if (MatteIsActive(yes_info,event.xbutton)) 3472 { 3473 confirm=1; 3474 state|=ExitState; 3475 } 3476 yes_info.raised=MagickTrue; 3477 XDrawBeveledButton(display,&windows->widget,&yes_info); 3478 } 3479 break; 3480 } 3481 case ClientMessage: 3482 { 3483 /* 3484 If client window delete message, exit. 3485 */ 3486 if (event.xclient.message_type != windows->wm_protocols) 3487 break; 3488 if (*event.xclient.data.l == (int) windows->wm_take_focus) 3489 { 3490 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 3491 (Time) event.xclient.data.l[1]); 3492 break; 3493 } 3494 if (*event.xclient.data.l != (int) windows->wm_delete_window) 3495 break; 3496 if (event.xclient.window == windows->widget.id) 3497 { 3498 state|=ExitState; 3499 break; 3500 } 3501 break; 3502 } 3503 case ConfigureNotify: 3504 { 3505 /* 3506 Update widget configuration. 3507 */ 3508 if (event.xconfigure.window != windows->widget.id) 3509 break; 3510 if ((event.xconfigure.width == (int) windows->widget.width) && 3511 (event.xconfigure.height == (int) windows->widget.height)) 3512 break; 3513 windows->widget.width=(unsigned int) 3514 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 3515 windows->widget.height=(unsigned int) 3516 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 3517 state|=UpdateConfigurationState; 3518 break; 3519 } 3520 case EnterNotify: 3521 { 3522 if (event.xcrossing.window != windows->widget.id) 3523 break; 3524 state&=(~InactiveWidgetState); 3525 break; 3526 } 3527 case Expose: 3528 { 3529 if (event.xexpose.window != windows->widget.id) 3530 break; 3531 if (event.xexpose.count != 0) 3532 break; 3533 state|=RedrawWidgetState; 3534 break; 3535 } 3536 case KeyPress: 3537 { 3538 static char 3539 command[MaxTextExtent]; 3540 3541 static KeySym 3542 key_symbol; 3543 3544 /* 3545 Respond to a user key press. 3546 */ 3547 if (event.xkey.window != windows->widget.id) 3548 break; 3549 (void) XLookupString((XKeyEvent *) &event.xkey,command, 3550 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 3551 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 3552 { 3553 yes_info.raised=MagickFalse; 3554 XDrawBeveledButton(display,&windows->widget,&yes_info); 3555 confirm=1; 3556 state|=ExitState; 3557 break; 3558 } 3559 break; 3560 } 3561 case LeaveNotify: 3562 { 3563 if (event.xcrossing.window != windows->widget.id) 3564 break; 3565 state|=InactiveWidgetState; 3566 break; 3567 } 3568 case MotionNotify: 3569 { 3570 /* 3571 Discard pending button motion events. 3572 */ 3573 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 3574 if (state & InactiveWidgetState) 3575 break; 3576 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 3577 { 3578 /* 3579 Cancel button status changed. 3580 */ 3581 cancel_info.raised=cancel_info.raised == MagickFalse ? 3582 MagickTrue : MagickFalse; 3583 XDrawBeveledButton(display,&windows->widget,&cancel_info); 3584 break; 3585 } 3586 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion)) 3587 { 3588 /* 3589 Dismiss button status changed. 3590 */ 3591 dismiss_info.raised=cancel_info.raised == MagickFalse ? 3592 MagickTrue : MagickFalse; 3593 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 3594 break; 3595 } 3596 if (yes_info.raised == MatteIsActive(yes_info,event.xmotion)) 3597 { 3598 /* 3599 Yes button status changed. 3600 */ 3601 yes_info.raised=yes_info.raised == MagickFalse ? 3602 MagickTrue : MagickFalse; 3603 XDrawBeveledButton(display,&windows->widget,&yes_info); 3604 break; 3605 } 3606 break; 3607 } 3608 default: 3609 break; 3610 } 3611 } while ((state & ExitState) == 0); 3612 XSetCursorState(display,windows,MagickFalse); 3613 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 3614 XCheckRefreshWindows(display,windows); 3615 return(confirm); 3616} 3617 3618/* 3619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3620% % 3621% % 3622% % 3623% X D i a l o g W i d g e t % 3624% % 3625% % 3626% % 3627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3628% 3629% XDialogWidget() displays a Dialog widget with a query to the user. The user 3630% keys a reply and presses the Ok or Cancel button to exit. The typed text is 3631% returned as the reply function parameter. 3632% 3633% The format of the XDialogWidget method is: 3634% 3635% int XDialogWidget(Display *display,XWindows *windows,const char *action, 3636% const char *query,char *reply) 3637% 3638% A description of each parameter follows: 3639% 3640% o display: Specifies a connection to an X server; returned from 3641% XOpenDisplay. 3642% 3643% o window: Specifies a pointer to a XWindows structure. 3644% 3645% o action: Specifies a pointer to the action of this widget. 3646% 3647% o query: Specifies a pointer to the query to present to the user. 3648% 3649% o reply: the response from the user is returned in this parameter. 3650% 3651*/ 3652MagickPrivate int XDialogWidget(Display *display,XWindows *windows, 3653 const char *action,const char *query,char *reply) 3654{ 3655#define CancelButtonText "Cancel" 3656 3657 char 3658 primary_selection[MaxTextExtent]; 3659 3660 int 3661 x; 3662 3663 register int 3664 i; 3665 3666 static MagickBooleanType 3667 raised = MagickFalse; 3668 3669 Status 3670 status; 3671 3672 unsigned int 3673 anomaly, 3674 height, 3675 width; 3676 3677 size_t 3678 state; 3679 3680 XEvent 3681 event; 3682 3683 XFontStruct 3684 *font_info; 3685 3686 XTextProperty 3687 window_name; 3688 3689 XWidgetInfo 3690 action_info, 3691 cancel_info, 3692 reply_info, 3693 special_info, 3694 text_info; 3695 3696 XWindowChanges 3697 window_changes; 3698 3699 /* 3700 Determine Dialog widget attributes. 3701 */ 3702 assert(display != (Display *) NULL); 3703 assert(windows != (XWindows *) NULL); 3704 assert(action != (char *) NULL); 3705 assert(query != (char *) NULL); 3706 assert(reply != (char *) NULL); 3707 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 3708 XCheckRefreshWindows(display,windows); 3709 font_info=windows->widget.font_info; 3710 width=WidgetTextWidth(font_info,(char *) action); 3711 if (WidgetTextWidth(font_info,CancelButtonText) > width) 3712 width=WidgetTextWidth(font_info,CancelButtonText); 3713 width+=(3*QuantumMargin) >> 1; 3714 height=(unsigned int) (font_info->ascent+font_info->descent); 3715 /* 3716 Position Dialog widget. 3717 */ 3718 windows->widget.width=(unsigned int) MagickMax((int) (2*width),(int) 3719 WidgetTextWidth(font_info,(char *) query)); 3720 if (windows->widget.width < WidgetTextWidth(font_info,reply)) 3721 windows->widget.width=WidgetTextWidth(font_info,reply); 3722 windows->widget.width+=6*QuantumMargin; 3723 windows->widget.min_width=(unsigned int) 3724 (width+28*XTextWidth(font_info,"#",1)+4*QuantumMargin); 3725 if (windows->widget.width < windows->widget.min_width) 3726 windows->widget.width=windows->widget.min_width; 3727 windows->widget.height=(unsigned int) (7*height+(QuantumMargin << 1)); 3728 windows->widget.min_height=windows->widget.height; 3729 if (windows->widget.height < windows->widget.min_height) 3730 windows->widget.height=windows->widget.min_height; 3731 XConstrainWindowPosition(display,&windows->widget); 3732 /* 3733 Map Dialog widget. 3734 */ 3735 (void) CopyMagickString(windows->widget.name,"Dialog",MaxTextExtent); 3736 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 3737 if (status != False) 3738 { 3739 XSetWMName(display,windows->widget.id,&window_name); 3740 XSetWMIconName(display,windows->widget.id,&window_name); 3741 (void) XFree((void *) window_name.value); 3742 } 3743 window_changes.width=(int) windows->widget.width; 3744 window_changes.height=(int) windows->widget.height; 3745 window_changes.x=windows->widget.x; 3746 window_changes.y=windows->widget.y; 3747 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 3748 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes); 3749 (void) XMapRaised(display,windows->widget.id); 3750 windows->widget.mapped=MagickFalse; 3751 /* 3752 Respond to X events. 3753 */ 3754 anomaly=(LocaleCompare(action,"Background") == 0) || 3755 (LocaleCompare(action,"New") == 0) || 3756 (LocaleCompare(action,"Quantize") == 0) || 3757 (LocaleCompare(action,"Resize") == 0) || 3758 (LocaleCompare(action,"Save") == 0) || 3759 (LocaleCompare(action,"Shade") == 0); 3760 state=UpdateConfigurationState; 3761 XSetCursorState(display,windows,MagickTrue); 3762 do 3763 { 3764 if (state & UpdateConfigurationState) 3765 { 3766 /* 3767 Initialize button information. 3768 */ 3769 XGetWidgetInfo(CancelButtonText,&cancel_info); 3770 cancel_info.width=width; 3771 cancel_info.height=(unsigned int) ((3*height) >> 1); 3772 cancel_info.x=(int) 3773 (windows->widget.width-cancel_info.width-((3*QuantumMargin) >> 1)); 3774 cancel_info.y=(int) 3775 (windows->widget.height-cancel_info.height-((3*QuantumMargin) >> 1)); 3776 XGetWidgetInfo(action,&action_info); 3777 action_info.width=width; 3778 action_info.height=(unsigned int) ((3*height) >> 1); 3779 action_info.x=cancel_info.x-(cancel_info.width+QuantumMargin+ 3780 (action_info.bevel_width << 1)); 3781 action_info.y=cancel_info.y; 3782 /* 3783 Initialize reply information. 3784 */ 3785 XGetWidgetInfo(reply,&reply_info); 3786 reply_info.raised=MagickFalse; 3787 reply_info.bevel_width--; 3788 reply_info.width=windows->widget.width-(3*QuantumMargin); 3789 reply_info.height=height << 1; 3790 reply_info.x=(3*QuantumMargin) >> 1; 3791 reply_info.y=action_info.y-reply_info.height-QuantumMargin; 3792 /* 3793 Initialize option information. 3794 */ 3795 XGetWidgetInfo("Dither",&special_info); 3796 special_info.raised=raised; 3797 special_info.bevel_width--; 3798 special_info.width=(unsigned int) QuantumMargin >> 1; 3799 special_info.height=(unsigned int) QuantumMargin >> 1; 3800 special_info.x=reply_info.x; 3801 special_info.y=action_info.y+action_info.height-special_info.height; 3802 if (LocaleCompare(action,"Background") == 0) 3803 special_info.text=(char *) "Backdrop"; 3804 if (LocaleCompare(action,"New") == 0) 3805 special_info.text=(char *) "Gradation"; 3806 if (LocaleCompare(action,"Resize") == 0) 3807 special_info.text=(char *) "Constrain ratio"; 3808 if (LocaleCompare(action,"Save") == 0) 3809 special_info.text=(char *) "Non-progressive"; 3810 if (LocaleCompare(action,"Shade") == 0) 3811 special_info.text=(char *) "Color shading"; 3812 /* 3813 Initialize text information. 3814 */ 3815 XGetWidgetInfo(query,&text_info); 3816 text_info.width=reply_info.width; 3817 text_info.height=height; 3818 text_info.x=reply_info.x-(QuantumMargin >> 1); 3819 text_info.y=QuantumMargin; 3820 text_info.center=MagickFalse; 3821 state&=(~UpdateConfigurationState); 3822 } 3823 if (state & RedrawWidgetState) 3824 { 3825 /* 3826 Redraw Dialog widget. 3827 */ 3828 XDrawWidgetText(display,&windows->widget,&text_info); 3829 XDrawBeveledMatte(display,&windows->widget,&reply_info); 3830 XDrawMatteText(display,&windows->widget,&reply_info); 3831 if (anomaly) 3832 XDrawBeveledButton(display,&windows->widget,&special_info); 3833 XDrawBeveledButton(display,&windows->widget,&action_info); 3834 XDrawBeveledButton(display,&windows->widget,&cancel_info); 3835 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 3836 state&=(~RedrawWidgetState); 3837 } 3838 /* 3839 Wait for next event. 3840 */ 3841 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 3842 switch (event.type) 3843 { 3844 case ButtonPress: 3845 { 3846 if (anomaly) 3847 if (MatteIsActive(special_info,event.xbutton)) 3848 { 3849 /* 3850 Option button status changed. 3851 */ 3852 special_info.raised=!special_info.raised; 3853 XDrawBeveledButton(display,&windows->widget,&special_info); 3854 break; 3855 } 3856 if (MatteIsActive(action_info,event.xbutton)) 3857 { 3858 /* 3859 User pressed Action button. 3860 */ 3861 action_info.raised=MagickFalse; 3862 XDrawBeveledButton(display,&windows->widget,&action_info); 3863 break; 3864 } 3865 if (MatteIsActive(cancel_info,event.xbutton)) 3866 { 3867 /* 3868 User pressed Cancel button. 3869 */ 3870 cancel_info.raised=MagickFalse; 3871 XDrawBeveledButton(display,&windows->widget,&cancel_info); 3872 break; 3873 } 3874 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 3875 break; 3876 if (event.xbutton.button != Button2) 3877 { 3878 static Time 3879 click_time; 3880 3881 /* 3882 Move text cursor to position of button press. 3883 */ 3884 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 3885 for (i=1; i <= Extent(reply_info.marker); i++) 3886 if (XTextWidth(font_info,reply_info.marker,i) > x) 3887 break; 3888 reply_info.cursor=reply_info.marker+i-1; 3889 if (event.xbutton.time > (click_time+DoubleClick)) 3890 reply_info.highlight=MagickFalse; 3891 else 3892 { 3893 /* 3894 Become the XA_PRIMARY selection owner. 3895 */ 3896 (void) CopyMagickString(primary_selection,reply_info.text, 3897 MaxTextExtent); 3898 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 3899 event.xbutton.time); 3900 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 3901 windows->widget.id ? MagickTrue : MagickFalse; 3902 } 3903 XDrawMatteText(display,&windows->widget,&reply_info); 3904 click_time=event.xbutton.time; 3905 break; 3906 } 3907 /* 3908 Request primary selection. 3909 */ 3910 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 3911 windows->widget.id,event.xbutton.time); 3912 break; 3913 } 3914 case ButtonRelease: 3915 { 3916 if (windows->widget.mapped == MagickFalse) 3917 break; 3918 if (action_info.raised == MagickFalse) 3919 { 3920 if (event.xbutton.window == windows->widget.id) 3921 if (MatteIsActive(action_info,event.xbutton)) 3922 state|=ExitState; 3923 action_info.raised=MagickTrue; 3924 XDrawBeveledButton(display,&windows->widget,&action_info); 3925 } 3926 if (cancel_info.raised == MagickFalse) 3927 { 3928 if (event.xbutton.window == windows->widget.id) 3929 if (MatteIsActive(cancel_info,event.xbutton)) 3930 { 3931 *reply_info.text='\0'; 3932 state|=ExitState; 3933 } 3934 cancel_info.raised=MagickTrue; 3935 XDrawBeveledButton(display,&windows->widget,&cancel_info); 3936 } 3937 break; 3938 } 3939 case ClientMessage: 3940 { 3941 /* 3942 If client window delete message, exit. 3943 */ 3944 if (event.xclient.message_type != windows->wm_protocols) 3945 break; 3946 if (*event.xclient.data.l == (int) windows->wm_take_focus) 3947 { 3948 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 3949 (Time) event.xclient.data.l[1]); 3950 break; 3951 } 3952 if (*event.xclient.data.l != (int) windows->wm_delete_window) 3953 break; 3954 if (event.xclient.window == windows->widget.id) 3955 { 3956 *reply_info.text='\0'; 3957 state|=ExitState; 3958 break; 3959 } 3960 break; 3961 } 3962 case ConfigureNotify: 3963 { 3964 /* 3965 Update widget configuration. 3966 */ 3967 if (event.xconfigure.window != windows->widget.id) 3968 break; 3969 if ((event.xconfigure.width == (int) windows->widget.width) && 3970 (event.xconfigure.height == (int) windows->widget.height)) 3971 break; 3972 windows->widget.width=(unsigned int) 3973 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 3974 windows->widget.height=(unsigned int) 3975 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 3976 state|=UpdateConfigurationState; 3977 break; 3978 } 3979 case EnterNotify: 3980 { 3981 if (event.xcrossing.window != windows->widget.id) 3982 break; 3983 state&=(~InactiveWidgetState); 3984 break; 3985 } 3986 case Expose: 3987 { 3988 if (event.xexpose.window != windows->widget.id) 3989 break; 3990 if (event.xexpose.count != 0) 3991 break; 3992 state|=RedrawWidgetState; 3993 break; 3994 } 3995 case KeyPress: 3996 { 3997 static char 3998 command[MaxTextExtent]; 3999 4000 static int 4001 length; 4002 4003 static KeySym 4004 key_symbol; 4005 4006 /* 4007 Respond to a user key press. 4008 */ 4009 if (event.xkey.window != windows->widget.id) 4010 break; 4011 length=XLookupString((XKeyEvent *) &event.xkey,command, 4012 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 4013 *(command+length)='\0'; 4014 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 4015 { 4016 action_info.raised=MagickFalse; 4017 XDrawBeveledButton(display,&windows->widget,&action_info); 4018 state|=ExitState; 4019 break; 4020 } 4021 if (key_symbol == XK_Control_L) 4022 { 4023 state|=ControlState; 4024 break; 4025 } 4026 if (state & ControlState) 4027 switch ((int) key_symbol) 4028 { 4029 case XK_u: 4030 case XK_U: 4031 { 4032 /* 4033 Erase the entire line of text. 4034 */ 4035 *reply_info.text='\0'; 4036 reply_info.cursor=reply_info.text; 4037 reply_info.marker=reply_info.text; 4038 reply_info.highlight=MagickFalse; 4039 break; 4040 } 4041 default: 4042 break; 4043 } 4044 XEditText(display,&reply_info,key_symbol,command,state); 4045 XDrawMatteText(display,&windows->widget,&reply_info); 4046 break; 4047 } 4048 case KeyRelease: 4049 { 4050 static char 4051 command[MaxTextExtent]; 4052 4053 static KeySym 4054 key_symbol; 4055 4056 /* 4057 Respond to a user key release. 4058 */ 4059 if (event.xkey.window != windows->widget.id) 4060 break; 4061 (void) XLookupString((XKeyEvent *) &event.xkey,command, 4062 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 4063 if (key_symbol == XK_Control_L) 4064 state&=(~ControlState); 4065 break; 4066 } 4067 case LeaveNotify: 4068 { 4069 if (event.xcrossing.window != windows->widget.id) 4070 break; 4071 state|=InactiveWidgetState; 4072 break; 4073 } 4074 case MotionNotify: 4075 { 4076 /* 4077 Discard pending button motion events. 4078 */ 4079 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 4080 if (state & InactiveWidgetState) 4081 break; 4082 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 4083 { 4084 /* 4085 Action button status changed. 4086 */ 4087 action_info.raised=action_info.raised == MagickFalse ? 4088 MagickTrue : MagickFalse; 4089 XDrawBeveledButton(display,&windows->widget,&action_info); 4090 break; 4091 } 4092 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 4093 { 4094 /* 4095 Cancel button status changed. 4096 */ 4097 cancel_info.raised=cancel_info.raised == MagickFalse ? 4098 MagickTrue : MagickFalse; 4099 XDrawBeveledButton(display,&windows->widget,&cancel_info); 4100 break; 4101 } 4102 break; 4103 } 4104 case SelectionClear: 4105 { 4106 reply_info.highlight=MagickFalse; 4107 XDrawMatteText(display,&windows->widget,&reply_info); 4108 break; 4109 } 4110 case SelectionNotify: 4111 { 4112 Atom 4113 type; 4114 4115 int 4116 format; 4117 4118 unsigned char 4119 *data; 4120 4121 unsigned long 4122 after, 4123 length; 4124 4125 /* 4126 Obtain response from primary selection. 4127 */ 4128 if (event.xselection.property == (Atom) None) 4129 break; 4130 status=XGetWindowProperty(display,event.xselection.requestor, 4131 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type, 4132 &format,&length,&after,&data); 4133 if ((status != Success) || (type != XA_STRING) || (format == 32) || 4134 (length == 0)) 4135 break; 4136 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 4137 (void) XBell(display,0); 4138 else 4139 { 4140 /* 4141 Insert primary selection in reply text. 4142 */ 4143 *(data+length)='\0'; 4144 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 4145 state); 4146 XDrawMatteText(display,&windows->widget,&reply_info); 4147 } 4148 (void) XFree((void *) data); 4149 break; 4150 } 4151 case SelectionRequest: 4152 { 4153 XSelectionEvent 4154 notify; 4155 4156 XSelectionRequestEvent 4157 *request; 4158 4159 if (reply_info.highlight == MagickFalse) 4160 break; 4161 /* 4162 Set primary selection. 4163 */ 4164 request=(&(event.xselectionrequest)); 4165 (void) XChangeProperty(request->display,request->requestor, 4166 request->property,request->target,8,PropModeReplace, 4167 (unsigned char *) primary_selection,Extent(primary_selection)); 4168 notify.type=SelectionNotify; 4169 notify.display=request->display; 4170 notify.requestor=request->requestor; 4171 notify.selection=request->selection; 4172 notify.target=request->target; 4173 notify.time=request->time; 4174 if (request->property == None) 4175 notify.property=request->target; 4176 else 4177 notify.property=request->property; 4178 (void) XSendEvent(request->display,request->requestor,False,0, 4179 (XEvent *) ¬ify); 4180 } 4181 default: 4182 break; 4183 } 4184 } while ((state & ExitState) == 0); 4185 XSetCursorState(display,windows,MagickFalse); 4186 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 4187 XCheckRefreshWindows(display,windows); 4188 if (anomaly) 4189 if (special_info.raised) 4190 if (*reply != '\0') 4191 raised=MagickTrue; 4192 return(raised == MagickFalse); 4193} 4194 4195/* 4196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4197% % 4198% % 4199% % 4200% X F i l e B r o w s e r W i d g e t % 4201% % 4202% % 4203% % 4204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4205% 4206% XFileBrowserWidget() displays a File Browser widget with a file query to the 4207% user. The user keys a reply and presses the Action or Cancel button to 4208% exit. The typed text is returned as the reply function parameter. 4209% 4210% The format of the XFileBrowserWidget method is: 4211% 4212% void XFileBrowserWidget(Display *display,XWindows *windows, 4213% const char *action,char *reply) 4214% 4215% A description of each parameter follows: 4216% 4217% o display: Specifies a connection to an X server; returned from 4218% XOpenDisplay. 4219% 4220% o window: Specifies a pointer to a XWindows structure. 4221% 4222% o action: Specifies a pointer to the action of this widget. 4223% 4224% o reply: the response from the user is returned in this parameter. 4225% 4226*/ 4227MagickPrivate void XFileBrowserWidget(Display *display,XWindows *windows, 4228 const char *action,char *reply) 4229{ 4230#define CancelButtonText "Cancel" 4231#define DirectoryText "Directory:" 4232#define FilenameText "File name:" 4233#define GrabButtonText "Grab" 4234#define FormatButtonText "Format" 4235#define HomeButtonText "Home" 4236#define UpButtonText "Up" 4237 4238 char 4239 *directory, 4240 **filelist, 4241 home_directory[MaxTextExtent], 4242 primary_selection[MaxTextExtent], 4243 text[MaxTextExtent], 4244 working_path[MaxTextExtent]; 4245 4246 int 4247 x, 4248 y; 4249 4250 register ssize_t 4251 i; 4252 4253 static char 4254 glob_pattern[MaxTextExtent] = "*", 4255 format[MaxTextExtent] = "miff"; 4256 4257 static MagickStatusType 4258 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 4259 4260 Status 4261 status; 4262 4263 unsigned int 4264 anomaly, 4265 height, 4266 text_width, 4267 visible_files, 4268 width; 4269 4270 size_t 4271 delay, 4272 files, 4273 state; 4274 4275 XEvent 4276 event; 4277 4278 XFontStruct 4279 *font_info; 4280 4281 XTextProperty 4282 window_name; 4283 4284 XWidgetInfo 4285 action_info, 4286 cancel_info, 4287 expose_info, 4288 special_info, 4289 list_info, 4290 home_info, 4291 north_info, 4292 reply_info, 4293 scroll_info, 4294 selection_info, 4295 slider_info, 4296 south_info, 4297 text_info, 4298 up_info; 4299 4300 XWindowChanges 4301 window_changes; 4302 4303 /* 4304 Read filelist from current directory. 4305 */ 4306 assert(display != (Display *) NULL); 4307 assert(windows != (XWindows *) NULL); 4308 assert(action != (char *) NULL); 4309 assert(reply != (char *) NULL); 4310 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 4311 XSetCursorState(display,windows,MagickTrue); 4312 XCheckRefreshWindows(display,windows); 4313 directory=getcwd(home_directory,MaxTextExtent); 4314 (void) directory; 4315 (void) CopyMagickString(working_path,home_directory,MaxTextExtent); 4316 filelist=ListFiles(working_path,glob_pattern,&files); 4317 if (filelist == (char **) NULL) 4318 { 4319 /* 4320 Directory read failed. 4321 */ 4322 XNoticeWidget(display,windows,"Unable to read directory:",working_path); 4323 (void) XDialogWidget(display,windows,action,"Enter filename:",reply); 4324 return; 4325 } 4326 /* 4327 Determine File Browser widget attributes. 4328 */ 4329 font_info=windows->widget.font_info; 4330 text_width=0; 4331 for (i=0; i < (ssize_t) files; i++) 4332 if (WidgetTextWidth(font_info,filelist[i]) > text_width) 4333 text_width=WidgetTextWidth(font_info,filelist[i]); 4334 width=WidgetTextWidth(font_info,(char *) action); 4335 if (WidgetTextWidth(font_info,GrabButtonText) > width) 4336 width=WidgetTextWidth(font_info,GrabButtonText); 4337 if (WidgetTextWidth(font_info,FormatButtonText) > width) 4338 width=WidgetTextWidth(font_info,FormatButtonText); 4339 if (WidgetTextWidth(font_info,CancelButtonText) > width) 4340 width=WidgetTextWidth(font_info,CancelButtonText); 4341 if (WidgetTextWidth(font_info,HomeButtonText) > width) 4342 width=WidgetTextWidth(font_info,HomeButtonText); 4343 if (WidgetTextWidth(font_info,UpButtonText) > width) 4344 width=WidgetTextWidth(font_info,UpButtonText); 4345 width+=QuantumMargin; 4346 if (WidgetTextWidth(font_info,DirectoryText) > width) 4347 width=WidgetTextWidth(font_info,DirectoryText); 4348 if (WidgetTextWidth(font_info,FilenameText) > width) 4349 width=WidgetTextWidth(font_info,FilenameText); 4350 height=(unsigned int) (font_info->ascent+font_info->descent); 4351 /* 4352 Position File Browser widget. 4353 */ 4354 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+ 4355 6*QuantumMargin; 4356 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin; 4357 if (windows->widget.width < windows->widget.min_width) 4358 windows->widget.width=windows->widget.min_width; 4359 windows->widget.height=(unsigned int) 4360 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4); 4361 windows->widget.min_height=(unsigned int) 4362 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4); 4363 if (windows->widget.height < windows->widget.min_height) 4364 windows->widget.height=windows->widget.min_height; 4365 XConstrainWindowPosition(display,&windows->widget); 4366 /* 4367 Map File Browser widget. 4368 */ 4369 (void) CopyMagickString(windows->widget.name,"Browse and Select a File", 4370 MaxTextExtent); 4371 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 4372 if (status != False) 4373 { 4374 XSetWMName(display,windows->widget.id,&window_name); 4375 XSetWMIconName(display,windows->widget.id,&window_name); 4376 (void) XFree((void *) window_name.value); 4377 } 4378 window_changes.width=(int) windows->widget.width; 4379 window_changes.height=(int) windows->widget.height; 4380 window_changes.x=windows->widget.x; 4381 window_changes.y=windows->widget.y; 4382 (void) XReconfigureWMWindow(display,windows->widget.id, 4383 windows->widget.screen,mask,&window_changes); 4384 (void) XMapRaised(display,windows->widget.id); 4385 windows->widget.mapped=MagickFalse; 4386 /* 4387 Respond to X events. 4388 */ 4389 XGetWidgetInfo((char *) NULL,&slider_info); 4390 XGetWidgetInfo((char *) NULL,&north_info); 4391 XGetWidgetInfo((char *) NULL,&south_info); 4392 XGetWidgetInfo((char *) NULL,&expose_info); 4393 visible_files=0; 4394 anomaly=(LocaleCompare(action,"Composite") == 0) || 4395 (LocaleCompare(action,"Open") == 0) || (LocaleCompare(action,"Map") == 0); 4396 *reply='\0'; 4397 delay=SuspendTime << 2; 4398 state=UpdateConfigurationState; 4399 do 4400 { 4401 if (state & UpdateConfigurationState) 4402 { 4403 int 4404 id; 4405 4406 /* 4407 Initialize button information. 4408 */ 4409 XGetWidgetInfo(CancelButtonText,&cancel_info); 4410 cancel_info.width=width; 4411 cancel_info.height=(unsigned int) ((3*height) >> 1); 4412 cancel_info.x=(int) 4413 (windows->widget.width-cancel_info.width-QuantumMargin-2); 4414 cancel_info.y=(int) 4415 (windows->widget.height-cancel_info.height-QuantumMargin); 4416 XGetWidgetInfo(action,&action_info); 4417 action_info.width=width; 4418 action_info.height=(unsigned int) ((3*height) >> 1); 4419 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+ 4420 (action_info.bevel_width << 1)); 4421 action_info.y=cancel_info.y; 4422 XGetWidgetInfo(GrabButtonText,&special_info); 4423 special_info.width=width; 4424 special_info.height=(unsigned int) ((3*height) >> 1); 4425 special_info.x=action_info.x-(action_info.width+(QuantumMargin >> 1)+ 4426 (special_info.bevel_width << 1)); 4427 special_info.y=action_info.y; 4428 if (anomaly == MagickFalse) 4429 { 4430 register char 4431 *p; 4432 4433 special_info.text=(char *) FormatButtonText; 4434 p=reply+Extent(reply)-1; 4435 while ((p > (reply+1)) && (*(p-1) != '.')) 4436 p--; 4437 if ((p > (reply+1)) && (*(p-1) == '.')) 4438 (void) CopyMagickString(format,p,MaxTextExtent); 4439 } 4440 XGetWidgetInfo(UpButtonText,&up_info); 4441 up_info.width=width; 4442 up_info.height=(unsigned int) ((3*height) >> 1); 4443 up_info.x=QuantumMargin; 4444 up_info.y=((5*QuantumMargin) >> 1)+height; 4445 XGetWidgetInfo(HomeButtonText,&home_info); 4446 home_info.width=width; 4447 home_info.height=(unsigned int) ((3*height) >> 1); 4448 home_info.x=QuantumMargin; 4449 home_info.y=up_info.y+up_info.height+QuantumMargin; 4450 /* 4451 Initialize reply information. 4452 */ 4453 XGetWidgetInfo(reply,&reply_info); 4454 reply_info.raised=MagickFalse; 4455 reply_info.bevel_width--; 4456 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1); 4457 reply_info.height=height << 1; 4458 reply_info.x=(int) (width+(QuantumMargin << 1)); 4459 reply_info.y=action_info.y-reply_info.height-QuantumMargin; 4460 /* 4461 Initialize scroll information. 4462 */ 4463 XGetWidgetInfo((char *) NULL,&scroll_info); 4464 scroll_info.bevel_width--; 4465 scroll_info.width=height; 4466 scroll_info.height=(unsigned int) 4467 (reply_info.y-up_info.y-(QuantumMargin >> 1)); 4468 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width); 4469 scroll_info.y=up_info.y-reply_info.bevel_width; 4470 scroll_info.raised=MagickFalse; 4471 scroll_info.trough=MagickTrue; 4472 north_info=scroll_info; 4473 north_info.raised=MagickTrue; 4474 north_info.width-=(north_info.bevel_width << 1); 4475 north_info.height=north_info.width-1; 4476 north_info.x+=north_info.bevel_width; 4477 north_info.y+=north_info.bevel_width; 4478 south_info=north_info; 4479 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 4480 south_info.height; 4481 id=slider_info.id; 4482 slider_info=north_info; 4483 slider_info.id=id; 4484 slider_info.width-=2; 4485 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 4486 slider_info.bevel_width+2; 4487 slider_info.height=scroll_info.height-((slider_info.min_y- 4488 scroll_info.y+1) << 1)+4; 4489 visible_files=scroll_info.height/(height+(height >> 3)); 4490 if (files > visible_files) 4491 slider_info.height=(unsigned int) 4492 ((visible_files*slider_info.height)/files); 4493 slider_info.max_y=south_info.y-south_info.bevel_width- 4494 slider_info.bevel_width-2; 4495 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 4496 slider_info.y=slider_info.min_y; 4497 expose_info=scroll_info; 4498 expose_info.y=slider_info.y; 4499 /* 4500 Initialize list information. 4501 */ 4502 XGetWidgetInfo((char *) NULL,&list_info); 4503 list_info.raised=MagickFalse; 4504 list_info.bevel_width--; 4505 list_info.width=(unsigned int) 4506 (scroll_info.x-reply_info.x-(QuantumMargin >> 1)); 4507 list_info.height=scroll_info.height; 4508 list_info.x=reply_info.x; 4509 list_info.y=scroll_info.y; 4510 if (windows->widget.mapped == MagickFalse) 4511 state|=JumpListState; 4512 /* 4513 Initialize text information. 4514 */ 4515 *text='\0'; 4516 XGetWidgetInfo(text,&text_info); 4517 text_info.center=MagickFalse; 4518 text_info.width=reply_info.width; 4519 text_info.height=height; 4520 text_info.x=list_info.x-(QuantumMargin >> 1); 4521 text_info.y=QuantumMargin; 4522 /* 4523 Initialize selection information. 4524 */ 4525 XGetWidgetInfo((char *) NULL,&selection_info); 4526 selection_info.center=MagickFalse; 4527 selection_info.width=list_info.width; 4528 selection_info.height=(unsigned int) ((9*height) >> 3); 4529 selection_info.x=list_info.x; 4530 state&=(~UpdateConfigurationState); 4531 } 4532 if (state & RedrawWidgetState) 4533 { 4534 /* 4535 Redraw File Browser window. 4536 */ 4537 x=QuantumMargin; 4538 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent; 4539 (void) XDrawString(display,windows->widget.id, 4540 windows->widget.annotate_context,x,y,DirectoryText, 4541 Extent(DirectoryText)); 4542 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent); 4543 (void) ConcatenateMagickString(text_info.text,DirectorySeparator, 4544 MaxTextExtent); 4545 (void) ConcatenateMagickString(text_info.text,glob_pattern, 4546 MaxTextExtent); 4547 XDrawWidgetText(display,&windows->widget,&text_info); 4548 XDrawBeveledButton(display,&windows->widget,&up_info); 4549 XDrawBeveledButton(display,&windows->widget,&home_info); 4550 XDrawBeveledMatte(display,&windows->widget,&list_info); 4551 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 4552 XDrawTriangleNorth(display,&windows->widget,&north_info); 4553 XDrawBeveledButton(display,&windows->widget,&slider_info); 4554 XDrawTriangleSouth(display,&windows->widget,&south_info); 4555 x=QuantumMargin; 4556 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent; 4557 (void) XDrawString(display,windows->widget.id, 4558 windows->widget.annotate_context,x,y,FilenameText, 4559 Extent(FilenameText)); 4560 XDrawBeveledMatte(display,&windows->widget,&reply_info); 4561 XDrawMatteText(display,&windows->widget,&reply_info); 4562 XDrawBeveledButton(display,&windows->widget,&special_info); 4563 XDrawBeveledButton(display,&windows->widget,&action_info); 4564 XDrawBeveledButton(display,&windows->widget,&cancel_info); 4565 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 4566 selection_info.id=(~0); 4567 state|=RedrawListState; 4568 state&=(~RedrawWidgetState); 4569 } 4570 if (state & UpdateListState) 4571 { 4572 char 4573 **checklist; 4574 4575 size_t 4576 number_files; 4577 4578 /* 4579 Update file list. 4580 */ 4581 checklist=ListFiles(working_path,glob_pattern,&number_files); 4582 if (checklist == (char **) NULL) 4583 { 4584 /* 4585 Reply is a filename, exit. 4586 */ 4587 action_info.raised=MagickFalse; 4588 XDrawBeveledButton(display,&windows->widget,&action_info); 4589 break; 4590 } 4591 for (i=0; i < (ssize_t) files; i++) 4592 filelist[i]=DestroyString(filelist[i]); 4593 if (filelist != (char **) NULL) 4594 filelist=(char **) RelinquishMagickMemory(filelist); 4595 filelist=checklist; 4596 files=number_files; 4597 /* 4598 Update file list. 4599 */ 4600 slider_info.height= 4601 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1; 4602 if (files > visible_files) 4603 slider_info.height=(unsigned int) 4604 ((visible_files*slider_info.height)/files); 4605 slider_info.max_y=south_info.y-south_info.bevel_width- 4606 slider_info.bevel_width-2; 4607 slider_info.id=0; 4608 slider_info.y=slider_info.min_y; 4609 expose_info.y=slider_info.y; 4610 selection_info.id=(~0); 4611 list_info.id=(~0); 4612 state|=RedrawListState; 4613 /* 4614 Redraw directory name & reply. 4615 */ 4616 if (IsGlob(reply_info.text) == MagickFalse) 4617 { 4618 *reply_info.text='\0'; 4619 reply_info.cursor=reply_info.text; 4620 } 4621 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent); 4622 (void) ConcatenateMagickString(text_info.text,DirectorySeparator, 4623 MaxTextExtent); 4624 (void) ConcatenateMagickString(text_info.text,glob_pattern, 4625 MaxTextExtent); 4626 XDrawWidgetText(display,&windows->widget,&text_info); 4627 XDrawMatteText(display,&windows->widget,&reply_info); 4628 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 4629 XDrawTriangleNorth(display,&windows->widget,&north_info); 4630 XDrawBeveledButton(display,&windows->widget,&slider_info); 4631 XDrawTriangleSouth(display,&windows->widget,&south_info); 4632 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 4633 state&=(~UpdateListState); 4634 } 4635 if (state & JumpListState) 4636 { 4637 /* 4638 Jump scroll to match user filename. 4639 */ 4640 list_info.id=(~0); 4641 for (i=0; i < (ssize_t) files; i++) 4642 if (LocaleCompare(filelist[i],reply) >= 0) 4643 { 4644 list_info.id=(int) 4645 (LocaleCompare(filelist[i],reply) == 0 ? i : ~0); 4646 break; 4647 } 4648 if ((i < (ssize_t) slider_info.id) || 4649 (i >= (ssize_t) (slider_info.id+visible_files))) 4650 slider_info.id=(int) i-(visible_files >> 1); 4651 selection_info.id=(~0); 4652 state|=RedrawListState; 4653 state&=(~JumpListState); 4654 } 4655 if (state & RedrawListState) 4656 { 4657 /* 4658 Determine slider id and position. 4659 */ 4660 if (slider_info.id >= (int) (files-visible_files)) 4661 slider_info.id=(int) (files-visible_files); 4662 if ((slider_info.id < 0) || (files <= visible_files)) 4663 slider_info.id=0; 4664 slider_info.y=slider_info.min_y; 4665 if (files > 0) 4666 slider_info.y+=(int) (slider_info.id*(slider_info.max_y- 4667 slider_info.min_y+1)/files); 4668 if (slider_info.id != selection_info.id) 4669 { 4670 /* 4671 Redraw scroll bar and file names. 4672 */ 4673 selection_info.id=slider_info.id; 4674 selection_info.y=list_info.y+(height >> 3)+2; 4675 for (i=0; i < (ssize_t) visible_files; i++) 4676 { 4677 selection_info.raised=(int) (slider_info.id+i) != list_info.id ? 4678 MagickTrue : MagickFalse; 4679 selection_info.text=(char *) NULL; 4680 if ((slider_info.id+i) < (ssize_t) files) 4681 selection_info.text=filelist[slider_info.id+i]; 4682 XDrawWidgetText(display,&windows->widget,&selection_info); 4683 selection_info.y+=(int) selection_info.height; 4684 } 4685 /* 4686 Update slider. 4687 */ 4688 if (slider_info.y > expose_info.y) 4689 { 4690 expose_info.height=(unsigned int) slider_info.y-expose_info.y; 4691 expose_info.y=slider_info.y-expose_info.height- 4692 slider_info.bevel_width-1; 4693 } 4694 else 4695 { 4696 expose_info.height=(unsigned int) expose_info.y-slider_info.y; 4697 expose_info.y=slider_info.y+slider_info.height+ 4698 slider_info.bevel_width+1; 4699 } 4700 XDrawTriangleNorth(display,&windows->widget,&north_info); 4701 XDrawMatte(display,&windows->widget,&expose_info); 4702 XDrawBeveledButton(display,&windows->widget,&slider_info); 4703 XDrawTriangleSouth(display,&windows->widget,&south_info); 4704 expose_info.y=slider_info.y; 4705 } 4706 state&=(~RedrawListState); 4707 } 4708 /* 4709 Wait for next event. 4710 */ 4711 if (north_info.raised && south_info.raised) 4712 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 4713 else 4714 { 4715 /* 4716 Brief delay before advancing scroll bar. 4717 */ 4718 XDelay(display,delay); 4719 delay=SuspendTime; 4720 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows); 4721 if (north_info.raised == MagickFalse) 4722 if (slider_info.id > 0) 4723 { 4724 /* 4725 Move slider up. 4726 */ 4727 slider_info.id--; 4728 state|=RedrawListState; 4729 } 4730 if (south_info.raised == MagickFalse) 4731 if (slider_info.id < (int) files) 4732 { 4733 /* 4734 Move slider down. 4735 */ 4736 slider_info.id++; 4737 state|=RedrawListState; 4738 } 4739 if (event.type != ButtonRelease) 4740 continue; 4741 } 4742 switch (event.type) 4743 { 4744 case ButtonPress: 4745 { 4746 if (MatteIsActive(slider_info,event.xbutton)) 4747 { 4748 /* 4749 Track slider. 4750 */ 4751 slider_info.active=MagickTrue; 4752 break; 4753 } 4754 if (MatteIsActive(north_info,event.xbutton)) 4755 if (slider_info.id > 0) 4756 { 4757 /* 4758 Move slider up. 4759 */ 4760 north_info.raised=MagickFalse; 4761 slider_info.id--; 4762 state|=RedrawListState; 4763 break; 4764 } 4765 if (MatteIsActive(south_info,event.xbutton)) 4766 if (slider_info.id < (int) files) 4767 { 4768 /* 4769 Move slider down. 4770 */ 4771 south_info.raised=MagickFalse; 4772 slider_info.id++; 4773 state|=RedrawListState; 4774 break; 4775 } 4776 if (MatteIsActive(scroll_info,event.xbutton)) 4777 { 4778 /* 4779 Move slider. 4780 */ 4781 if (event.xbutton.y < slider_info.y) 4782 slider_info.id-=(visible_files-1); 4783 else 4784 slider_info.id+=(visible_files-1); 4785 state|=RedrawListState; 4786 break; 4787 } 4788 if (MatteIsActive(list_info,event.xbutton)) 4789 { 4790 int 4791 id; 4792 4793 /* 4794 User pressed file matte. 4795 */ 4796 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/ 4797 selection_info.height; 4798 if (id >= (int) files) 4799 break; 4800 (void) CopyMagickString(reply_info.text,filelist[id],MaxTextExtent); 4801 reply_info.highlight=MagickFalse; 4802 reply_info.marker=reply_info.text; 4803 reply_info.cursor=reply_info.text+Extent(reply_info.text); 4804 XDrawMatteText(display,&windows->widget,&reply_info); 4805 if (id == list_info.id) 4806 { 4807 register char 4808 *p; 4809 4810 p=reply_info.text+strlen(reply_info.text)-1; 4811 if (*p == *DirectorySeparator) 4812 ChopPathComponents(reply_info.text,1); 4813 (void) ConcatenateMagickString(working_path,DirectorySeparator, 4814 MaxTextExtent); 4815 (void) ConcatenateMagickString(working_path,reply_info.text, 4816 MaxTextExtent); 4817 *reply='\0'; 4818 state|=UpdateListState; 4819 } 4820 selection_info.id=(~0); 4821 list_info.id=id; 4822 state|=RedrawListState; 4823 break; 4824 } 4825 if (MatteIsActive(up_info,event.xbutton)) 4826 { 4827 /* 4828 User pressed Up button. 4829 */ 4830 up_info.raised=MagickFalse; 4831 XDrawBeveledButton(display,&windows->widget,&up_info); 4832 break; 4833 } 4834 if (MatteIsActive(home_info,event.xbutton)) 4835 { 4836 /* 4837 User pressed Home button. 4838 */ 4839 home_info.raised=MagickFalse; 4840 XDrawBeveledButton(display,&windows->widget,&home_info); 4841 break; 4842 } 4843 if (MatteIsActive(special_info,event.xbutton)) 4844 { 4845 /* 4846 User pressed Special button. 4847 */ 4848 special_info.raised=MagickFalse; 4849 XDrawBeveledButton(display,&windows->widget,&special_info); 4850 break; 4851 } 4852 if (MatteIsActive(action_info,event.xbutton)) 4853 { 4854 /* 4855 User pressed action button. 4856 */ 4857 action_info.raised=MagickFalse; 4858 XDrawBeveledButton(display,&windows->widget,&action_info); 4859 break; 4860 } 4861 if (MatteIsActive(cancel_info,event.xbutton)) 4862 { 4863 /* 4864 User pressed Cancel button. 4865 */ 4866 cancel_info.raised=MagickFalse; 4867 XDrawBeveledButton(display,&windows->widget,&cancel_info); 4868 break; 4869 } 4870 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 4871 break; 4872 if (event.xbutton.button != Button2) 4873 { 4874 static Time 4875 click_time; 4876 4877 /* 4878 Move text cursor to position of button press. 4879 */ 4880 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 4881 for (i=1; i <= (ssize_t) Extent(reply_info.marker); i++) 4882 if (XTextWidth(font_info,reply_info.marker,(int) i) > x) 4883 break; 4884 reply_info.cursor=reply_info.marker+i-1; 4885 if (event.xbutton.time > (click_time+DoubleClick)) 4886 reply_info.highlight=MagickFalse; 4887 else 4888 { 4889 /* 4890 Become the XA_PRIMARY selection owner. 4891 */ 4892 (void) CopyMagickString(primary_selection,reply_info.text, 4893 MaxTextExtent); 4894 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 4895 event.xbutton.time); 4896 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 4897 windows->widget.id ? MagickTrue : MagickFalse; 4898 } 4899 XDrawMatteText(display,&windows->widget,&reply_info); 4900 click_time=event.xbutton.time; 4901 break; 4902 } 4903 /* 4904 Request primary selection. 4905 */ 4906 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 4907 windows->widget.id,event.xbutton.time); 4908 break; 4909 } 4910 case ButtonRelease: 4911 { 4912 if (windows->widget.mapped == MagickFalse) 4913 break; 4914 if (north_info.raised == MagickFalse) 4915 { 4916 /* 4917 User released up button. 4918 */ 4919 delay=SuspendTime << 2; 4920 north_info.raised=MagickTrue; 4921 XDrawTriangleNorth(display,&windows->widget,&north_info); 4922 } 4923 if (south_info.raised == MagickFalse) 4924 { 4925 /* 4926 User released down button. 4927 */ 4928 delay=SuspendTime << 2; 4929 south_info.raised=MagickTrue; 4930 XDrawTriangleSouth(display,&windows->widget,&south_info); 4931 } 4932 if (slider_info.active) 4933 { 4934 /* 4935 Stop tracking slider. 4936 */ 4937 slider_info.active=MagickFalse; 4938 break; 4939 } 4940 if (up_info.raised == MagickFalse) 4941 { 4942 if (event.xbutton.window == windows->widget.id) 4943 if (MatteIsActive(up_info,event.xbutton)) 4944 { 4945 ChopPathComponents(working_path,1); 4946 if (*working_path == '\0') 4947 (void) CopyMagickString(working_path,DirectorySeparator, 4948 MaxTextExtent); 4949 state|=UpdateListState; 4950 } 4951 up_info.raised=MagickTrue; 4952 XDrawBeveledButton(display,&windows->widget,&up_info); 4953 } 4954 if (home_info.raised == MagickFalse) 4955 { 4956 if (event.xbutton.window == windows->widget.id) 4957 if (MatteIsActive(home_info,event.xbutton)) 4958 { 4959 (void) CopyMagickString(working_path,home_directory, 4960 MaxTextExtent); 4961 state|=UpdateListState; 4962 } 4963 home_info.raised=MagickTrue; 4964 XDrawBeveledButton(display,&windows->widget,&home_info); 4965 } 4966 if (special_info.raised == MagickFalse) 4967 { 4968 if (anomaly == MagickFalse) 4969 { 4970 char 4971 **formats; 4972 4973 ExceptionInfo 4974 *exception; 4975 4976 size_t 4977 number_formats; 4978 4979 /* 4980 Let user select image format. 4981 */ 4982 exception=AcquireExceptionInfo(); 4983 formats=GetMagickList("*",&number_formats,exception); 4984 exception=DestroyExceptionInfo(exception); 4985 (void) XCheckDefineCursor(display,windows->widget.id, 4986 windows->widget.busy_cursor); 4987 windows->popup.x=windows->widget.x+60; 4988 windows->popup.y=windows->widget.y+60; 4989 XListBrowserWidget(display,windows,&windows->popup, 4990 (const char **) formats,"Select","Select image format type:", 4991 format); 4992 XSetCursorState(display,windows,MagickTrue); 4993 (void) XCheckDefineCursor(display,windows->widget.id, 4994 windows->widget.cursor); 4995 LocaleLower(format); 4996 AppendImageFormat(format,reply_info.text); 4997 reply_info.cursor=reply_info.text+Extent(reply_info.text); 4998 XDrawMatteText(display,&windows->widget,&reply_info); 4999 special_info.raised=MagickTrue; 5000 XDrawBeveledButton(display,&windows->widget,&special_info); 5001 for (i=0; i < (ssize_t) number_formats; i++) 5002 formats[i]=DestroyString(formats[i]); 5003 formats=(char **) RelinquishMagickMemory(formats); 5004 break; 5005 } 5006 if (event.xbutton.window == windows->widget.id) 5007 if (MatteIsActive(special_info,event.xbutton)) 5008 { 5009 (void) CopyMagickString(working_path,"x:",MaxTextExtent); 5010 state|=ExitState; 5011 } 5012 special_info.raised=MagickTrue; 5013 XDrawBeveledButton(display,&windows->widget,&special_info); 5014 } 5015 if (action_info.raised == MagickFalse) 5016 { 5017 if (event.xbutton.window == windows->widget.id) 5018 { 5019 if (MatteIsActive(action_info,event.xbutton)) 5020 { 5021 if (*reply_info.text == '\0') 5022 (void) XBell(display,0); 5023 else 5024 state|=ExitState; 5025 } 5026 } 5027 action_info.raised=MagickTrue; 5028 XDrawBeveledButton(display,&windows->widget,&action_info); 5029 } 5030 if (cancel_info.raised == MagickFalse) 5031 { 5032 if (event.xbutton.window == windows->widget.id) 5033 if (MatteIsActive(cancel_info,event.xbutton)) 5034 { 5035 *reply_info.text='\0'; 5036 *reply='\0'; 5037 state|=ExitState; 5038 } 5039 cancel_info.raised=MagickTrue; 5040 XDrawBeveledButton(display,&windows->widget,&cancel_info); 5041 } 5042 break; 5043 } 5044 case ClientMessage: 5045 { 5046 /* 5047 If client window delete message, exit. 5048 */ 5049 if (event.xclient.message_type != windows->wm_protocols) 5050 break; 5051 if (*event.xclient.data.l == (int) windows->wm_take_focus) 5052 { 5053 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 5054 (Time) event.xclient.data.l[1]); 5055 break; 5056 } 5057 if (*event.xclient.data.l != (int) windows->wm_delete_window) 5058 break; 5059 if (event.xclient.window == windows->widget.id) 5060 { 5061 *reply_info.text='\0'; 5062 state|=ExitState; 5063 break; 5064 } 5065 break; 5066 } 5067 case ConfigureNotify: 5068 { 5069 /* 5070 Update widget configuration. 5071 */ 5072 if (event.xconfigure.window != windows->widget.id) 5073 break; 5074 if ((event.xconfigure.width == (int) windows->widget.width) && 5075 (event.xconfigure.height == (int) windows->widget.height)) 5076 break; 5077 windows->widget.width=(unsigned int) 5078 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 5079 windows->widget.height=(unsigned int) 5080 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 5081 state|=UpdateConfigurationState; 5082 break; 5083 } 5084 case EnterNotify: 5085 { 5086 if (event.xcrossing.window != windows->widget.id) 5087 break; 5088 state&=(~InactiveWidgetState); 5089 break; 5090 } 5091 case Expose: 5092 { 5093 if (event.xexpose.window != windows->widget.id) 5094 break; 5095 if (event.xexpose.count != 0) 5096 break; 5097 state|=RedrawWidgetState; 5098 break; 5099 } 5100 case KeyPress: 5101 { 5102 static char 5103 command[MaxTextExtent]; 5104 5105 static int 5106 length; 5107 5108 static KeySym 5109 key_symbol; 5110 5111 /* 5112 Respond to a user key press. 5113 */ 5114 if (event.xkey.window != windows->widget.id) 5115 break; 5116 length=XLookupString((XKeyEvent *) &event.xkey,command, 5117 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 5118 *(command+length)='\0'; 5119 if (AreaIsActive(scroll_info,event.xkey)) 5120 { 5121 /* 5122 Move slider. 5123 */ 5124 switch ((int) key_symbol) 5125 { 5126 case XK_Home: 5127 case XK_KP_Home: 5128 { 5129 slider_info.id=0; 5130 break; 5131 } 5132 case XK_Up: 5133 case XK_KP_Up: 5134 { 5135 slider_info.id--; 5136 break; 5137 } 5138 case XK_Down: 5139 case XK_KP_Down: 5140 { 5141 slider_info.id++; 5142 break; 5143 } 5144 case XK_Prior: 5145 case XK_KP_Prior: 5146 { 5147 slider_info.id-=visible_files; 5148 break; 5149 } 5150 case XK_Next: 5151 case XK_KP_Next: 5152 { 5153 slider_info.id+=visible_files; 5154 break; 5155 } 5156 case XK_End: 5157 case XK_KP_End: 5158 { 5159 slider_info.id=(int) files; 5160 break; 5161 } 5162 } 5163 state|=RedrawListState; 5164 break; 5165 } 5166 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 5167 { 5168 /* 5169 Read new directory or glob patterm. 5170 */ 5171 if (*reply_info.text == '\0') 5172 break; 5173 if (IsGlob(reply_info.text)) 5174 (void) CopyMagickString(glob_pattern,reply_info.text, 5175 MaxTextExtent); 5176 else 5177 { 5178 (void) ConcatenateMagickString(working_path,DirectorySeparator, 5179 MaxTextExtent); 5180 (void) ConcatenateMagickString(working_path,reply_info.text, 5181 MaxTextExtent); 5182 if (*working_path == '~') 5183 ExpandFilename(working_path); 5184 *reply='\0'; 5185 } 5186 state|=UpdateListState; 5187 break; 5188 } 5189 if (key_symbol == XK_Control_L) 5190 { 5191 state|=ControlState; 5192 break; 5193 } 5194 if (state & ControlState) 5195 switch ((int) key_symbol) 5196 { 5197 case XK_u: 5198 case XK_U: 5199 { 5200 /* 5201 Erase the entire line of text. 5202 */ 5203 *reply_info.text='\0'; 5204 reply_info.cursor=reply_info.text; 5205 reply_info.marker=reply_info.text; 5206 reply_info.highlight=MagickFalse; 5207 break; 5208 } 5209 default: 5210 break; 5211 } 5212 XEditText(display,&reply_info,key_symbol,command,state); 5213 XDrawMatteText(display,&windows->widget,&reply_info); 5214 state|=JumpListState; 5215 break; 5216 } 5217 case KeyRelease: 5218 { 5219 static char 5220 command[MaxTextExtent]; 5221 5222 static KeySym 5223 key_symbol; 5224 5225 /* 5226 Respond to a user key release. 5227 */ 5228 if (event.xkey.window != windows->widget.id) 5229 break; 5230 (void) XLookupString((XKeyEvent *) &event.xkey,command, 5231 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 5232 if (key_symbol == XK_Control_L) 5233 state&=(~ControlState); 5234 break; 5235 } 5236 case LeaveNotify: 5237 { 5238 if (event.xcrossing.window != windows->widget.id) 5239 break; 5240 state|=InactiveWidgetState; 5241 break; 5242 } 5243 case MapNotify: 5244 { 5245 mask&=(~CWX); 5246 mask&=(~CWY); 5247 break; 5248 } 5249 case MotionNotify: 5250 { 5251 /* 5252 Discard pending button motion events. 5253 */ 5254 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 5255 if (slider_info.active) 5256 { 5257 /* 5258 Move slider matte. 5259 */ 5260 slider_info.y=event.xmotion.y- 5261 ((slider_info.height+slider_info.bevel_width) >> 1)+1; 5262 if (slider_info.y < slider_info.min_y) 5263 slider_info.y=slider_info.min_y; 5264 if (slider_info.y > slider_info.max_y) 5265 slider_info.y=slider_info.max_y; 5266 slider_info.id=0; 5267 if (slider_info.y != slider_info.min_y) 5268 slider_info.id=(int) ((files*(slider_info.y-slider_info.min_y+1))/ 5269 (slider_info.max_y-slider_info.min_y+1)); 5270 state|=RedrawListState; 5271 break; 5272 } 5273 if (state & InactiveWidgetState) 5274 break; 5275 if (up_info.raised == MatteIsActive(up_info,event.xmotion)) 5276 { 5277 /* 5278 Up button status changed. 5279 */ 5280 up_info.raised=!up_info.raised; 5281 XDrawBeveledButton(display,&windows->widget,&up_info); 5282 break; 5283 } 5284 if (home_info.raised == MatteIsActive(home_info,event.xmotion)) 5285 { 5286 /* 5287 Home button status changed. 5288 */ 5289 home_info.raised=!home_info.raised; 5290 XDrawBeveledButton(display,&windows->widget,&home_info); 5291 break; 5292 } 5293 if (special_info.raised == MatteIsActive(special_info,event.xmotion)) 5294 { 5295 /* 5296 Grab button status changed. 5297 */ 5298 special_info.raised=!special_info.raised; 5299 XDrawBeveledButton(display,&windows->widget,&special_info); 5300 break; 5301 } 5302 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 5303 { 5304 /* 5305 Action button status changed. 5306 */ 5307 action_info.raised=action_info.raised == MagickFalse ? 5308 MagickTrue : MagickFalse; 5309 XDrawBeveledButton(display,&windows->widget,&action_info); 5310 break; 5311 } 5312 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 5313 { 5314 /* 5315 Cancel button status changed. 5316 */ 5317 cancel_info.raised=cancel_info.raised == MagickFalse ? 5318 MagickTrue : MagickFalse; 5319 XDrawBeveledButton(display,&windows->widget,&cancel_info); 5320 break; 5321 } 5322 break; 5323 } 5324 case SelectionClear: 5325 { 5326 reply_info.highlight=MagickFalse; 5327 XDrawMatteText(display,&windows->widget,&reply_info); 5328 break; 5329 } 5330 case SelectionNotify: 5331 { 5332 Atom 5333 type; 5334 5335 int 5336 format; 5337 5338 unsigned char 5339 *data; 5340 5341 unsigned long 5342 after, 5343 length; 5344 5345 /* 5346 Obtain response from primary selection. 5347 */ 5348 if (event.xselection.property == (Atom) None) 5349 break; 5350 status=XGetWindowProperty(display,event.xselection.requestor, 5351 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type, 5352 &format,&length,&after,&data); 5353 if ((status != Success) || (type != XA_STRING) || (format == 32) || 5354 (length == 0)) 5355 break; 5356 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 5357 (void) XBell(display,0); 5358 else 5359 { 5360 /* 5361 Insert primary selection in reply text. 5362 */ 5363 *(data+length)='\0'; 5364 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 5365 state); 5366 XDrawMatteText(display,&windows->widget,&reply_info); 5367 state|=JumpListState; 5368 state|=RedrawActionState; 5369 } 5370 (void) XFree((void *) data); 5371 break; 5372 } 5373 case SelectionRequest: 5374 { 5375 XSelectionEvent 5376 notify; 5377 5378 XSelectionRequestEvent 5379 *request; 5380 5381 if (reply_info.highlight == MagickFalse) 5382 break; 5383 /* 5384 Set primary selection. 5385 */ 5386 request=(&(event.xselectionrequest)); 5387 (void) XChangeProperty(request->display,request->requestor, 5388 request->property,request->target,8,PropModeReplace, 5389 (unsigned char *) primary_selection,Extent(primary_selection)); 5390 notify.type=SelectionNotify; 5391 notify.display=request->display; 5392 notify.requestor=request->requestor; 5393 notify.selection=request->selection; 5394 notify.target=request->target; 5395 notify.time=request->time; 5396 if (request->property == None) 5397 notify.property=request->target; 5398 else 5399 notify.property=request->property; 5400 (void) XSendEvent(request->display,request->requestor,False,0, 5401 (XEvent *) ¬ify); 5402 } 5403 default: 5404 break; 5405 } 5406 } while ((state & ExitState) == 0); 5407 XSetCursorState(display,windows,MagickFalse); 5408 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 5409 XCheckRefreshWindows(display,windows); 5410 /* 5411 Free file list. 5412 */ 5413 for (i=0; i < (ssize_t) files; i++) 5414 filelist[i]=DestroyString(filelist[i]); 5415 if (filelist != (char **) NULL) 5416 filelist=(char **) RelinquishMagickMemory(filelist); 5417 if (*reply != '\0') 5418 { 5419 (void) ConcatenateMagickString(working_path,DirectorySeparator, 5420 MaxTextExtent); 5421 (void) ConcatenateMagickString(working_path,reply,MaxTextExtent); 5422 } 5423 (void) CopyMagickString(reply,working_path,MaxTextExtent); 5424 if (*reply == '~') 5425 ExpandFilename(reply); 5426} 5427 5428/* 5429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5430% % 5431% % 5432% % 5433% X F o n t B r o w s e r W i d g e t % 5434% % 5435% % 5436% % 5437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5438% 5439% XFontBrowserWidget() displays a Font Browser widget with a font query to the 5440% user. The user keys a reply and presses the Action or Cancel button to 5441% exit. The typed text is returned as the reply function parameter. 5442% 5443% The format of the XFontBrowserWidget method is: 5444% 5445% void XFontBrowserWidget(Display *display,XWindows *windows, 5446% const char *action,char *reply) 5447% 5448% A description of each parameter follows: 5449% 5450% o display: Specifies a connection to an X server; returned from 5451% XOpenDisplay. 5452% 5453% o window: Specifies a pointer to a XWindows structure. 5454% 5455% o action: Specifies a pointer to the action of this widget. 5456% 5457% o reply: the response from the user is returned in this parameter. 5458% 5459% 5460*/ 5461 5462#if defined(__cplusplus) || defined(c_plusplus) 5463extern "C" { 5464#endif 5465 5466static int FontCompare(const void *x,const void *y) 5467{ 5468 register char 5469 *p, 5470 *q; 5471 5472 p=(char *) *((char **) x); 5473 q=(char *) *((char **) y); 5474 while ((*p != '\0') && (*q != '\0') && (*p == *q)) 5475 { 5476 p++; 5477 q++; 5478 } 5479 return(*p-(*q)); 5480} 5481 5482#if defined(__cplusplus) || defined(c_plusplus) 5483} 5484#endif 5485 5486MagickPrivate void XFontBrowserWidget(Display *display,XWindows *windows, 5487 const char *action,char *reply) 5488{ 5489#define BackButtonText "Back" 5490#define CancelButtonText "Cancel" 5491#define FontnameText "Name:" 5492#define FontPatternText "Pattern:" 5493#define ResetButtonText "Reset" 5494 5495 char 5496 back_pattern[MaxTextExtent], 5497 **fontlist, 5498 **listhead, 5499 primary_selection[MaxTextExtent], 5500 reset_pattern[MaxTextExtent], 5501 text[MaxTextExtent]; 5502 5503 int 5504 fonts, 5505 x, 5506 y; 5507 5508 register int 5509 i; 5510 5511 static char 5512 glob_pattern[MaxTextExtent] = "*"; 5513 5514 static MagickStatusType 5515 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 5516 5517 Status 5518 status; 5519 5520 unsigned int 5521 height, 5522 text_width, 5523 visible_fonts, 5524 width; 5525 5526 size_t 5527 delay, 5528 state; 5529 5530 XEvent 5531 event; 5532 5533 XFontStruct 5534 *font_info; 5535 5536 XTextProperty 5537 window_name; 5538 5539 XWidgetInfo 5540 action_info, 5541 back_info, 5542 cancel_info, 5543 expose_info, 5544 list_info, 5545 mode_info, 5546 north_info, 5547 reply_info, 5548 reset_info, 5549 scroll_info, 5550 selection_info, 5551 slider_info, 5552 south_info, 5553 text_info; 5554 5555 XWindowChanges 5556 window_changes; 5557 5558 /* 5559 Get font list and sort in ascending order. 5560 */ 5561 assert(display != (Display *) NULL); 5562 assert(windows != (XWindows *) NULL); 5563 assert(action != (char *) NULL); 5564 assert(reply != (char *) NULL); 5565 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 5566 XSetCursorState(display,windows,MagickTrue); 5567 XCheckRefreshWindows(display,windows); 5568 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent); 5569 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent); 5570 fontlist=XListFonts(display,glob_pattern,32767,&fonts); 5571 if (fonts == 0) 5572 { 5573 /* 5574 Pattern failed, obtain all the fonts. 5575 */ 5576 XNoticeWidget(display,windows,"Unable to obtain fonts names:", 5577 glob_pattern); 5578 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent); 5579 fontlist=XListFonts(display,glob_pattern,32767,&fonts); 5580 if (fontlist == (char **) NULL) 5581 { 5582 XNoticeWidget(display,windows,"Unable to obtain fonts names:", 5583 glob_pattern); 5584 return; 5585 } 5586 } 5587 /* 5588 Sort font list in ascending order. 5589 */ 5590 listhead=fontlist; 5591 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,sizeof(*fontlist)); 5592 if (fontlist == (char **) NULL) 5593 { 5594 XNoticeWidget(display,windows,"MemoryAllocationFailed", 5595 "UnableToViewFonts"); 5596 return; 5597 } 5598 for (i=0; i < fonts; i++) 5599 fontlist[i]=listhead[i]; 5600 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare); 5601 /* 5602 Determine Font Browser widget attributes. 5603 */ 5604 font_info=windows->widget.font_info; 5605 text_width=0; 5606 for (i=0; i < fonts; i++) 5607 if (WidgetTextWidth(font_info,fontlist[i]) > text_width) 5608 text_width=WidgetTextWidth(font_info,fontlist[i]); 5609 width=WidgetTextWidth(font_info,(char *) action); 5610 if (WidgetTextWidth(font_info,CancelButtonText) > width) 5611 width=WidgetTextWidth(font_info,CancelButtonText); 5612 if (WidgetTextWidth(font_info,ResetButtonText) > width) 5613 width=WidgetTextWidth(font_info,ResetButtonText); 5614 if (WidgetTextWidth(font_info,BackButtonText) > width) 5615 width=WidgetTextWidth(font_info,BackButtonText); 5616 width+=QuantumMargin; 5617 if (WidgetTextWidth(font_info,FontPatternText) > width) 5618 width=WidgetTextWidth(font_info,FontPatternText); 5619 if (WidgetTextWidth(font_info,FontnameText) > width) 5620 width=WidgetTextWidth(font_info,FontnameText); 5621 height=(unsigned int) (font_info->ascent+font_info->descent); 5622 /* 5623 Position Font Browser widget. 5624 */ 5625 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+ 5626 6*QuantumMargin; 5627 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin; 5628 if (windows->widget.width < windows->widget.min_width) 5629 windows->widget.width=windows->widget.min_width; 5630 windows->widget.height=(unsigned int) 5631 (((85*height) >> 2)+((13*QuantumMargin) >> 1)+4); 5632 windows->widget.min_height=(unsigned int) 5633 (((27*height) >> 1)+((13*QuantumMargin) >> 1)+4); 5634 if (windows->widget.height < windows->widget.min_height) 5635 windows->widget.height=windows->widget.min_height; 5636 XConstrainWindowPosition(display,&windows->widget); 5637 /* 5638 Map Font Browser widget. 5639 */ 5640 (void) CopyMagickString(windows->widget.name,"Browse and Select a Font", 5641 MaxTextExtent); 5642 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 5643 if (status != False) 5644 { 5645 XSetWMName(display,windows->widget.id,&window_name); 5646 XSetWMIconName(display,windows->widget.id,&window_name); 5647 (void) XFree((void *) window_name.value); 5648 } 5649 window_changes.width=(int) windows->widget.width; 5650 window_changes.height=(int) windows->widget.height; 5651 window_changes.x=windows->widget.x; 5652 window_changes.y=windows->widget.y; 5653 (void) XReconfigureWMWindow(display,windows->widget.id, 5654 windows->widget.screen,mask,&window_changes); 5655 (void) XMapRaised(display,windows->widget.id); 5656 windows->widget.mapped=MagickFalse; 5657 /* 5658 Respond to X events. 5659 */ 5660 XGetWidgetInfo((char *) NULL,&slider_info); 5661 XGetWidgetInfo((char *) NULL,&north_info); 5662 XGetWidgetInfo((char *) NULL,&south_info); 5663 XGetWidgetInfo((char *) NULL,&expose_info); 5664 visible_fonts=0; 5665 delay=SuspendTime << 2; 5666 state=UpdateConfigurationState; 5667 do 5668 { 5669 if (state & UpdateConfigurationState) 5670 { 5671 int 5672 id; 5673 5674 /* 5675 Initialize button information. 5676 */ 5677 XGetWidgetInfo(CancelButtonText,&cancel_info); 5678 cancel_info.width=width; 5679 cancel_info.height=(unsigned int) ((3*height) >> 1); 5680 cancel_info.x=(int) 5681 (windows->widget.width-cancel_info.width-QuantumMargin-2); 5682 cancel_info.y=(int) 5683 (windows->widget.height-cancel_info.height-QuantumMargin); 5684 XGetWidgetInfo(action,&action_info); 5685 action_info.width=width; 5686 action_info.height=(unsigned int) ((3*height) >> 1); 5687 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+ 5688 (action_info.bevel_width << 1)); 5689 action_info.y=cancel_info.y; 5690 XGetWidgetInfo(BackButtonText,&back_info); 5691 back_info.width=width; 5692 back_info.height=(unsigned int) ((3*height) >> 1); 5693 back_info.x=QuantumMargin; 5694 back_info.y=((5*QuantumMargin) >> 1)+height; 5695 XGetWidgetInfo(ResetButtonText,&reset_info); 5696 reset_info.width=width; 5697 reset_info.height=(unsigned int) ((3*height) >> 1); 5698 reset_info.x=QuantumMargin; 5699 reset_info.y=back_info.y+back_info.height+QuantumMargin; 5700 /* 5701 Initialize reply information. 5702 */ 5703 XGetWidgetInfo(reply,&reply_info); 5704 reply_info.raised=MagickFalse; 5705 reply_info.bevel_width--; 5706 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1); 5707 reply_info.height=height << 1; 5708 reply_info.x=(int) (width+(QuantumMargin << 1)); 5709 reply_info.y=action_info.y-(action_info.height << 1)-QuantumMargin; 5710 /* 5711 Initialize mode information. 5712 */ 5713 XGetWidgetInfo(reply,&mode_info); 5714 mode_info.bevel_width=0; 5715 mode_info.width=(unsigned int) 5716 (action_info.x-reply_info.x-QuantumMargin); 5717 mode_info.height=action_info.height << 1; 5718 mode_info.x=reply_info.x; 5719 mode_info.y=action_info.y-action_info.height+action_info.bevel_width; 5720 /* 5721 Initialize scroll information. 5722 */ 5723 XGetWidgetInfo((char *) NULL,&scroll_info); 5724 scroll_info.bevel_width--; 5725 scroll_info.width=height; 5726 scroll_info.height=(unsigned int) 5727 (reply_info.y-back_info.y-(QuantumMargin >> 1)); 5728 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width); 5729 scroll_info.y=back_info.y-reply_info.bevel_width; 5730 scroll_info.raised=MagickFalse; 5731 scroll_info.trough=MagickTrue; 5732 north_info=scroll_info; 5733 north_info.raised=MagickTrue; 5734 north_info.width-=(north_info.bevel_width << 1); 5735 north_info.height=north_info.width-1; 5736 north_info.x+=north_info.bevel_width; 5737 north_info.y+=north_info.bevel_width; 5738 south_info=north_info; 5739 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 5740 south_info.height; 5741 id=slider_info.id; 5742 slider_info=north_info; 5743 slider_info.id=id; 5744 slider_info.width-=2; 5745 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 5746 slider_info.bevel_width+2; 5747 slider_info.height=scroll_info.height-((slider_info.min_y- 5748 scroll_info.y+1) << 1)+4; 5749 visible_fonts=scroll_info.height/(height+(height >> 3)); 5750 if (fonts > (int) visible_fonts) 5751 slider_info.height=(visible_fonts*slider_info.height)/fonts; 5752 slider_info.max_y=south_info.y-south_info.bevel_width- 5753 slider_info.bevel_width-2; 5754 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 5755 slider_info.y=slider_info.min_y; 5756 expose_info=scroll_info; 5757 expose_info.y=slider_info.y; 5758 /* 5759 Initialize list information. 5760 */ 5761 XGetWidgetInfo((char *) NULL,&list_info); 5762 list_info.raised=MagickFalse; 5763 list_info.bevel_width--; 5764 list_info.width=(unsigned int) 5765 (scroll_info.x-reply_info.x-(QuantumMargin >> 1)); 5766 list_info.height=scroll_info.height; 5767 list_info.x=reply_info.x; 5768 list_info.y=scroll_info.y; 5769 if (windows->widget.mapped == MagickFalse) 5770 state|=JumpListState; 5771 /* 5772 Initialize text information. 5773 */ 5774 *text='\0'; 5775 XGetWidgetInfo(text,&text_info); 5776 text_info.center=MagickFalse; 5777 text_info.width=reply_info.width; 5778 text_info.height=height; 5779 text_info.x=list_info.x-(QuantumMargin >> 1); 5780 text_info.y=QuantumMargin; 5781 /* 5782 Initialize selection information. 5783 */ 5784 XGetWidgetInfo((char *) NULL,&selection_info); 5785 selection_info.center=MagickFalse; 5786 selection_info.width=list_info.width; 5787 selection_info.height=(unsigned int) ((9*height) >> 3); 5788 selection_info.x=list_info.x; 5789 state&=(~UpdateConfigurationState); 5790 } 5791 if (state & RedrawWidgetState) 5792 { 5793 /* 5794 Redraw Font Browser window. 5795 */ 5796 x=QuantumMargin; 5797 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent; 5798 (void) XDrawString(display,windows->widget.id, 5799 windows->widget.annotate_context,x,y,FontPatternText, 5800 Extent(FontPatternText)); 5801 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent); 5802 XDrawWidgetText(display,&windows->widget,&text_info); 5803 XDrawBeveledButton(display,&windows->widget,&back_info); 5804 XDrawBeveledButton(display,&windows->widget,&reset_info); 5805 XDrawBeveledMatte(display,&windows->widget,&list_info); 5806 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 5807 XDrawTriangleNorth(display,&windows->widget,&north_info); 5808 XDrawBeveledButton(display,&windows->widget,&slider_info); 5809 XDrawTriangleSouth(display,&windows->widget,&south_info); 5810 x=QuantumMargin; 5811 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent; 5812 (void) XDrawString(display,windows->widget.id, 5813 windows->widget.annotate_context,x,y,FontnameText, 5814 Extent(FontnameText)); 5815 XDrawBeveledMatte(display,&windows->widget,&reply_info); 5816 XDrawMatteText(display,&windows->widget,&reply_info); 5817 XDrawBeveledButton(display,&windows->widget,&action_info); 5818 XDrawBeveledButton(display,&windows->widget,&cancel_info); 5819 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 5820 selection_info.id=(~0); 5821 state|=RedrawActionState; 5822 state|=RedrawListState; 5823 state&=(~RedrawWidgetState); 5824 } 5825 if (state & UpdateListState) 5826 { 5827 char 5828 **checklist; 5829 5830 int 5831 number_fonts; 5832 5833 /* 5834 Update font list. 5835 */ 5836 checklist=XListFonts(display,glob_pattern,32767,&number_fonts); 5837 if (checklist == (char **) NULL) 5838 { 5839 if ((strchr(glob_pattern,'*') == (char *) NULL) && 5840 (strchr(glob_pattern,'?') == (char *) NULL)) 5841 { 5842 /* 5843 Might be a scaleable font-- exit. 5844 */ 5845 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent); 5846 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent); 5847 action_info.raised=MagickFalse; 5848 XDrawBeveledButton(display,&windows->widget,&action_info); 5849 break; 5850 } 5851 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent); 5852 (void) XBell(display,0); 5853 } 5854 else 5855 if (number_fonts == 1) 5856 { 5857 /* 5858 Reply is a single font name-- exit. 5859 */ 5860 (void) CopyMagickString(reply,checklist[0],MaxTextExtent); 5861 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent); 5862 (void) XFreeFontNames(checklist); 5863 action_info.raised=MagickFalse; 5864 XDrawBeveledButton(display,&windows->widget,&action_info); 5865 break; 5866 } 5867 else 5868 { 5869 (void) XFreeFontNames(listhead); 5870 fontlist=(char **) RelinquishMagickMemory(fontlist); 5871 fontlist=checklist; 5872 fonts=number_fonts; 5873 } 5874 /* 5875 Sort font list in ascending order. 5876 */ 5877 listhead=fontlist; 5878 fontlist=(char **) AcquireQuantumMemory((size_t) fonts, 5879 sizeof(*fontlist)); 5880 if (fontlist == (char **) NULL) 5881 { 5882 XNoticeWidget(display,windows,"MemoryAllocationFailed", 5883 "UnableToViewFonts"); 5884 return; 5885 } 5886 for (i=0; i < fonts; i++) 5887 fontlist[i]=listhead[i]; 5888 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare); 5889 slider_info.height= 5890 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1; 5891 if (fonts > (int) visible_fonts) 5892 slider_info.height=(visible_fonts*slider_info.height)/fonts; 5893 slider_info.max_y=south_info.y-south_info.bevel_width- 5894 slider_info.bevel_width-2; 5895 slider_info.id=0; 5896 slider_info.y=slider_info.min_y; 5897 expose_info.y=slider_info.y; 5898 selection_info.id=(~0); 5899 list_info.id=(~0); 5900 state|=RedrawListState; 5901 /* 5902 Redraw font name & reply. 5903 */ 5904 *reply_info.text='\0'; 5905 reply_info.cursor=reply_info.text; 5906 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent); 5907 XDrawWidgetText(display,&windows->widget,&text_info); 5908 XDrawMatteText(display,&windows->widget,&reply_info); 5909 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 5910 XDrawTriangleNorth(display,&windows->widget,&north_info); 5911 XDrawBeveledButton(display,&windows->widget,&slider_info); 5912 XDrawTriangleSouth(display,&windows->widget,&south_info); 5913 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 5914 state&=(~UpdateListState); 5915 } 5916 if (state & JumpListState) 5917 { 5918 /* 5919 Jump scroll to match user font. 5920 */ 5921 list_info.id=(~0); 5922 for (i=0; i < fonts; i++) 5923 if (LocaleCompare(fontlist[i],reply) >= 0) 5924 { 5925 list_info.id=LocaleCompare(fontlist[i],reply) == 0 ? i : ~0; 5926 break; 5927 } 5928 if ((i < slider_info.id) || (i >= (int) (slider_info.id+visible_fonts))) 5929 slider_info.id=i-(visible_fonts >> 1); 5930 selection_info.id=(~0); 5931 state|=RedrawListState; 5932 state&=(~JumpListState); 5933 } 5934 if (state & RedrawListState) 5935 { 5936 /* 5937 Determine slider id and position. 5938 */ 5939 if (slider_info.id >= (int) (fonts-visible_fonts)) 5940 slider_info.id=fonts-visible_fonts; 5941 if ((slider_info.id < 0) || (fonts <= (int) visible_fonts)) 5942 slider_info.id=0; 5943 slider_info.y=slider_info.min_y; 5944 if (fonts > 0) 5945 slider_info.y+= 5946 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/fonts; 5947 if (slider_info.id != selection_info.id) 5948 { 5949 /* 5950 Redraw scroll bar and file names. 5951 */ 5952 selection_info.id=slider_info.id; 5953 selection_info.y=list_info.y+(height >> 3)+2; 5954 for (i=0; i < (int) visible_fonts; i++) 5955 { 5956 selection_info.raised=(slider_info.id+i) != list_info.id ? 5957 MagickTrue : MagickFalse; 5958 selection_info.text=(char *) NULL; 5959 if ((slider_info.id+i) < fonts) 5960 selection_info.text=fontlist[slider_info.id+i]; 5961 XDrawWidgetText(display,&windows->widget,&selection_info); 5962 selection_info.y+=(int) selection_info.height; 5963 } 5964 /* 5965 Update slider. 5966 */ 5967 if (slider_info.y > expose_info.y) 5968 { 5969 expose_info.height=(unsigned int) slider_info.y-expose_info.y; 5970 expose_info.y=slider_info.y-expose_info.height- 5971 slider_info.bevel_width-1; 5972 } 5973 else 5974 { 5975 expose_info.height=(unsigned int) expose_info.y-slider_info.y; 5976 expose_info.y=slider_info.y+slider_info.height+ 5977 slider_info.bevel_width+1; 5978 } 5979 XDrawTriangleNorth(display,&windows->widget,&north_info); 5980 XDrawMatte(display,&windows->widget,&expose_info); 5981 XDrawBeveledButton(display,&windows->widget,&slider_info); 5982 XDrawTriangleSouth(display,&windows->widget,&south_info); 5983 expose_info.y=slider_info.y; 5984 } 5985 state&=(~RedrawListState); 5986 } 5987 if (state & RedrawActionState) 5988 { 5989 XFontStruct 5990 *save_info; 5991 5992 /* 5993 Display the selected font in a drawing area. 5994 */ 5995 save_info=windows->widget.font_info; 5996 font_info=XLoadQueryFont(display,reply_info.text); 5997 if (font_info != (XFontStruct *) NULL) 5998 { 5999 windows->widget.font_info=font_info; 6000 (void) XSetFont(display,windows->widget.widget_context, 6001 font_info->fid); 6002 } 6003 XDrawBeveledButton(display,&windows->widget,&mode_info); 6004 windows->widget.font_info=save_info; 6005 if (font_info != (XFontStruct *) NULL) 6006 { 6007 (void) XSetFont(display,windows->widget.widget_context, 6008 windows->widget.font_info->fid); 6009 (void) XFreeFont(display,font_info); 6010 } 6011 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 6012 XDrawMatteText(display,&windows->widget,&reply_info); 6013 state&=(~RedrawActionState); 6014 } 6015 /* 6016 Wait for next event. 6017 */ 6018 if (north_info.raised && south_info.raised) 6019 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 6020 else 6021 { 6022 /* 6023 Brief delay before advancing scroll bar. 6024 */ 6025 XDelay(display,delay); 6026 delay=SuspendTime; 6027 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows); 6028 if (north_info.raised == MagickFalse) 6029 if (slider_info.id > 0) 6030 { 6031 /* 6032 Move slider up. 6033 */ 6034 slider_info.id--; 6035 state|=RedrawListState; 6036 } 6037 if (south_info.raised == MagickFalse) 6038 if (slider_info.id < fonts) 6039 { 6040 /* 6041 Move slider down. 6042 */ 6043 slider_info.id++; 6044 state|=RedrawListState; 6045 } 6046 if (event.type != ButtonRelease) 6047 continue; 6048 } 6049 switch (event.type) 6050 { 6051 case ButtonPress: 6052 { 6053 if (MatteIsActive(slider_info,event.xbutton)) 6054 { 6055 /* 6056 Track slider. 6057 */ 6058 slider_info.active=MagickTrue; 6059 break; 6060 } 6061 if (MatteIsActive(north_info,event.xbutton)) 6062 if (slider_info.id > 0) 6063 { 6064 /* 6065 Move slider up. 6066 */ 6067 north_info.raised=MagickFalse; 6068 slider_info.id--; 6069 state|=RedrawListState; 6070 break; 6071 } 6072 if (MatteIsActive(south_info,event.xbutton)) 6073 if (slider_info.id < fonts) 6074 { 6075 /* 6076 Move slider down. 6077 */ 6078 south_info.raised=MagickFalse; 6079 slider_info.id++; 6080 state|=RedrawListState; 6081 break; 6082 } 6083 if (MatteIsActive(scroll_info,event.xbutton)) 6084 { 6085 /* 6086 Move slider. 6087 */ 6088 if (event.xbutton.y < slider_info.y) 6089 slider_info.id-=(visible_fonts-1); 6090 else 6091 slider_info.id+=(visible_fonts-1); 6092 state|=RedrawListState; 6093 break; 6094 } 6095 if (MatteIsActive(list_info,event.xbutton)) 6096 { 6097 int 6098 id; 6099 6100 /* 6101 User pressed list matte. 6102 */ 6103 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/ 6104 selection_info.height; 6105 if (id >= (int) fonts) 6106 break; 6107 (void) CopyMagickString(reply_info.text,fontlist[id],MaxTextExtent); 6108 reply_info.highlight=MagickFalse; 6109 reply_info.marker=reply_info.text; 6110 reply_info.cursor=reply_info.text+Extent(reply_info.text); 6111 XDrawMatteText(display,&windows->widget,&reply_info); 6112 state|=RedrawActionState; 6113 if (id == list_info.id) 6114 { 6115 (void) CopyMagickString(glob_pattern,reply_info.text, 6116 MaxTextExtent); 6117 state|=UpdateListState; 6118 } 6119 selection_info.id=(~0); 6120 list_info.id=id; 6121 state|=RedrawListState; 6122 break; 6123 } 6124 if (MatteIsActive(back_info,event.xbutton)) 6125 { 6126 /* 6127 User pressed Back button. 6128 */ 6129 back_info.raised=MagickFalse; 6130 XDrawBeveledButton(display,&windows->widget,&back_info); 6131 break; 6132 } 6133 if (MatteIsActive(reset_info,event.xbutton)) 6134 { 6135 /* 6136 User pressed Reset button. 6137 */ 6138 reset_info.raised=MagickFalse; 6139 XDrawBeveledButton(display,&windows->widget,&reset_info); 6140 break; 6141 } 6142 if (MatteIsActive(action_info,event.xbutton)) 6143 { 6144 /* 6145 User pressed action button. 6146 */ 6147 action_info.raised=MagickFalse; 6148 XDrawBeveledButton(display,&windows->widget,&action_info); 6149 break; 6150 } 6151 if (MatteIsActive(cancel_info,event.xbutton)) 6152 { 6153 /* 6154 User pressed Cancel button. 6155 */ 6156 cancel_info.raised=MagickFalse; 6157 XDrawBeveledButton(display,&windows->widget,&cancel_info); 6158 break; 6159 } 6160 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 6161 break; 6162 if (event.xbutton.button != Button2) 6163 { 6164 static Time 6165 click_time; 6166 6167 /* 6168 Move text cursor to position of button press. 6169 */ 6170 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 6171 for (i=1; i <= Extent(reply_info.marker); i++) 6172 if (XTextWidth(font_info,reply_info.marker,i) > x) 6173 break; 6174 reply_info.cursor=reply_info.marker+i-1; 6175 if (event.xbutton.time > (click_time+DoubleClick)) 6176 reply_info.highlight=MagickFalse; 6177 else 6178 { 6179 /* 6180 Become the XA_PRIMARY selection owner. 6181 */ 6182 (void) CopyMagickString(primary_selection,reply_info.text, 6183 MaxTextExtent); 6184 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 6185 event.xbutton.time); 6186 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 6187 windows->widget.id ? MagickTrue : MagickFalse; 6188 } 6189 XDrawMatteText(display,&windows->widget,&reply_info); 6190 click_time=event.xbutton.time; 6191 break; 6192 } 6193 /* 6194 Request primary selection. 6195 */ 6196 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 6197 windows->widget.id,event.xbutton.time); 6198 break; 6199 } 6200 case ButtonRelease: 6201 { 6202 if (windows->widget.mapped == MagickFalse) 6203 break; 6204 if (north_info.raised == MagickFalse) 6205 { 6206 /* 6207 User released up button. 6208 */ 6209 delay=SuspendTime << 2; 6210 north_info.raised=MagickTrue; 6211 XDrawTriangleNorth(display,&windows->widget,&north_info); 6212 } 6213 if (south_info.raised == MagickFalse) 6214 { 6215 /* 6216 User released down button. 6217 */ 6218 delay=SuspendTime << 2; 6219 south_info.raised=MagickTrue; 6220 XDrawTriangleSouth(display,&windows->widget,&south_info); 6221 } 6222 if (slider_info.active) 6223 { 6224 /* 6225 Stop tracking slider. 6226 */ 6227 slider_info.active=MagickFalse; 6228 break; 6229 } 6230 if (back_info.raised == MagickFalse) 6231 { 6232 if (event.xbutton.window == windows->widget.id) 6233 if (MatteIsActive(back_info,event.xbutton)) 6234 { 6235 (void) CopyMagickString(glob_pattern,back_pattern, 6236 MaxTextExtent); 6237 state|=UpdateListState; 6238 } 6239 back_info.raised=MagickTrue; 6240 XDrawBeveledButton(display,&windows->widget,&back_info); 6241 } 6242 if (reset_info.raised == MagickFalse) 6243 { 6244 if (event.xbutton.window == windows->widget.id) 6245 if (MatteIsActive(reset_info,event.xbutton)) 6246 { 6247 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent); 6248 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent); 6249 state|=UpdateListState; 6250 } 6251 reset_info.raised=MagickTrue; 6252 XDrawBeveledButton(display,&windows->widget,&reset_info); 6253 } 6254 if (action_info.raised == MagickFalse) 6255 { 6256 if (event.xbutton.window == windows->widget.id) 6257 { 6258 if (MatteIsActive(action_info,event.xbutton)) 6259 { 6260 if (*reply_info.text == '\0') 6261 (void) XBell(display,0); 6262 else 6263 state|=ExitState; 6264 } 6265 } 6266 action_info.raised=MagickTrue; 6267 XDrawBeveledButton(display,&windows->widget,&action_info); 6268 } 6269 if (cancel_info.raised == MagickFalse) 6270 { 6271 if (event.xbutton.window == windows->widget.id) 6272 if (MatteIsActive(cancel_info,event.xbutton)) 6273 { 6274 *reply_info.text='\0'; 6275 state|=ExitState; 6276 } 6277 cancel_info.raised=MagickTrue; 6278 XDrawBeveledButton(display,&windows->widget,&cancel_info); 6279 } 6280 break; 6281 } 6282 case ClientMessage: 6283 { 6284 /* 6285 If client window delete message, exit. 6286 */ 6287 if (event.xclient.message_type != windows->wm_protocols) 6288 break; 6289 if (*event.xclient.data.l == (int) windows->wm_take_focus) 6290 { 6291 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 6292 (Time) event.xclient.data.l[1]); 6293 break; 6294 } 6295 if (*event.xclient.data.l != (int) windows->wm_delete_window) 6296 break; 6297 if (event.xclient.window == windows->widget.id) 6298 { 6299 *reply_info.text='\0'; 6300 state|=ExitState; 6301 break; 6302 } 6303 break; 6304 } 6305 case ConfigureNotify: 6306 { 6307 /* 6308 Update widget configuration. 6309 */ 6310 if (event.xconfigure.window != windows->widget.id) 6311 break; 6312 if ((event.xconfigure.width == (int) windows->widget.width) && 6313 (event.xconfigure.height == (int) windows->widget.height)) 6314 break; 6315 windows->widget.width=(unsigned int) 6316 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 6317 windows->widget.height=(unsigned int) 6318 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 6319 state|=UpdateConfigurationState; 6320 break; 6321 } 6322 case EnterNotify: 6323 { 6324 if (event.xcrossing.window != windows->widget.id) 6325 break; 6326 state&=(~InactiveWidgetState); 6327 break; 6328 } 6329 case Expose: 6330 { 6331 if (event.xexpose.window != windows->widget.id) 6332 break; 6333 if (event.xexpose.count != 0) 6334 break; 6335 state|=RedrawWidgetState; 6336 break; 6337 } 6338 case KeyPress: 6339 { 6340 static char 6341 command[MaxTextExtent]; 6342 6343 static int 6344 length; 6345 6346 static KeySym 6347 key_symbol; 6348 6349 /* 6350 Respond to a user key press. 6351 */ 6352 if (event.xkey.window != windows->widget.id) 6353 break; 6354 length=XLookupString((XKeyEvent *) &event.xkey,command, 6355 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 6356 *(command+length)='\0'; 6357 if (AreaIsActive(scroll_info,event.xkey)) 6358 { 6359 /* 6360 Move slider. 6361 */ 6362 switch ((int) key_symbol) 6363 { 6364 case XK_Home: 6365 case XK_KP_Home: 6366 { 6367 slider_info.id=0; 6368 break; 6369 } 6370 case XK_Up: 6371 case XK_KP_Up: 6372 { 6373 slider_info.id--; 6374 break; 6375 } 6376 case XK_Down: 6377 case XK_KP_Down: 6378 { 6379 slider_info.id++; 6380 break; 6381 } 6382 case XK_Prior: 6383 case XK_KP_Prior: 6384 { 6385 slider_info.id-=visible_fonts; 6386 break; 6387 } 6388 case XK_Next: 6389 case XK_KP_Next: 6390 { 6391 slider_info.id+=visible_fonts; 6392 break; 6393 } 6394 case XK_End: 6395 case XK_KP_End: 6396 { 6397 slider_info.id=fonts; 6398 break; 6399 } 6400 } 6401 state|=RedrawListState; 6402 break; 6403 } 6404 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 6405 { 6406 /* 6407 Read new font or glob patterm. 6408 */ 6409 if (*reply_info.text == '\0') 6410 break; 6411 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent); 6412 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent); 6413 state|=UpdateListState; 6414 break; 6415 } 6416 if (key_symbol == XK_Control_L) 6417 { 6418 state|=ControlState; 6419 break; 6420 } 6421 if (state & ControlState) 6422 switch ((int) key_symbol) 6423 { 6424 case XK_u: 6425 case XK_U: 6426 { 6427 /* 6428 Erase the entire line of text. 6429 */ 6430 *reply_info.text='\0'; 6431 reply_info.cursor=reply_info.text; 6432 reply_info.marker=reply_info.text; 6433 reply_info.highlight=MagickFalse; 6434 break; 6435 } 6436 default: 6437 break; 6438 } 6439 XEditText(display,&reply_info,key_symbol,command,state); 6440 XDrawMatteText(display,&windows->widget,&reply_info); 6441 state|=JumpListState; 6442 break; 6443 } 6444 case KeyRelease: 6445 { 6446 static char 6447 command[MaxTextExtent]; 6448 6449 static KeySym 6450 key_symbol; 6451 6452 /* 6453 Respond to a user key release. 6454 */ 6455 if (event.xkey.window != windows->widget.id) 6456 break; 6457 (void) XLookupString((XKeyEvent *) &event.xkey,command, 6458 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 6459 if (key_symbol == XK_Control_L) 6460 state&=(~ControlState); 6461 break; 6462 } 6463 case LeaveNotify: 6464 { 6465 if (event.xcrossing.window != windows->widget.id) 6466 break; 6467 state|=InactiveWidgetState; 6468 break; 6469 } 6470 case MapNotify: 6471 { 6472 mask&=(~CWX); 6473 mask&=(~CWY); 6474 break; 6475 } 6476 case MotionNotify: 6477 { 6478 /* 6479 Discard pending button motion events. 6480 */ 6481 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 6482 if (slider_info.active) 6483 { 6484 /* 6485 Move slider matte. 6486 */ 6487 slider_info.y=event.xmotion.y- 6488 ((slider_info.height+slider_info.bevel_width) >> 1)+1; 6489 if (slider_info.y < slider_info.min_y) 6490 slider_info.y=slider_info.min_y; 6491 if (slider_info.y > slider_info.max_y) 6492 slider_info.y=slider_info.max_y; 6493 slider_info.id=0; 6494 if (slider_info.y != slider_info.min_y) 6495 slider_info.id=(fonts*(slider_info.y-slider_info.min_y+1))/ 6496 (slider_info.max_y-slider_info.min_y+1); 6497 state|=RedrawListState; 6498 break; 6499 } 6500 if (state & InactiveWidgetState) 6501 break; 6502 if (back_info.raised == MatteIsActive(back_info,event.xmotion)) 6503 { 6504 /* 6505 Back button status changed. 6506 */ 6507 back_info.raised=!back_info.raised; 6508 XDrawBeveledButton(display,&windows->widget,&back_info); 6509 break; 6510 } 6511 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion)) 6512 { 6513 /* 6514 Reset button status changed. 6515 */ 6516 reset_info.raised=!reset_info.raised; 6517 XDrawBeveledButton(display,&windows->widget,&reset_info); 6518 break; 6519 } 6520 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 6521 { 6522 /* 6523 Action button status changed. 6524 */ 6525 action_info.raised=action_info.raised == MagickFalse ? 6526 MagickTrue : MagickFalse; 6527 XDrawBeveledButton(display,&windows->widget,&action_info); 6528 break; 6529 } 6530 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 6531 { 6532 /* 6533 Cancel button status changed. 6534 */ 6535 cancel_info.raised=cancel_info.raised == MagickFalse ? 6536 MagickTrue : MagickFalse; 6537 XDrawBeveledButton(display,&windows->widget,&cancel_info); 6538 break; 6539 } 6540 break; 6541 } 6542 case SelectionClear: 6543 { 6544 reply_info.highlight=MagickFalse; 6545 XDrawMatteText(display,&windows->widget,&reply_info); 6546 break; 6547 } 6548 case SelectionNotify: 6549 { 6550 Atom 6551 type; 6552 6553 int 6554 format; 6555 6556 unsigned char 6557 *data; 6558 6559 unsigned long 6560 after, 6561 length; 6562 6563 /* 6564 Obtain response from primary selection. 6565 */ 6566 if (event.xselection.property == (Atom) None) 6567 break; 6568 status=XGetWindowProperty(display,event.xselection.requestor, 6569 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type, 6570 &format,&length,&after,&data); 6571 if ((status != Success) || (type != XA_STRING) || (format == 32) || 6572 (length == 0)) 6573 break; 6574 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 6575 (void) XBell(display,0); 6576 else 6577 { 6578 /* 6579 Insert primary selection in reply text. 6580 */ 6581 *(data+length)='\0'; 6582 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 6583 state); 6584 XDrawMatteText(display,&windows->widget,&reply_info); 6585 state|=JumpListState; 6586 state|=RedrawActionState; 6587 } 6588 (void) XFree((void *) data); 6589 break; 6590 } 6591 case SelectionRequest: 6592 { 6593 XSelectionEvent 6594 notify; 6595 6596 XSelectionRequestEvent 6597 *request; 6598 6599 /* 6600 Set XA_PRIMARY selection. 6601 */ 6602 request=(&(event.xselectionrequest)); 6603 (void) XChangeProperty(request->display,request->requestor, 6604 request->property,request->target,8,PropModeReplace, 6605 (unsigned char *) primary_selection,Extent(primary_selection)); 6606 notify.type=SelectionNotify; 6607 notify.display=request->display; 6608 notify.requestor=request->requestor; 6609 notify.selection=request->selection; 6610 notify.target=request->target; 6611 notify.time=request->time; 6612 if (request->property == None) 6613 notify.property=request->target; 6614 else 6615 notify.property=request->property; 6616 (void) XSendEvent(request->display,request->requestor,False,0, 6617 (XEvent *) ¬ify); 6618 } 6619 default: 6620 break; 6621 } 6622 } while ((state & ExitState) == 0); 6623 XSetCursorState(display,windows,MagickFalse); 6624 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 6625 XCheckRefreshWindows(display,windows); 6626 /* 6627 Free font list. 6628 */ 6629 (void) XFreeFontNames(listhead); 6630 fontlist=(char **) RelinquishMagickMemory(fontlist); 6631} 6632 6633/* 6634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6635% % 6636% % 6637% % 6638% X I n f o W i d g e t % 6639% % 6640% % 6641% % 6642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6643% 6644% XInfoWidget() displays text in the Info widget. The purpose is to inform 6645% the user that what activity is currently being performed (e.g. reading 6646% an image, rotating an image, etc.). 6647% 6648% The format of the XInfoWidget method is: 6649% 6650% void XInfoWidget(Display *display,XWindows *windows,const char *activity) 6651% 6652% A description of each parameter follows: 6653% 6654% o display: Specifies a connection to an X server; returned from 6655% XOpenDisplay. 6656% 6657% o window: Specifies a pointer to a XWindows structure. 6658% 6659% o activity: This character string reflects the current activity and is 6660% displayed in the Info widget. 6661% 6662*/ 6663MagickPrivate void XInfoWidget(Display *display,XWindows *windows, 6664 const char *activity) 6665{ 6666 unsigned int 6667 height, 6668 margin, 6669 width; 6670 6671 XFontStruct 6672 *font_info; 6673 6674 XWindowChanges 6675 window_changes; 6676 6677 /* 6678 Map Info widget. 6679 */ 6680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 6681 assert(display != (Display *) NULL); 6682 assert(windows != (XWindows *) NULL); 6683 assert(activity != (char *) NULL); 6684 font_info=windows->info.font_info; 6685 width=WidgetTextWidth(font_info,(char *) activity)+((3*QuantumMargin) >> 1)+4; 6686 height=(unsigned int) (((6*(font_info->ascent+font_info->descent)) >> 2)+4); 6687 if ((windows->info.width != width) || (windows->info.height != height)) 6688 { 6689 /* 6690 Size Info widget to accommodate the activity text. 6691 */ 6692 windows->info.width=width; 6693 windows->info.height=height; 6694 window_changes.width=(int) width; 6695 window_changes.height=(int) height; 6696 (void) XReconfigureWMWindow(display,windows->info.id,windows->info.screen, 6697 (unsigned int) (CWWidth | CWHeight),&window_changes); 6698 } 6699 if (windows->info.mapped == MagickFalse) 6700 { 6701 (void) XMapRaised(display,windows->info.id); 6702 windows->info.mapped=MagickTrue; 6703 } 6704 /* 6705 Initialize Info matte information. 6706 */ 6707 height=(unsigned int) (font_info->ascent+font_info->descent); 6708 XGetWidgetInfo(activity,&monitor_info); 6709 monitor_info.bevel_width--; 6710 margin=monitor_info.bevel_width+((windows->info.height-height) >> 1)-2; 6711 monitor_info.center=MagickFalse; 6712 monitor_info.x=(int) margin; 6713 monitor_info.y=(int) margin; 6714 monitor_info.width=windows->info.width-(margin << 1); 6715 monitor_info.height=windows->info.height-(margin << 1)+1; 6716 /* 6717 Draw Info widget. 6718 */ 6719 monitor_info.raised=MagickFalse; 6720 XDrawBeveledMatte(display,&windows->info,&monitor_info); 6721 monitor_info.raised=MagickTrue; 6722 XDrawWidgetText(display,&windows->info,&monitor_info); 6723} 6724 6725/* 6726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6727% % 6728% % 6729% % 6730% X L i s t B r o w s e r W i d g e t % 6731% % 6732% % 6733% % 6734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6735% 6736% XListBrowserWidget() displays a List Browser widget with a query to the 6737% user. The user keys a reply or select a reply from the list. Finally, the 6738% user presses the Action or Cancel button to exit. The typed text is 6739% returned as the reply function parameter. 6740% 6741% The format of the XListBrowserWidget method is: 6742% 6743% void XListBrowserWidget(Display *display,XWindows *windows, 6744% XWindowInfo *window_info,const char **list,const char *action, 6745% const char *query,char *reply) 6746% 6747% A description of each parameter follows: 6748% 6749% o display: Specifies a connection to an X server; returned from 6750% XOpenDisplay. 6751% 6752% o window: Specifies a pointer to a XWindows structure. 6753% 6754% o list: Specifies a pointer to an array of strings. The user can 6755% select from these strings as a possible reply value. 6756% 6757% o action: Specifies a pointer to the action of this widget. 6758% 6759% o query: Specifies a pointer to the query to present to the user. 6760% 6761% o reply: the response from the user is returned in this parameter. 6762% 6763*/ 6764MagickPrivate void XListBrowserWidget(Display *display,XWindows *windows, 6765 XWindowInfo *window_info,const char **list,const char *action, 6766 const char *query,char *reply) 6767{ 6768#define CancelButtonText "Cancel" 6769 6770 char 6771 primary_selection[MaxTextExtent]; 6772 6773 int 6774 x; 6775 6776 register int 6777 i; 6778 6779 static MagickStatusType 6780 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 6781 6782 Status 6783 status; 6784 6785 unsigned int 6786 entries, 6787 height, 6788 text_width, 6789 visible_entries, 6790 width; 6791 6792 size_t 6793 delay, 6794 state; 6795 6796 XEvent 6797 event; 6798 6799 XFontStruct 6800 *font_info; 6801 6802 XTextProperty 6803 window_name; 6804 6805 XWidgetInfo 6806 action_info, 6807 cancel_info, 6808 expose_info, 6809 list_info, 6810 north_info, 6811 reply_info, 6812 scroll_info, 6813 selection_info, 6814 slider_info, 6815 south_info, 6816 text_info; 6817 6818 XWindowChanges 6819 window_changes; 6820 6821 /* 6822 Count the number of entries in the list. 6823 */ 6824 assert(display != (Display *) NULL); 6825 assert(windows != (XWindows *) NULL); 6826 assert(window_info != (XWindowInfo *) NULL); 6827 assert(list != (const char **) NULL); 6828 assert(action != (char *) NULL); 6829 assert(query != (char *) NULL); 6830 assert(reply != (char *) NULL); 6831 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 6832 XSetCursorState(display,windows,MagickTrue); 6833 XCheckRefreshWindows(display,windows); 6834 if (list == (const char **) NULL) 6835 { 6836 XNoticeWidget(display,windows,"No text to browse:",(char *) NULL); 6837 return; 6838 } 6839 for (entries=0; ; entries++) 6840 if (list[entries] == (char *) NULL) 6841 break; 6842 /* 6843 Determine Font Browser widget attributes. 6844 */ 6845 font_info=window_info->font_info; 6846 text_width=WidgetTextWidth(font_info,(char *) query); 6847 for (i=0; i < (int) entries; i++) 6848 if (WidgetTextWidth(font_info,(char *) list[i]) > text_width) 6849 text_width=WidgetTextWidth(font_info,(char *) list[i]); 6850 width=WidgetTextWidth(font_info,(char *) action); 6851 if (WidgetTextWidth(font_info,CancelButtonText) > width) 6852 width=WidgetTextWidth(font_info,CancelButtonText); 6853 width+=QuantumMargin; 6854 height=(unsigned int) (font_info->ascent+font_info->descent); 6855 /* 6856 Position List Browser widget. 6857 */ 6858 window_info->width=(unsigned int) MagickMin((int) text_width,(int) 6859 MaxTextWidth)+((9*QuantumMargin) >> 1); 6860 window_info->min_width=(unsigned int) (MinTextWidth+4*QuantumMargin); 6861 if (window_info->width < window_info->min_width) 6862 window_info->width=window_info->min_width; 6863 window_info->height=(unsigned int) 6864 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4); 6865 window_info->min_height=(unsigned int) 6866 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4); 6867 if (window_info->height < window_info->min_height) 6868 window_info->height=window_info->min_height; 6869 XConstrainWindowPosition(display,window_info); 6870 /* 6871 Map List Browser widget. 6872 */ 6873 (void) CopyMagickString(window_info->name,"Browse",MaxTextExtent); 6874 status=XStringListToTextProperty(&window_info->name,1,&window_name); 6875 if (status != False) 6876 { 6877 XSetWMName(display,window_info->id,&window_name); 6878 XSetWMIconName(display,windows->widget.id,&window_name); 6879 (void) XFree((void *) window_name.value); 6880 } 6881 window_changes.width=(int) window_info->width; 6882 window_changes.height=(int) window_info->height; 6883 window_changes.x=window_info->x; 6884 window_changes.y=window_info->y; 6885 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,mask, 6886 &window_changes); 6887 (void) XMapRaised(display,window_info->id); 6888 window_info->mapped=MagickFalse; 6889 /* 6890 Respond to X events. 6891 */ 6892 XGetWidgetInfo((char *) NULL,&slider_info); 6893 XGetWidgetInfo((char *) NULL,&north_info); 6894 XGetWidgetInfo((char *) NULL,&south_info); 6895 XGetWidgetInfo((char *) NULL,&expose_info); 6896 visible_entries=0; 6897 delay=SuspendTime << 2; 6898 state=UpdateConfigurationState; 6899 do 6900 { 6901 if (state & UpdateConfigurationState) 6902 { 6903 int 6904 id; 6905 6906 /* 6907 Initialize button information. 6908 */ 6909 XGetWidgetInfo(CancelButtonText,&cancel_info); 6910 cancel_info.width=width; 6911 cancel_info.height=(unsigned int) ((3*height) >> 1); 6912 cancel_info.x=(int) 6913 (window_info->width-cancel_info.width-QuantumMargin-2); 6914 cancel_info.y=(int) 6915 (window_info->height-cancel_info.height-QuantumMargin); 6916 XGetWidgetInfo(action,&action_info); 6917 action_info.width=width; 6918 action_info.height=(unsigned int) ((3*height) >> 1); 6919 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+ 6920 (action_info.bevel_width << 1)); 6921 action_info.y=cancel_info.y; 6922 /* 6923 Initialize reply information. 6924 */ 6925 XGetWidgetInfo(reply,&reply_info); 6926 reply_info.raised=MagickFalse; 6927 reply_info.bevel_width--; 6928 reply_info.width=window_info->width-((4*QuantumMargin) >> 1); 6929 reply_info.height=height << 1; 6930 reply_info.x=QuantumMargin; 6931 reply_info.y=action_info.y-reply_info.height-QuantumMargin; 6932 /* 6933 Initialize scroll information. 6934 */ 6935 XGetWidgetInfo((char *) NULL,&scroll_info); 6936 scroll_info.bevel_width--; 6937 scroll_info.width=height; 6938 scroll_info.height=(unsigned int) 6939 (reply_info.y-((6*QuantumMargin) >> 1)-height); 6940 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width); 6941 scroll_info.y=((5*QuantumMargin) >> 1)+height-reply_info.bevel_width; 6942 scroll_info.raised=MagickFalse; 6943 scroll_info.trough=MagickTrue; 6944 north_info=scroll_info; 6945 north_info.raised=MagickTrue; 6946 north_info.width-=(north_info.bevel_width << 1); 6947 north_info.height=north_info.width-1; 6948 north_info.x+=north_info.bevel_width; 6949 north_info.y+=north_info.bevel_width; 6950 south_info=north_info; 6951 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 6952 south_info.height; 6953 id=slider_info.id; 6954 slider_info=north_info; 6955 slider_info.id=id; 6956 slider_info.width-=2; 6957 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 6958 slider_info.bevel_width+2; 6959 slider_info.height=scroll_info.height-((slider_info.min_y- 6960 scroll_info.y+1) << 1)+4; 6961 visible_entries=scroll_info.height/(height+(height >> 3)); 6962 if (entries > visible_entries) 6963 slider_info.height=(visible_entries*slider_info.height)/entries; 6964 slider_info.max_y=south_info.y-south_info.bevel_width- 6965 slider_info.bevel_width-2; 6966 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 6967 slider_info.y=slider_info.min_y; 6968 expose_info=scroll_info; 6969 expose_info.y=slider_info.y; 6970 /* 6971 Initialize list information. 6972 */ 6973 XGetWidgetInfo((char *) NULL,&list_info); 6974 list_info.raised=MagickFalse; 6975 list_info.bevel_width--; 6976 list_info.width=(unsigned int) 6977 (scroll_info.x-reply_info.x-(QuantumMargin >> 1)); 6978 list_info.height=scroll_info.height; 6979 list_info.x=reply_info.x; 6980 list_info.y=scroll_info.y; 6981 if (window_info->mapped == MagickFalse) 6982 for (i=0; i < (int) entries; i++) 6983 if (LocaleCompare(list[i],reply) == 0) 6984 { 6985 list_info.id=i; 6986 slider_info.id=i-(visible_entries >> 1); 6987 if (slider_info.id < 0) 6988 slider_info.id=0; 6989 } 6990 /* 6991 Initialize text information. 6992 */ 6993 XGetWidgetInfo(query,&text_info); 6994 text_info.width=reply_info.width; 6995 text_info.height=height; 6996 text_info.x=list_info.x-(QuantumMargin >> 1); 6997 text_info.y=QuantumMargin; 6998 /* 6999 Initialize selection information. 7000 */ 7001 XGetWidgetInfo((char *) NULL,&selection_info); 7002 selection_info.center=MagickFalse; 7003 selection_info.width=list_info.width; 7004 selection_info.height=(unsigned int) ((9*height) >> 3); 7005 selection_info.x=list_info.x; 7006 state&=(~UpdateConfigurationState); 7007 } 7008 if (state & RedrawWidgetState) 7009 { 7010 /* 7011 Redraw List Browser window. 7012 */ 7013 XDrawWidgetText(display,window_info,&text_info); 7014 XDrawBeveledMatte(display,window_info,&list_info); 7015 XDrawBeveledMatte(display,window_info,&scroll_info); 7016 XDrawTriangleNorth(display,window_info,&north_info); 7017 XDrawBeveledButton(display,window_info,&slider_info); 7018 XDrawTriangleSouth(display,window_info,&south_info); 7019 XDrawBeveledMatte(display,window_info,&reply_info); 7020 XDrawMatteText(display,window_info,&reply_info); 7021 XDrawBeveledButton(display,window_info,&action_info); 7022 XDrawBeveledButton(display,window_info,&cancel_info); 7023 XHighlightWidget(display,window_info,BorderOffset,BorderOffset); 7024 selection_info.id=(~0); 7025 state|=RedrawActionState; 7026 state|=RedrawListState; 7027 state&=(~RedrawWidgetState); 7028 } 7029 if (state & RedrawListState) 7030 { 7031 /* 7032 Determine slider id and position. 7033 */ 7034 if (slider_info.id >= (int) (entries-visible_entries)) 7035 slider_info.id=(int) (entries-visible_entries); 7036 if ((slider_info.id < 0) || (entries <= visible_entries)) 7037 slider_info.id=0; 7038 slider_info.y=slider_info.min_y; 7039 if (entries > 0) 7040 slider_info.y+= 7041 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/entries; 7042 if (slider_info.id != selection_info.id) 7043 { 7044 /* 7045 Redraw scroll bar and file names. 7046 */ 7047 selection_info.id=slider_info.id; 7048 selection_info.y=list_info.y+(height >> 3)+2; 7049 for (i=0; i < (int) visible_entries; i++) 7050 { 7051 selection_info.raised=(slider_info.id+i) != list_info.id ? 7052 MagickTrue : MagickFalse; 7053 selection_info.text=(char *) NULL; 7054 if ((slider_info.id+i) < (int) entries) 7055 selection_info.text=(char *) list[slider_info.id+i]; 7056 XDrawWidgetText(display,window_info,&selection_info); 7057 selection_info.y+=(int) selection_info.height; 7058 } 7059 /* 7060 Update slider. 7061 */ 7062 if (slider_info.y > expose_info.y) 7063 { 7064 expose_info.height=(unsigned int) slider_info.y-expose_info.y; 7065 expose_info.y=slider_info.y-expose_info.height- 7066 slider_info.bevel_width-1; 7067 } 7068 else 7069 { 7070 expose_info.height=(unsigned int) expose_info.y-slider_info.y; 7071 expose_info.y=slider_info.y+slider_info.height+ 7072 slider_info.bevel_width+1; 7073 } 7074 XDrawTriangleNorth(display,window_info,&north_info); 7075 XDrawMatte(display,window_info,&expose_info); 7076 XDrawBeveledButton(display,window_info,&slider_info); 7077 XDrawTriangleSouth(display,window_info,&south_info); 7078 expose_info.y=slider_info.y; 7079 } 7080 state&=(~RedrawListState); 7081 } 7082 /* 7083 Wait for next event. 7084 */ 7085 if (north_info.raised && south_info.raised) 7086 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 7087 else 7088 { 7089 /* 7090 Brief delay before advancing scroll bar. 7091 */ 7092 XDelay(display,delay); 7093 delay=SuspendTime; 7094 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows); 7095 if (north_info.raised == MagickFalse) 7096 if (slider_info.id > 0) 7097 { 7098 /* 7099 Move slider up. 7100 */ 7101 slider_info.id--; 7102 state|=RedrawListState; 7103 } 7104 if (south_info.raised == MagickFalse) 7105 if (slider_info.id < (int) entries) 7106 { 7107 /* 7108 Move slider down. 7109 */ 7110 slider_info.id++; 7111 state|=RedrawListState; 7112 } 7113 if (event.type != ButtonRelease) 7114 continue; 7115 } 7116 switch (event.type) 7117 { 7118 case ButtonPress: 7119 { 7120 if (MatteIsActive(slider_info,event.xbutton)) 7121 { 7122 /* 7123 Track slider. 7124 */ 7125 slider_info.active=MagickTrue; 7126 break; 7127 } 7128 if (MatteIsActive(north_info,event.xbutton)) 7129 if (slider_info.id > 0) 7130 { 7131 /* 7132 Move slider up. 7133 */ 7134 north_info.raised=MagickFalse; 7135 slider_info.id--; 7136 state|=RedrawListState; 7137 break; 7138 } 7139 if (MatteIsActive(south_info,event.xbutton)) 7140 if (slider_info.id < (int) entries) 7141 { 7142 /* 7143 Move slider down. 7144 */ 7145 south_info.raised=MagickFalse; 7146 slider_info.id++; 7147 state|=RedrawListState; 7148 break; 7149 } 7150 if (MatteIsActive(scroll_info,event.xbutton)) 7151 { 7152 /* 7153 Move slider. 7154 */ 7155 if (event.xbutton.y < slider_info.y) 7156 slider_info.id-=(visible_entries-1); 7157 else 7158 slider_info.id+=(visible_entries-1); 7159 state|=RedrawListState; 7160 break; 7161 } 7162 if (MatteIsActive(list_info,event.xbutton)) 7163 { 7164 int 7165 id; 7166 7167 /* 7168 User pressed list matte. 7169 */ 7170 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/ 7171 selection_info.height; 7172 if (id >= (int) entries) 7173 break; 7174 (void) CopyMagickString(reply_info.text,list[id],MaxTextExtent); 7175 reply_info.highlight=MagickFalse; 7176 reply_info.marker=reply_info.text; 7177 reply_info.cursor=reply_info.text+Extent(reply_info.text); 7178 XDrawMatteText(display,window_info,&reply_info); 7179 selection_info.id=(~0); 7180 if (id == list_info.id) 7181 { 7182 action_info.raised=MagickFalse; 7183 XDrawBeveledButton(display,window_info,&action_info); 7184 state|=ExitState; 7185 } 7186 list_info.id=id; 7187 state|=RedrawListState; 7188 break; 7189 } 7190 if (MatteIsActive(action_info,event.xbutton)) 7191 { 7192 /* 7193 User pressed action button. 7194 */ 7195 action_info.raised=MagickFalse; 7196 XDrawBeveledButton(display,window_info,&action_info); 7197 break; 7198 } 7199 if (MatteIsActive(cancel_info,event.xbutton)) 7200 { 7201 /* 7202 User pressed Cancel button. 7203 */ 7204 cancel_info.raised=MagickFalse; 7205 XDrawBeveledButton(display,window_info,&cancel_info); 7206 break; 7207 } 7208 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 7209 break; 7210 if (event.xbutton.button != Button2) 7211 { 7212 static Time 7213 click_time; 7214 7215 /* 7216 Move text cursor to position of button press. 7217 */ 7218 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 7219 for (i=1; i <= Extent(reply_info.marker); i++) 7220 if (XTextWidth(font_info,reply_info.marker,i) > x) 7221 break; 7222 reply_info.cursor=reply_info.marker+i-1; 7223 if (event.xbutton.time > (click_time+DoubleClick)) 7224 reply_info.highlight=MagickFalse; 7225 else 7226 { 7227 /* 7228 Become the XA_PRIMARY selection owner. 7229 */ 7230 (void) CopyMagickString(primary_selection,reply_info.text, 7231 MaxTextExtent); 7232 (void) XSetSelectionOwner(display,XA_PRIMARY,window_info->id, 7233 event.xbutton.time); 7234 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 7235 window_info->id ? MagickTrue : MagickFalse; 7236 } 7237 XDrawMatteText(display,window_info,&reply_info); 7238 click_time=event.xbutton.time; 7239 break; 7240 } 7241 /* 7242 Request primary selection. 7243 */ 7244 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 7245 window_info->id,event.xbutton.time); 7246 break; 7247 } 7248 case ButtonRelease: 7249 { 7250 if (window_info->mapped == MagickFalse) 7251 break; 7252 if (north_info.raised == MagickFalse) 7253 { 7254 /* 7255 User released up button. 7256 */ 7257 delay=SuspendTime << 2; 7258 north_info.raised=MagickTrue; 7259 XDrawTriangleNorth(display,window_info,&north_info); 7260 } 7261 if (south_info.raised == MagickFalse) 7262 { 7263 /* 7264 User released down button. 7265 */ 7266 delay=SuspendTime << 2; 7267 south_info.raised=MagickTrue; 7268 XDrawTriangleSouth(display,window_info,&south_info); 7269 } 7270 if (slider_info.active) 7271 { 7272 /* 7273 Stop tracking slider. 7274 */ 7275 slider_info.active=MagickFalse; 7276 break; 7277 } 7278 if (action_info.raised == MagickFalse) 7279 { 7280 if (event.xbutton.window == window_info->id) 7281 { 7282 if (MatteIsActive(action_info,event.xbutton)) 7283 { 7284 if (*reply_info.text == '\0') 7285 (void) XBell(display,0); 7286 else 7287 state|=ExitState; 7288 } 7289 } 7290 action_info.raised=MagickTrue; 7291 XDrawBeveledButton(display,window_info,&action_info); 7292 } 7293 if (cancel_info.raised == MagickFalse) 7294 { 7295 if (event.xbutton.window == window_info->id) 7296 if (MatteIsActive(cancel_info,event.xbutton)) 7297 { 7298 *reply_info.text='\0'; 7299 state|=ExitState; 7300 } 7301 cancel_info.raised=MagickTrue; 7302 XDrawBeveledButton(display,window_info,&cancel_info); 7303 } 7304 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 7305 break; 7306 break; 7307 } 7308 case ClientMessage: 7309 { 7310 /* 7311 If client window delete message, exit. 7312 */ 7313 if (event.xclient.message_type != windows->wm_protocols) 7314 break; 7315 if (*event.xclient.data.l == (int) windows->wm_take_focus) 7316 { 7317 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 7318 (Time) event.xclient.data.l[1]); 7319 break; 7320 } 7321 if (*event.xclient.data.l != (int) windows->wm_delete_window) 7322 break; 7323 if (event.xclient.window == window_info->id) 7324 { 7325 *reply_info.text='\0'; 7326 state|=ExitState; 7327 break; 7328 } 7329 break; 7330 } 7331 case ConfigureNotify: 7332 { 7333 /* 7334 Update widget configuration. 7335 */ 7336 if (event.xconfigure.window != window_info->id) 7337 break; 7338 if ((event.xconfigure.width == (int) window_info->width) && 7339 (event.xconfigure.height == (int) window_info->height)) 7340 break; 7341 window_info->width=(unsigned int) 7342 MagickMax(event.xconfigure.width,(int) window_info->min_width); 7343 window_info->height=(unsigned int) 7344 MagickMax(event.xconfigure.height,(int) window_info->min_height); 7345 state|=UpdateConfigurationState; 7346 break; 7347 } 7348 case EnterNotify: 7349 { 7350 if (event.xcrossing.window != window_info->id) 7351 break; 7352 state&=(~InactiveWidgetState); 7353 break; 7354 } 7355 case Expose: 7356 { 7357 if (event.xexpose.window != window_info->id) 7358 break; 7359 if (event.xexpose.count != 0) 7360 break; 7361 state|=RedrawWidgetState; 7362 break; 7363 } 7364 case KeyPress: 7365 { 7366 static char 7367 command[MaxTextExtent]; 7368 7369 static int 7370 length; 7371 7372 static KeySym 7373 key_symbol; 7374 7375 /* 7376 Respond to a user key press. 7377 */ 7378 if (event.xkey.window != window_info->id) 7379 break; 7380 length=XLookupString((XKeyEvent *) &event.xkey,command, 7381 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 7382 *(command+length)='\0'; 7383 if (AreaIsActive(scroll_info,event.xkey)) 7384 { 7385 /* 7386 Move slider. 7387 */ 7388 switch ((int) key_symbol) 7389 { 7390 case XK_Home: 7391 case XK_KP_Home: 7392 { 7393 slider_info.id=0; 7394 break; 7395 } 7396 case XK_Up: 7397 case XK_KP_Up: 7398 { 7399 slider_info.id--; 7400 break; 7401 } 7402 case XK_Down: 7403 case XK_KP_Down: 7404 { 7405 slider_info.id++; 7406 break; 7407 } 7408 case XK_Prior: 7409 case XK_KP_Prior: 7410 { 7411 slider_info.id-=visible_entries; 7412 break; 7413 } 7414 case XK_Next: 7415 case XK_KP_Next: 7416 { 7417 slider_info.id+=visible_entries; 7418 break; 7419 } 7420 case XK_End: 7421 case XK_KP_End: 7422 { 7423 slider_info.id=(int) entries; 7424 break; 7425 } 7426 } 7427 state|=RedrawListState; 7428 break; 7429 } 7430 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 7431 { 7432 /* 7433 Read new entry. 7434 */ 7435 if (*reply_info.text == '\0') 7436 break; 7437 action_info.raised=MagickFalse; 7438 XDrawBeveledButton(display,window_info,&action_info); 7439 state|=ExitState; 7440 break; 7441 } 7442 if (key_symbol == XK_Control_L) 7443 { 7444 state|=ControlState; 7445 break; 7446 } 7447 if (state & ControlState) 7448 switch ((int) key_symbol) 7449 { 7450 case XK_u: 7451 case XK_U: 7452 { 7453 /* 7454 Erase the entire line of text. 7455 */ 7456 *reply_info.text='\0'; 7457 reply_info.cursor=reply_info.text; 7458 reply_info.marker=reply_info.text; 7459 reply_info.highlight=MagickFalse; 7460 break; 7461 } 7462 default: 7463 break; 7464 } 7465 XEditText(display,&reply_info,key_symbol,command,state); 7466 XDrawMatteText(display,window_info,&reply_info); 7467 break; 7468 } 7469 case KeyRelease: 7470 { 7471 static char 7472 command[MaxTextExtent]; 7473 7474 static KeySym 7475 key_symbol; 7476 7477 /* 7478 Respond to a user key release. 7479 */ 7480 if (event.xkey.window != window_info->id) 7481 break; 7482 (void) XLookupString((XKeyEvent *) &event.xkey,command, 7483 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 7484 if (key_symbol == XK_Control_L) 7485 state&=(~ControlState); 7486 break; 7487 } 7488 case LeaveNotify: 7489 { 7490 if (event.xcrossing.window != window_info->id) 7491 break; 7492 state|=InactiveWidgetState; 7493 break; 7494 } 7495 case MapNotify: 7496 { 7497 mask&=(~CWX); 7498 mask&=(~CWY); 7499 break; 7500 } 7501 case MotionNotify: 7502 { 7503 /* 7504 Discard pending button motion events. 7505 */ 7506 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 7507 if (slider_info.active) 7508 { 7509 /* 7510 Move slider matte. 7511 */ 7512 slider_info.y=event.xmotion.y- 7513 ((slider_info.height+slider_info.bevel_width) >> 1)+1; 7514 if (slider_info.y < slider_info.min_y) 7515 slider_info.y=slider_info.min_y; 7516 if (slider_info.y > slider_info.max_y) 7517 slider_info.y=slider_info.max_y; 7518 slider_info.id=0; 7519 if (slider_info.y != slider_info.min_y) 7520 slider_info.id=(int) ((entries*(slider_info.y- 7521 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1)); 7522 state|=RedrawListState; 7523 break; 7524 } 7525 if (state & InactiveWidgetState) 7526 break; 7527 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 7528 { 7529 /* 7530 Action button status changed. 7531 */ 7532 action_info.raised=action_info.raised == MagickFalse ? 7533 MagickTrue : MagickFalse; 7534 XDrawBeveledButton(display,window_info,&action_info); 7535 break; 7536 } 7537 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 7538 { 7539 /* 7540 Cancel button status changed. 7541 */ 7542 cancel_info.raised=cancel_info.raised == MagickFalse ? 7543 MagickTrue : MagickFalse; 7544 XDrawBeveledButton(display,window_info,&cancel_info); 7545 break; 7546 } 7547 break; 7548 } 7549 case SelectionClear: 7550 { 7551 reply_info.highlight=MagickFalse; 7552 XDrawMatteText(display,window_info,&reply_info); 7553 break; 7554 } 7555 case SelectionNotify: 7556 { 7557 Atom 7558 type; 7559 7560 int 7561 format; 7562 7563 unsigned char 7564 *data; 7565 7566 unsigned long 7567 after, 7568 length; 7569 7570 /* 7571 Obtain response from primary selection. 7572 */ 7573 if (event.xselection.property == (Atom) None) 7574 break; 7575 status=XGetWindowProperty(display, 7576 event.xselection.requestor,event.xselection.property,0L,2047L, 7577 MagickTrue,XA_STRING,&type,&format,&length,&after,&data); 7578 if ((status != Success) || (type != XA_STRING) || (format == 32) || 7579 (length == 0)) 7580 break; 7581 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 7582 (void) XBell(display,0); 7583 else 7584 { 7585 /* 7586 Insert primary selection in reply text. 7587 */ 7588 *(data+length)='\0'; 7589 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 7590 state); 7591 XDrawMatteText(display,window_info,&reply_info); 7592 state|=RedrawActionState; 7593 } 7594 (void) XFree((void *) data); 7595 break; 7596 } 7597 case SelectionRequest: 7598 { 7599 XSelectionEvent 7600 notify; 7601 7602 XSelectionRequestEvent 7603 *request; 7604 7605 if (reply_info.highlight == MagickFalse) 7606 break; 7607 /* 7608 Set primary selection. 7609 */ 7610 request=(&(event.xselectionrequest)); 7611 (void) XChangeProperty(request->display,request->requestor, 7612 request->property,request->target,8,PropModeReplace, 7613 (unsigned char *) primary_selection,Extent(primary_selection)); 7614 notify.type=SelectionNotify; 7615 notify.send_event=MagickTrue; 7616 notify.display=request->display; 7617 notify.requestor=request->requestor; 7618 notify.selection=request->selection; 7619 notify.target=request->target; 7620 notify.time=request->time; 7621 if (request->property == None) 7622 notify.property=request->target; 7623 else 7624 notify.property=request->property; 7625 (void) XSendEvent(request->display,request->requestor,False,NoEventMask, 7626 (XEvent *) ¬ify); 7627 } 7628 default: 7629 break; 7630 } 7631 } while ((state & ExitState) == 0); 7632 XSetCursorState(display,windows,MagickFalse); 7633 (void) XWithdrawWindow(display,window_info->id,window_info->screen); 7634 XCheckRefreshWindows(display,windows); 7635} 7636 7637/* 7638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7639% % 7640% % 7641% % 7642% X M e n u W i d g e t % 7643% % 7644% % 7645% % 7646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7647% 7648% XMenuWidget() maps a menu and returns the command pointed to by the user 7649% when the button is released. 7650% 7651% The format of the XMenuWidget method is: 7652% 7653% int XMenuWidget(Display *display,XWindows *windows,const char *title, 7654% const char **selections,char *item) 7655% 7656% A description of each parameter follows: 7657% 7658% o selection_number: Specifies the number of the selection that the 7659% user choose. 7660% 7661% o display: Specifies a connection to an X server; returned from 7662% XOpenDisplay. 7663% 7664% o window: Specifies a pointer to a XWindows structure. 7665% 7666% o title: Specifies a character string that describes the menu selections. 7667% 7668% o selections: Specifies a pointer to one or more strings that comprise 7669% the choices in the menu. 7670% 7671% o item: Specifies a character array. The item selected from the menu 7672% is returned here. 7673% 7674*/ 7675MagickPrivate int XMenuWidget(Display *display,XWindows *windows, 7676 const char *title,const char **selections,char *item) 7677{ 7678 Cursor 7679 cursor; 7680 7681 int 7682 id, 7683 x, 7684 y; 7685 7686 unsigned int 7687 height, 7688 number_selections, 7689 title_height, 7690 top_offset, 7691 width; 7692 7693 size_t 7694 state; 7695 7696 XEvent 7697 event; 7698 7699 XFontStruct 7700 *font_info; 7701 7702 XSetWindowAttributes 7703 window_attributes; 7704 7705 XWidgetInfo 7706 highlight_info, 7707 menu_info, 7708 selection_info; 7709 7710 XWindowChanges 7711 window_changes; 7712 7713 /* 7714 Determine Menu widget attributes. 7715 */ 7716 assert(display != (Display *) NULL); 7717 assert(windows != (XWindows *) NULL); 7718 assert(title != (char *) NULL); 7719 assert(selections != (const char **) NULL); 7720 assert(item != (char *) NULL); 7721 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title); 7722 font_info=windows->widget.font_info; 7723 windows->widget.width=submenu_info.active == 0 ? 7724 WidgetTextWidth(font_info,(char *) title) : 0; 7725 for (id=0; selections[id] != (char *) NULL; id++) 7726 { 7727 width=WidgetTextWidth(font_info,(char *) selections[id]); 7728 if (width > windows->widget.width) 7729 windows->widget.width=width; 7730 } 7731 number_selections=(unsigned int) id; 7732 XGetWidgetInfo((char *) NULL,&menu_info); 7733 title_height=(unsigned int) (submenu_info.active == 0 ? 7734 (3*(font_info->descent+font_info->ascent) >> 1)+5 : 2); 7735 width=WidgetTextWidth(font_info,(char *) title); 7736 height=(unsigned int) ((3*(font_info->ascent+font_info->descent)) >> 1); 7737 /* 7738 Position Menu widget. 7739 */ 7740 windows->widget.width+=QuantumMargin+(menu_info.bevel_width << 1); 7741 top_offset=title_height+menu_info.bevel_width-1; 7742 windows->widget.height=top_offset+number_selections*height+4; 7743 windows->widget.min_width=windows->widget.width; 7744 windows->widget.min_height=windows->widget.height; 7745 XQueryPosition(display,windows->widget.root,&x,&y); 7746 windows->widget.x=x-(QuantumMargin >> 1); 7747 if (submenu_info.active != 0) 7748 { 7749 windows->widget.x= 7750 windows->command.x+windows->command.width-QuantumMargin; 7751 toggle_info.raised=MagickTrue; 7752 XDrawTriangleEast(display,&windows->command,&toggle_info); 7753 } 7754 windows->widget.y=submenu_info.active == 0 ? y-(int) 7755 ((3*title_height) >> 2) : y; 7756 if (submenu_info.active != 0) 7757 windows->widget.y=windows->command.y+submenu_info.y; 7758 XConstrainWindowPosition(display,&windows->widget); 7759 /* 7760 Map Menu widget. 7761 */ 7762 window_attributes.override_redirect=MagickTrue; 7763 (void) XChangeWindowAttributes(display,windows->widget.id, 7764 (size_t) CWOverrideRedirect,&window_attributes); 7765 window_changes.width=(int) windows->widget.width; 7766 window_changes.height=(int) windows->widget.height; 7767 window_changes.x=windows->widget.x; 7768 window_changes.y=windows->widget.y; 7769 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 7770 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes); 7771 (void) XMapRaised(display,windows->widget.id); 7772 windows->widget.mapped=MagickFalse; 7773 /* 7774 Respond to X events. 7775 */ 7776 selection_info.height=height; 7777 cursor=XCreateFontCursor(display,XC_right_ptr); 7778 (void) XCheckDefineCursor(display,windows->image.id,cursor); 7779 (void) XCheckDefineCursor(display,windows->command.id,cursor); 7780 (void) XCheckDefineCursor(display,windows->widget.id,cursor); 7781 state=UpdateConfigurationState; 7782 do 7783 { 7784 if (state & UpdateConfigurationState) 7785 { 7786 /* 7787 Initialize selection information. 7788 */ 7789 XGetWidgetInfo((char *) NULL,&menu_info); 7790 menu_info.bevel_width--; 7791 menu_info.width=windows->widget.width-((menu_info.bevel_width) << 1); 7792 menu_info.height=windows->widget.height-((menu_info.bevel_width) << 1); 7793 menu_info.x=(int) menu_info.bevel_width; 7794 menu_info.y=(int) menu_info.bevel_width; 7795 XGetWidgetInfo((char *) NULL,&selection_info); 7796 selection_info.center=MagickFalse; 7797 selection_info.width=menu_info.width; 7798 selection_info.height=height; 7799 selection_info.x=menu_info.x; 7800 highlight_info=selection_info; 7801 highlight_info.bevel_width--; 7802 highlight_info.width-=(highlight_info.bevel_width << 1); 7803 highlight_info.height-=(highlight_info.bevel_width << 1); 7804 highlight_info.x+=highlight_info.bevel_width; 7805 state&=(~UpdateConfigurationState); 7806 } 7807 if (state & RedrawWidgetState) 7808 { 7809 /* 7810 Redraw Menu widget. 7811 */ 7812 if (submenu_info.active == 0) 7813 { 7814 y=(int) title_height; 7815 XSetBevelColor(display,&windows->widget,MagickFalse); 7816 (void) XDrawLine(display,windows->widget.id, 7817 windows->widget.widget_context,selection_info.x,y-1, 7818 (int) selection_info.width,y-1); 7819 XSetBevelColor(display,&windows->widget,MagickTrue); 7820 (void) XDrawLine(display,windows->widget.id, 7821 windows->widget.widget_context,selection_info.x,y, 7822 (int) selection_info.width,y); 7823 (void) XSetFillStyle(display,windows->widget.widget_context, 7824 FillSolid); 7825 } 7826 /* 7827 Draw menu selections. 7828 */ 7829 selection_info.center=MagickTrue; 7830 selection_info.y=(int) menu_info.bevel_width; 7831 selection_info.text=(char *) title; 7832 if (submenu_info.active == 0) 7833 XDrawWidgetText(display,&windows->widget,&selection_info); 7834 selection_info.center=MagickFalse; 7835 selection_info.y=(int) top_offset; 7836 for (id=0; id < (int) number_selections; id++) 7837 { 7838 selection_info.text=(char *) selections[id]; 7839 XDrawWidgetText(display,&windows->widget,&selection_info); 7840 highlight_info.y=selection_info.y+highlight_info.bevel_width; 7841 if (id == selection_info.id) 7842 XDrawBevel(display,&windows->widget,&highlight_info); 7843 selection_info.y+=(int) selection_info.height; 7844 } 7845 XDrawBevel(display,&windows->widget,&menu_info); 7846 state&=(~RedrawWidgetState); 7847 } 7848 if (number_selections > 2) 7849 { 7850 /* 7851 Redraw Menu line. 7852 */ 7853 y=(int) (top_offset+selection_info.height*(number_selections-1)); 7854 XSetBevelColor(display,&windows->widget,MagickFalse); 7855 (void) XDrawLine(display,windows->widget.id, 7856 windows->widget.widget_context,selection_info.x,y-1, 7857 (int) selection_info.width,y-1); 7858 XSetBevelColor(display,&windows->widget,MagickTrue); 7859 (void) XDrawLine(display,windows->widget.id, 7860 windows->widget.widget_context,selection_info.x,y, 7861 (int) selection_info.width,y); 7862 (void) XSetFillStyle(display,windows->widget.widget_context,FillSolid); 7863 } 7864 /* 7865 Wait for next event. 7866 */ 7867 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 7868 switch (event.type) 7869 { 7870 case ButtonPress: 7871 { 7872 if (event.xbutton.window != windows->widget.id) 7873 { 7874 /* 7875 exit menu. 7876 */ 7877 if (event.xbutton.window == windows->command.id) 7878 (void) XPutBackEvent(display,&event); 7879 selection_info.id=(~0); 7880 *item='\0'; 7881 state|=ExitState; 7882 break; 7883 } 7884 state&=(~InactiveWidgetState); 7885 id=(event.xbutton.y-top_offset)/(int) selection_info.height; 7886 selection_info.id=id; 7887 if ((id < 0) || (id >= (int) number_selections)) 7888 break; 7889 /* 7890 Highlight this selection. 7891 */ 7892 selection_info.y=(int) (top_offset+id*selection_info.height); 7893 selection_info.text=(char *) selections[id]; 7894 XDrawWidgetText(display,&windows->widget,&selection_info); 7895 highlight_info.y=selection_info.y+highlight_info.bevel_width; 7896 XDrawBevel(display,&windows->widget,&highlight_info); 7897 break; 7898 } 7899 case ButtonRelease: 7900 { 7901 if (windows->widget.mapped == MagickFalse) 7902 break; 7903 if (event.xbutton.window == windows->command.id) 7904 if ((state & InactiveWidgetState) == 0) 7905 break; 7906 /* 7907 exit menu. 7908 */ 7909 XSetCursorState(display,windows,MagickFalse); 7910 *item='\0'; 7911 state|=ExitState; 7912 break; 7913 } 7914 case ConfigureNotify: 7915 { 7916 /* 7917 Update widget configuration. 7918 */ 7919 if (event.xconfigure.window != windows->widget.id) 7920 break; 7921 if ((event.xconfigure.width == (int) windows->widget.width) && 7922 (event.xconfigure.height == (int) windows->widget.height)) 7923 break; 7924 windows->widget.width=(unsigned int) 7925 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 7926 windows->widget.height=(unsigned int) 7927 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 7928 state|=UpdateConfigurationState; 7929 break; 7930 } 7931 case EnterNotify: 7932 { 7933 if (event.xcrossing.window != windows->widget.id) 7934 break; 7935 if (event.xcrossing.state == 0) 7936 break; 7937 state&=(~InactiveWidgetState); 7938 id=((event.xcrossing.y-top_offset)/(int) selection_info.height); 7939 if ((selection_info.id >= 0) && 7940 (selection_info.id < (int) number_selections)) 7941 { 7942 /* 7943 Unhighlight last selection. 7944 */ 7945 if (id == selection_info.id) 7946 break; 7947 selection_info.y=(int) 7948 (top_offset+selection_info.id*selection_info.height); 7949 selection_info.text=(char *) selections[selection_info.id]; 7950 XDrawWidgetText(display,&windows->widget,&selection_info); 7951 } 7952 if ((id < 0) || (id >= (int) number_selections)) 7953 break; 7954 /* 7955 Highlight this selection. 7956 */ 7957 selection_info.id=id; 7958 selection_info.y=(int) 7959 (top_offset+selection_info.id*selection_info.height); 7960 selection_info.text=(char *) selections[selection_info.id]; 7961 XDrawWidgetText(display,&windows->widget,&selection_info); 7962 highlight_info.y=selection_info.y+highlight_info.bevel_width; 7963 XDrawBevel(display,&windows->widget,&highlight_info); 7964 break; 7965 } 7966 case Expose: 7967 { 7968 if (event.xexpose.window != windows->widget.id) 7969 break; 7970 if (event.xexpose.count != 0) 7971 break; 7972 state|=RedrawWidgetState; 7973 break; 7974 } 7975 case LeaveNotify: 7976 { 7977 if (event.xcrossing.window != windows->widget.id) 7978 break; 7979 state|=InactiveWidgetState; 7980 id=selection_info.id; 7981 if ((id < 0) || (id >= (int) number_selections)) 7982 break; 7983 /* 7984 Unhighlight last selection. 7985 */ 7986 selection_info.y=(int) (top_offset+id*selection_info.height); 7987 selection_info.id=(~0); 7988 selection_info.text=(char *) selections[id]; 7989 XDrawWidgetText(display,&windows->widget,&selection_info); 7990 break; 7991 } 7992 case MotionNotify: 7993 { 7994 /* 7995 Discard pending button motion events. 7996 */ 7997 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 7998 if (submenu_info.active != 0) 7999 if (event.xmotion.window == windows->command.id) 8000 { 8001 if ((state & InactiveWidgetState) == 0) 8002 { 8003 if (MatteIsActive(submenu_info,event.xmotion) == MagickFalse) 8004 { 8005 selection_info.id=(~0); 8006 *item='\0'; 8007 state|=ExitState; 8008 break; 8009 } 8010 } 8011 else 8012 if (WindowIsActive(windows->command,event.xmotion)) 8013 { 8014 selection_info.id=(~0); 8015 *item='\0'; 8016 state|=ExitState; 8017 break; 8018 } 8019 } 8020 if (event.xmotion.window != windows->widget.id) 8021 break; 8022 if (state & InactiveWidgetState) 8023 break; 8024 id=(event.xmotion.y-top_offset)/(int) selection_info.height; 8025 if ((selection_info.id >= 0) && 8026 (selection_info.id < (int) number_selections)) 8027 { 8028 /* 8029 Unhighlight last selection. 8030 */ 8031 if (id == selection_info.id) 8032 break; 8033 selection_info.y=(int) 8034 (top_offset+selection_info.id*selection_info.height); 8035 selection_info.text=(char *) selections[selection_info.id]; 8036 XDrawWidgetText(display,&windows->widget,&selection_info); 8037 } 8038 selection_info.id=id; 8039 if ((id < 0) || (id >= (int) number_selections)) 8040 break; 8041 /* 8042 Highlight this selection. 8043 */ 8044 selection_info.y=(int) (top_offset+id*selection_info.height); 8045 selection_info.text=(char *) selections[id]; 8046 XDrawWidgetText(display,&windows->widget,&selection_info); 8047 highlight_info.y=selection_info.y+highlight_info.bevel_width; 8048 XDrawBevel(display,&windows->widget,&highlight_info); 8049 break; 8050 } 8051 default: 8052 break; 8053 } 8054 } while ((state & ExitState) == 0); 8055 (void) XFreeCursor(display,cursor); 8056 window_attributes.override_redirect=MagickFalse; 8057 (void) XChangeWindowAttributes(display,windows->widget.id, 8058 (size_t) CWOverrideRedirect,&window_attributes); 8059 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 8060 XCheckRefreshWindows(display,windows); 8061 if (submenu_info.active != 0) 8062 { 8063 submenu_info.active=MagickFalse; 8064 toggle_info.raised=MagickFalse; 8065 XDrawTriangleEast(display,&windows->command,&toggle_info); 8066 } 8067 if ((selection_info.id < 0) || (selection_info.id >= (int) number_selections)) 8068 return(~0); 8069 (void) CopyMagickString(item,selections[selection_info.id],MaxTextExtent); 8070 return(selection_info.id); 8071} 8072 8073/* 8074%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8075% % 8076% % 8077% % 8078% X N o t i c e W i d g e t % 8079% % 8080% % 8081% % 8082%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8083% 8084% XNoticeWidget() displays a Notice widget with a notice to the user. The 8085% function returns when the user presses the "Dismiss" button. 8086% 8087% The format of the XNoticeWidget method is: 8088% 8089% void XNoticeWidget(Display *display,XWindows *windows, 8090% const char *reason,const char *description) 8091% 8092% A description of each parameter follows: 8093% 8094% o display: Specifies a connection to an X server; returned from 8095% XOpenDisplay. 8096% 8097% o window: Specifies a pointer to a XWindows structure. 8098% 8099% o reason: Specifies the message to display before terminating the 8100% program. 8101% 8102% o description: Specifies any description to the message. 8103% 8104*/ 8105MagickPrivate void XNoticeWidget(Display *display,XWindows *windows, 8106 const char *reason,const char *description) 8107{ 8108#define DismissButtonText "Dismiss" 8109#define Timeout 8 8110 8111 const char 8112 *text; 8113 8114 int 8115 x, 8116 y; 8117 8118 Status 8119 status; 8120 8121 time_t 8122 timer; 8123 8124 unsigned int 8125 height, 8126 width; 8127 8128 size_t 8129 state; 8130 8131 XEvent 8132 event; 8133 8134 XFontStruct 8135 *font_info; 8136 8137 XTextProperty 8138 window_name; 8139 8140 XWidgetInfo 8141 dismiss_info; 8142 8143 XWindowChanges 8144 window_changes; 8145 8146 /* 8147 Determine Notice widget attributes. 8148 */ 8149 assert(display != (Display *) NULL); 8150 assert(windows != (XWindows *) NULL); 8151 assert(reason != (char *) NULL); 8152 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason); 8153 XDelay(display,SuspendTime << 3); /* avoid surpise with delay */ 8154 XSetCursorState(display,windows,MagickTrue); 8155 XCheckRefreshWindows(display,windows); 8156 font_info=windows->widget.font_info; 8157 width=WidgetTextWidth(font_info,DismissButtonText); 8158 text=GetLocaleExceptionMessage(XServerError,reason); 8159 if (text != (char *) NULL) 8160 if (WidgetTextWidth(font_info,(char *) text) > width) 8161 width=WidgetTextWidth(font_info,(char *) text); 8162 if (description != (char *) NULL) 8163 { 8164 text=GetLocaleExceptionMessage(XServerError,description); 8165 if (text != (char *) NULL) 8166 if (WidgetTextWidth(font_info,(char *) text) > width) 8167 width=WidgetTextWidth(font_info,(char *) text); 8168 } 8169 height=(unsigned int) (font_info->ascent+font_info->descent); 8170 /* 8171 Position Notice widget. 8172 */ 8173 windows->widget.width=width+4*QuantumMargin; 8174 windows->widget.min_width=width+QuantumMargin; 8175 if (windows->widget.width < windows->widget.min_width) 8176 windows->widget.width=windows->widget.min_width; 8177 windows->widget.height=(unsigned int) (12*height); 8178 windows->widget.min_height=(unsigned int) (7*height); 8179 if (windows->widget.height < windows->widget.min_height) 8180 windows->widget.height=windows->widget.min_height; 8181 XConstrainWindowPosition(display,&windows->widget); 8182 /* 8183 Map Notice widget. 8184 */ 8185 (void) CopyMagickString(windows->widget.name,"Notice",MaxTextExtent); 8186 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 8187 if (status != False) 8188 { 8189 XSetWMName(display,windows->widget.id,&window_name); 8190 XSetWMIconName(display,windows->widget.id,&window_name); 8191 (void) XFree((void *) window_name.value); 8192 } 8193 window_changes.width=(int) windows->widget.width; 8194 window_changes.height=(int) windows->widget.height; 8195 window_changes.x=windows->widget.x; 8196 window_changes.y=windows->widget.y; 8197 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 8198 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes); 8199 (void) XMapRaised(display,windows->widget.id); 8200 windows->widget.mapped=MagickFalse; 8201 (void) XBell(display,0); 8202 /* 8203 Respond to X events. 8204 */ 8205 timer=time((time_t *) NULL)+Timeout; 8206 state=UpdateConfigurationState; 8207 do 8208 { 8209 if (time((time_t *) NULL) > timer) 8210 break; 8211 if (state & UpdateConfigurationState) 8212 { 8213 /* 8214 Initialize Dismiss button information. 8215 */ 8216 XGetWidgetInfo(DismissButtonText,&dismiss_info); 8217 dismiss_info.width=(unsigned int) QuantumMargin+ 8218 WidgetTextWidth(font_info,DismissButtonText); 8219 dismiss_info.height=(unsigned int) ((3*height) >> 1); 8220 dismiss_info.x=(int) 8221 ((windows->widget.width >> 1)-(dismiss_info.width >> 1)); 8222 dismiss_info.y=(int) 8223 (windows->widget.height-(dismiss_info.height << 1)); 8224 state&=(~UpdateConfigurationState); 8225 } 8226 if (state & RedrawWidgetState) 8227 { 8228 /* 8229 Redraw Notice widget. 8230 */ 8231 width=WidgetTextWidth(font_info,(char *) reason); 8232 x=(int) ((windows->widget.width >> 1)-(width >> 1)); 8233 y=(int) ((windows->widget.height >> 1)-(height << 1)); 8234 (void) XDrawString(display,windows->widget.id, 8235 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason)); 8236 if (description != (char *) NULL) 8237 { 8238 width=WidgetTextWidth(font_info,(char *) description); 8239 x=(int) ((windows->widget.width >> 1)-(width >> 1)); 8240 y+=height; 8241 (void) XDrawString(display,windows->widget.id, 8242 windows->widget.annotate_context,x,y,(char *) description, 8243 Extent(description)); 8244 } 8245 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 8246 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 8247 state&=(~RedrawWidgetState); 8248 } 8249 /* 8250 Wait for next event. 8251 */ 8252 if (XCheckIfEvent(display,&event,XScreenEvent,(char *) windows) == MagickFalse) 8253 { 8254 /* 8255 Do not block if delay > 0. 8256 */ 8257 XDelay(display,SuspendTime << 2); 8258 continue; 8259 } 8260 switch (event.type) 8261 { 8262 case ButtonPress: 8263 { 8264 if (MatteIsActive(dismiss_info,event.xbutton)) 8265 { 8266 /* 8267 User pressed Dismiss button. 8268 */ 8269 dismiss_info.raised=MagickFalse; 8270 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 8271 break; 8272 } 8273 break; 8274 } 8275 case ButtonRelease: 8276 { 8277 if (windows->widget.mapped == MagickFalse) 8278 break; 8279 if (dismiss_info.raised == MagickFalse) 8280 { 8281 if (event.xbutton.window == windows->widget.id) 8282 if (MatteIsActive(dismiss_info,event.xbutton)) 8283 state|=ExitState; 8284 dismiss_info.raised=MagickTrue; 8285 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 8286 } 8287 break; 8288 } 8289 case ClientMessage: 8290 { 8291 /* 8292 If client window delete message, exit. 8293 */ 8294 if (event.xclient.message_type != windows->wm_protocols) 8295 break; 8296 if (*event.xclient.data.l == (int) windows->wm_take_focus) 8297 { 8298 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 8299 (Time) event.xclient.data.l[1]); 8300 break; 8301 } 8302 if (*event.xclient.data.l != (int) windows->wm_delete_window) 8303 break; 8304 if (event.xclient.window == windows->widget.id) 8305 { 8306 state|=ExitState; 8307 break; 8308 } 8309 break; 8310 } 8311 case ConfigureNotify: 8312 { 8313 /* 8314 Update widget configuration. 8315 */ 8316 if (event.xconfigure.window != windows->widget.id) 8317 break; 8318 if ((event.xconfigure.width == (int) windows->widget.width) && 8319 (event.xconfigure.height == (int) windows->widget.height)) 8320 break; 8321 windows->widget.width=(unsigned int) 8322 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 8323 windows->widget.height=(unsigned int) 8324 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 8325 state|=UpdateConfigurationState; 8326 break; 8327 } 8328 case EnterNotify: 8329 { 8330 if (event.xcrossing.window != windows->widget.id) 8331 break; 8332 state&=(~InactiveWidgetState); 8333 break; 8334 } 8335 case Expose: 8336 { 8337 if (event.xexpose.window != windows->widget.id) 8338 break; 8339 if (event.xexpose.count != 0) 8340 break; 8341 state|=RedrawWidgetState; 8342 break; 8343 } 8344 case KeyPress: 8345 { 8346 static char 8347 command[MaxTextExtent]; 8348 8349 static KeySym 8350 key_symbol; 8351 8352 /* 8353 Respond to a user key press. 8354 */ 8355 if (event.xkey.window != windows->widget.id) 8356 break; 8357 (void) XLookupString((XKeyEvent *) &event.xkey,command, 8358 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 8359 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 8360 { 8361 dismiss_info.raised=MagickFalse; 8362 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 8363 state|=ExitState; 8364 break; 8365 } 8366 break; 8367 } 8368 case LeaveNotify: 8369 { 8370 if (event.xcrossing.window != windows->widget.id) 8371 break; 8372 state|=InactiveWidgetState; 8373 break; 8374 } 8375 case MotionNotify: 8376 { 8377 /* 8378 Discard pending button motion events. 8379 */ 8380 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 8381 if (state & InactiveWidgetState) 8382 break; 8383 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion)) 8384 { 8385 /* 8386 Dismiss button status changed. 8387 */ 8388 dismiss_info.raised= 8389 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse; 8390 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 8391 break; 8392 } 8393 break; 8394 } 8395 default: 8396 break; 8397 } 8398 } while ((state & ExitState) == 0); 8399 XSetCursorState(display,windows,MagickFalse); 8400 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 8401 XCheckRefreshWindows(display,windows); 8402} 8403 8404/* 8405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8406% % 8407% % 8408% % 8409% X P r e f e r e n c e s W i d g e t % 8410% % 8411% % 8412% % 8413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8414% 8415% XPreferencesWidget() displays a Preferences widget with program preferences. 8416% If the user presses the Apply button, the preferences are stored in a 8417% configuration file in the users' home directory. 8418% 8419% The format of the XPreferencesWidget method is: 8420% 8421% MagickBooleanType XPreferencesWidget(Display *display, 8422% XResourceInfo *resource_info,XWindows *windows) 8423% 8424% A description of each parameter follows: 8425% 8426% o display: Specifies a connection to an X server; returned from 8427% XOpenDisplay. 8428% 8429% o resource_info: Specifies a pointer to a X11 XResourceInfo structure. 8430% 8431% o window: Specifies a pointer to a XWindows structure. 8432% 8433*/ 8434MagickPrivate MagickBooleanType XPreferencesWidget(Display *display, 8435 XResourceInfo *resource_info,XWindows *windows) 8436{ 8437#define ApplyButtonText "Apply" 8438#define CacheButtonText "%lu mega-bytes of memory in the undo edit cache " 8439#define CancelButtonText "Cancel" 8440#define NumberPreferences 8 8441 8442 static const char 8443 *Preferences[] = 8444 { 8445 "display image centered on a backdrop", 8446 "confirm on program exit", 8447 "confirm on image edits", 8448 "correct image for display gamma", 8449 "display warning messages", 8450 "apply Floyd/Steinberg error diffusion to image", 8451 "use a shared colormap for colormapped X visuals", 8452 "display images as an X server pixmap" 8453 }; 8454 8455 char 8456 cache[MaxTextExtent]; 8457 8458 int 8459 x, 8460 y; 8461 8462 register int 8463 i; 8464 8465 Status 8466 status; 8467 8468 unsigned int 8469 height, 8470 text_width, 8471 width; 8472 8473 size_t 8474 state; 8475 8476 XEvent 8477 event; 8478 8479 XFontStruct 8480 *font_info; 8481 8482 XTextProperty 8483 window_name; 8484 8485 XWidgetInfo 8486 apply_info, 8487 cache_info, 8488 cancel_info, 8489 preferences_info[NumberPreferences]; 8490 8491 XWindowChanges 8492 window_changes; 8493 8494 /* 8495 Determine Preferences widget attributes. 8496 */ 8497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 8498 assert(display != (Display *) NULL); 8499 assert(resource_info != (XResourceInfo *) NULL); 8500 assert(windows != (XWindows *) NULL); 8501 XCheckRefreshWindows(display,windows); 8502 font_info=windows->widget.font_info; 8503 text_width=WidgetTextWidth(font_info,CacheButtonText); 8504 for (i=0; i < NumberPreferences; i++) 8505 if (WidgetTextWidth(font_info,(char *) Preferences[i]) > text_width) 8506 text_width=WidgetTextWidth(font_info,(char *) Preferences[i]); 8507 width=WidgetTextWidth(font_info,ApplyButtonText); 8508 if (WidgetTextWidth(font_info,CancelButtonText) > width) 8509 width=WidgetTextWidth(font_info,CancelButtonText); 8510 width+=(unsigned int) QuantumMargin; 8511 height=(unsigned int) (font_info->ascent+font_info->descent); 8512 /* 8513 Position Preferences widget. 8514 */ 8515 windows->widget.width=(unsigned int) (MagickMax((int) (width << 1), 8516 (int) text_width)+6*QuantumMargin); 8517 windows->widget.min_width=(width << 1)+QuantumMargin; 8518 if (windows->widget.width < windows->widget.min_width) 8519 windows->widget.width=windows->widget.min_width; 8520 windows->widget.height=(unsigned int) 8521 (7*height+NumberPreferences*(height+(QuantumMargin >> 1))); 8522 windows->widget.min_height=(unsigned int) 8523 (7*height+NumberPreferences*(height+(QuantumMargin >> 1))); 8524 if (windows->widget.height < windows->widget.min_height) 8525 windows->widget.height=windows->widget.min_height; 8526 XConstrainWindowPosition(display,&windows->widget); 8527 /* 8528 Map Preferences widget. 8529 */ 8530 (void) CopyMagickString(windows->widget.name,"Preferences",MaxTextExtent); 8531 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 8532 if (status != False) 8533 { 8534 XSetWMName(display,windows->widget.id,&window_name); 8535 XSetWMIconName(display,windows->widget.id,&window_name); 8536 (void) XFree((void *) window_name.value); 8537 } 8538 window_changes.width=(int) windows->widget.width; 8539 window_changes.height=(int) windows->widget.height; 8540 window_changes.x=windows->widget.x; 8541 window_changes.y=windows->widget.y; 8542 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 8543 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes); 8544 (void) XMapRaised(display,windows->widget.id); 8545 windows->widget.mapped=MagickFalse; 8546 /* 8547 Respond to X events. 8548 */ 8549 state=UpdateConfigurationState; 8550 XSetCursorState(display,windows,MagickTrue); 8551 do 8552 { 8553 if (state & UpdateConfigurationState) 8554 { 8555 /* 8556 Initialize button information. 8557 */ 8558 XGetWidgetInfo(CancelButtonText,&cancel_info); 8559 cancel_info.width=width; 8560 cancel_info.height=(unsigned int) (3*height) >> 1; 8561 cancel_info.x=(int) windows->widget.width-cancel_info.width- 8562 (QuantumMargin << 1); 8563 cancel_info.y=(int) windows->widget.height- 8564 cancel_info.height-QuantumMargin; 8565 XGetWidgetInfo(ApplyButtonText,&apply_info); 8566 apply_info.width=width; 8567 apply_info.height=(unsigned int) (3*height) >> 1; 8568 apply_info.x=QuantumMargin << 1; 8569 apply_info.y=cancel_info.y; 8570 y=(int) (height << 1); 8571 for (i=0; i < NumberPreferences; i++) 8572 { 8573 XGetWidgetInfo(Preferences[i],&preferences_info[i]); 8574 preferences_info[i].bevel_width--; 8575 preferences_info[i].width=(unsigned int) QuantumMargin >> 1; 8576 preferences_info[i].height=(unsigned int) QuantumMargin >> 1; 8577 preferences_info[i].x=QuantumMargin << 1; 8578 preferences_info[i].y=y; 8579 y+=height+(QuantumMargin >> 1); 8580 } 8581 preferences_info[0].raised=resource_info->backdrop == 8582 MagickFalse ? MagickTrue : MagickFalse; 8583 preferences_info[1].raised=resource_info->confirm_exit == 8584 MagickFalse ? MagickTrue : MagickFalse; 8585 preferences_info[2].raised=resource_info->confirm_edit == 8586 MagickFalse ? MagickTrue : MagickFalse; 8587 preferences_info[3].raised=resource_info->gamma_correct == 8588 MagickFalse ? MagickTrue : MagickFalse; 8589 preferences_info[4].raised=resource_info->display_warnings == 8590 MagickFalse ? MagickTrue : MagickFalse; 8591 preferences_info[5].raised= 8592 resource_info->quantize_info->dither_method == NoDitherMethod ? 8593 MagickTrue : MagickFalse; 8594 preferences_info[6].raised=resource_info->colormap != 8595 SharedColormap ? MagickTrue : MagickFalse; 8596 preferences_info[7].raised=resource_info->use_pixmap == 8597 MagickFalse ? MagickTrue : MagickFalse; 8598 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText, 8599 (unsigned long) resource_info->undo_cache); 8600 XGetWidgetInfo(cache,&cache_info); 8601 cache_info.bevel_width--; 8602 cache_info.width=(unsigned int) QuantumMargin >> 1; 8603 cache_info.height=(unsigned int) QuantumMargin >> 1; 8604 cache_info.x=QuantumMargin << 1; 8605 cache_info.y=y; 8606 state&=(~UpdateConfigurationState); 8607 } 8608 if (state & RedrawWidgetState) 8609 { 8610 /* 8611 Redraw Preferences widget. 8612 */ 8613 XDrawBeveledButton(display,&windows->widget,&apply_info); 8614 XDrawBeveledButton(display,&windows->widget,&cancel_info); 8615 for (i=0; i < NumberPreferences; i++) 8616 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]); 8617 XDrawTriangleEast(display,&windows->widget,&cache_info); 8618 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 8619 state&=(~RedrawWidgetState); 8620 } 8621 /* 8622 Wait for next event. 8623 */ 8624 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 8625 switch (event.type) 8626 { 8627 case ButtonPress: 8628 { 8629 if (MatteIsActive(apply_info,event.xbutton)) 8630 { 8631 /* 8632 User pressed Apply button. 8633 */ 8634 apply_info.raised=MagickFalse; 8635 XDrawBeveledButton(display,&windows->widget,&apply_info); 8636 break; 8637 } 8638 if (MatteIsActive(cancel_info,event.xbutton)) 8639 { 8640 /* 8641 User pressed Cancel button. 8642 */ 8643 cancel_info.raised=MagickFalse; 8644 XDrawBeveledButton(display,&windows->widget,&cancel_info); 8645 break; 8646 } 8647 for (i=0; i < NumberPreferences; i++) 8648 if (MatteIsActive(preferences_info[i],event.xbutton)) 8649 { 8650 /* 8651 User pressed a Preferences button. 8652 */ 8653 preferences_info[i].raised=preferences_info[i].raised == 8654 MagickFalse ? MagickTrue : MagickFalse; 8655 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]); 8656 break; 8657 } 8658 if (MatteIsActive(cache_info,event.xbutton)) 8659 { 8660 /* 8661 User pressed Cache button. 8662 */ 8663 x=cache_info.x+cache_info.width+cache_info.bevel_width+ 8664 (QuantumMargin >> 1); 8665 y=cache_info.y+((cache_info.height-height) >> 1); 8666 width=WidgetTextWidth(font_info,cache); 8667 (void) XClearArea(display,windows->widget.id,x,y,width,height, 8668 False); 8669 resource_info->undo_cache<<=1; 8670 if (resource_info->undo_cache > 256) 8671 resource_info->undo_cache=1; 8672 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText, 8673 (unsigned long) resource_info->undo_cache); 8674 cache_info.raised=MagickFalse; 8675 XDrawTriangleEast(display,&windows->widget,&cache_info); 8676 break; 8677 } 8678 break; 8679 } 8680 case ButtonRelease: 8681 { 8682 if (windows->widget.mapped == MagickFalse) 8683 break; 8684 if (apply_info.raised == MagickFalse) 8685 { 8686 if (event.xbutton.window == windows->widget.id) 8687 if (MatteIsActive(apply_info,event.xbutton)) 8688 state|=ExitState; 8689 apply_info.raised=MagickTrue; 8690 XDrawBeveledButton(display,&windows->widget,&apply_info); 8691 apply_info.raised=MagickFalse; 8692 } 8693 if (cancel_info.raised == MagickFalse) 8694 { 8695 if (event.xbutton.window == windows->widget.id) 8696 if (MatteIsActive(cancel_info,event.xbutton)) 8697 state|=ExitState; 8698 cancel_info.raised=MagickTrue; 8699 XDrawBeveledButton(display,&windows->widget,&cancel_info); 8700 } 8701 if (cache_info.raised == MagickFalse) 8702 { 8703 cache_info.raised=MagickTrue; 8704 XDrawTriangleEast(display,&windows->widget,&cache_info); 8705 } 8706 break; 8707 } 8708 case ClientMessage: 8709 { 8710 /* 8711 If client window delete message, exit. 8712 */ 8713 if (event.xclient.message_type != windows->wm_protocols) 8714 break; 8715 if (*event.xclient.data.l == (int) windows->wm_take_focus) 8716 { 8717 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 8718 (Time) event.xclient.data.l[1]); 8719 break; 8720 } 8721 if (*event.xclient.data.l != (int) windows->wm_delete_window) 8722 break; 8723 if (event.xclient.window == windows->widget.id) 8724 { 8725 state|=ExitState; 8726 break; 8727 } 8728 break; 8729 } 8730 case ConfigureNotify: 8731 { 8732 /* 8733 Update widget configuration. 8734 */ 8735 if (event.xconfigure.window != windows->widget.id) 8736 break; 8737 if ((event.xconfigure.width == (int) windows->widget.width) && 8738 (event.xconfigure.height == (int) windows->widget.height)) 8739 break; 8740 windows->widget.width=(unsigned int) 8741 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 8742 windows->widget.height=(unsigned int) 8743 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 8744 state|=UpdateConfigurationState; 8745 break; 8746 } 8747 case EnterNotify: 8748 { 8749 if (event.xcrossing.window != windows->widget.id) 8750 break; 8751 state&=(~InactiveWidgetState); 8752 break; 8753 } 8754 case Expose: 8755 { 8756 if (event.xexpose.window != windows->widget.id) 8757 break; 8758 if (event.xexpose.count != 0) 8759 break; 8760 state|=RedrawWidgetState; 8761 break; 8762 } 8763 case KeyPress: 8764 { 8765 static char 8766 command[MaxTextExtent]; 8767 8768 static KeySym 8769 key_symbol; 8770 8771 /* 8772 Respond to a user key press. 8773 */ 8774 if (event.xkey.window != windows->widget.id) 8775 break; 8776 (void) XLookupString((XKeyEvent *) &event.xkey,command, 8777 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 8778 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 8779 { 8780 apply_info.raised=MagickFalse; 8781 XDrawBeveledButton(display,&windows->widget,&apply_info); 8782 state|=ExitState; 8783 break; 8784 } 8785 break; 8786 } 8787 case LeaveNotify: 8788 { 8789 if (event.xcrossing.window != windows->widget.id) 8790 break; 8791 state|=InactiveWidgetState; 8792 break; 8793 } 8794 case MotionNotify: 8795 { 8796 /* 8797 Discard pending button motion events. 8798 */ 8799 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 8800 if (state & InactiveWidgetState) 8801 break; 8802 if (apply_info.raised == MatteIsActive(apply_info,event.xmotion)) 8803 { 8804 /* 8805 Apply button status changed. 8806 */ 8807 apply_info.raised= 8808 apply_info.raised == MagickFalse ? MagickTrue : MagickFalse; 8809 XDrawBeveledButton(display,&windows->widget,&apply_info); 8810 break; 8811 } 8812 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 8813 { 8814 /* 8815 Cancel button status changed. 8816 */ 8817 cancel_info.raised= 8818 cancel_info.raised == MagickFalse ? MagickTrue : MagickFalse; 8819 XDrawBeveledButton(display,&windows->widget,&cancel_info); 8820 break; 8821 } 8822 break; 8823 } 8824 default: 8825 break; 8826 } 8827 } while ((state & ExitState) == 0); 8828 XSetCursorState(display,windows,MagickFalse); 8829 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 8830 XCheckRefreshWindows(display,windows); 8831 if (apply_info.raised) 8832 return(MagickFalse); 8833 /* 8834 Save user preferences to the client configuration file. 8835 */ 8836 resource_info->backdrop= 8837 preferences_info[0].raised == MagickFalse ? MagickTrue : MagickFalse; 8838 resource_info->confirm_exit= 8839 preferences_info[1].raised == MagickFalse ? MagickTrue : MagickFalse; 8840 resource_info->confirm_edit= 8841 preferences_info[2].raised == MagickFalse ? MagickTrue : MagickFalse; 8842 resource_info->gamma_correct= 8843 preferences_info[3].raised == MagickFalse ? MagickTrue : MagickFalse; 8844 resource_info->display_warnings= 8845 preferences_info[4].raised == MagickFalse ? MagickTrue : MagickFalse; 8846 resource_info->quantize_info->dither_method= 8847 preferences_info[5].raised == MagickFalse ? 8848 RiemersmaDitherMethod : NoDitherMethod; 8849 resource_info->colormap=SharedColormap; 8850 if (preferences_info[6].raised) 8851 resource_info->colormap=PrivateColormap; 8852 resource_info->use_pixmap= 8853 preferences_info[7].raised == MagickFalse ? MagickTrue : MagickFalse; 8854 XUserPreferences(resource_info); 8855 return(MagickTrue); 8856} 8857 8858/* 8859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8860% % 8861% % 8862% % 8863% X P r o g r e s s M o n i t o r W i d g e t % 8864% % 8865% % 8866% % 8867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8868% 8869% XProgressMonitorWidget() displays the progress a task is making in 8870% completing a task. A span of zero toggles the active status. An inactive 8871% state disables the progress monitor. 8872% 8873% The format of the XProgressMonitorWidget method is: 8874% 8875% void XProgressMonitorWidget(Display *display,XWindows *windows, 8876% const char *task,const MagickOffsetType offset, 8877% const MagickSizeType span) 8878% 8879% A description of each parameter follows: 8880% 8881% o display: Specifies a connection to an X server; returned from 8882% XOpenDisplay. 8883% 8884% o window: Specifies a pointer to a XWindows structure. 8885% 8886% o task: Identifies the task in progress. 8887% 8888% o offset: Specifies the offset position within the span which represents 8889% how much progress has been made in completing a task. 8890% 8891% o span: Specifies the span relative to completing a task. 8892% 8893*/ 8894MagickPrivate void XProgressMonitorWidget(Display *display,XWindows *windows, 8895 const char *task,const MagickOffsetType offset,const MagickSizeType span) 8896{ 8897 unsigned int 8898 width; 8899 8900 XEvent 8901 event; 8902 8903 assert(display != (Display *) NULL); 8904 assert(windows != (XWindows *) NULL); 8905 assert(task != (const char *) NULL); 8906 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",task); 8907 if (span == 0) 8908 return; 8909 /* 8910 Update image windows if there is a pending expose event. 8911 */ 8912 while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event)) 8913 (void) XCommandWidget(display,windows,(const char **) NULL,&event); 8914 while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event)) 8915 XRefreshWindow(display,&windows->image,&event); 8916 while (XCheckTypedWindowEvent(display,windows->info.id,Expose,&event)) 8917 if (monitor_info.text != (char *) NULL) 8918 XInfoWidget(display,windows,monitor_info.text); 8919 /* 8920 Draw progress monitor bar to represent percent completion of a task. 8921 */ 8922 if ((windows->info.mapped == MagickFalse) || (task != monitor_info.text)) 8923 XInfoWidget(display,windows,task); 8924 width=(unsigned int) (((offset+1)*(windows->info.width- 8925 (2*monitor_info.x)))/span); 8926 if (width < monitor_info.width) 8927 { 8928 monitor_info.raised=MagickTrue; 8929 XDrawWidgetText(display,&windows->info,&monitor_info); 8930 monitor_info.raised=MagickFalse; 8931 } 8932 monitor_info.width=width; 8933 XDrawWidgetText(display,&windows->info,&monitor_info); 8934 (void) XFlush(display); 8935} 8936 8937/* 8938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8939% % 8940% % 8941% % 8942% X T e x t V i e w W i d g e t % 8943% % 8944% % 8945% % 8946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8947% 8948% XTextViewWidget() displays text in a Text View widget. 8949% 8950% The format of the XTextViewWidget method is: 8951% 8952% void XTextViewWidget(Display *display,const XResourceInfo *resource_info, 8953% XWindows *windows,const MagickBooleanType mono,const char *title, 8954% const char **textlist) 8955% 8956% A description of each parameter follows: 8957% 8958% o display: Specifies a connection to an X server; returned from 8959% XOpenDisplay. 8960% 8961% o resource_info: Specifies a pointer to a X11 XResourceInfo structure. 8962% 8963% o window: Specifies a pointer to a XWindows structure. 8964% 8965% o mono: Use mono-spaced font when displaying text. 8966% 8967% o title: This character string is displayed at the top of the widget 8968% window. 8969% 8970% o textlist: This string list is displayed within the Text View widget. 8971% 8972*/ 8973MagickPrivate void XTextViewWidget(Display *display, 8974 const XResourceInfo *resource_info,XWindows *windows, 8975 const MagickBooleanType mono,const char *title,const char **textlist) 8976{ 8977#define DismissButtonText "Dismiss" 8978 8979 char 8980 primary_selection[MaxTextExtent]; 8981 8982 register int 8983 i; 8984 8985 static MagickStatusType 8986 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 8987 8988 Status 8989 status; 8990 8991 unsigned int 8992 height, 8993 lines, 8994 text_width, 8995 visible_lines, 8996 width; 8997 8998 size_t 8999 delay, 9000 state; 9001 9002 XEvent 9003 event; 9004 9005 XFontStruct 9006 *font_info, 9007 *text_info; 9008 9009 XTextProperty 9010 window_name; 9011 9012 XWidgetInfo 9013 dismiss_info, 9014 expose_info, 9015 list_info, 9016 north_info, 9017 scroll_info, 9018 selection_info, 9019 slider_info, 9020 south_info; 9021 9022 XWindowChanges 9023 window_changes; 9024 9025 /* 9026 Convert text string to a text list. 9027 */ 9028 assert(display != (Display *) NULL); 9029 assert(resource_info != (XResourceInfo *) NULL); 9030 assert(windows != (XWindows *) NULL); 9031 assert(title != (const char *) NULL); 9032 assert(textlist != (const char **) NULL); 9033 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title); 9034 XSetCursorState(display,windows,MagickTrue); 9035 XCheckRefreshWindows(display,windows); 9036 if (textlist == (const char **) NULL) 9037 { 9038 XNoticeWidget(display,windows,"No text to view:",(char *) NULL); 9039 return; 9040 } 9041 /* 9042 Determine Text View widget attributes. 9043 */ 9044 font_info=windows->widget.font_info; 9045 text_info=(XFontStruct *) NULL; 9046 if (mono != MagickFalse) 9047 text_info=XBestFont(display,resource_info,MagickTrue); 9048 if (text_info == (XFontStruct *) NULL) 9049 text_info=windows->widget.font_info; 9050 text_width=0; 9051 for (i=0; textlist[i] != (char *) NULL; i++) 9052 if (WidgetTextWidth(text_info,(char *) textlist[i]) > text_width) 9053 text_width=(unsigned int) XTextWidth(text_info,(char *) textlist[i], 9054 MagickMin(Extent(textlist[i]),160)); 9055 lines=(unsigned int) i; 9056 width=WidgetTextWidth(font_info,DismissButtonText); 9057 width+=QuantumMargin; 9058 height=(unsigned int) (text_info->ascent+text_info->descent); 9059 /* 9060 Position Text View widget. 9061 */ 9062 windows->widget.width=(unsigned int) (MagickMin((int) text_width, 9063 (int) MaxTextWidth)+5*QuantumMargin); 9064 windows->widget.min_width=(unsigned int) (MinTextWidth+4*QuantumMargin); 9065 if (windows->widget.width < windows->widget.min_width) 9066 windows->widget.width=windows->widget.min_width; 9067 windows->widget.height=(unsigned int) (MagickMin(MagickMax((int) lines,3),32)* 9068 height+((13*height) >> 1)+((9*QuantumMargin) >> 1)); 9069 windows->widget.min_height=(unsigned int) (3*height+((13*height) >> 1)+((9* 9070 QuantumMargin) >> 1)); 9071 if (windows->widget.height < windows->widget.min_height) 9072 windows->widget.height=windows->widget.min_height; 9073 XConstrainWindowPosition(display,&windows->widget); 9074 /* 9075 Map Text View widget. 9076 */ 9077 (void) CopyMagickString(windows->widget.name,title,MaxTextExtent); 9078 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 9079 if (status != False) 9080 { 9081 XSetWMName(display,windows->widget.id,&window_name); 9082 XSetWMIconName(display,windows->widget.id,&window_name); 9083 (void) XFree((void *) window_name.value); 9084 } 9085 window_changes.width=(int) windows->widget.width; 9086 window_changes.height=(int) windows->widget.height; 9087 window_changes.x=windows->widget.x; 9088 window_changes.y=windows->widget.y; 9089 (void) XReconfigureWMWindow(display,windows->widget.id, 9090 windows->widget.screen,(unsigned int) mask,&window_changes); 9091 (void) XMapRaised(display,windows->widget.id); 9092 windows->widget.mapped=MagickFalse; 9093 /* 9094 Respond to X events. 9095 */ 9096 XGetWidgetInfo((char *) NULL,&slider_info); 9097 XGetWidgetInfo((char *) NULL,&north_info); 9098 XGetWidgetInfo((char *) NULL,&south_info); 9099 XGetWidgetInfo((char *) NULL,&expose_info); 9100 visible_lines=0; 9101 delay=SuspendTime << 2; 9102 height=(unsigned int) (font_info->ascent+font_info->descent); 9103 state=UpdateConfigurationState; 9104 do 9105 { 9106 if (state & UpdateConfigurationState) 9107 { 9108 int 9109 id; 9110 9111 /* 9112 Initialize button information. 9113 */ 9114 XGetWidgetInfo(DismissButtonText,&dismiss_info); 9115 dismiss_info.width=width; 9116 dismiss_info.height=(unsigned int) ((3*height) >> 1); 9117 dismiss_info.x=(int) windows->widget.width-dismiss_info.width- 9118 QuantumMargin-2; 9119 dismiss_info.y=(int) windows->widget.height-dismiss_info.height- 9120 QuantumMargin; 9121 /* 9122 Initialize scroll information. 9123 */ 9124 XGetWidgetInfo((char *) NULL,&scroll_info); 9125 scroll_info.bevel_width--; 9126 scroll_info.width=height; 9127 scroll_info.height=(unsigned int) (dismiss_info.y-((5*QuantumMargin) >> 9128 1)); 9129 scroll_info.x=(int) windows->widget.width-QuantumMargin- 9130 scroll_info.width; 9131 scroll_info.y=(3*QuantumMargin) >> 1; 9132 scroll_info.raised=MagickFalse; 9133 scroll_info.trough=MagickTrue; 9134 north_info=scroll_info; 9135 north_info.raised=MagickTrue; 9136 north_info.width-=(north_info.bevel_width << 1); 9137 north_info.height=north_info.width-1; 9138 north_info.x+=north_info.bevel_width; 9139 north_info.y+=north_info.bevel_width; 9140 south_info=north_info; 9141 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 9142 south_info.height; 9143 id=slider_info.id; 9144 slider_info=north_info; 9145 slider_info.id=id; 9146 slider_info.width-=2; 9147 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 9148 slider_info.bevel_width+2; 9149 slider_info.height=scroll_info.height-((slider_info.min_y- 9150 scroll_info.y+1) << 1)+4; 9151 visible_lines=scroll_info.height/(text_info->ascent+text_info->descent+ 9152 ((text_info->ascent+text_info->descent) >> 3)); 9153 if (lines > visible_lines) 9154 slider_info.height=(unsigned int) (visible_lines*slider_info.height)/ 9155 lines; 9156 slider_info.max_y=south_info.y-south_info.bevel_width- 9157 slider_info.bevel_width-2; 9158 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 9159 slider_info.y=slider_info.min_y; 9160 expose_info=scroll_info; 9161 expose_info.y=slider_info.y; 9162 /* 9163 Initialize list information. 9164 */ 9165 XGetWidgetInfo((char *) NULL,&list_info); 9166 list_info.raised=MagickFalse; 9167 list_info.bevel_width--; 9168 list_info.width=(unsigned int) scroll_info.x-((3*QuantumMargin) >> 1); 9169 list_info.height=scroll_info.height; 9170 list_info.x=QuantumMargin; 9171 list_info.y=scroll_info.y; 9172 /* 9173 Initialize selection information. 9174 */ 9175 XGetWidgetInfo((char *) NULL,&selection_info); 9176 selection_info.center=MagickFalse; 9177 selection_info.width=list_info.width; 9178 selection_info.height=(unsigned int) 9179 (9*(text_info->ascent+text_info->descent)) >> 3; 9180 selection_info.x=list_info.x; 9181 state&=(~UpdateConfigurationState); 9182 } 9183 if (state & RedrawWidgetState) 9184 { 9185 /* 9186 Redraw Text View window. 9187 */ 9188 XDrawBeveledMatte(display,&windows->widget,&list_info); 9189 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 9190 XDrawTriangleNorth(display,&windows->widget,&north_info); 9191 XDrawBeveledButton(display,&windows->widget,&slider_info); 9192 XDrawTriangleSouth(display,&windows->widget,&south_info); 9193 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 9194 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 9195 selection_info.id=(~0); 9196 state|=RedrawListState; 9197 state&=(~RedrawWidgetState); 9198 } 9199 if (state & RedrawListState) 9200 { 9201 /* 9202 Determine slider id and position. 9203 */ 9204 if (slider_info.id >= (int) (lines-visible_lines)) 9205 slider_info.id=(int) lines-visible_lines; 9206 if ((slider_info.id < 0) || (lines <= visible_lines)) 9207 slider_info.id=0; 9208 slider_info.y=slider_info.min_y; 9209 if (lines != 0) 9210 slider_info.y+= 9211 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/lines; 9212 if (slider_info.id != selection_info.id) 9213 { 9214 /* 9215 Redraw scroll bar and text. 9216 */ 9217 windows->widget.font_info=text_info; 9218 (void) XSetFont(display,windows->widget.annotate_context, 9219 text_info->fid); 9220 (void) XSetFont(display,windows->widget.highlight_context, 9221 text_info->fid); 9222 selection_info.id=slider_info.id; 9223 selection_info.y=list_info.y+(height >> 3)+2; 9224 for (i=0; i < (int) visible_lines; i++) 9225 { 9226 selection_info.raised= 9227 (slider_info.id+i) != list_info.id ? MagickTrue : MagickFalse; 9228 selection_info.text=(char *) NULL; 9229 if ((slider_info.id+i) < (int) lines) 9230 selection_info.text=(char *) textlist[slider_info.id+i]; 9231 XDrawWidgetText(display,&windows->widget,&selection_info); 9232 selection_info.y+=(int) selection_info.height; 9233 } 9234 windows->widget.font_info=font_info; 9235 (void) XSetFont(display,windows->widget.annotate_context, 9236 font_info->fid); 9237 (void) XSetFont(display,windows->widget.highlight_context, 9238 font_info->fid); 9239 /* 9240 Update slider. 9241 */ 9242 if (slider_info.y > expose_info.y) 9243 { 9244 expose_info.height=(unsigned int) slider_info.y-expose_info.y; 9245 expose_info.y=slider_info.y-expose_info.height- 9246 slider_info.bevel_width-1; 9247 } 9248 else 9249 { 9250 expose_info.height=(unsigned int) expose_info.y-slider_info.y; 9251 expose_info.y=slider_info.y+slider_info.height+ 9252 slider_info.bevel_width+1; 9253 } 9254 XDrawTriangleNorth(display,&windows->widget,&north_info); 9255 XDrawMatte(display,&windows->widget,&expose_info); 9256 XDrawBeveledButton(display,&windows->widget,&slider_info); 9257 XDrawTriangleSouth(display,&windows->widget,&south_info); 9258 expose_info.y=slider_info.y; 9259 } 9260 state&=(~RedrawListState); 9261 } 9262 /* 9263 Wait for next event. 9264 */ 9265 if (north_info.raised && south_info.raised) 9266 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 9267 else 9268 { 9269 /* 9270 Brief delay before advancing scroll bar. 9271 */ 9272 XDelay(display,delay); 9273 delay=SuspendTime; 9274 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows); 9275 if (north_info.raised == MagickFalse) 9276 if (slider_info.id > 0) 9277 { 9278 /* 9279 Move slider up. 9280 */ 9281 slider_info.id--; 9282 state|=RedrawListState; 9283 } 9284 if (south_info.raised == MagickFalse) 9285 if (slider_info.id < (int) lines) 9286 { 9287 /* 9288 Move slider down. 9289 */ 9290 slider_info.id++; 9291 state|=RedrawListState; 9292 } 9293 if (event.type != ButtonRelease) 9294 continue; 9295 } 9296 switch (event.type) 9297 { 9298 case ButtonPress: 9299 { 9300 if (MatteIsActive(slider_info,event.xbutton)) 9301 { 9302 /* 9303 Track slider. 9304 */ 9305 slider_info.active=MagickTrue; 9306 break; 9307 } 9308 if (MatteIsActive(north_info,event.xbutton)) 9309 if (slider_info.id > 0) 9310 { 9311 /* 9312 Move slider up. 9313 */ 9314 north_info.raised=MagickFalse; 9315 slider_info.id--; 9316 state|=RedrawListState; 9317 break; 9318 } 9319 if (MatteIsActive(south_info,event.xbutton)) 9320 if (slider_info.id < (int) lines) 9321 { 9322 /* 9323 Move slider down. 9324 */ 9325 south_info.raised=MagickFalse; 9326 slider_info.id++; 9327 state|=RedrawListState; 9328 break; 9329 } 9330 if (MatteIsActive(scroll_info,event.xbutton)) 9331 { 9332 /* 9333 Move slider. 9334 */ 9335 if (event.xbutton.y < slider_info.y) 9336 slider_info.id-=(visible_lines-1); 9337 else 9338 slider_info.id+=(visible_lines-1); 9339 state|=RedrawListState; 9340 break; 9341 } 9342 if (MatteIsActive(dismiss_info,event.xbutton)) 9343 { 9344 /* 9345 User pressed Dismiss button. 9346 */ 9347 dismiss_info.raised=MagickFalse; 9348 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 9349 break; 9350 } 9351 if (MatteIsActive(list_info,event.xbutton)) 9352 { 9353 int 9354 id; 9355 9356 static Time 9357 click_time; 9358 9359 /* 9360 User pressed list matte. 9361 */ 9362 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/ 9363 selection_info.height; 9364 if (id >= (int) lines) 9365 break; 9366 if (id != list_info.id) 9367 { 9368 list_info.id=id; 9369 click_time=event.xbutton.time; 9370 break; 9371 } 9372 list_info.id=id; 9373 if (event.xbutton.time >= (click_time+DoubleClick)) 9374 { 9375 click_time=event.xbutton.time; 9376 break; 9377 } 9378 click_time=event.xbutton.time; 9379 /* 9380 Become the XA_PRIMARY selection owner. 9381 */ 9382 (void) CopyMagickString(primary_selection,textlist[list_info.id], 9383 MaxTextExtent); 9384 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 9385 event.xbutton.time); 9386 if (XGetSelectionOwner(display,XA_PRIMARY) != windows->widget.id) 9387 break; 9388 selection_info.id=(~0); 9389 list_info.id=id; 9390 state|=RedrawListState; 9391 break; 9392 } 9393 break; 9394 } 9395 case ButtonRelease: 9396 { 9397 if (windows->widget.mapped == MagickFalse) 9398 break; 9399 if (north_info.raised == MagickFalse) 9400 { 9401 /* 9402 User released up button. 9403 */ 9404 delay=SuspendTime << 2; 9405 north_info.raised=MagickTrue; 9406 XDrawTriangleNorth(display,&windows->widget,&north_info); 9407 } 9408 if (south_info.raised == MagickFalse) 9409 { 9410 /* 9411 User released down button. 9412 */ 9413 delay=SuspendTime << 2; 9414 south_info.raised=MagickTrue; 9415 XDrawTriangleSouth(display,&windows->widget,&south_info); 9416 } 9417 if (slider_info.active) 9418 { 9419 /* 9420 Stop tracking slider. 9421 */ 9422 slider_info.active=MagickFalse; 9423 break; 9424 } 9425 if (dismiss_info.raised == MagickFalse) 9426 { 9427 if (event.xbutton.window == windows->widget.id) 9428 if (MatteIsActive(dismiss_info,event.xbutton)) 9429 state|=ExitState; 9430 dismiss_info.raised=MagickTrue; 9431 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 9432 } 9433 break; 9434 } 9435 case ClientMessage: 9436 { 9437 /* 9438 If client window delete message, exit. 9439 */ 9440 if (event.xclient.message_type != windows->wm_protocols) 9441 break; 9442 if (*event.xclient.data.l == (int) windows->wm_take_focus) 9443 { 9444 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 9445 (Time) event.xclient.data.l[1]); 9446 break; 9447 } 9448 if (*event.xclient.data.l != (int) windows->wm_delete_window) 9449 break; 9450 if (event.xclient.window == windows->widget.id) 9451 { 9452 state|=ExitState; 9453 break; 9454 } 9455 break; 9456 } 9457 case ConfigureNotify: 9458 { 9459 /* 9460 Update widget configuration. 9461 */ 9462 if (event.xconfigure.window != windows->widget.id) 9463 break; 9464 if ((event.xconfigure.width == (int) windows->widget.width) && 9465 (event.xconfigure.height == (int) windows->widget.height)) 9466 break; 9467 windows->widget.width=(unsigned int) 9468 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 9469 windows->widget.height=(unsigned int) 9470 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 9471 state|=UpdateConfigurationState; 9472 break; 9473 } 9474 case EnterNotify: 9475 { 9476 if (event.xcrossing.window != windows->widget.id) 9477 break; 9478 state&=(~InactiveWidgetState); 9479 break; 9480 } 9481 case Expose: 9482 { 9483 if (event.xexpose.window != windows->widget.id) 9484 break; 9485 if (event.xexpose.count != 0) 9486 break; 9487 state|=RedrawWidgetState; 9488 break; 9489 } 9490 case KeyPress: 9491 { 9492 static char 9493 command[MaxTextExtent]; 9494 9495 static int 9496 length; 9497 9498 static KeySym 9499 key_symbol; 9500 9501 /* 9502 Respond to a user key press. 9503 */ 9504 if (event.xkey.window != windows->widget.id) 9505 break; 9506 length=XLookupString((XKeyEvent *) &event.xkey,command, 9507 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 9508 *(command+length)='\0'; 9509 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 9510 { 9511 dismiss_info.raised=MagickFalse; 9512 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 9513 state|=ExitState; 9514 break; 9515 } 9516 if (AreaIsActive(scroll_info,event.xkey)) 9517 { 9518 /* 9519 Move slider. 9520 */ 9521 switch ((int) key_symbol) 9522 { 9523 case XK_Home: 9524 case XK_KP_Home: 9525 { 9526 slider_info.id=0; 9527 break; 9528 } 9529 case XK_Up: 9530 case XK_KP_Up: 9531 { 9532 slider_info.id--; 9533 break; 9534 } 9535 case XK_Down: 9536 case XK_KP_Down: 9537 { 9538 slider_info.id++; 9539 break; 9540 } 9541 case XK_Prior: 9542 case XK_KP_Prior: 9543 { 9544 slider_info.id-=visible_lines; 9545 break; 9546 } 9547 case XK_Next: 9548 case XK_KP_Next: 9549 { 9550 slider_info.id+=visible_lines; 9551 break; 9552 } 9553 case XK_End: 9554 case XK_KP_End: 9555 { 9556 slider_info.id=(int) lines; 9557 break; 9558 } 9559 } 9560 state|=RedrawListState; 9561 break; 9562 } 9563 break; 9564 } 9565 case KeyRelease: 9566 break; 9567 case LeaveNotify: 9568 { 9569 if (event.xcrossing.window != windows->widget.id) 9570 break; 9571 state|=InactiveWidgetState; 9572 break; 9573 } 9574 case MapNotify: 9575 { 9576 mask&=(~CWX); 9577 mask&=(~CWY); 9578 break; 9579 } 9580 case MotionNotify: 9581 { 9582 /* 9583 Discard pending button motion events. 9584 */ 9585 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 9586 if (slider_info.active) 9587 { 9588 /* 9589 Move slider matte. 9590 */ 9591 slider_info.y=event.xmotion.y- 9592 ((slider_info.height+slider_info.bevel_width) >> 1)+1; 9593 if (slider_info.y < slider_info.min_y) 9594 slider_info.y=slider_info.min_y; 9595 if (slider_info.y > slider_info.max_y) 9596 slider_info.y=slider_info.max_y; 9597 slider_info.id=0; 9598 if (slider_info.y != slider_info.min_y) 9599 slider_info.id=(int) (lines*(slider_info.y-slider_info.min_y+1))/ 9600 (slider_info.max_y-slider_info.min_y+1); 9601 state|=RedrawListState; 9602 break; 9603 } 9604 if (state & InactiveWidgetState) 9605 break; 9606 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion)) 9607 { 9608 /* 9609 Dismiss button status changed. 9610 */ 9611 dismiss_info.raised= 9612 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse; 9613 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 9614 break; 9615 } 9616 break; 9617 } 9618 case SelectionClear: 9619 { 9620 list_info.id=(~0); 9621 selection_info.id=(~0); 9622 state|=RedrawListState; 9623 break; 9624 } 9625 case SelectionRequest: 9626 { 9627 XSelectionEvent 9628 notify; 9629 9630 XSelectionRequestEvent 9631 *request; 9632 9633 if (list_info.id == (~0)) 9634 break; 9635 /* 9636 Set primary selection. 9637 */ 9638 request=(&(event.xselectionrequest)); 9639 (void) XChangeProperty(request->display,request->requestor, 9640 request->property,request->target,8,PropModeReplace, 9641 (unsigned char *) primary_selection,Extent(primary_selection)); 9642 notify.type=SelectionNotify; 9643 notify.send_event=MagickTrue; 9644 notify.display=request->display; 9645 notify.requestor=request->requestor; 9646 notify.selection=request->selection; 9647 notify.target=request->target; 9648 notify.time=request->time; 9649 if (request->property == None) 9650 notify.property=request->target; 9651 else 9652 notify.property=request->property; 9653 (void) XSendEvent(request->display,request->requestor,False,NoEventMask, 9654 (XEvent *) ¬ify); 9655 } 9656 default: 9657 break; 9658 } 9659 } while ((state & ExitState) == 0); 9660 if (text_info != windows->widget.font_info) 9661 (void) XFreeFont(display,text_info); 9662 XSetCursorState(display,windows,MagickFalse); 9663 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 9664 XCheckRefreshWindows(display,windows); 9665} 9666#endif 9667