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