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