2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 % W W IIIII DDDD GGGG EEEEE TTTTT %
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 %
14 % MagickCore X11 User Interface Methods %
21 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
27 % http://www.imagemagick.org/script/license.php %
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. %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/color.h"
45 #include "MagickCore/color-private.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/magick.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/PreRvIcccm.h"
52 #include "MagickCore/string_.h"
53 #include "MagickCore/token.h"
54 #include "MagickCore/token-private.h"
55 #include "MagickCore/utility.h"
56 #include "MagickCore/utility-private.h"
57 #include "MagickCore/xwindow-private.h"
58 #include "MagickCore/widget.h"
59 #include "MagickCore/widget-private.h"
61 #if defined(MAGICKCORE_X11_DELEGATE)
66 #define AreaIsActive(matte_info,position) ( \
67 ((position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
68 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
69 ? MagickTrue : MagickFalse)
70 #define Extent(s) ((int) strlen(s))
71 #define MatteIsActive(matte_info,position) ( \
72 ((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \
73 (position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
74 (position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) && \
75 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
76 ? MagickTrue : MagickFalse)
77 #define MaxTextWidth ((unsigned int) (255*XTextWidth(font_info,"_",1)))
78 #define MinTextWidth (26*XTextWidth(font_info,"_",1))
79 #define QuantumMargin MagickMax(font_info->max_bounds.width,12)
80 #define WidgetTextWidth(font_info,text) \
81 ((unsigned int) XTextWidth(font_info,text,Extent(text)))
82 #define WindowIsActive(window_info,position) ( \
83 ((position.x >= 0) && (position.y >= 0) && \
84 (position.x < (int) window_info.width) && \
85 (position.y < (int) window_info.height)) ? MagickTrue : MagickFalse)
92 ControlState = 0x0001,
93 InactiveWidgetState = 0x0004,
94 JumpListState = 0x0008,
95 RedrawActionState = 0x0010,
96 RedrawListState = 0x0020,
97 RedrawWidgetState = 0x0040,
98 UpdateListState = 0x0100
102 Typedef declarations.
104 typedef struct _XWidgetInfo
134 Variable declarations.
139 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
140 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
144 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
145 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
147 *selection_info = (XWidgetInfo *) NULL,
150 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
151 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
155 Constant declarations.
165 XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *),
166 XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType),
167 XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType),
168 XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType);
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 % D e s t r o y X W i d g e t %
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 % DestroyXWidget() destroys resources associated with the X widget.
183 % The format of the DestroyXWidget method is:
185 % void DestroyXWidget()
187 % A description of each parameter follows:
190 MagickPrivate void DestroyXWidget(void)
192 if (selection_info != (XWidgetInfo *) NULL)
193 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 + X D r a w B e v e l %
205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 % XDrawBevel() "sets off" an area with a highlighted upper and left bevel and
208 % a shadowed lower and right bevel. The highlighted and shadowed bevels
209 % create a 3-D effect.
211 % The format of the XDrawBevel function is:
213 % XDrawBevel(display,window_info,bevel_info)
215 % A description of each parameter follows:
217 % o display: Specifies a pointer to the Display structure; returned from
220 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
222 % o bevel_info: Specifies a pointer to a XWidgetInfo structure. It
223 % contains the extents of the bevel.
226 static void XDrawBevel(Display *display,const XWindowInfo *window_info,
227 const XWidgetInfo *bevel_info)
242 Draw upper and left beveled border.
245 y1=bevel_info->y+bevel_info->height;
246 x2=bevel_info->x+bevel_info->width;
248 bevel_width=bevel_info->bevel_width;
255 points[3].x=x2+bevel_width;
256 points[3].y=y2-bevel_width;
257 points[4].x=x1-bevel_width;
258 points[4].y=y2-bevel_width;
259 points[5].x=x1-bevel_width;
260 points[5].y=y1+bevel_width;
261 XSetBevelColor(display,window_info,bevel_info->raised);
262 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
263 points,6,Complex,CoordModeOrigin);
265 Draw lower and right beveled border.
273 points[3].x=x2+bevel_width;
274 points[3].y=y2-bevel_width;
275 points[4].x=x2+bevel_width;
276 points[4].y=y1+bevel_width;
277 points[5].x=x1-bevel_width;
278 points[5].y=y1+bevel_width;
279 XSetBevelColor(display,window_info,!bevel_info->raised);
280 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
281 points,6,Complex,CoordModeOrigin);
282 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290 + X D r a w B e v e l e d B u t t o n %
294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 % XDrawBeveledButton() draws a button with a highlighted upper and left bevel
297 % and a shadowed lower and right bevel. The highlighted and shadowed bevels
298 % create a 3-D effect.
300 % The format of the XDrawBeveledButton function is:
302 % XDrawBeveledButton(display,window_info,button_info)
304 % A description of each parameter follows:
306 % o display: Specifies a pointer to the Display structure; returned from
309 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
311 % o button_info: Specifies a pointer to a XWidgetInfo structure. It
312 % contains the extents of the button.
316 static inline int MagickAbsoluteValue(const int x)
323 static inline int MagickMax(const int x,const int y)
330 static inline int MagickMin(const int x,const int y)
337 static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info,
338 const XWidgetInfo *button_info)
356 XDrawBevel(display,window_info,button_info);
357 XSetMatteColor(display,window_info,button_info->raised);
358 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
359 button_info->x,button_info->y,button_info->width,button_info->height);
360 x=button_info->x-button_info->bevel_width-1;
361 y=button_info->y-button_info->bevel_width-1;
362 (void) XSetForeground(display,window_info->widget_context,
363 window_info->pixel_info->trough_color.pixel);
364 if (button_info->raised || (window_info->depth == 1))
365 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
366 x,y,button_info->width+(button_info->bevel_width << 1)+1,
367 button_info->height+(button_info->bevel_width << 1)+1);
368 if (button_info->text == (char *) NULL)
373 crop_info.width=(unsigned short) button_info->width;
374 crop_info.height=(unsigned short) button_info->height;
375 crop_info.x=button_info->x;
376 crop_info.y=button_info->y;
380 font_info=window_info->font_info;
381 width=WidgetTextWidth(font_info,button_info->text);
382 x=button_info->x+(QuantumMargin >> 1);
383 if (button_info->center)
384 x=button_info->x+(button_info->width >> 1)-(width >> 1);
385 y=button_info->y+((button_info->height-
386 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
387 if ((int) button_info->width == (QuantumMargin >> 1))
390 Option button-- write label to right of button.
392 XSetTextColor(display,window_info,MagickTrue);
393 x=button_info->x+button_info->width+button_info->bevel_width+
394 (QuantumMargin >> 1);
395 (void) XDrawString(display,window_info->id,window_info->widget_context,
396 x,y,button_info->text,Extent(button_info->text));
399 (void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info,
401 XSetTextColor(display,window_info,button_info->raised);
402 (void) XDrawString(display,window_info->id,window_info->widget_context,x,y,
403 button_info->text,Extent(button_info->text));
404 (void) XSetClipMask(display,window_info->widget_context,None);
405 if (button_info->raised == MagickFalse)
406 XDelay(display,SuspendTime << 2);
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414 + X D r a w B e v e l e d M a t t e %
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 % XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and
421 % a highlighted lower and right bevel. The highlighted and shadowed bevels
422 % create a 3-D effect.
424 % The format of the XDrawBeveledMatte function is:
426 % XDrawBeveledMatte(display,window_info,matte_info)
428 % A description of each parameter follows:
430 % o display: Specifies a pointer to the Display structure; returned from
433 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
435 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
436 % contains the extents of the matte.
439 static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info,
440 const XWidgetInfo *matte_info)
445 XDrawBevel(display,window_info,matte_info);
446 XDrawMatte(display,window_info,matte_info);
450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 + X D r a w M a t t e %
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460 % XDrawMatte() fills a rectangular area with the matte color.
462 % The format of the XDrawMatte function is:
464 % XDrawMatte(display,window_info,matte_info)
466 % A description of each parameter follows:
468 % o display: Specifies a pointer to the Display structure; returned from
471 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
473 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
474 % contains the extents of the matte.
477 static void XDrawMatte(Display *display,const XWindowInfo *window_info,
478 const XWidgetInfo *matte_info)
483 if ((matte_info->trough == MagickFalse) || (window_info->depth == 1))
484 (void) XFillRectangle(display,window_info->id,
485 window_info->highlight_context,matte_info->x,matte_info->y,
486 matte_info->width,matte_info->height);
489 (void) XSetForeground(display,window_info->widget_context,
490 window_info->pixel_info->trough_color.pixel);
491 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
492 matte_info->x,matte_info->y,matte_info->width,matte_info->height);
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 + X D r a w M a t t e T e x t %
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 % XDrawMatteText() draws a matte with text. If the text exceeds the extents
508 % of the text, a portion of the text relative to the cursor is displayed.
510 % The format of the XDrawMatteText function is:
512 % XDrawMatteText(display,window_info,text_info)
514 % A description of each parameter follows:
516 % o display: Specifies a pointer to the Display structure; returned from
519 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
521 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
522 % contains the extents of the text.
525 static void XDrawMatteText(Display *display,const XWindowInfo *window_info,
526 XWidgetInfo *text_info)
552 XSetMatteColor(display,window_info,MagickFalse);
553 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
554 text_info->x,text_info->y,text_info->width,text_info->height);
555 if (text_info->text == (char *) NULL)
557 XSetTextColor(display,window_info,text_info->highlight);
558 font_info=window_info->font_info;
559 x=text_info->x+(QuantumMargin >> 2);
560 y=text_info->y+font_info->ascent+(text_info->height >> 2);
561 width=text_info->width-(QuantumMargin >> 1);
562 height=(unsigned int) (font_info->ascent+font_info->descent);
563 if (*text_info->text == '\0')
566 No text-- just draw cursor.
568 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
575 crop_info.width=(unsigned short) text_info->width;
576 crop_info.height=(unsigned short) text_info->height;
577 crop_info.x=text_info->x;
578 crop_info.y=text_info->y;
580 Determine beginning of the visible text.
582 if (text_info->cursor < text_info->marker)
583 text_info->marker=text_info->cursor;
586 text=text_info->marker;
587 if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) >
590 text=text_info->text;
591 for (i=0; i < Extent(text); i++)
593 n=XTextWidth(font_info,(char *) text+i,(int)
594 (text_info->cursor-text-i));
595 if (n <= (int) width)
598 text_info->marker=(char *) text+i;
602 Draw text and cursor.
604 if (text_info->highlight == MagickFalse)
606 (void) XSetClipRectangles(display,window_info->widget_context,0,0,
607 &crop_info,1,Unsorted);
608 (void) XDrawString(display,window_info->id,window_info->widget_context,
609 x,y,text_info->marker,Extent(text_info->marker));
610 (void) XSetClipMask(display,window_info->widget_context,None);
614 (void) XSetClipRectangles(display,window_info->annotate_context,0,0,
615 &crop_info,1,Unsorted);
616 width=WidgetTextWidth(font_info,text_info->marker);
617 (void) XFillRectangle(display,window_info->id,
618 window_info->annotate_context,x,y-font_info->ascent,width,height);
619 (void) XSetClipMask(display,window_info->annotate_context,None);
620 (void) XSetClipRectangles(display,window_info->highlight_context,0,0,
621 &crop_info,1,Unsorted);
622 (void) XDrawString(display,window_info->id,
623 window_info->highlight_context,x,y,text_info->marker,
624 Extent(text_info->marker));
625 (void) XSetClipMask(display,window_info->highlight_context,None);
627 x+=XTextWidth(font_info,text_info->marker,(int)
628 (text_info->cursor-text_info->marker));
629 (void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3,
634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638 + X D r a w T r i a n g l e E a s t %
642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 % XDrawTriangleEast() draws a triangle with a highlighted left bevel and a
645 % shadowed right and lower bevel. The highlighted and shadowed bevels create
648 % The format of the XDrawTriangleEast function is:
650 % XDrawTriangleEast(display,window_info,triangle_info)
652 % A description of each parameter follows:
654 % o display: Specifies a pointer to the Display structure; returned from
657 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
659 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
660 % contains the extents of the triangle.
663 static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info,
664 const XWidgetInfo *triangle_info)
688 x2=triangle_info->x+triangle_info->width;
689 y2=triangle_info->y+(triangle_info->height >> 1);
691 y3=triangle_info->y+triangle_info->height;
692 bevel_width=triangle_info->bevel_width;
699 XSetMatteColor(display,window_info,triangle_info->raised);
700 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
701 points,3,Complex,CoordModeOrigin);
709 points[2].x=x3-bevel_width;
710 points[2].y=y3+bevel_width;
711 points[3].x=x2+bevel_width;
713 XSetBevelColor(display,window_info,!triangle_info->raised);
714 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
715 points,4,Complex,CoordModeOrigin);
723 points[2].x=x1-bevel_width+1;
724 points[2].y=y1-bevel_width;
725 points[3].x=x3-bevel_width+1;
726 points[3].y=y3+bevel_width;
727 XSetBevelColor(display,window_info,triangle_info->raised);
728 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
729 points,4,Complex,CoordModeOrigin);
737 points[2].x=x2+bevel_width;
739 points[3].x=x1-bevel_width;
740 points[3].y=y1-bevel_width;
741 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
742 points,4,Complex,CoordModeOrigin);
743 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
744 if (triangle_info->text == (char *) NULL)
747 Write label to right of triangle.
749 font_info=window_info->font_info;
750 XSetTextColor(display,window_info,MagickTrue);
751 x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+
752 (QuantumMargin >> 1);
753 y1=triangle_info->y+((triangle_info->height-
754 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
755 (void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1,
756 triangle_info->text,Extent(triangle_info->text));
760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 + X D r a w T r i a n g l e N o r t h %
768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 % XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a
771 % shadowed right and lower bevel. The highlighted and shadowed bevels create
774 % The format of the XDrawTriangleNorth function is:
776 % XDrawTriangleNorth(display,window_info,triangle_info)
778 % A description of each parameter follows:
780 % o display: Specifies a pointer to the Display structure; returned from
783 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
785 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
786 % contains the extents of the triangle.
789 static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info,
790 const XWidgetInfo *triangle_info)
810 y1=triangle_info->y+triangle_info->height;
811 x2=triangle_info->x+(triangle_info->width >> 1);
813 x3=triangle_info->x+triangle_info->width;
814 y3=triangle_info->y+triangle_info->height;
815 bevel_width=triangle_info->bevel_width;
822 XSetMatteColor(display,window_info,triangle_info->raised);
823 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
824 points,3,Complex,CoordModeOrigin);
833 points[2].y=y2-bevel_width-2;
834 points[3].x=x1-bevel_width-1;
835 points[3].y=y1+bevel_width;
836 XSetBevelColor(display,window_info,triangle_info->raised);
837 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
838 points,4,Complex,CoordModeOrigin);
846 points[2].x=x3+bevel_width;
847 points[2].y=y3+bevel_width;
849 points[3].y=y2-bevel_width;
850 XSetBevelColor(display,window_info,!triangle_info->raised);
851 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
852 points,4,Complex,CoordModeOrigin);
860 points[2].x=x1-bevel_width;
861 points[2].y=y1+bevel_width;
862 points[3].x=x3+bevel_width;
863 points[3].y=y3+bevel_width;
864 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
865 points,4,Complex,CoordModeOrigin);
866 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874 + X D r a w T r i a n g l e S o u t h %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880 % XDrawTriangleSouth() draws a border with a highlighted left and right bevel
881 % and a shadowed lower bevel. The highlighted and shadowed bevels create a
884 % The format of the XDrawTriangleSouth function is:
886 % XDrawTriangleSouth(display,window_info,triangle_info)
888 % A description of each parameter follows:
890 % o display: Specifies a pointer to the Display structure; returned from
893 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
895 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
896 % contains the extents of the triangle.
899 static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info,
900 const XWidgetInfo *triangle_info)
921 x2=triangle_info->x+(triangle_info->width >> 1);
922 y2=triangle_info->y+triangle_info->height;
923 x3=triangle_info->x+triangle_info->width;
925 bevel_width=triangle_info->bevel_width;
932 XSetMatteColor(display,window_info,triangle_info->raised);
933 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
934 points,3,Complex,CoordModeOrigin);
942 points[2].x=x1-bevel_width;
943 points[2].y=y1-bevel_width;
944 points[3].x=x3+bevel_width;
945 points[3].y=y3-bevel_width;
946 XSetBevelColor(display,window_info,triangle_info->raised);
947 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
948 points,4,Complex,CoordModeOrigin);
955 points[1].y=y3-bevel_width;
956 points[2].x=x3+bevel_width;
957 points[2].y=y3-bevel_width;
959 points[3].y=y2+bevel_width;
960 XSetBevelColor(display,window_info,!triangle_info->raised);
961 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
962 points,4,Complex,CoordModeOrigin);
971 points[2].y=y2+bevel_width;
972 points[3].x=x1-bevel_width;
973 points[3].y=y1-bevel_width;
974 XSetBevelColor(display,window_info,triangle_info->raised);
975 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
976 points,4,Complex,CoordModeOrigin);
977 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985 + X D r a w W i d g e t T e x t %
989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 % XDrawWidgetText() first clears the widget and draws a text string justifed
992 % left (or center) in the x-direction and centered within the y-direction.
994 % The format of the XDrawWidgetText function is:
996 % XDrawWidgetText(display,window_info,text_info)
998 % A description of each parameter follows:
1000 % o display: Specifies a pointer to the Display structure; returned from
1003 % o window_info: Specifies a pointer to a XWindowText structure.
1005 % o text_info: Specifies a pointer to XWidgetInfo structure.
1008 static void XDrawWidgetText(Display *display,const XWindowInfo *window_info,
1009 XWidgetInfo *text_info)
1029 Clear the text area.
1031 widget_context=window_info->annotate_context;
1032 if (text_info->raised)
1033 (void) XClearArea(display,window_info->id,text_info->x,text_info->y,
1034 text_info->width,text_info->height,MagickFalse);
1037 (void) XFillRectangle(display,window_info->id,widget_context,text_info->x,
1038 text_info->y,text_info->width,text_info->height);
1039 widget_context=window_info->highlight_context;
1041 if (text_info->text == (char *) NULL)
1043 if (*text_info->text == '\0')
1046 Set cropping region.
1048 font_info=window_info->font_info;
1049 crop_info.width=(unsigned short) text_info->width;
1050 crop_info.height=(unsigned short) text_info->height;
1051 crop_info.x=text_info->x;
1052 crop_info.y=text_info->y;
1056 width=WidgetTextWidth(font_info,text_info->text);
1057 x=text_info->x+(QuantumMargin >> 1);
1058 if (text_info->center)
1059 x=text_info->x+(text_info->width >> 1)-(width >> 1);
1060 if (text_info->raised)
1061 if (width > (text_info->width-QuantumMargin))
1062 x+=(text_info->width-QuantumMargin-width);
1063 height=(unsigned int) (font_info->ascent+font_info->descent);
1064 y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent;
1065 (void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted);
1066 (void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text,
1067 Extent(text_info->text));
1068 (void) XSetClipMask(display,widget_context,None);
1069 if (x < text_info->x)
1070 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
1071 text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1);
1075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 + X E d i t T e x t %
1083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1085 % XEditText() edits a text string as indicated by the key symbol.
1087 % The format of the XEditText function is:
1089 % XEditText(display,text_info,key_symbol,text,state)
1091 % A description of each parameter follows:
1093 % o display: Specifies a connection to an X server; returned from
1096 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
1097 % contains the extents of the text.
1099 % o key_symbol: A X11 KeySym that indicates what editing function to
1100 % perform to the text.
1102 % o text: A character string to insert into the text.
1104 % o state: An size_t that indicates whether the key symbol is a
1105 % control character or not.
1108 static void XEditText(Display *display,XWidgetInfo *text_info,
1109 const KeySym key_symbol,char *text,const size_t state)
1111 switch ((int) key_symbol)
1116 if (text_info->highlight)
1119 Erase the entire line of text.
1121 *text_info->text='\0';
1122 text_info->cursor=text_info->text;
1123 text_info->marker=text_info->text;
1124 text_info->highlight=MagickFalse;
1127 Erase one character.
1129 if (text_info->cursor != text_info->text)
1131 text_info->cursor--;
1132 (void) CopyMagickString(text_info->cursor,text_info->cursor+1,
1134 text_info->highlight=MagickFalse;
1142 Move cursor one position left.
1144 if (text_info->cursor == text_info->text)
1146 text_info->cursor--;
1153 Move cursor one position right.
1155 if (text_info->cursor == (text_info->text+Extent(text_info->text)))
1157 text_info->cursor++;
1169 if (state & ControlState)
1173 if ((Extent(text_info->text)+1) >= (int) MaxTextExtent)
1174 (void) XBell(display,0);
1177 if (text_info->highlight)
1180 Erase the entire line of text.
1182 *text_info->text='\0';
1183 text_info->cursor=text_info->text;
1184 text_info->marker=text_info->text;
1185 text_info->highlight=MagickFalse;
1188 Insert a string into the text.
1190 q=text_info->text+Extent(text_info->text)+strlen(text);
1191 for (i=0; i <= Extent(text_info->cursor); i++)
1193 *q=(*(q-Extent(text)));
1197 for (i=0; i < Extent(text); i++)
1198 *text_info->cursor++=(*p++);
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210 + X G e t W i d g e t I n f o %
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216 % XGetWidgetInfo() initializes the XWidgetInfo structure.
1218 % The format of the XGetWidgetInfo function is:
1220 % XGetWidgetInfo(text,widget_info)
1222 % A description of each parameter follows:
1224 % o text: A string of characters associated with the widget.
1226 % o widget_info: Specifies a pointer to a X11 XWidgetInfo structure.
1229 static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info)
1232 Initialize widget info.
1234 widget_info->id=(~0);
1235 widget_info->bevel_width=3;
1236 widget_info->width=1;
1237 widget_info->height=1;
1240 widget_info->min_y=0;
1241 widget_info->max_y=0;
1242 widget_info->raised=MagickTrue;
1243 widget_info->active=MagickFalse;
1244 widget_info->center=MagickTrue;
1245 widget_info->trough=MagickFalse;
1246 widget_info->highlight=MagickFalse;
1247 widget_info->text=(char *) text;
1248 widget_info->cursor=(char *) text;
1249 if (text != (char *) NULL)
1250 widget_info->cursor+=Extent(text);
1251 widget_info->marker=(char *) text;
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259 + X H i g h l i g h t W i d g e t %
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265 % XHighlightWidget() draws a highlighted border around a window.
1267 % The format of the XHighlightWidget function is:
1269 % XHighlightWidget(display,window_info,x,y)
1271 % A description of each parameter follows:
1273 % o display: Specifies a pointer to the Display structure; returned from
1276 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1278 % o x: Specifies an integer representing the rectangle offset in the
1281 % o y: Specifies an integer representing the rectangle offset in the
1285 static void XHighlightWidget(Display *display,const XWindowInfo *window_info,
1286 const int x,const int y)
1289 Draw the widget highlighting rectangle.
1291 XSetBevelColor(display,window_info,MagickTrue);
1292 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y,
1293 window_info->width-(x << 1),window_info->height-(y << 1));
1294 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1295 x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1);
1296 XSetBevelColor(display,window_info,MagickFalse);
1297 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1298 x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1));
1299 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
1303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1307 + X S c r e e n E v e n t %
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1313 % XScreenEvent() returns MagickTrue if the any event on the X server queue is
1314 % associated with the widget window.
1316 % The format of the XScreenEvent function is:
1318 % int XScreenEvent(Display *display,XEvent *event,char *data)
1320 % A description of each parameter follows:
1322 % o display: Specifies a pointer to the Display structure; returned from
1325 % o event: Specifies a pointer to a X11 XEvent structure.
1327 % o data: Specifies a pointer to a XWindows structure.
1331 #if defined(__cplusplus) || defined(c_plusplus)
1335 static int XScreenEvent(Display *display,XEvent *event,char *data)
1340 windows=(XWindows *) data;
1341 if (event->xany.window == windows->popup.id)
1343 if (event->type == MapNotify)
1344 windows->popup.mapped=MagickTrue;
1345 if (event->type == UnmapNotify)
1346 windows->popup.mapped=MagickFalse;
1349 if (event->xany.window == windows->widget.id)
1351 if (event->type == MapNotify)
1352 windows->widget.mapped=MagickTrue;
1353 if (event->type == UnmapNotify)
1354 windows->widget.mapped=MagickFalse;
1357 switch (event->type)
1361 if ((event->xbutton.button == Button3) &&
1362 (event->xbutton.state & Mod1Mask))
1365 Convert Alt-Button3 to Button2.
1367 event->xbutton.button=Button2;
1368 event->xbutton.state&=(~Mod1Mask);
1374 if (event->xexpose.window == windows->image.id)
1376 XRefreshWindow(display,&windows->image,event);
1379 if (event->xexpose.window == windows->magnify.id)
1380 if (event->xexpose.count == 0)
1381 if (windows->magnify.mapped)
1386 exception=AcquireExceptionInfo();
1387 XMakeMagnifyImage(display,windows,exception);
1388 exception=DestroyExceptionInfo(exception);
1391 if (event->xexpose.window == windows->command.id)
1392 if (event->xexpose.count == 0)
1394 (void) XCommandWidget(display,windows,(const char **) NULL,event);
1402 Set input focus for backdrop window.
1404 if (event->xfocus.window == windows->image.id)
1405 (void) XSetInputFocus(display,windows->image.id,RevertToNone,
1413 case SelectionNotify:
1418 return(MagickFalse);
1421 #if defined(__cplusplus) || defined(c_plusplus)
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 + X S e t B e v e l C o l o r %
1434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 % XSetBevelColor() sets the graphic context for drawing a beveled border.
1438 % The format of the XSetBevelColor function is:
1440 % XSetBevelColor(display,window_info,raised)
1442 % A description of each parameter follows:
1444 % o display: Specifies a pointer to the Display structure; returned from
1447 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1449 % o raised: A value other than zero indicates the color show be a
1450 % "highlight" color, otherwise the "shadow" color is set.
1453 static void XSetBevelColor(Display *display,const XWindowInfo *window_info,
1454 const MagickStatusType raised)
1456 if (window_info->depth == 1)
1464 (void) XSetBackground(display,window_info->widget_context,
1465 XBlackPixel(display,window_info->screen));
1466 (void) XSetForeground(display,window_info->widget_context,
1467 XWhitePixel(display,window_info->screen));
1468 (void) XSetFillStyle(display,window_info->widget_context,
1469 FillOpaqueStippled);
1470 stipple=window_info->highlight_stipple;
1471 if (raised == MagickFalse)
1472 stipple=window_info->shadow_stipple;
1473 (void) XSetStipple(display,window_info->widget_context,stipple);
1477 (void) XSetForeground(display,window_info->widget_context,
1478 window_info->pixel_info->highlight_color.pixel);
1480 (void) XSetForeground(display,window_info->widget_context,
1481 window_info->pixel_info->shadow_color.pixel);
1485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489 + X S e t M a t t e C o l o r %
1493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1495 % XSetMatteColor() sets the graphic context for drawing the matte.
1497 % The format of the XSetMatteColor function is:
1499 % XSetMatteColor(display,window_info,raised)
1501 % A description of each parameter follows:
1503 % o display: Specifies a pointer to the Display structure; returned from
1506 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1508 % o raised: A value other than zero indicates the matte is active.
1511 static void XSetMatteColor(Display *display,const XWindowInfo *window_info,
1512 const MagickStatusType raised)
1514 if (window_info->depth == 1)
1520 (void) XSetForeground(display,window_info->widget_context,
1521 XWhitePixel(display,window_info->screen));
1523 (void) XSetForeground(display,window_info->widget_context,
1524 XBlackPixel(display,window_info->screen));
1528 (void) XSetForeground(display,window_info->widget_context,
1529 window_info->pixel_info->matte_color.pixel);
1531 (void) XSetForeground(display,window_info->widget_context,
1532 window_info->pixel_info->depth_color.pixel);
1536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1540 + X S e t T e x t C o l o r %
1544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1546 % XSetTextColor() sets the graphic context for drawing text on a matte.
1548 % The format of the XSetTextColor function is:
1550 % XSetTextColor(display,window_info,raised)
1552 % A description of each parameter follows:
1554 % o display: Specifies a pointer to the Display structure; returned from
1557 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1559 % o raised: A value other than zero indicates the color show be a
1560 % "highlight" color, otherwise the "shadow" color is set.
1563 static void XSetTextColor(Display *display,const XWindowInfo *window_info,
1564 const MagickStatusType raised)
1570 if (window_info->depth == 1)
1576 (void) XSetForeground(display,window_info->widget_context,
1577 XBlackPixel(display,window_info->screen));
1579 (void) XSetForeground(display,window_info->widget_context,
1580 XWhitePixel(display,window_info->screen));
1583 foreground=(ssize_t) XPixelIntensity(
1584 &window_info->pixel_info->foreground_color);
1585 matte=(ssize_t) XPixelIntensity(&window_info->pixel_info->matte_color);
1586 if (MagickAbsoluteValue((int) (foreground-matte)) > (65535L >> 3))
1587 (void) XSetForeground(display,window_info->widget_context,
1588 window_info->pixel_info->foreground_color.pixel);
1590 (void) XSetForeground(display,window_info->widget_context,
1591 window_info->pixel_info->background_color.pixel);
1595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1599 % X C o l o r B r o w s e r W i d g e t %
1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605 % XColorBrowserWidget() displays a Color Browser widget with a color query
1606 % to the user. The user keys a reply and presses the Action or Cancel button
1607 % to exit. The typed text is returned as the reply function parameter.
1609 % The format of the XColorBrowserWidget method is:
1611 % void XColorBrowserWidget(Display *display,XWindows *windows,
1612 % const char *action,char *reply)
1614 % A description of each parameter follows:
1616 % o display: Specifies a connection to an X server; returned from
1619 % o window: Specifies a pointer to a XWindows structure.
1621 % o action: Specifies a pointer to the action of this widget.
1623 % o reply: the response from the user is returned in this parameter.
1626 MagickPrivate void XColorBrowserWidget(Display *display,XWindows *windows,
1627 const char *action,char *reply)
1629 #define CancelButtonText "Cancel"
1630 #define ColornameText "Name:"
1631 #define ColorPatternText "Pattern:"
1632 #define GrabButtonText "Grab"
1633 #define ResetButtonText "Reset"
1637 primary_selection[MaxTextExtent],
1638 reset_pattern[MaxTextExtent],
1639 text[MaxTextExtent];
1652 glob_pattern[MaxTextExtent] = "*";
1654 static MagickStatusType
1655 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
1703 Get color list and sort in ascending order.
1705 assert(display != (Display *) NULL);
1706 assert(windows != (XWindows *) NULL);
1707 assert(action != (char *) NULL);
1708 assert(reply != (char *) NULL);
1709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
1710 XSetCursorState(display,windows,MagickTrue);
1711 XCheckRefreshWindows(display,windows);
1712 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
1713 exception=AcquireExceptionInfo();
1714 colorlist=GetColorList(glob_pattern,&colors,exception);
1715 if (colorlist == (char **) NULL)
1718 Pattern failed, obtain all the colors.
1720 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
1721 colorlist=GetColorList(glob_pattern,&colors,exception);
1722 if (colorlist == (char **) NULL)
1724 XNoticeWidget(display,windows,"Unable to obtain colors names:",
1726 (void) XDialogWidget(display,windows,action,"Enter color name:",
1732 Determine Color Browser widget attributes.
1734 font_info=windows->widget.font_info;
1736 for (i=0; i < (int) colors; i++)
1737 if (WidgetTextWidth(font_info,colorlist[i]) > text_width)
1738 text_width=WidgetTextWidth(font_info,colorlist[i]);
1739 width=WidgetTextWidth(font_info,(char *) action);
1740 if (WidgetTextWidth(font_info,CancelButtonText) > width)
1741 width=WidgetTextWidth(font_info,CancelButtonText);
1742 if (WidgetTextWidth(font_info,ResetButtonText) > width)
1743 width=WidgetTextWidth(font_info,ResetButtonText);
1744 if (WidgetTextWidth(font_info,GrabButtonText) > width)
1745 width=WidgetTextWidth(font_info,GrabButtonText);
1746 width+=QuantumMargin;
1747 if (WidgetTextWidth(font_info,ColorPatternText) > width)
1748 width=WidgetTextWidth(font_info,ColorPatternText);
1749 if (WidgetTextWidth(font_info,ColornameText) > width)
1750 width=WidgetTextWidth(font_info,ColornameText);
1751 height=(unsigned int) (font_info->ascent+font_info->descent);
1753 Position Color Browser widget.
1755 windows->widget.width=(unsigned int)
1756 (width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin);
1757 windows->widget.min_width=(unsigned int)
1758 (width+MinTextWidth+4*QuantumMargin);
1759 if (windows->widget.width < windows->widget.min_width)
1760 windows->widget.width=windows->widget.min_width;
1761 windows->widget.height=(unsigned int)
1762 ((81*height) >> 2)+((13*QuantumMargin) >> 1)+4;
1763 windows->widget.min_height=(unsigned int)
1764 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
1765 if (windows->widget.height < windows->widget.min_height)
1766 windows->widget.height=windows->widget.min_height;
1767 XConstrainWindowPosition(display,&windows->widget);
1769 Map Color Browser widget.
1771 (void) CopyMagickString(windows->widget.name,"Browse and Select a Color",
1773 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
1774 if (status != False)
1776 XSetWMName(display,windows->widget.id,&window_name);
1777 XSetWMIconName(display,windows->widget.id,&window_name);
1778 (void) XFree((void *) window_name.value);
1780 window_changes.width=(int) windows->widget.width;
1781 window_changes.height=(int) windows->widget.height;
1782 window_changes.x=windows->widget.x;
1783 window_changes.y=windows->widget.y;
1784 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
1785 mask,&window_changes);
1786 (void) XMapRaised(display,windows->widget.id);
1787 windows->widget.mapped=MagickFalse;
1789 Respond to X events.
1791 XGetWidgetInfo((char *) NULL,&slider_info);
1792 XGetWidgetInfo((char *) NULL,&north_info);
1793 XGetWidgetInfo((char *) NULL,&south_info);
1794 XGetWidgetInfo((char *) NULL,&expose_info);
1796 delay=SuspendTime << 2;
1797 state=UpdateConfigurationState;
1800 if (state & UpdateConfigurationState)
1806 Initialize button information.
1808 XGetWidgetInfo(CancelButtonText,&cancel_info);
1809 cancel_info.width=width;
1810 cancel_info.height=(unsigned int) ((3*height) >> 1);
1812 (windows->widget.width-cancel_info.width-QuantumMargin-2);
1814 (windows->widget.height-cancel_info.height-QuantumMargin);
1815 XGetWidgetInfo(action,&action_info);
1816 action_info.width=width;
1817 action_info.height=(unsigned int) ((3*height) >> 1);
1818 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
1819 (action_info.bevel_width << 1));
1820 action_info.y=cancel_info.y;
1821 XGetWidgetInfo(GrabButtonText,&grab_info);
1822 grab_info.width=width;
1823 grab_info.height=(unsigned int) ((3*height) >> 1);
1824 grab_info.x=QuantumMargin;
1825 grab_info.y=((5*QuantumMargin) >> 1)+height;
1826 XGetWidgetInfo(ResetButtonText,&reset_info);
1827 reset_info.width=width;
1828 reset_info.height=(unsigned int) ((3*height) >> 1);
1829 reset_info.x=QuantumMargin;
1830 reset_info.y=grab_info.y+grab_info.height+QuantumMargin;
1832 Initialize reply information.
1834 XGetWidgetInfo(reply,&reply_info);
1835 reply_info.raised=MagickFalse;
1836 reply_info.bevel_width--;
1837 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
1838 reply_info.height=height << 1;
1839 reply_info.x=(int) (width+(QuantumMargin << 1));
1840 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
1842 Initialize mode information.
1844 XGetWidgetInfo((char *) NULL,&mode_info);
1845 mode_info.active=MagickTrue;
1846 mode_info.bevel_width=0;
1847 mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1));
1848 mode_info.height=action_info.height;
1849 mode_info.x=QuantumMargin;
1850 mode_info.y=action_info.y;
1852 Initialize scroll information.
1854 XGetWidgetInfo((char *) NULL,&scroll_info);
1855 scroll_info.bevel_width--;
1856 scroll_info.width=height;
1857 scroll_info.height=(unsigned int) (reply_info.y-grab_info.y-
1858 (QuantumMargin >> 1));
1859 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
1860 scroll_info.y=grab_info.y-reply_info.bevel_width;
1861 scroll_info.raised=MagickFalse;
1862 scroll_info.trough=MagickTrue;
1863 north_info=scroll_info;
1864 north_info.raised=MagickTrue;
1865 north_info.width-=(north_info.bevel_width << 1);
1866 north_info.height=north_info.width-1;
1867 north_info.x+=north_info.bevel_width;
1868 north_info.y+=north_info.bevel_width;
1869 south_info=north_info;
1870 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
1873 slider_info=north_info;
1875 slider_info.width-=2;
1876 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
1877 slider_info.bevel_width+2;
1878 slider_info.height=scroll_info.height-((slider_info.min_y-
1879 scroll_info.y+1) << 1)+4;
1880 visible_colors=scroll_info.height/(height+(height >> 3));
1881 if (colors > visible_colors)
1882 slider_info.height=(unsigned int)
1883 ((visible_colors*slider_info.height)/colors);
1884 slider_info.max_y=south_info.y-south_info.bevel_width-
1885 slider_info.bevel_width-2;
1886 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
1887 slider_info.y=slider_info.min_y;
1888 expose_info=scroll_info;
1889 expose_info.y=slider_info.y;
1891 Initialize list information.
1893 XGetWidgetInfo((char *) NULL,&list_info);
1894 list_info.raised=MagickFalse;
1895 list_info.bevel_width--;
1896 list_info.width=(unsigned int)
1897 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
1898 list_info.height=scroll_info.height;
1899 list_info.x=reply_info.x;
1900 list_info.y=scroll_info.y;
1901 if (windows->widget.mapped == MagickFalse)
1902 state|=JumpListState;
1904 Initialize text information.
1907 XGetWidgetInfo(text,&text_info);
1908 text_info.center=MagickFalse;
1909 text_info.width=reply_info.width;
1910 text_info.height=height;
1911 text_info.x=list_info.x-(QuantumMargin >> 1);
1912 text_info.y=QuantumMargin;
1914 Initialize selection information.
1916 XGetWidgetInfo((char *) NULL,&selection_info);
1917 selection_info.center=MagickFalse;
1918 selection_info.width=list_info.width;
1919 selection_info.height=(unsigned int) ((9*height) >> 3);
1920 selection_info.x=list_info.x;
1921 state&=(~UpdateConfigurationState);
1923 if (state & RedrawWidgetState)
1926 Redraw Color Browser window.
1929 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
1930 (void) XDrawString(display,windows->widget.id,
1931 windows->widget.annotate_context,x,y,ColorPatternText,
1932 Extent(ColorPatternText));
1933 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
1934 XDrawWidgetText(display,&windows->widget,&text_info);
1935 XDrawBeveledButton(display,&windows->widget,&grab_info);
1936 XDrawBeveledButton(display,&windows->widget,&reset_info);
1937 XDrawBeveledMatte(display,&windows->widget,&list_info);
1938 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
1939 XDrawTriangleNorth(display,&windows->widget,&north_info);
1940 XDrawBeveledButton(display,&windows->widget,&slider_info);
1941 XDrawTriangleSouth(display,&windows->widget,&south_info);
1943 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
1944 (void) XDrawString(display,windows->widget.id,
1945 windows->widget.annotate_context,x,y,ColornameText,
1946 Extent(ColornameText));
1947 XDrawBeveledMatte(display,&windows->widget,&reply_info);
1948 XDrawMatteText(display,&windows->widget,&reply_info);
1949 XDrawBeveledButton(display,&windows->widget,&action_info);
1950 XDrawBeveledButton(display,&windows->widget,&cancel_info);
1951 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
1952 selection_info.id=(~0);
1953 state|=RedrawActionState;
1954 state|=RedrawListState;
1955 state&=(~RedrawWidgetState);
1957 if (state & UpdateListState)
1965 status=XParseColor(display,windows->widget.map_info->colormap,
1966 glob_pattern,&color);
1967 if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL))
1970 Reply is a single color name-- exit.
1972 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
1973 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1974 action_info.raised=MagickFalse;
1975 XDrawBeveledButton(display,&windows->widget,&action_info);
1981 checklist=GetColorList(glob_pattern,&number_colors,exception);
1982 if (number_colors == 0)
1984 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1985 (void) XBell(display,0);
1989 for (i=0; i < (int) colors; i++)
1990 colorlist[i]=DestroyString(colorlist[i]);
1991 if (colorlist != (char **) NULL)
1992 colorlist=(char **) RelinquishMagickMemory(colorlist);
1993 colorlist=checklist;
1994 colors=number_colors;
1997 Sort color list in ascending order.
2000 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
2001 if (colors > visible_colors)
2002 slider_info.height=(unsigned int)
2003 ((visible_colors*slider_info.height)/colors);
2004 slider_info.max_y=south_info.y-south_info.bevel_width-
2005 slider_info.bevel_width-2;
2007 slider_info.y=slider_info.min_y;
2008 expose_info.y=slider_info.y;
2009 selection_info.id=(~0);
2011 state|=RedrawListState;
2013 Redraw color name & reply.
2015 *reply_info.text='\0';
2016 reply_info.cursor=reply_info.text;
2017 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
2018 XDrawWidgetText(display,&windows->widget,&text_info);
2019 XDrawMatteText(display,&windows->widget,&reply_info);
2020 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
2021 XDrawTriangleNorth(display,&windows->widget,&north_info);
2022 XDrawBeveledButton(display,&windows->widget,&slider_info);
2023 XDrawTriangleSouth(display,&windows->widget,&south_info);
2024 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
2025 state&=(~UpdateListState);
2027 if (state & JumpListState)
2030 Jump scroll to match user color.
2033 for (i=0; i < (int) colors; i++)
2034 if (LocaleCompare(colorlist[i],reply) >= 0)
2036 list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0;
2039 if ((i < slider_info.id) ||
2040 (i >= (int) (slider_info.id+visible_colors)))
2041 slider_info.id=i-(visible_colors >> 1);
2042 selection_info.id=(~0);
2043 state|=RedrawListState;
2044 state&=(~JumpListState);
2046 if (state & RedrawListState)
2049 Determine slider id and position.
2051 if (slider_info.id >= (int) (colors-visible_colors))
2052 slider_info.id=(int) (colors-visible_colors);
2053 if ((slider_info.id < 0) || (colors <= visible_colors))
2055 slider_info.y=slider_info.min_y;
2057 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
2058 slider_info.min_y+1)/colors);
2059 if (slider_info.id != selection_info.id)
2062 Redraw scroll bar and file names.
2064 selection_info.id=slider_info.id;
2065 selection_info.y=list_info.y+(height >> 3)+2;
2066 for (i=0; i < (int) visible_colors; i++)
2068 selection_info.raised=(slider_info.id+i) != list_info.id ?
2069 MagickTrue : MagickFalse;
2070 selection_info.text=(char *) NULL;
2071 if ((slider_info.id+i) < (int) colors)
2072 selection_info.text=colorlist[slider_info.id+i];
2073 XDrawWidgetText(display,&windows->widget,&selection_info);
2074 selection_info.y+=(int) selection_info.height;
2079 if (slider_info.y > expose_info.y)
2081 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
2082 expose_info.y=slider_info.y-expose_info.height-
2083 slider_info.bevel_width-1;
2087 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
2088 expose_info.y=slider_info.y+slider_info.height+
2089 slider_info.bevel_width+1;
2091 XDrawTriangleNorth(display,&windows->widget,&north_info);
2092 XDrawMatte(display,&windows->widget,&expose_info);
2093 XDrawBeveledButton(display,&windows->widget,&slider_info);
2094 XDrawTriangleSouth(display,&windows->widget,&south_info);
2095 expose_info.y=slider_info.y;
2097 state&=(~RedrawListState);
2099 if (state & RedrawActionState)
2102 colorname[MaxTextExtent];
2105 Display the selected color in a drawing area.
2107 color=windows->widget.pixel_info->matte_color;
2108 (void) XParseColor(display,windows->widget.map_info->colormap,
2109 reply_info.text,&windows->widget.pixel_info->matte_color);
2110 XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL,
2111 (unsigned int) windows->widget.visual_info->colormap_size,
2112 &windows->widget.pixel_info->matte_color);
2113 mode_info.text=colorname;
2114 (void) FormatLocaleString(mode_info.text,MaxTextExtent,"#%02x%02x%02x",
2115 windows->widget.pixel_info->matte_color.red,
2116 windows->widget.pixel_info->matte_color.green,
2117 windows->widget.pixel_info->matte_color.blue);
2118 XDrawBeveledButton(display,&windows->widget,&mode_info);
2119 windows->widget.pixel_info->matte_color=color;
2120 state&=(~RedrawActionState);
2123 Wait for next event.
2125 if (north_info.raised && south_info.raised)
2126 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
2130 Brief delay before advancing scroll bar.
2132 XDelay(display,delay);
2134 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
2135 if (north_info.raised == MagickFalse)
2136 if (slider_info.id > 0)
2142 state|=RedrawListState;
2144 if (south_info.raised == MagickFalse)
2145 if (slider_info.id < (int) colors)
2151 state|=RedrawListState;
2153 if (event.type != ButtonRelease)
2160 if (MatteIsActive(slider_info,event.xbutton))
2165 slider_info.active=MagickTrue;
2168 if (MatteIsActive(north_info,event.xbutton))
2169 if (slider_info.id > 0)
2174 north_info.raised=MagickFalse;
2176 state|=RedrawListState;
2179 if (MatteIsActive(south_info,event.xbutton))
2180 if (slider_info.id < (int) colors)
2185 south_info.raised=MagickFalse;
2187 state|=RedrawListState;
2190 if (MatteIsActive(scroll_info,event.xbutton))
2195 if (event.xbutton.y < slider_info.y)
2196 slider_info.id-=(visible_colors-1);
2198 slider_info.id+=(visible_colors-1);
2199 state|=RedrawListState;
2202 if (MatteIsActive(list_info,event.xbutton))
2208 User pressed list matte.
2210 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
2211 selection_info.height;
2212 if (id >= (int) colors)
2214 (void) CopyMagickString(reply_info.text,colorlist[id],
2216 reply_info.highlight=MagickFalse;
2217 reply_info.marker=reply_info.text;
2218 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2219 XDrawMatteText(display,&windows->widget,&reply_info);
2220 state|=RedrawActionState;
2221 if (id == list_info.id)
2223 (void) CopyMagickString(glob_pattern,reply_info.text,
2225 state|=UpdateListState;
2227 selection_info.id=(~0);
2229 state|=RedrawListState;
2232 if (MatteIsActive(grab_info,event.xbutton))
2235 User pressed Grab button.
2237 grab_info.raised=MagickFalse;
2238 XDrawBeveledButton(display,&windows->widget,&grab_info);
2241 if (MatteIsActive(reset_info,event.xbutton))
2244 User pressed Reset button.
2246 reset_info.raised=MagickFalse;
2247 XDrawBeveledButton(display,&windows->widget,&reset_info);
2250 if (MatteIsActive(mode_info,event.xbutton))
2253 User pressed mode button.
2255 (void) CopyMagickString(reply_info.text,mode_info.text,
2257 (void) CopyMagickString(primary_selection,reply_info.text,
2259 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2260 event.xbutton.time);
2261 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2262 windows->widget.id ? MagickTrue : MagickFalse;
2263 reply_info.marker=reply_info.text;
2264 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2265 XDrawMatteText(display,&windows->widget,&reply_info);
2268 if (MatteIsActive(action_info,event.xbutton))
2271 User pressed action button.
2273 action_info.raised=MagickFalse;
2274 XDrawBeveledButton(display,&windows->widget,&action_info);
2277 if (MatteIsActive(cancel_info,event.xbutton))
2280 User pressed Cancel button.
2282 cancel_info.raised=MagickFalse;
2283 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2286 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2288 if (event.xbutton.button != Button2)
2294 Move text cursor to position of button press.
2296 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
2297 for (i=1; i <= Extent(reply_info.marker); i++)
2298 if (XTextWidth(font_info,reply_info.marker,i) > x)
2300 reply_info.cursor=reply_info.marker+i-1;
2301 if (event.xbutton.time > (click_time+DoubleClick))
2302 reply_info.highlight=MagickFalse;
2306 Become the XA_PRIMARY selection owner.
2308 (void) CopyMagickString(primary_selection,reply_info.text,
2310 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2311 event.xbutton.time);
2312 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2313 windows->widget.id ? MagickTrue : MagickFalse;
2315 XDrawMatteText(display,&windows->widget,&reply_info);
2316 click_time=event.xbutton.time;
2320 Request primary selection.
2322 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2323 windows->widget.id,event.xbutton.time);
2328 if (windows->widget.mapped == MagickFalse)
2330 if (north_info.raised == MagickFalse)
2333 User released up button.
2335 delay=SuspendTime << 2;
2336 north_info.raised=MagickTrue;
2337 XDrawTriangleNorth(display,&windows->widget,&north_info);
2339 if (south_info.raised == MagickFalse)
2342 User released down button.
2344 delay=SuspendTime << 2;
2345 south_info.raised=MagickTrue;
2346 XDrawTriangleSouth(display,&windows->widget,&south_info);
2348 if (slider_info.active)
2351 Stop tracking slider.
2353 slider_info.active=MagickFalse;
2356 if (grab_info.raised == MagickFalse)
2358 if (event.xbutton.window == windows->widget.id)
2359 if (MatteIsActive(grab_info,event.xbutton))
2362 Select a pen color from the X server.
2364 (void) XGetWindowColor(display,windows,reply_info.text,
2366 reply_info.marker=reply_info.text;
2367 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2368 XDrawMatteText(display,&windows->widget,&reply_info);
2369 state|=RedrawActionState;
2371 grab_info.raised=MagickTrue;
2372 XDrawBeveledButton(display,&windows->widget,&grab_info);
2374 if (reset_info.raised == MagickFalse)
2376 if (event.xbutton.window == windows->widget.id)
2377 if (MatteIsActive(reset_info,event.xbutton))
2379 (void) CopyMagickString(glob_pattern,reset_pattern,
2381 state|=UpdateListState;
2383 reset_info.raised=MagickTrue;
2384 XDrawBeveledButton(display,&windows->widget,&reset_info);
2386 if (action_info.raised == MagickFalse)
2388 if (event.xbutton.window == windows->widget.id)
2390 if (MatteIsActive(action_info,event.xbutton))
2392 if (*reply_info.text == '\0')
2393 (void) XBell(display,0);
2398 action_info.raised=MagickTrue;
2399 XDrawBeveledButton(display,&windows->widget,&action_info);
2401 if (cancel_info.raised == MagickFalse)
2403 if (event.xbutton.window == windows->widget.id)
2404 if (MatteIsActive(cancel_info,event.xbutton))
2406 *reply_info.text='\0';
2409 cancel_info.raised=MagickTrue;
2410 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2412 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2419 If client window delete message, exit.
2421 if (event.xclient.message_type != windows->wm_protocols)
2423 if (*event.xclient.data.l == (int) windows->wm_take_focus)
2425 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2426 (Time) event.xclient.data.l[1]);
2429 if (*event.xclient.data.l != (int) windows->wm_delete_window)
2431 if (event.xclient.window == windows->widget.id)
2433 *reply_info.text='\0';
2439 case ConfigureNotify:
2442 Update widget configuration.
2444 if (event.xconfigure.window != windows->widget.id)
2446 if ((event.xconfigure.width == (int) windows->widget.width) &&
2447 (event.xconfigure.height == (int) windows->widget.height))
2449 windows->widget.width=(unsigned int)
2450 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
2451 windows->widget.height=(unsigned int)
2452 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
2453 state|=UpdateConfigurationState;
2458 if (event.xcrossing.window != windows->widget.id)
2460 state&=(~InactiveWidgetState);
2465 if (event.xexpose.window != windows->widget.id)
2467 if (event.xexpose.count != 0)
2469 state|=RedrawWidgetState;
2475 command[MaxTextExtent];
2484 Respond to a user key press.
2486 if (event.xkey.window != windows->widget.id)
2488 length=XLookupString((XKeyEvent *) &event.xkey,command,
2489 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2490 *(command+length)='\0';
2491 if (AreaIsActive(scroll_info,event.xkey))
2496 switch ((int) key_symbol)
2519 slider_info.id-=visible_colors;
2525 slider_info.id+=visible_colors;
2531 slider_info.id=(int) colors;
2535 state|=RedrawListState;
2538 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
2541 Read new color or glob patterm.
2543 if (*reply_info.text == '\0')
2545 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
2546 state|=UpdateListState;
2549 if (key_symbol == XK_Control_L)
2551 state|=ControlState;
2554 if (state & ControlState)
2555 switch ((int) key_symbol)
2561 Erase the entire line of text.
2563 *reply_info.text='\0';
2564 reply_info.cursor=reply_info.text;
2565 reply_info.marker=reply_info.text;
2566 reply_info.highlight=MagickFalse;
2572 XEditText(display,&reply_info,key_symbol,command,state);
2573 XDrawMatteText(display,&windows->widget,&reply_info);
2574 state|=JumpListState;
2575 status=XParseColor(display,windows->widget.map_info->colormap,
2576 reply_info.text,&color);
2577 if (status != False)
2578 state|=RedrawActionState;
2584 command[MaxTextExtent];
2590 Respond to a user key release.
2592 if (event.xkey.window != windows->widget.id)
2594 (void) XLookupString((XKeyEvent *) &event.xkey,command,
2595 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2596 if (key_symbol == XK_Control_L)
2597 state&=(~ControlState);
2602 if (event.xcrossing.window != windows->widget.id)
2604 state|=InactiveWidgetState;
2616 Discard pending button motion events.
2618 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
2619 if (slider_info.active)
2624 slider_info.y=event.xmotion.y-
2625 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
2626 if (slider_info.y < slider_info.min_y)
2627 slider_info.y=slider_info.min_y;
2628 if (slider_info.y > slider_info.max_y)
2629 slider_info.y=slider_info.max_y;
2631 if (slider_info.y != slider_info.min_y)
2632 slider_info.id=(int) ((colors*(slider_info.y-
2633 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
2634 state|=RedrawListState;
2637 if (state & InactiveWidgetState)
2639 if (grab_info.raised == MatteIsActive(grab_info,event.xmotion))
2642 Grab button status changed.
2644 grab_info.raised=!grab_info.raised;
2645 XDrawBeveledButton(display,&windows->widget,&grab_info);
2648 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
2651 Reset button status changed.
2653 reset_info.raised=!reset_info.raised;
2654 XDrawBeveledButton(display,&windows->widget,&reset_info);
2657 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
2660 Action button status changed.
2662 action_info.raised=action_info.raised == MagickFalse ?
2663 MagickTrue : MagickFalse;
2664 XDrawBeveledButton(display,&windows->widget,&action_info);
2667 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
2670 Cancel button status changed.
2672 cancel_info.raised=cancel_info.raised == MagickFalse ?
2673 MagickTrue : MagickFalse;
2674 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2679 case SelectionClear:
2681 reply_info.highlight=MagickFalse;
2682 XDrawMatteText(display,&windows->widget,&reply_info);
2685 case SelectionNotify:
2701 Obtain response from primary selection.
2703 if (event.xselection.property == (Atom) None)
2705 status=XGetWindowProperty(display,event.xselection.requestor,
2706 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
2707 &format,&length,&after,&data);
2708 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2711 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
2712 (void) XBell(display,0);
2716 Insert primary selection in reply text.
2718 *(data+length)='\0';
2719 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
2721 XDrawMatteText(display,&windows->widget,&reply_info);
2722 state|=JumpListState;
2723 state|=RedrawActionState;
2725 (void) XFree((void *) data);
2728 case SelectionRequest:
2733 XSelectionRequestEvent
2736 if (reply_info.highlight == MagickFalse)
2739 Set primary selection.
2741 request=(&(event.xselectionrequest));
2742 (void) XChangeProperty(request->display,request->requestor,
2743 request->property,request->target,8,PropModeReplace,
2744 (unsigned char *) primary_selection,Extent(primary_selection));
2745 notify.type=SelectionNotify;
2746 notify.send_event=MagickTrue;
2747 notify.display=request->display;
2748 notify.requestor=request->requestor;
2749 notify.selection=request->selection;
2750 notify.target=request->target;
2751 notify.time=request->time;
2752 if (request->property == None)
2753 notify.property=request->target;
2755 notify.property=request->property;
2756 (void) XSendEvent(request->display,request->requestor,False,
2757 NoEventMask,(XEvent *) ¬ify);
2762 } while ((state & ExitState) == 0);
2763 XSetCursorState(display,windows,MagickFalse);
2764 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
2765 XCheckRefreshWindows(display,windows);
2769 for (i=0; i < (int) colors; i++)
2770 colorlist[i]=DestroyString(colorlist[i]);
2771 if (colorlist != (char **) NULL)
2772 colorlist=(char **) RelinquishMagickMemory(colorlist);
2773 exception=DestroyExceptionInfo(exception);
2774 if ((*reply == '\0') || (strchr(reply,'-') != (char *) NULL))
2776 status=XParseColor(display,windows->widget.map_info->colormap,reply,&color);
2777 if (status != False)
2779 XNoticeWidget(display,windows,"Color is unknown to X server:",reply);
2780 (void) CopyMagickString(reply,"gray",MaxTextExtent);
2784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2788 % X C o m m a n d W i d g e t %
2792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2794 % XCommandWidget() maps a menu and returns the command pointed to by the user
2795 % when the button is released.
2797 % The format of the XCommandWidget method is:
2799 % int XCommandWidget(Display *display,XWindows *windows,
2800 % const char **selections,XEvent *event)
2802 % A description of each parameter follows:
2804 % o selection_number: Specifies the number of the selection that the
2807 % o display: Specifies a connection to an X server; returned from
2810 % o window: Specifies a pointer to a XWindows structure.
2812 % o selections: Specifies a pointer to one or more strings that comprise
2813 % the choices in the menu.
2815 % o event: Specifies a pointer to a X11 XEvent structure.
2818 MagickPrivate int XCommandWidget(Display *display,XWindows *windows,
2819 const char **selections,XEvent *event)
2821 #define tile_width 112
2822 #define tile_height 70
2824 static const unsigned char
2827 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2828 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2829 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
2831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
2833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2834 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2835 0x00, 0x00, 0x1e, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2836 0x00, 0x00, 0x00, 0x00, 0x1e, 0xbc, 0x9f, 0x03, 0x00, 0x3e, 0x00, 0xc0,
2837 0x1f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x0f, 0x80, 0x3f,
2838 0x00, 0xf0, 0x1f, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x1f,
2839 0xe0, 0x3f, 0x00, 0xfc, 0x1f, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc,
2840 0xff, 0x1f, 0xf0, 0x3f, 0x00, 0xfe, 0x1f, 0xf8, 0x0f, 0x00, 0x00, 0x00,
2841 0x1e, 0xfc, 0xfc, 0x3f, 0xf8, 0x3f, 0x00, 0xff, 0x1e, 0xfc, 0x0f, 0x00,
2842 0x00, 0x00, 0x1e, 0x7c, 0xfc, 0x3e, 0xf8, 0x3c, 0x80, 0x1f, 0x1e, 0x7c,
2843 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 0xc0, 0x0f,
2844 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c,
2845 0xc0, 0x07, 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c,
2846 0x7c, 0x7c, 0xc0, 0x0f, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78,
2847 0x78, 0x3c, 0xfc, 0x7c, 0x80, 0x7f, 0x1e, 0x7c, 0x00, 0x00, 0x00, 0x00,
2848 0x1e, 0xf8, 0x78, 0x7c, 0xf8, 0xff, 0x00, 0xff, 0x1f, 0xf8, 0xff, 0x00,
2849 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xfe, 0x1f, 0xf8,
2850 0xff, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xf8,
2851 0x1f, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xc0, 0xef,
2852 0x07, 0xe0, 0x1f, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0x70, 0x40, 0x78,
2853 0x00, 0xc7, 0x07, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00,
2854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
2855 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
2857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
2858 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2859 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2860 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2861 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
2862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00,
2863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
2864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
2865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2866 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00,
2867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
2868 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2869 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2870 0x60, 0x00, 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2871 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2872 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00,
2873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0x9f, 0x7f, 0x00,
2874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0xdf,
2875 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00,
2876 0xe0, 0xdf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0c,
2877 0x78, 0x30, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
2878 0x00, 0x0f, 0xf8, 0x70, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x1f, 0x00, 0xe0,
2879 0x0f, 0x1e, 0x80, 0x0f, 0xf8, 0x78, 0xf0, 0xfd, 0xf9, 0x00, 0xc0, 0x1f,
2880 0x00, 0xf8, 0x0f, 0x00, 0xe0, 0x1f, 0xf8, 0x7c, 0xf0, 0xfc, 0xf9, 0x00,
2881 0xf0, 0x1f, 0x00, 0xfe, 0x0f, 0x00, 0xf0, 0x07, 0xf8, 0x3e, 0xf8, 0xfc,
2882 0xf0, 0x01, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x1e, 0xf0, 0x03, 0xf8, 0x3f,
2883 0xf8, 0xf8, 0xf0, 0x01, 0xfc, 0x1f, 0x80, 0x7f, 0x0f, 0x1e, 0xf8, 0x00,
2884 0xf8, 0x1f, 0x78, 0x18, 0xf0, 0x01, 0x7c, 0x1e, 0xc0, 0x0f, 0x0f, 0x1e,
2885 0x7c, 0x00, 0xf0, 0x0f, 0x78, 0x00, 0xf0, 0x01, 0x3e, 0x1e, 0xe0, 0x07,
2886 0x0f, 0x1e, 0x7c, 0x00, 0xf0, 0x07, 0x7c, 0x00, 0xe0, 0x01, 0x3e, 0x1e,
2887 0xe0, 0x03, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x0f, 0x7c, 0x00, 0xe0, 0x03,
2888 0x3e, 0x3e, 0xe0, 0x07, 0x0f, 0x1e, 0x1e, 0x00, 0xf0, 0x1f, 0x3c, 0x00,
2889 0xe0, 0x03, 0x7e, 0x3e, 0xc0, 0x3f, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x1f,
2890 0x3e, 0x00, 0xe0, 0x03, 0xfc, 0x7f, 0x80, 0xff, 0x0f, 0x1e, 0xfc, 0x00,
2891 0xf0, 0x3e, 0x3e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xff, 0x0f, 0x1e,
2892 0xfc, 0x07, 0xf0, 0x7c, 0x1e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xfc,
2893 0x0f, 0x1e, 0xf8, 0x1f, 0xf0, 0xf8, 0x1e, 0x00, 0xc0, 0x03, 0xe0, 0xf7,
2894 0x03, 0xf0, 0x0f, 0x1e, 0xe0, 0x3f, 0xf0, 0x78, 0x1c, 0x00, 0x80, 0x03,
2895 0x80, 0xe3, 0x03, 0x00, 0x0f, 0x1e, 0xc0, 0x3f, 0xf0, 0x30, 0x00, 0x00,
2896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x3e, 0x00, 0x00,
2897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x10,
2898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00,
2899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
2900 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2901 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2902 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2903 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
2905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
2906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
2907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2908 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2931 assert(display != (Display *) NULL);
2932 assert(windows != (XWindows *) NULL);
2933 font_info=windows->command.font_info;
2934 height=(unsigned int) (font_info->ascent+font_info->descent);
2937 if (event == (XEvent *) NULL)
2949 Determine command window attributes.
2951 assert(selections != (const char **) NULL);
2952 windows->command.width=0;
2953 for (i=0; selections[i] != (char *) NULL; i++)
2955 width=WidgetTextWidth(font_info,(char *) selections[i]);
2956 if (width > windows->command.width)
2957 windows->command.width=width;
2959 number_selections=(unsigned int) i;
2960 windows->command.width+=3*QuantumMargin+10;
2961 if ((int) windows->command.width < (tile_width+QuantumMargin+10))
2962 windows->command.width=(unsigned int) (tile_width+QuantumMargin+10);
2963 windows->command.height=(unsigned int) (number_selections*
2964 (((3*height) >> 1)+10)+tile_height+20);
2965 windows->command.min_width=windows->command.width;
2966 windows->command.min_height=windows->command.height;
2967 XConstrainWindowPosition(display,&windows->command);
2968 if (windows->command.id != (Window) NULL)
2974 Reconfigure command window.
2976 status=XStringListToTextProperty(&windows->command.name,1,
2978 if (status != False)
2980 XSetWMName(display,windows->command.id,&window_name);
2981 XSetWMIconName(display,windows->command.id,&window_name);
2982 (void) XFree((void *) window_name.value);
2984 window_changes.width=(int) windows->command.width;
2985 window_changes.height=(int) windows->command.height;
2986 (void) XReconfigureWMWindow(display,windows->command.id,
2987 windows->command.screen,(unsigned int) (CWWidth | CWHeight),
2991 Allocate selection info memory.
2993 if (selection_info != (XWidgetInfo *) NULL)
2994 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
2995 selection_info=(XWidgetInfo *) AcquireQuantumMemory(number_selections,
2996 sizeof(*selection_info));
2997 if (selection_info == (XWidgetInfo *) NULL)
2999 ThrowXWindowFatalException(ResourceLimitError,
3000 "MemoryAllocationFailed","...");
3003 state|=UpdateConfigurationState | RedrawWidgetState;
3006 Wait for next event.
3008 if (event != (XEvent *) NULL)
3009 switch (event->type)
3013 for (i=0; i < (int) number_selections; i++)
3015 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3017 if (i >= (int) windows->command.data)
3019 selection_info[i].raised=MagickFalse;
3020 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3023 submenu_info=selection_info[i];
3024 submenu_info.active=MagickTrue;
3026 submenu_info.y+(submenu_info.height >> 1)-(toggle_info.height >> 1);
3028 (void) XCheckWindowEvent(display,windows->widget.id,LeaveWindowMask,
3036 for (i=0; i < (int) number_selections; i++)
3038 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3041 if (id >= (int) windows->command.data)
3043 selection_info[id].raised=MagickTrue;
3044 XDrawBeveledButton(display,&windows->command,&selection_info[id]);
3054 If client window delete message, withdraw command widget.
3056 if (event->xclient.message_type != windows->wm_protocols)
3058 if (*event->xclient.data.l != (int) windows->wm_delete_window)
3060 (void) XWithdrawWindow(display,windows->command.id,
3061 windows->command.screen);
3064 case ConfigureNotify:
3067 Update widget configuration.
3069 if (event->xconfigure.window != windows->command.id)
3071 if (event->xconfigure.send_event != 0)
3073 windows->command.x=event->xconfigure.x;
3074 windows->command.y=event->xconfigure.y;
3076 if ((event->xconfigure.width == (int) windows->command.width) &&
3077 (event->xconfigure.height == (int) windows->command.height))
3079 windows->command.width=(unsigned int)
3080 MagickMax(event->xconfigure.width,(int) windows->command.min_width);
3081 windows->command.height=(unsigned int)
3082 MagickMax(event->xconfigure.height,(int) windows->command.min_height);
3083 state|=UpdateConfigurationState;
3088 if (event->xexpose.window != windows->command.id)
3090 if (event->xexpose.count != 0)
3092 state|=RedrawWidgetState;
3098 Return the ID of the highlighted menu entry.
3102 for (i=0; i < (int) number_selections; i++)
3104 if (i >= (int) windows->command.data)
3106 if (selection_info[i].raised ==
3107 MatteIsActive(selection_info[i],event->xmotion))
3110 Button status changed.
3112 selection_info[i].raised=!selection_info[i].raised;
3113 XDrawBeveledButton(display,&windows->command,
3114 &selection_info[i]);
3118 if (MatteIsActive(selection_info[i],event->xmotion) == MagickFalse)
3120 submenu_info=selection_info[i];
3121 submenu_info.active=MagickTrue;
3122 toggle_info.raised=MagickTrue;
3123 toggle_info.y=submenu_info.y+(submenu_info.height >> 1)-
3124 (toggle_info.height >> 1);
3125 XDrawTriangleEast(display,&windows->command,&toggle_info);
3128 XDelay(display,SuspendTime);
3129 if (XCheckMaskEvent(display,ButtonMotionMask,event) == MagickFalse)
3131 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
3132 toggle_info.raised=MagickFalse;
3133 if (windows->command.data != 0)
3134 XDrawTriangleEast(display,&windows->command,&toggle_info);
3140 windows->command.mapped=MagickTrue;
3145 windows->command.mapped=MagickFalse;
3151 if (state & UpdateConfigurationState)
3154 Initialize button information.
3156 assert(selections != (const char **) NULL);
3158 for (i=0; i < (int) number_selections; i++)
3160 XGetWidgetInfo(selections[i],&selection_info[i]);
3161 selection_info[i].center=MagickFalse;
3162 selection_info[i].bevel_width--;
3163 selection_info[i].height=(unsigned int) ((3*height) >> 1);
3164 selection_info[i].x=(QuantumMargin >> 1)+4;
3165 selection_info[i].width=(unsigned int)
3166 (windows->command.width-(selection_info[i].x << 1));
3167 selection_info[i].y=y;
3168 y+=selection_info[i].height+(selection_info[i].bevel_width << 1)+6;
3170 XGetWidgetInfo((char *) NULL,&toggle_info);
3171 toggle_info.bevel_width--;
3172 toggle_info.width=(unsigned int)
3173 (((5*height) >> 3)-(toggle_info.bevel_width << 1));
3174 toggle_info.height=toggle_info.width;
3175 toggle_info.x=selection_info[0].x+selection_info[0].width-
3176 toggle_info.width-(QuantumMargin >> 1);
3177 if (windows->command.mapped)
3178 (void) XClearWindow(display,windows->command.id);
3180 if (state & RedrawWidgetState)
3186 Draw command buttons.
3188 tile_pixmap=XCreatePixmapFromBitmapData(display,windows->command.id,
3189 (char *) tile_bits,tile_width,tile_height,1L,0L,1);
3190 if (tile_pixmap != (Pixmap) NULL)
3192 (void) XCopyPlane(display,tile_pixmap,windows->command.id,
3193 windows->command.annotate_context,0,0,tile_width,tile_height,
3194 (int) ((windows->command.width-tile_width) >> 1),10,1L);
3195 (void) XFreePixmap(display,tile_pixmap);
3197 for (i=0; i < (int) number_selections; i++)
3199 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3200 if (i >= (int) windows->command.data)
3202 toggle_info.raised=i == id ? MagickTrue : MagickFalse;
3203 toggle_info.y=selection_info[i].y+
3204 (selection_info[i].height >> 1)-(toggle_info.height >> 1);
3205 XDrawTriangleEast(display,&windows->command,&toggle_info);
3207 XHighlightWidget(display,&windows->command,BorderOffset,BorderOffset);
3213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3217 % X C o n f i r m W i d g e t %
3221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3223 % XConfirmWidget() displays a Confirm widget with a notice to the user. The
3224 % function returns -1 if Dismiss is pressed, 0 for Cancel, and 1 for Yes.
3226 % The format of the XConfirmWidget method is:
3228 % int XConfirmWidget(Display *display,XWindows *windows,
3229 % const char *reason,const char *description)
3231 % A description of each parameter follows:
3233 % o display: Specifies a connection to an X server; returned from
3236 % o window: Specifies a pointer to a XWindows structure.
3238 % o reason: Specifies the message to display before terminating the
3241 % o description: Specifies any description to the message.
3244 MagickPrivate int XConfirmWidget(Display *display,XWindows *windows,
3245 const char *reason,const char *description)
3247 #define CancelButtonText "Cancel"
3248 #define DismissButtonText "Dismiss"
3249 #define YesButtonText "Yes"
3284 Determine Confirm widget attributes.
3286 assert(display != (Display *) NULL);
3287 assert(windows != (XWindows *) NULL);
3288 assert(reason != (char *) NULL);
3289 assert(description != (char *) NULL);
3290 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
3291 XCheckRefreshWindows(display,windows);
3292 font_info=windows->widget.font_info;
3293 width=WidgetTextWidth(font_info,CancelButtonText);
3294 if (WidgetTextWidth(font_info,DismissButtonText) > width)
3295 width=WidgetTextWidth(font_info,DismissButtonText);
3296 if (WidgetTextWidth(font_info,YesButtonText) > width)
3297 width=WidgetTextWidth(font_info,YesButtonText);
3299 if (description != (char *) NULL)
3300 if (WidgetTextWidth(font_info,(char *) description) > width)
3301 width=WidgetTextWidth(font_info,(char *) description);
3302 height=(unsigned int) (font_info->ascent+font_info->descent);
3304 Position Confirm widget.
3306 windows->widget.width=(unsigned int) (width+9*QuantumMargin);
3307 windows->widget.min_width=(unsigned int) (9*QuantumMargin+
3308 WidgetTextWidth(font_info,CancelButtonText)+
3309 WidgetTextWidth(font_info,DismissButtonText)+
3310 WidgetTextWidth(font_info,YesButtonText));
3311 if (windows->widget.width < windows->widget.min_width)
3312 windows->widget.width=windows->widget.min_width;
3313 windows->widget.height=(unsigned int) (12*height);
3314 windows->widget.min_height=(unsigned int) (7*height);
3315 if (windows->widget.height < windows->widget.min_height)
3316 windows->widget.height=windows->widget.min_height;
3317 XConstrainWindowPosition(display,&windows->widget);
3321 (void) CopyMagickString(windows->widget.name,"Confirm",MaxTextExtent);
3322 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3323 if (status != False)
3325 XSetWMName(display,windows->widget.id,&window_name);
3326 XSetWMIconName(display,windows->widget.id,&window_name);
3327 (void) XFree((void *) window_name.value);
3329 window_changes.width=(int) windows->widget.width;
3330 window_changes.height=(int) windows->widget.height;
3331 window_changes.x=windows->widget.x;
3332 window_changes.y=windows->widget.y;
3333 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3334 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3335 (void) XMapRaised(display,windows->widget.id);
3336 windows->widget.mapped=MagickFalse;
3338 Respond to X events.
3341 state=UpdateConfigurationState;
3342 XSetCursorState(display,windows,MagickTrue);
3345 if (state & UpdateConfigurationState)
3348 Initialize button information.
3350 XGetWidgetInfo(CancelButtonText,&cancel_info);
3351 cancel_info.width=(unsigned int) QuantumMargin+
3352 WidgetTextWidth(font_info,CancelButtonText);
3353 cancel_info.height=(unsigned int) ((3*height) >> 1);
3354 cancel_info.x=(int) (windows->widget.width-cancel_info.width-
3356 cancel_info.y=(int) (windows->widget.height-(cancel_info.height << 1));
3357 dismiss_info=cancel_info;
3358 dismiss_info.text=(char *) DismissButtonText;
3359 if (LocaleCompare(description,"Do you want to save it") == 0)
3360 dismiss_info.text=(char *) "Don't Save";
3361 dismiss_info.width=(unsigned int) QuantumMargin+
3362 WidgetTextWidth(font_info,dismiss_info.text);
3363 dismiss_info.x=(int)
3364 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
3365 yes_info=cancel_info;
3366 yes_info.text=(char *) YesButtonText;
3367 if (LocaleCompare(description,"Do you want to save it") == 0)
3368 yes_info.text=(char *) "Save";
3369 yes_info.width=(unsigned int) QuantumMargin+
3370 WidgetTextWidth(font_info,yes_info.text);
3371 if (yes_info.width < cancel_info.width)
3372 yes_info.width=cancel_info.width;
3373 yes_info.x=QuantumMargin;
3374 state&=(~UpdateConfigurationState);
3376 if (state & RedrawWidgetState)
3379 Redraw Confirm widget.
3381 width=WidgetTextWidth(font_info,(char *) reason);
3382 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3383 y=(int) ((windows->widget.height >> 1)-(height << 1));
3384 (void) XDrawString(display,windows->widget.id,
3385 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
3386 if (description != (char *) NULL)
3389 question[MaxTextExtent];
3391 (void) CopyMagickString(question,description,MaxTextExtent);
3392 (void) ConcatenateMagickString(question,"?",MaxTextExtent);
3393 width=WidgetTextWidth(font_info,question);
3394 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3396 (void) XDrawString(display,windows->widget.id,
3397 windows->widget.annotate_context,x,y,question,Extent(question));
3399 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3400 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3401 XDrawBeveledButton(display,&windows->widget,&yes_info);
3402 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3403 state&=(~RedrawWidgetState);
3406 Wait for next event.
3408 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3413 if (MatteIsActive(cancel_info,event.xbutton))
3416 User pressed No button.
3418 cancel_info.raised=MagickFalse;
3419 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3422 if (MatteIsActive(dismiss_info,event.xbutton))
3425 User pressed Dismiss button.
3427 dismiss_info.raised=MagickFalse;
3428 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3431 if (MatteIsActive(yes_info,event.xbutton))
3434 User pressed Yes button.
3436 yes_info.raised=MagickFalse;
3437 XDrawBeveledButton(display,&windows->widget,&yes_info);
3444 if (windows->widget.mapped == MagickFalse)
3446 if (cancel_info.raised == MagickFalse)
3448 if (event.xbutton.window == windows->widget.id)
3449 if (MatteIsActive(cancel_info,event.xbutton))
3454 cancel_info.raised=MagickTrue;
3455 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3457 if (dismiss_info.raised == MagickFalse)
3459 if (event.xbutton.window == windows->widget.id)
3460 if (MatteIsActive(dismiss_info,event.xbutton))
3465 dismiss_info.raised=MagickTrue;
3466 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3468 if (yes_info.raised == MagickFalse)
3470 if (event.xbutton.window == windows->widget.id)
3471 if (MatteIsActive(yes_info,event.xbutton))
3476 yes_info.raised=MagickTrue;
3477 XDrawBeveledButton(display,&windows->widget,&yes_info);
3484 If client window delete message, exit.
3486 if (event.xclient.message_type != windows->wm_protocols)
3488 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3490 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3491 (Time) event.xclient.data.l[1]);
3494 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3496 if (event.xclient.window == windows->widget.id)
3503 case ConfigureNotify:
3506 Update widget configuration.
3508 if (event.xconfigure.window != windows->widget.id)
3510 if ((event.xconfigure.width == (int) windows->widget.width) &&
3511 (event.xconfigure.height == (int) windows->widget.height))
3513 windows->widget.width=(unsigned int)
3514 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3515 windows->widget.height=(unsigned int)
3516 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3517 state|=UpdateConfigurationState;
3522 if (event.xcrossing.window != windows->widget.id)
3524 state&=(~InactiveWidgetState);
3529 if (event.xexpose.window != windows->widget.id)
3531 if (event.xexpose.count != 0)
3533 state|=RedrawWidgetState;
3539 command[MaxTextExtent];
3545 Respond to a user key press.
3547 if (event.xkey.window != windows->widget.id)
3549 (void) XLookupString((XKeyEvent *) &event.xkey,command,
3550 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3551 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
3553 yes_info.raised=MagickFalse;
3554 XDrawBeveledButton(display,&windows->widget,&yes_info);
3563 if (event.xcrossing.window != windows->widget.id)
3565 state|=InactiveWidgetState;
3571 Discard pending button motion events.
3573 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
3574 if (state & InactiveWidgetState)
3576 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
3579 Cancel button status changed.
3581 cancel_info.raised=cancel_info.raised == MagickFalse ?
3582 MagickTrue : MagickFalse;
3583 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3586 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
3589 Dismiss button status changed.
3591 dismiss_info.raised=cancel_info.raised == MagickFalse ?
3592 MagickTrue : MagickFalse;
3593 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3596 if (yes_info.raised == MatteIsActive(yes_info,event.xmotion))
3599 Yes button status changed.
3601 yes_info.raised=yes_info.raised == MagickFalse ?
3602 MagickTrue : MagickFalse;
3603 XDrawBeveledButton(display,&windows->widget,&yes_info);
3611 } while ((state & ExitState) == 0);
3612 XSetCursorState(display,windows,MagickFalse);
3613 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
3614 XCheckRefreshWindows(display,windows);
3619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3623 % X D i a l o g W i d g e t %
3627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3629 % XDialogWidget() displays a Dialog widget with a query to the user. The user
3630 % keys a reply and presses the Ok or Cancel button to exit. The typed text is
3631 % returned as the reply function parameter.
3633 % The format of the XDialogWidget method is:
3635 % int XDialogWidget(Display *display,XWindows *windows,const char *action,
3636 % const char *query,char *reply)
3638 % A description of each parameter follows:
3640 % o display: Specifies a connection to an X server; returned from
3643 % o window: Specifies a pointer to a XWindows structure.
3645 % o action: Specifies a pointer to the action of this widget.
3647 % o query: Specifies a pointer to the query to present to the user.
3649 % o reply: the response from the user is returned in this parameter.
3652 MagickPrivate int XDialogWidget(Display *display,XWindows *windows,
3653 const char *action,const char *query,char *reply)
3655 #define CancelButtonText "Cancel"
3658 primary_selection[MaxTextExtent];
3666 static MagickBooleanType
3667 raised = MagickFalse;
3700 Determine Dialog widget attributes.
3702 assert(display != (Display *) NULL);
3703 assert(windows != (XWindows *) NULL);
3704 assert(action != (char *) NULL);
3705 assert(query != (char *) NULL);
3706 assert(reply != (char *) NULL);
3707 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
3708 XCheckRefreshWindows(display,windows);
3709 font_info=windows->widget.font_info;
3710 width=WidgetTextWidth(font_info,(char *) action);
3711 if (WidgetTextWidth(font_info,CancelButtonText) > width)
3712 width=WidgetTextWidth(font_info,CancelButtonText);
3713 width+=(3*QuantumMargin) >> 1;
3714 height=(unsigned int) (font_info->ascent+font_info->descent);
3716 Position Dialog widget.
3718 windows->widget.width=(unsigned int) MagickMax((int) (2*width),(int)
3719 WidgetTextWidth(font_info,(char *) query));
3720 if (windows->widget.width < WidgetTextWidth(font_info,reply))
3721 windows->widget.width=WidgetTextWidth(font_info,reply);
3722 windows->widget.width+=6*QuantumMargin;
3723 windows->widget.min_width=(unsigned int)
3724 (width+28*XTextWidth(font_info,"#",1)+4*QuantumMargin);
3725 if (windows->widget.width < windows->widget.min_width)
3726 windows->widget.width=windows->widget.min_width;
3727 windows->widget.height=(unsigned int) (7*height+(QuantumMargin << 1));
3728 windows->widget.min_height=windows->widget.height;
3729 if (windows->widget.height < windows->widget.min_height)
3730 windows->widget.height=windows->widget.min_height;
3731 XConstrainWindowPosition(display,&windows->widget);
3735 (void) CopyMagickString(windows->widget.name,"Dialog",MaxTextExtent);
3736 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3737 if (status != False)
3739 XSetWMName(display,windows->widget.id,&window_name);
3740 XSetWMIconName(display,windows->widget.id,&window_name);
3741 (void) XFree((void *) window_name.value);
3743 window_changes.width=(int) windows->widget.width;
3744 window_changes.height=(int) windows->widget.height;
3745 window_changes.x=windows->widget.x;
3746 window_changes.y=windows->widget.y;
3747 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3748 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3749 (void) XMapRaised(display,windows->widget.id);
3750 windows->widget.mapped=MagickFalse;
3752 Respond to X events.
3754 anomaly=(LocaleCompare(action,"Background") == 0) ||
3755 (LocaleCompare(action,"New") == 0) ||
3756 (LocaleCompare(action,"Quantize") == 0) ||
3757 (LocaleCompare(action,"Resize") == 0) ||
3758 (LocaleCompare(action,"Save") == 0) ||
3759 (LocaleCompare(action,"Shade") == 0);
3760 state=UpdateConfigurationState;
3761 XSetCursorState(display,windows,MagickTrue);
3764 if (state & UpdateConfigurationState)
3767 Initialize button information.
3769 XGetWidgetInfo(CancelButtonText,&cancel_info);
3770 cancel_info.width=width;
3771 cancel_info.height=(unsigned int) ((3*height) >> 1);
3773 (windows->widget.width-cancel_info.width-((3*QuantumMargin) >> 1));
3775 (windows->widget.height-cancel_info.height-((3*QuantumMargin) >> 1));
3776 XGetWidgetInfo(action,&action_info);
3777 action_info.width=width;
3778 action_info.height=(unsigned int) ((3*height) >> 1);
3779 action_info.x=cancel_info.x-(cancel_info.width+QuantumMargin+
3780 (action_info.bevel_width << 1));
3781 action_info.y=cancel_info.y;
3783 Initialize reply information.
3785 XGetWidgetInfo(reply,&reply_info);
3786 reply_info.raised=MagickFalse;
3787 reply_info.bevel_width--;
3788 reply_info.width=windows->widget.width-(3*QuantumMargin);
3789 reply_info.height=height << 1;
3790 reply_info.x=(3*QuantumMargin) >> 1;
3791 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
3793 Initialize option information.
3795 XGetWidgetInfo("Dither",&special_info);
3796 special_info.raised=raised;
3797 special_info.bevel_width--;
3798 special_info.width=(unsigned int) QuantumMargin >> 1;
3799 special_info.height=(unsigned int) QuantumMargin >> 1;
3800 special_info.x=reply_info.x;
3801 special_info.y=action_info.y+action_info.height-special_info.height;
3802 if (LocaleCompare(action,"Background") == 0)
3803 special_info.text=(char *) "Backdrop";
3804 if (LocaleCompare(action,"New") == 0)
3805 special_info.text=(char *) "Gradation";
3806 if (LocaleCompare(action,"Resize") == 0)
3807 special_info.text=(char *) "Constrain ratio";
3808 if (LocaleCompare(action,"Save") == 0)
3809 special_info.text=(char *) "Non-progressive";
3810 if (LocaleCompare(action,"Shade") == 0)
3811 special_info.text=(char *) "Color shading";
3813 Initialize text information.
3815 XGetWidgetInfo(query,&text_info);
3816 text_info.width=reply_info.width;
3817 text_info.height=height;
3818 text_info.x=reply_info.x-(QuantumMargin >> 1);
3819 text_info.y=QuantumMargin;
3820 text_info.center=MagickFalse;
3821 state&=(~UpdateConfigurationState);
3823 if (state & RedrawWidgetState)
3826 Redraw Dialog widget.
3828 XDrawWidgetText(display,&windows->widget,&text_info);
3829 XDrawBeveledMatte(display,&windows->widget,&reply_info);
3830 XDrawMatteText(display,&windows->widget,&reply_info);
3832 XDrawBeveledButton(display,&windows->widget,&special_info);
3833 XDrawBeveledButton(display,&windows->widget,&action_info);
3834 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3835 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3836 state&=(~RedrawWidgetState);
3839 Wait for next event.
3841 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3847 if (MatteIsActive(special_info,event.xbutton))
3850 Option button status changed.
3852 special_info.raised=!special_info.raised;
3853 XDrawBeveledButton(display,&windows->widget,&special_info);
3856 if (MatteIsActive(action_info,event.xbutton))
3859 User pressed Action button.
3861 action_info.raised=MagickFalse;
3862 XDrawBeveledButton(display,&windows->widget,&action_info);
3865 if (MatteIsActive(cancel_info,event.xbutton))
3868 User pressed Cancel button.
3870 cancel_info.raised=MagickFalse;
3871 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3874 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
3876 if (event.xbutton.button != Button2)
3882 Move text cursor to position of button press.
3884 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
3885 for (i=1; i <= Extent(reply_info.marker); i++)
3886 if (XTextWidth(font_info,reply_info.marker,i) > x)
3888 reply_info.cursor=reply_info.marker+i-1;
3889 if (event.xbutton.time > (click_time+DoubleClick))
3890 reply_info.highlight=MagickFalse;
3894 Become the XA_PRIMARY selection owner.
3896 (void) CopyMagickString(primary_selection,reply_info.text,
3898 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
3899 event.xbutton.time);
3900 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
3901 windows->widget.id ? MagickTrue : MagickFalse;
3903 XDrawMatteText(display,&windows->widget,&reply_info);
3904 click_time=event.xbutton.time;
3908 Request primary selection.
3910 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
3911 windows->widget.id,event.xbutton.time);
3916 if (windows->widget.mapped == MagickFalse)
3918 if (action_info.raised == MagickFalse)
3920 if (event.xbutton.window == windows->widget.id)
3921 if (MatteIsActive(action_info,event.xbutton))
3923 action_info.raised=MagickTrue;
3924 XDrawBeveledButton(display,&windows->widget,&action_info);
3926 if (cancel_info.raised == MagickFalse)
3928 if (event.xbutton.window == windows->widget.id)
3929 if (MatteIsActive(cancel_info,event.xbutton))
3931 *reply_info.text='\0';
3934 cancel_info.raised=MagickTrue;
3935 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3942 If client window delete message, exit.
3944 if (event.xclient.message_type != windows->wm_protocols)
3946 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3948 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3949 (Time) event.xclient.data.l[1]);
3952 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3954 if (event.xclient.window == windows->widget.id)
3956 *reply_info.text='\0';
3962 case ConfigureNotify:
3965 Update widget configuration.
3967 if (event.xconfigure.window != windows->widget.id)
3969 if ((event.xconfigure.width == (int) windows->widget.width) &&
3970 (event.xconfigure.height == (int) windows->widget.height))
3972 windows->widget.width=(unsigned int)
3973 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3974 windows->widget.height=(unsigned int)
3975 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3976 state|=UpdateConfigurationState;
3981 if (event.xcrossing.window != windows->widget.id)
3983 state&=(~InactiveWidgetState);
3988 if (event.xexpose.window != windows->widget.id)
3990 if (event.xexpose.count != 0)
3992 state|=RedrawWidgetState;
3998 command[MaxTextExtent];
4007 Respond to a user key press.
4009 if (event.xkey.window != windows->widget.id)
4011 length=XLookupString((XKeyEvent *) &event.xkey,command,
4012 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4013 *(command+length)='\0';
4014 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
4016 action_info.raised=MagickFalse;
4017 XDrawBeveledButton(display,&windows->widget,&action_info);
4021 if (key_symbol == XK_Control_L)
4023 state|=ControlState;
4026 if (state & ControlState)
4027 switch ((int) key_symbol)
4033 Erase the entire line of text.
4035 *reply_info.text='\0';
4036 reply_info.cursor=reply_info.text;
4037 reply_info.marker=reply_info.text;
4038 reply_info.highlight=MagickFalse;
4044 XEditText(display,&reply_info,key_symbol,command,state);
4045 XDrawMatteText(display,&windows->widget,&reply_info);
4051 command[MaxTextExtent];
4057 Respond to a user key release.
4059 if (event.xkey.window != windows->widget.id)
4061 (void) XLookupString((XKeyEvent *) &event.xkey,command,
4062 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4063 if (key_symbol == XK_Control_L)
4064 state&=(~ControlState);
4069 if (event.xcrossing.window != windows->widget.id)
4071 state|=InactiveWidgetState;
4077 Discard pending button motion events.
4079 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
4080 if (state & InactiveWidgetState)
4082 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
4085 Action button status changed.
4087 action_info.raised=action_info.raised == MagickFalse ?
4088 MagickTrue : MagickFalse;
4089 XDrawBeveledButton(display,&windows->widget,&action_info);
4092 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
4095 Cancel button status changed.
4097 cancel_info.raised=cancel_info.raised == MagickFalse ?
4098 MagickTrue : MagickFalse;
4099 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4104 case SelectionClear:
4106 reply_info.highlight=MagickFalse;
4107 XDrawMatteText(display,&windows->widget,&reply_info);
4110 case SelectionNotify:
4126 Obtain response from primary selection.
4128 if (event.xselection.property == (Atom) None)
4130 status=XGetWindowProperty(display,event.xselection.requestor,
4131 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
4132 &format,&length,&after,&data);
4133 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
4136 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
4137 (void) XBell(display,0);
4141 Insert primary selection in reply text.
4143 *(data+length)='\0';
4144 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
4146 XDrawMatteText(display,&windows->widget,&reply_info);
4148 (void) XFree((void *) data);
4151 case SelectionRequest:
4156 XSelectionRequestEvent
4159 if (reply_info.highlight == MagickFalse)
4162 Set primary selection.
4164 request=(&(event.xselectionrequest));
4165 (void) XChangeProperty(request->display,request->requestor,
4166 request->property,request->target,8,PropModeReplace,
4167 (unsigned char *) primary_selection,Extent(primary_selection));
4168 notify.type=SelectionNotify;
4169 notify.display=request->display;
4170 notify.requestor=request->requestor;
4171 notify.selection=request->selection;
4172 notify.target=request->target;
4173 notify.time=request->time;
4174 if (request->property == None)
4175 notify.property=request->target;
4177 notify.property=request->property;
4178 (void) XSendEvent(request->display,request->requestor,False,0,
4179 (XEvent *) ¬ify);
4184 } while ((state & ExitState) == 0);
4185 XSetCursorState(display,windows,MagickFalse);
4186 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
4187 XCheckRefreshWindows(display,windows);
4189 if (special_info.raised)
4192 return(raised == MagickFalse);
4196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4200 % X F i l e B r o w s e r W i d g e t %
4204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4206 % XFileBrowserWidget() displays a File Browser widget with a file query to the
4207 % user. The user keys a reply and presses the Action or Cancel button to
4208 % exit. The typed text is returned as the reply function parameter.
4210 % The format of the XFileBrowserWidget method is:
4212 % void XFileBrowserWidget(Display *display,XWindows *windows,
4213 % const char *action,char *reply)
4215 % A description of each parameter follows:
4217 % o display: Specifies a connection to an X server; returned from
4220 % o window: Specifies a pointer to a XWindows structure.
4222 % o action: Specifies a pointer to the action of this widget.
4224 % o reply: the response from the user is returned in this parameter.
4227 MagickPrivate void XFileBrowserWidget(Display *display,XWindows *windows,
4228 const char *action,char *reply)
4230 #define CancelButtonText "Cancel"
4231 #define DirectoryText "Directory:"
4232 #define FilenameText "File name:"
4233 #define GrabButtonText "Grab"
4234 #define FormatButtonText "Format"
4235 #define HomeButtonText "Home"
4236 #define UpButtonText "Up"
4241 home_directory[MaxTextExtent],
4242 primary_selection[MaxTextExtent],
4243 text[MaxTextExtent],
4244 working_path[MaxTextExtent];
4254 glob_pattern[MaxTextExtent] = "*",
4255 format[MaxTextExtent] = "miff";
4257 static MagickStatusType
4258 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
4304 Read filelist from current directory.
4306 assert(display != (Display *) NULL);
4307 assert(windows != (XWindows *) NULL);
4308 assert(action != (char *) NULL);
4309 assert(reply != (char *) NULL);
4310 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
4311 XSetCursorState(display,windows,MagickTrue);
4312 XCheckRefreshWindows(display,windows);
4313 directory=getcwd(home_directory,MaxTextExtent);
4315 (void) CopyMagickString(working_path,home_directory,MaxTextExtent);
4316 filelist=ListFiles(working_path,glob_pattern,&files);
4317 if (filelist == (char **) NULL)
4320 Directory read failed.
4322 XNoticeWidget(display,windows,"Unable to read directory:",working_path);
4323 (void) XDialogWidget(display,windows,action,"Enter filename:",reply);
4327 Determine File Browser widget attributes.
4329 font_info=windows->widget.font_info;
4331 for (i=0; i < (ssize_t) files; i++)
4332 if (WidgetTextWidth(font_info,filelist[i]) > text_width)
4333 text_width=WidgetTextWidth(font_info,filelist[i]);
4334 width=WidgetTextWidth(font_info,(char *) action);
4335 if (WidgetTextWidth(font_info,GrabButtonText) > width)
4336 width=WidgetTextWidth(font_info,GrabButtonText);
4337 if (WidgetTextWidth(font_info,FormatButtonText) > width)
4338 width=WidgetTextWidth(font_info,FormatButtonText);
4339 if (WidgetTextWidth(font_info,CancelButtonText) > width)
4340 width=WidgetTextWidth(font_info,CancelButtonText);
4341 if (WidgetTextWidth(font_info,HomeButtonText) > width)
4342 width=WidgetTextWidth(font_info,HomeButtonText);
4343 if (WidgetTextWidth(font_info,UpButtonText) > width)
4344 width=WidgetTextWidth(font_info,UpButtonText);
4345 width+=QuantumMargin;
4346 if (WidgetTextWidth(font_info,DirectoryText) > width)
4347 width=WidgetTextWidth(font_info,DirectoryText);
4348 if (WidgetTextWidth(font_info,FilenameText) > width)
4349 width=WidgetTextWidth(font_info,FilenameText);
4350 height=(unsigned int) (font_info->ascent+font_info->descent);
4352 Position File Browser widget.
4354 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
4356 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
4357 if (windows->widget.width < windows->widget.min_width)
4358 windows->widget.width=windows->widget.min_width;
4359 windows->widget.height=(unsigned int)
4360 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
4361 windows->widget.min_height=(unsigned int)
4362 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
4363 if (windows->widget.height < windows->widget.min_height)
4364 windows->widget.height=windows->widget.min_height;
4365 XConstrainWindowPosition(display,&windows->widget);
4367 Map File Browser widget.
4369 (void) CopyMagickString(windows->widget.name,"Browse and Select a File",
4371 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
4372 if (status != False)
4374 XSetWMName(display,windows->widget.id,&window_name);
4375 XSetWMIconName(display,windows->widget.id,&window_name);
4376 (void) XFree((void *) window_name.value);
4378 window_changes.width=(int) windows->widget.width;
4379 window_changes.height=(int) windows->widget.height;
4380 window_changes.x=windows->widget.x;
4381 window_changes.y=windows->widget.y;
4382 (void) XReconfigureWMWindow(display,windows->widget.id,
4383 windows->widget.screen,mask,&window_changes);
4384 (void) XMapRaised(display,windows->widget.id);
4385 windows->widget.mapped=MagickFalse;
4387 Respond to X events.
4389 XGetWidgetInfo((char *) NULL,&slider_info);
4390 XGetWidgetInfo((char *) NULL,&north_info);
4391 XGetWidgetInfo((char *) NULL,&south_info);
4392 XGetWidgetInfo((char *) NULL,&expose_info);
4394 anomaly=(LocaleCompare(action,"Composite") == 0) ||
4395 (LocaleCompare(action,"Open") == 0) || (LocaleCompare(action,"Map") == 0);
4397 delay=SuspendTime << 2;
4398 state=UpdateConfigurationState;
4401 if (state & UpdateConfigurationState)
4407 Initialize button information.
4409 XGetWidgetInfo(CancelButtonText,&cancel_info);
4410 cancel_info.width=width;
4411 cancel_info.height=(unsigned int) ((3*height) >> 1);
4413 (windows->widget.width-cancel_info.width-QuantumMargin-2);
4415 (windows->widget.height-cancel_info.height-QuantumMargin);
4416 XGetWidgetInfo(action,&action_info);
4417 action_info.width=width;
4418 action_info.height=(unsigned int) ((3*height) >> 1);
4419 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
4420 (action_info.bevel_width << 1));
4421 action_info.y=cancel_info.y;
4422 XGetWidgetInfo(GrabButtonText,&special_info);
4423 special_info.width=width;
4424 special_info.height=(unsigned int) ((3*height) >> 1);
4425 special_info.x=action_info.x-(action_info.width+(QuantumMargin >> 1)+
4426 (special_info.bevel_width << 1));
4427 special_info.y=action_info.y;
4428 if (anomaly == MagickFalse)
4433 special_info.text=(char *) FormatButtonText;
4434 p=reply+Extent(reply)-1;
4435 while ((p > (reply+1)) && (*(p-1) != '.'))
4437 if ((p > (reply+1)) && (*(p-1) == '.'))
4438 (void) CopyMagickString(format,p,MaxTextExtent);
4440 XGetWidgetInfo(UpButtonText,&up_info);
4441 up_info.width=width;
4442 up_info.height=(unsigned int) ((3*height) >> 1);
4443 up_info.x=QuantumMargin;
4444 up_info.y=((5*QuantumMargin) >> 1)+height;
4445 XGetWidgetInfo(HomeButtonText,&home_info);
4446 home_info.width=width;
4447 home_info.height=(unsigned int) ((3*height) >> 1);
4448 home_info.x=QuantumMargin;
4449 home_info.y=up_info.y+up_info.height+QuantumMargin;
4451 Initialize reply information.
4453 XGetWidgetInfo(reply,&reply_info);
4454 reply_info.raised=MagickFalse;
4455 reply_info.bevel_width--;
4456 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
4457 reply_info.height=height << 1;
4458 reply_info.x=(int) (width+(QuantumMargin << 1));
4459 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
4461 Initialize scroll information.
4463 XGetWidgetInfo((char *) NULL,&scroll_info);
4464 scroll_info.bevel_width--;
4465 scroll_info.width=height;
4466 scroll_info.height=(unsigned int)
4467 (reply_info.y-up_info.y-(QuantumMargin >> 1));
4468 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
4469 scroll_info.y=up_info.y-reply_info.bevel_width;
4470 scroll_info.raised=MagickFalse;
4471 scroll_info.trough=MagickTrue;
4472 north_info=scroll_info;
4473 north_info.raised=MagickTrue;
4474 north_info.width-=(north_info.bevel_width << 1);
4475 north_info.height=north_info.width-1;
4476 north_info.x+=north_info.bevel_width;
4477 north_info.y+=north_info.bevel_width;
4478 south_info=north_info;
4479 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
4482 slider_info=north_info;
4484 slider_info.width-=2;
4485 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
4486 slider_info.bevel_width+2;
4487 slider_info.height=scroll_info.height-((slider_info.min_y-
4488 scroll_info.y+1) << 1)+4;
4489 visible_files=scroll_info.height/(height+(height >> 3));
4490 if (files > visible_files)
4491 slider_info.height=(unsigned int)
4492 ((visible_files*slider_info.height)/files);
4493 slider_info.max_y=south_info.y-south_info.bevel_width-
4494 slider_info.bevel_width-2;
4495 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
4496 slider_info.y=slider_info.min_y;
4497 expose_info=scroll_info;
4498 expose_info.y=slider_info.y;
4500 Initialize list information.
4502 XGetWidgetInfo((char *) NULL,&list_info);
4503 list_info.raised=MagickFalse;
4504 list_info.bevel_width--;
4505 list_info.width=(unsigned int)
4506 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
4507 list_info.height=scroll_info.height;
4508 list_info.x=reply_info.x;
4509 list_info.y=scroll_info.y;
4510 if (windows->widget.mapped == MagickFalse)
4511 state|=JumpListState;
4513 Initialize text information.
4516 XGetWidgetInfo(text,&text_info);
4517 text_info.center=MagickFalse;
4518 text_info.width=reply_info.width;
4519 text_info.height=height;
4520 text_info.x=list_info.x-(QuantumMargin >> 1);
4521 text_info.y=QuantumMargin;
4523 Initialize selection information.
4525 XGetWidgetInfo((char *) NULL,&selection_info);
4526 selection_info.center=MagickFalse;
4527 selection_info.width=list_info.width;
4528 selection_info.height=(unsigned int) ((9*height) >> 3);
4529 selection_info.x=list_info.x;
4530 state&=(~UpdateConfigurationState);
4532 if (state & RedrawWidgetState)
4535 Redraw File Browser window.
4538 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
4539 (void) XDrawString(display,windows->widget.id,
4540 windows->widget.annotate_context,x,y,DirectoryText,
4541 Extent(DirectoryText));
4542 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4543 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4545 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4547 XDrawWidgetText(display,&windows->widget,&text_info);
4548 XDrawBeveledButton(display,&windows->widget,&up_info);
4549 XDrawBeveledButton(display,&windows->widget,&home_info);
4550 XDrawBeveledMatte(display,&windows->widget,&list_info);
4551 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4552 XDrawTriangleNorth(display,&windows->widget,&north_info);
4553 XDrawBeveledButton(display,&windows->widget,&slider_info);
4554 XDrawTriangleSouth(display,&windows->widget,&south_info);
4556 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
4557 (void) XDrawString(display,windows->widget.id,
4558 windows->widget.annotate_context,x,y,FilenameText,
4559 Extent(FilenameText));
4560 XDrawBeveledMatte(display,&windows->widget,&reply_info);
4561 XDrawMatteText(display,&windows->widget,&reply_info);
4562 XDrawBeveledButton(display,&windows->widget,&special_info);
4563 XDrawBeveledButton(display,&windows->widget,&action_info);
4564 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4565 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4566 selection_info.id=(~0);
4567 state|=RedrawListState;
4568 state&=(~RedrawWidgetState);
4570 if (state & UpdateListState)
4581 checklist=ListFiles(working_path,glob_pattern,&number_files);
4582 if (checklist == (char **) NULL)
4585 Reply is a filename, exit.
4587 action_info.raised=MagickFalse;
4588 XDrawBeveledButton(display,&windows->widget,&action_info);
4591 for (i=0; i < (ssize_t) files; i++)
4592 filelist[i]=DestroyString(filelist[i]);
4593 if (filelist != (char **) NULL)
4594 filelist=(char **) RelinquishMagickMemory(filelist);
4601 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
4602 if (files > visible_files)
4603 slider_info.height=(unsigned int)
4604 ((visible_files*slider_info.height)/files);
4605 slider_info.max_y=south_info.y-south_info.bevel_width-
4606 slider_info.bevel_width-2;
4608 slider_info.y=slider_info.min_y;
4609 expose_info.y=slider_info.y;
4610 selection_info.id=(~0);
4612 state|=RedrawListState;
4614 Redraw directory name & reply.
4616 if (IsGlob(reply_info.text) == MagickFalse)
4618 *reply_info.text='\0';
4619 reply_info.cursor=reply_info.text;
4621 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4622 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4624 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4626 XDrawWidgetText(display,&windows->widget,&text_info);
4627 XDrawMatteText(display,&windows->widget,&reply_info);
4628 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4629 XDrawTriangleNorth(display,&windows->widget,&north_info);
4630 XDrawBeveledButton(display,&windows->widget,&slider_info);
4631 XDrawTriangleSouth(display,&windows->widget,&south_info);
4632 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4633 state&=(~UpdateListState);
4635 if (state & JumpListState)
4638 Jump scroll to match user filename.
4641 for (i=0; i < (ssize_t) files; i++)
4642 if (LocaleCompare(filelist[i],reply) >= 0)
4645 (LocaleCompare(filelist[i],reply) == 0 ? i : ~0);
4648 if ((i < (ssize_t) slider_info.id) ||
4649 (i >= (ssize_t) (slider_info.id+visible_files)))
4650 slider_info.id=(int) i-(visible_files >> 1);
4651 selection_info.id=(~0);
4652 state|=RedrawListState;
4653 state&=(~JumpListState);
4655 if (state & RedrawListState)
4658 Determine slider id and position.
4660 if (slider_info.id >= (int) (files-visible_files))
4661 slider_info.id=(int) (files-visible_files);
4662 if ((slider_info.id < 0) || (files <= visible_files))
4664 slider_info.y=slider_info.min_y;
4666 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
4667 slider_info.min_y+1)/files);
4668 if (slider_info.id != selection_info.id)
4671 Redraw scroll bar and file names.
4673 selection_info.id=slider_info.id;
4674 selection_info.y=list_info.y+(height >> 3)+2;
4675 for (i=0; i < (ssize_t) visible_files; i++)
4677 selection_info.raised=(int) (slider_info.id+i) != list_info.id ?
4678 MagickTrue : MagickFalse;
4679 selection_info.text=(char *) NULL;
4680 if ((slider_info.id+i) < (ssize_t) files)
4681 selection_info.text=filelist[slider_info.id+i];
4682 XDrawWidgetText(display,&windows->widget,&selection_info);
4683 selection_info.y+=(int) selection_info.height;
4688 if (slider_info.y > expose_info.y)
4690 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
4691 expose_info.y=slider_info.y-expose_info.height-
4692 slider_info.bevel_width-1;
4696 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
4697 expose_info.y=slider_info.y+slider_info.height+
4698 slider_info.bevel_width+1;
4700 XDrawTriangleNorth(display,&windows->widget,&north_info);
4701 XDrawMatte(display,&windows->widget,&expose_info);
4702 XDrawBeveledButton(display,&windows->widget,&slider_info);
4703 XDrawTriangleSouth(display,&windows->widget,&south_info);
4704 expose_info.y=slider_info.y;
4706 state&=(~RedrawListState);
4709 Wait for next event.
4711 if (north_info.raised && south_info.raised)
4712 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
4716 Brief delay before advancing scroll bar.
4718 XDelay(display,delay);
4720 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
4721 if (north_info.raised == MagickFalse)
4722 if (slider_info.id > 0)
4728 state|=RedrawListState;
4730 if (south_info.raised == MagickFalse)
4731 if (slider_info.id < (int) files)
4737 state|=RedrawListState;
4739 if (event.type != ButtonRelease)
4746 if (MatteIsActive(slider_info,event.xbutton))
4751 slider_info.active=MagickTrue;
4754 if (MatteIsActive(north_info,event.xbutton))
4755 if (slider_info.id > 0)
4760 north_info.raised=MagickFalse;
4762 state|=RedrawListState;
4765 if (MatteIsActive(south_info,event.xbutton))
4766 if (slider_info.id < (int) files)
4771 south_info.raised=MagickFalse;
4773 state|=RedrawListState;
4776 if (MatteIsActive(scroll_info,event.xbutton))
4781 if (event.xbutton.y < slider_info.y)
4782 slider_info.id-=(visible_files-1);
4784 slider_info.id+=(visible_files-1);
4785 state|=RedrawListState;
4788 if (MatteIsActive(list_info,event.xbutton))
4794 User pressed file matte.
4796 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
4797 selection_info.height;
4798 if (id >= (int) files)
4800 (void) CopyMagickString(reply_info.text,filelist[id],MaxTextExtent);
4801 reply_info.highlight=MagickFalse;
4802 reply_info.marker=reply_info.text;
4803 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4804 XDrawMatteText(display,&windows->widget,&reply_info);
4805 if (id == list_info.id)
4810 p=reply_info.text+strlen(reply_info.text)-1;
4811 if (*p == *DirectorySeparator)
4812 ChopPathComponents(reply_info.text,1);
4813 (void) ConcatenateMagickString(working_path,DirectorySeparator,
4815 (void) ConcatenateMagickString(working_path,reply_info.text,
4818 state|=UpdateListState;
4820 selection_info.id=(~0);
4822 state|=RedrawListState;
4825 if (MatteIsActive(up_info,event.xbutton))
4828 User pressed Up button.
4830 up_info.raised=MagickFalse;
4831 XDrawBeveledButton(display,&windows->widget,&up_info);
4834 if (MatteIsActive(home_info,event.xbutton))
4837 User pressed Home button.
4839 home_info.raised=MagickFalse;
4840 XDrawBeveledButton(display,&windows->widget,&home_info);
4843 if (MatteIsActive(special_info,event.xbutton))
4846 User pressed Special button.
4848 special_info.raised=MagickFalse;
4849 XDrawBeveledButton(display,&windows->widget,&special_info);
4852 if (MatteIsActive(action_info,event.xbutton))
4855 User pressed action button.
4857 action_info.raised=MagickFalse;
4858 XDrawBeveledButton(display,&windows->widget,&action_info);
4861 if (MatteIsActive(cancel_info,event.xbutton))
4864 User pressed Cancel button.
4866 cancel_info.raised=MagickFalse;
4867 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4870 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
4872 if (event.xbutton.button != Button2)
4878 Move text cursor to position of button press.
4880 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
4881 for (i=1; i <= (ssize_t) Extent(reply_info.marker); i++)
4882 if (XTextWidth(font_info,reply_info.marker,(int) i) > x)
4884 reply_info.cursor=reply_info.marker+i-1;
4885 if (event.xbutton.time > (click_time+DoubleClick))
4886 reply_info.highlight=MagickFalse;
4890 Become the XA_PRIMARY selection owner.
4892 (void) CopyMagickString(primary_selection,reply_info.text,
4894 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
4895 event.xbutton.time);
4896 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
4897 windows->widget.id ? MagickTrue : MagickFalse;
4899 XDrawMatteText(display,&windows->widget,&reply_info);
4900 click_time=event.xbutton.time;
4904 Request primary selection.
4906 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
4907 windows->widget.id,event.xbutton.time);
4912 if (windows->widget.mapped == MagickFalse)
4914 if (north_info.raised == MagickFalse)
4917 User released up button.
4919 delay=SuspendTime << 2;
4920 north_info.raised=MagickTrue;
4921 XDrawTriangleNorth(display,&windows->widget,&north_info);
4923 if (south_info.raised == MagickFalse)
4926 User released down button.
4928 delay=SuspendTime << 2;
4929 south_info.raised=MagickTrue;
4930 XDrawTriangleSouth(display,&windows->widget,&south_info);
4932 if (slider_info.active)
4935 Stop tracking slider.
4937 slider_info.active=MagickFalse;
4940 if (up_info.raised == MagickFalse)
4942 if (event.xbutton.window == windows->widget.id)
4943 if (MatteIsActive(up_info,event.xbutton))
4945 ChopPathComponents(working_path,1);
4946 if (*working_path == '\0')
4947 (void) CopyMagickString(working_path,DirectorySeparator,
4949 state|=UpdateListState;
4951 up_info.raised=MagickTrue;
4952 XDrawBeveledButton(display,&windows->widget,&up_info);
4954 if (home_info.raised == MagickFalse)
4956 if (event.xbutton.window == windows->widget.id)
4957 if (MatteIsActive(home_info,event.xbutton))
4959 (void) CopyMagickString(working_path,home_directory,
4961 state|=UpdateListState;
4963 home_info.raised=MagickTrue;
4964 XDrawBeveledButton(display,&windows->widget,&home_info);
4966 if (special_info.raised == MagickFalse)
4968 if (anomaly == MagickFalse)
4980 Let user select image format.
4982 exception=AcquireExceptionInfo();
4983 formats=GetMagickList("*",&number_formats,exception);
4984 exception=DestroyExceptionInfo(exception);
4985 (void) XCheckDefineCursor(display,windows->widget.id,
4986 windows->widget.busy_cursor);
4987 windows->popup.x=windows->widget.x+60;
4988 windows->popup.y=windows->widget.y+60;
4989 XListBrowserWidget(display,windows,&windows->popup,
4990 (const char **) formats,"Select","Select image format type:",
4992 XSetCursorState(display,windows,MagickTrue);
4993 (void) XCheckDefineCursor(display,windows->widget.id,
4994 windows->widget.cursor);
4995 LocaleLower(format);
4996 AppendImageFormat(format,reply_info.text);
4997 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4998 XDrawMatteText(display,&windows->widget,&reply_info);
4999 special_info.raised=MagickTrue;
5000 XDrawBeveledButton(display,&windows->widget,&special_info);
5001 for (i=0; i < (ssize_t) number_formats; i++)
5002 formats[i]=DestroyString(formats[i]);
5003 formats=(char **) RelinquishMagickMemory(formats);
5006 if (event.xbutton.window == windows->widget.id)
5007 if (MatteIsActive(special_info,event.xbutton))
5009 (void) CopyMagickString(working_path,"x:",MaxTextExtent);
5012 special_info.raised=MagickTrue;
5013 XDrawBeveledButton(display,&windows->widget,&special_info);
5015 if (action_info.raised == MagickFalse)
5017 if (event.xbutton.window == windows->widget.id)
5019 if (MatteIsActive(action_info,event.xbutton))
5021 if (*reply_info.text == '\0')
5022 (void) XBell(display,0);
5027 action_info.raised=MagickTrue;
5028 XDrawBeveledButton(display,&windows->widget,&action_info);
5030 if (cancel_info.raised == MagickFalse)
5032 if (event.xbutton.window == windows->widget.id)
5033 if (MatteIsActive(cancel_info,event.xbutton))
5035 *reply_info.text='\0';
5039 cancel_info.raised=MagickTrue;
5040 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5047 If client window delete message, exit.
5049 if (event.xclient.message_type != windows->wm_protocols)
5051 if (*event.xclient.data.l == (int) windows->wm_take_focus)
5053 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
5054 (Time) event.xclient.data.l[1]);
5057 if (*event.xclient.data.l != (int) windows->wm_delete_window)
5059 if (event.xclient.window == windows->widget.id)
5061 *reply_info.text='\0';
5067 case ConfigureNotify:
5070 Update widget configuration.
5072 if (event.xconfigure.window != windows->widget.id)
5074 if ((event.xconfigure.width == (int) windows->widget.width) &&
5075 (event.xconfigure.height == (int) windows->widget.height))
5077 windows->widget.width=(unsigned int)
5078 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
5079 windows->widget.height=(unsigned int)
5080 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
5081 state|=UpdateConfigurationState;
5086 if (event.xcrossing.window != windows->widget.id)
5088 state&=(~InactiveWidgetState);
5093 if (event.xexpose.window != windows->widget.id)
5095 if (event.xexpose.count != 0)
5097 state|=RedrawWidgetState;
5103 command[MaxTextExtent];
5112 Respond to a user key press.
5114 if (event.xkey.window != windows->widget.id)
5116 length=XLookupString((XKeyEvent *) &event.xkey,command,
5117 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5118 *(command+length)='\0';
5119 if (AreaIsActive(scroll_info,event.xkey))
5124 switch ((int) key_symbol)
5147 slider_info.id-=visible_files;
5153 slider_info.id+=visible_files;
5159 slider_info.id=(int) files;
5163 state|=RedrawListState;
5166 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
5169 Read new directory or glob patterm.
5171 if (*reply_info.text == '\0')
5173 if (IsGlob(reply_info.text))
5174 (void) CopyMagickString(glob_pattern,reply_info.text,
5178 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5180 (void) ConcatenateMagickString(working_path,reply_info.text,
5182 if (*working_path == '~')
5183 ExpandFilename(working_path);
5186 state|=UpdateListState;
5189 if (key_symbol == XK_Control_L)
5191 state|=ControlState;
5194 if (state & ControlState)
5195 switch ((int) key_symbol)
5201 Erase the entire line of text.
5203 *reply_info.text='\0';
5204 reply_info.cursor=reply_info.text;
5205 reply_info.marker=reply_info.text;
5206 reply_info.highlight=MagickFalse;
5212 XEditText(display,&reply_info,key_symbol,command,state);
5213 XDrawMatteText(display,&windows->widget,&reply_info);
5214 state|=JumpListState;
5220 command[MaxTextExtent];
5226 Respond to a user key release.
5228 if (event.xkey.window != windows->widget.id)
5230 (void) XLookupString((XKeyEvent *) &event.xkey,command,
5231 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5232 if (key_symbol == XK_Control_L)
5233 state&=(~ControlState);
5238 if (event.xcrossing.window != windows->widget.id)
5240 state|=InactiveWidgetState;
5252 Discard pending button motion events.
5254 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
5255 if (slider_info.active)
5260 slider_info.y=event.xmotion.y-
5261 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
5262 if (slider_info.y < slider_info.min_y)
5263 slider_info.y=slider_info.min_y;
5264 if (slider_info.y > slider_info.max_y)
5265 slider_info.y=slider_info.max_y;
5267 if (slider_info.y != slider_info.min_y)
5268 slider_info.id=(int) ((files*(slider_info.y-slider_info.min_y+1))/
5269 (slider_info.max_y-slider_info.min_y+1));
5270 state|=RedrawListState;
5273 if (state & InactiveWidgetState)
5275 if (up_info.raised == MatteIsActive(up_info,event.xmotion))
5278 Up button status changed.
5280 up_info.raised=!up_info.raised;
5281 XDrawBeveledButton(display,&windows->widget,&up_info);
5284 if (home_info.raised == MatteIsActive(home_info,event.xmotion))
5287 Home button status changed.
5289 home_info.raised=!home_info.raised;
5290 XDrawBeveledButton(display,&windows->widget,&home_info);
5293 if (special_info.raised == MatteIsActive(special_info,event.xmotion))
5296 Grab button status changed.
5298 special_info.raised=!special_info.raised;
5299 XDrawBeveledButton(display,&windows->widget,&special_info);
5302 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
5305 Action button status changed.
5307 action_info.raised=action_info.raised == MagickFalse ?
5308 MagickTrue : MagickFalse;
5309 XDrawBeveledButton(display,&windows->widget,&action_info);
5312 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
5315 Cancel button status changed.
5317 cancel_info.raised=cancel_info.raised == MagickFalse ?
5318 MagickTrue : MagickFalse;
5319 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5324 case SelectionClear:
5326 reply_info.highlight=MagickFalse;
5327 XDrawMatteText(display,&windows->widget,&reply_info);
5330 case SelectionNotify:
5346 Obtain response from primary selection.
5348 if (event.xselection.property == (Atom) None)
5350 status=XGetWindowProperty(display,event.xselection.requestor,
5351 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
5352 &format,&length,&after,&data);
5353 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
5356 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
5357 (void) XBell(display,0);
5361 Insert primary selection in reply text.
5363 *(data+length)='\0';
5364 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
5366 XDrawMatteText(display,&windows->widget,&reply_info);
5367 state|=JumpListState;
5368 state|=RedrawActionState;
5370 (void) XFree((void *) data);
5373 case SelectionRequest:
5378 XSelectionRequestEvent
5381 if (reply_info.highlight == MagickFalse)
5384 Set primary selection.
5386 request=(&(event.xselectionrequest));
5387 (void) XChangeProperty(request->display,request->requestor,
5388 request->property,request->target,8,PropModeReplace,
5389 (unsigned char *) primary_selection,Extent(primary_selection));
5390 notify.type=SelectionNotify;
5391 notify.display=request->display;
5392 notify.requestor=request->requestor;
5393 notify.selection=request->selection;
5394 notify.target=request->target;
5395 notify.time=request->time;
5396 if (request->property == None)
5397 notify.property=request->target;
5399 notify.property=request->property;
5400 (void) XSendEvent(request->display,request->requestor,False,0,
5401 (XEvent *) ¬ify);
5406 } while ((state & ExitState) == 0);
5407 XSetCursorState(display,windows,MagickFalse);
5408 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
5409 XCheckRefreshWindows(display,windows);
5413 for (i=0; i < (ssize_t) files; i++)
5414 filelist[i]=DestroyString(filelist[i]);
5415 if (filelist != (char **) NULL)
5416 filelist=(char **) RelinquishMagickMemory(filelist);
5419 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5421 (void) ConcatenateMagickString(working_path,reply,MaxTextExtent);
5423 (void) CopyMagickString(reply,working_path,MaxTextExtent);
5425 ExpandFilename(reply);
5429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5433 % X F o n t B r o w s e r W i d g e t %
5437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5439 % XFontBrowserWidget() displays a Font Browser widget with a font query to the
5440 % user. The user keys a reply and presses the Action or Cancel button to
5441 % exit. The typed text is returned as the reply function parameter.
5443 % The format of the XFontBrowserWidget method is:
5445 % void XFontBrowserWidget(Display *display,XWindows *windows,
5446 % const char *action,char *reply)
5448 % A description of each parameter follows:
5450 % o display: Specifies a connection to an X server; returned from
5453 % o window: Specifies a pointer to a XWindows structure.
5455 % o action: Specifies a pointer to the action of this widget.
5457 % o reply: the response from the user is returned in this parameter.
5462 #if defined(__cplusplus) || defined(c_plusplus)
5466 static int FontCompare(const void *x,const void *y)
5472 p=(char *) *((char **) x);
5473 q=(char *) *((char **) y);
5474 while ((*p != '\0') && (*q != '\0') && (*p == *q))
5482 #if defined(__cplusplus) || defined(c_plusplus)
5486 MagickPrivate void XFontBrowserWidget(Display *display,XWindows *windows,
5487 const char *action,char *reply)
5489 #define BackButtonText "Back"
5490 #define CancelButtonText "Cancel"
5491 #define FontnameText "Name:"
5492 #define FontPatternText "Pattern:"
5493 #define ResetButtonText "Reset"
5496 back_pattern[MaxTextExtent],
5499 primary_selection[MaxTextExtent],
5500 reset_pattern[MaxTextExtent],
5501 text[MaxTextExtent];
5512 glob_pattern[MaxTextExtent] = "*";
5514 static MagickStatusType
5515 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
5559 Get font list and sort in ascending order.
5561 assert(display != (Display *) NULL);
5562 assert(windows != (XWindows *) NULL);
5563 assert(action != (char *) NULL);
5564 assert(reply != (char *) NULL);
5565 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
5566 XSetCursorState(display,windows,MagickTrue);
5567 XCheckRefreshWindows(display,windows);
5568 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
5569 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
5570 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5574 Pattern failed, obtain all the fonts.
5576 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5578 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
5579 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5580 if (fontlist == (char **) NULL)
5582 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5588 Sort font list in ascending order.
5591 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,sizeof(*fontlist));
5592 if (fontlist == (char **) NULL)
5594 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5595 "UnableToViewFonts");
5598 for (i=0; i < fonts; i++)
5599 fontlist[i]=listhead[i];
5600 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5602 Determine Font Browser widget attributes.
5604 font_info=windows->widget.font_info;
5606 for (i=0; i < fonts; i++)
5607 if (WidgetTextWidth(font_info,fontlist[i]) > text_width)
5608 text_width=WidgetTextWidth(font_info,fontlist[i]);
5609 width=WidgetTextWidth(font_info,(char *) action);
5610 if (WidgetTextWidth(font_info,CancelButtonText) > width)
5611 width=WidgetTextWidth(font_info,CancelButtonText);
5612 if (WidgetTextWidth(font_info,ResetButtonText) > width)
5613 width=WidgetTextWidth(font_info,ResetButtonText);
5614 if (WidgetTextWidth(font_info,BackButtonText) > width)
5615 width=WidgetTextWidth(font_info,BackButtonText);
5616 width+=QuantumMargin;
5617 if (WidgetTextWidth(font_info,FontPatternText) > width)
5618 width=WidgetTextWidth(font_info,FontPatternText);
5619 if (WidgetTextWidth(font_info,FontnameText) > width)
5620 width=WidgetTextWidth(font_info,FontnameText);
5621 height=(unsigned int) (font_info->ascent+font_info->descent);
5623 Position Font Browser widget.
5625 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
5627 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
5628 if (windows->widget.width < windows->widget.min_width)
5629 windows->widget.width=windows->widget.min_width;
5630 windows->widget.height=(unsigned int)
5631 (((85*height) >> 2)+((13*QuantumMargin) >> 1)+4);
5632 windows->widget.min_height=(unsigned int)
5633 (((27*height) >> 1)+((13*QuantumMargin) >> 1)+4);
5634 if (windows->widget.height < windows->widget.min_height)
5635 windows->widget.height=windows->widget.min_height;
5636 XConstrainWindowPosition(display,&windows->widget);
5638 Map Font Browser widget.
5640 (void) CopyMagickString(windows->widget.name,"Browse and Select a Font",
5642 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
5643 if (status != False)
5645 XSetWMName(display,windows->widget.id,&window_name);
5646 XSetWMIconName(display,windows->widget.id,&window_name);
5647 (void) XFree((void *) window_name.value);
5649 window_changes.width=(int) windows->widget.width;
5650 window_changes.height=(int) windows->widget.height;
5651 window_changes.x=windows->widget.x;
5652 window_changes.y=windows->widget.y;
5653 (void) XReconfigureWMWindow(display,windows->widget.id,
5654 windows->widget.screen,mask,&window_changes);
5655 (void) XMapRaised(display,windows->widget.id);
5656 windows->widget.mapped=MagickFalse;
5658 Respond to X events.
5660 XGetWidgetInfo((char *) NULL,&slider_info);
5661 XGetWidgetInfo((char *) NULL,&north_info);
5662 XGetWidgetInfo((char *) NULL,&south_info);
5663 XGetWidgetInfo((char *) NULL,&expose_info);
5665 delay=SuspendTime << 2;
5666 state=UpdateConfigurationState;
5669 if (state & UpdateConfigurationState)
5675 Initialize button information.
5677 XGetWidgetInfo(CancelButtonText,&cancel_info);
5678 cancel_info.width=width;
5679 cancel_info.height=(unsigned int) ((3*height) >> 1);
5681 (windows->widget.width-cancel_info.width-QuantumMargin-2);
5683 (windows->widget.height-cancel_info.height-QuantumMargin);
5684 XGetWidgetInfo(action,&action_info);
5685 action_info.width=width;
5686 action_info.height=(unsigned int) ((3*height) >> 1);
5687 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
5688 (action_info.bevel_width << 1));
5689 action_info.y=cancel_info.y;
5690 XGetWidgetInfo(BackButtonText,&back_info);
5691 back_info.width=width;
5692 back_info.height=(unsigned int) ((3*height) >> 1);
5693 back_info.x=QuantumMargin;
5694 back_info.y=((5*QuantumMargin) >> 1)+height;
5695 XGetWidgetInfo(ResetButtonText,&reset_info);
5696 reset_info.width=width;
5697 reset_info.height=(unsigned int) ((3*height) >> 1);
5698 reset_info.x=QuantumMargin;
5699 reset_info.y=back_info.y+back_info.height+QuantumMargin;
5701 Initialize reply information.
5703 XGetWidgetInfo(reply,&reply_info);
5704 reply_info.raised=MagickFalse;
5705 reply_info.bevel_width--;
5706 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
5707 reply_info.height=height << 1;
5708 reply_info.x=(int) (width+(QuantumMargin << 1));
5709 reply_info.y=action_info.y-(action_info.height << 1)-QuantumMargin;
5711 Initialize mode information.
5713 XGetWidgetInfo(reply,&mode_info);
5714 mode_info.bevel_width=0;
5715 mode_info.width=(unsigned int)
5716 (action_info.x-reply_info.x-QuantumMargin);
5717 mode_info.height=action_info.height << 1;
5718 mode_info.x=reply_info.x;
5719 mode_info.y=action_info.y-action_info.height+action_info.bevel_width;
5721 Initialize scroll information.
5723 XGetWidgetInfo((char *) NULL,&scroll_info);
5724 scroll_info.bevel_width--;
5725 scroll_info.width=height;
5726 scroll_info.height=(unsigned int)
5727 (reply_info.y-back_info.y-(QuantumMargin >> 1));
5728 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
5729 scroll_info.y=back_info.y-reply_info.bevel_width;
5730 scroll_info.raised=MagickFalse;
5731 scroll_info.trough=MagickTrue;
5732 north_info=scroll_info;
5733 north_info.raised=MagickTrue;
5734 north_info.width-=(north_info.bevel_width << 1);
5735 north_info.height=north_info.width-1;
5736 north_info.x+=north_info.bevel_width;
5737 north_info.y+=north_info.bevel_width;
5738 south_info=north_info;
5739 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
5742 slider_info=north_info;
5744 slider_info.width-=2;
5745 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
5746 slider_info.bevel_width+2;
5747 slider_info.height=scroll_info.height-((slider_info.min_y-
5748 scroll_info.y+1) << 1)+4;
5749 visible_fonts=scroll_info.height/(height+(height >> 3));
5750 if (fonts > (int) visible_fonts)
5751 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5752 slider_info.max_y=south_info.y-south_info.bevel_width-
5753 slider_info.bevel_width-2;
5754 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
5755 slider_info.y=slider_info.min_y;
5756 expose_info=scroll_info;
5757 expose_info.y=slider_info.y;
5759 Initialize list information.
5761 XGetWidgetInfo((char *) NULL,&list_info);
5762 list_info.raised=MagickFalse;
5763 list_info.bevel_width--;
5764 list_info.width=(unsigned int)
5765 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
5766 list_info.height=scroll_info.height;
5767 list_info.x=reply_info.x;
5768 list_info.y=scroll_info.y;
5769 if (windows->widget.mapped == MagickFalse)
5770 state|=JumpListState;
5772 Initialize text information.
5775 XGetWidgetInfo(text,&text_info);
5776 text_info.center=MagickFalse;
5777 text_info.width=reply_info.width;
5778 text_info.height=height;
5779 text_info.x=list_info.x-(QuantumMargin >> 1);
5780 text_info.y=QuantumMargin;
5782 Initialize selection information.
5784 XGetWidgetInfo((char *) NULL,&selection_info);
5785 selection_info.center=MagickFalse;
5786 selection_info.width=list_info.width;
5787 selection_info.height=(unsigned int) ((9*height) >> 3);
5788 selection_info.x=list_info.x;
5789 state&=(~UpdateConfigurationState);
5791 if (state & RedrawWidgetState)
5794 Redraw Font Browser window.
5797 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
5798 (void) XDrawString(display,windows->widget.id,
5799 windows->widget.annotate_context,x,y,FontPatternText,
5800 Extent(FontPatternText));
5801 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5802 XDrawWidgetText(display,&windows->widget,&text_info);
5803 XDrawBeveledButton(display,&windows->widget,&back_info);
5804 XDrawBeveledButton(display,&windows->widget,&reset_info);
5805 XDrawBeveledMatte(display,&windows->widget,&list_info);
5806 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5807 XDrawTriangleNorth(display,&windows->widget,&north_info);
5808 XDrawBeveledButton(display,&windows->widget,&slider_info);
5809 XDrawTriangleSouth(display,&windows->widget,&south_info);
5811 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
5812 (void) XDrawString(display,windows->widget.id,
5813 windows->widget.annotate_context,x,y,FontnameText,
5814 Extent(FontnameText));
5815 XDrawBeveledMatte(display,&windows->widget,&reply_info);
5816 XDrawMatteText(display,&windows->widget,&reply_info);
5817 XDrawBeveledButton(display,&windows->widget,&action_info);
5818 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5819 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5820 selection_info.id=(~0);
5821 state|=RedrawActionState;
5822 state|=RedrawListState;
5823 state&=(~RedrawWidgetState);
5825 if (state & UpdateListState)
5836 checklist=XListFonts(display,glob_pattern,32767,&number_fonts);
5837 if (checklist == (char **) NULL)
5839 if ((strchr(glob_pattern,'*') == (char *) NULL) &&
5840 (strchr(glob_pattern,'?') == (char *) NULL))
5843 Might be a scaleable font-- exit.
5845 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
5846 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5847 action_info.raised=MagickFalse;
5848 XDrawBeveledButton(display,&windows->widget,&action_info);
5851 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5852 (void) XBell(display,0);
5855 if (number_fonts == 1)
5858 Reply is a single font name-- exit.
5860 (void) CopyMagickString(reply,checklist[0],MaxTextExtent);
5861 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5862 (void) XFreeFontNames(checklist);
5863 action_info.raised=MagickFalse;
5864 XDrawBeveledButton(display,&windows->widget,&action_info);
5869 (void) XFreeFontNames(listhead);
5870 fontlist=(char **) RelinquishMagickMemory(fontlist);
5875 Sort font list in ascending order.
5878 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,
5880 if (fontlist == (char **) NULL)
5882 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5883 "UnableToViewFonts");
5886 for (i=0; i < fonts; i++)
5887 fontlist[i]=listhead[i];
5888 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5890 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
5891 if (fonts > (int) visible_fonts)
5892 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5893 slider_info.max_y=south_info.y-south_info.bevel_width-
5894 slider_info.bevel_width-2;
5896 slider_info.y=slider_info.min_y;
5897 expose_info.y=slider_info.y;
5898 selection_info.id=(~0);
5900 state|=RedrawListState;
5902 Redraw font name & reply.
5904 *reply_info.text='\0';
5905 reply_info.cursor=reply_info.text;
5906 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5907 XDrawWidgetText(display,&windows->widget,&text_info);
5908 XDrawMatteText(display,&windows->widget,&reply_info);
5909 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5910 XDrawTriangleNorth(display,&windows->widget,&north_info);
5911 XDrawBeveledButton(display,&windows->widget,&slider_info);
5912 XDrawTriangleSouth(display,&windows->widget,&south_info);
5913 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5914 state&=(~UpdateListState);
5916 if (state & JumpListState)
5919 Jump scroll to match user font.
5922 for (i=0; i < fonts; i++)
5923 if (LocaleCompare(fontlist[i],reply) >= 0)
5925 list_info.id=LocaleCompare(fontlist[i],reply) == 0 ? i : ~0;
5928 if ((i < slider_info.id) || (i >= (int) (slider_info.id+visible_fonts)))
5929 slider_info.id=i-(visible_fonts >> 1);
5930 selection_info.id=(~0);
5931 state|=RedrawListState;
5932 state&=(~JumpListState);
5934 if (state & RedrawListState)
5937 Determine slider id and position.
5939 if (slider_info.id >= (int) (fonts-visible_fonts))
5940 slider_info.id=fonts-visible_fonts;
5941 if ((slider_info.id < 0) || (fonts <= (int) visible_fonts))
5943 slider_info.y=slider_info.min_y;
5946 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/fonts;
5947 if (slider_info.id != selection_info.id)
5950 Redraw scroll bar and file names.
5952 selection_info.id=slider_info.id;
5953 selection_info.y=list_info.y+(height >> 3)+2;
5954 for (i=0; i < (int) visible_fonts; i++)
5956 selection_info.raised=(slider_info.id+i) != list_info.id ?
5957 MagickTrue : MagickFalse;
5958 selection_info.text=(char *) NULL;
5959 if ((slider_info.id+i) < fonts)
5960 selection_info.text=fontlist[slider_info.id+i];
5961 XDrawWidgetText(display,&windows->widget,&selection_info);
5962 selection_info.y+=(int) selection_info.height;
5967 if (slider_info.y > expose_info.y)
5969 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
5970 expose_info.y=slider_info.y-expose_info.height-
5971 slider_info.bevel_width-1;
5975 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
5976 expose_info.y=slider_info.y+slider_info.height+
5977 slider_info.bevel_width+1;
5979 XDrawTriangleNorth(display,&windows->widget,&north_info);
5980 XDrawMatte(display,&windows->widget,&expose_info);
5981 XDrawBeveledButton(display,&windows->widget,&slider_info);
5982 XDrawTriangleSouth(display,&windows->widget,&south_info);
5983 expose_info.y=slider_info.y;
5985 state&=(~RedrawListState);
5987 if (state & RedrawActionState)
5993 Display the selected font in a drawing area.
5995 save_info=windows->widget.font_info;
5996 font_info=XLoadQueryFont(display,reply_info.text);
5997 if (font_info != (XFontStruct *) NULL)
5999 windows->widget.font_info=font_info;
6000 (void) XSetFont(display,windows->widget.widget_context,
6003 XDrawBeveledButton(display,&windows->widget,&mode_info);
6004 windows->widget.font_info=save_info;
6005 if (font_info != (XFontStruct *) NULL)
6007 (void) XSetFont(display,windows->widget.widget_context,
6008 windows->widget.font_info->fid);
6009 (void) XFreeFont(display,font_info);
6011 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
6012 XDrawMatteText(display,&windows->widget,&reply_info);
6013 state&=(~RedrawActionState);
6016 Wait for next event.
6018 if (north_info.raised && south_info.raised)
6019 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
6023 Brief delay before advancing scroll bar.
6025 XDelay(display,delay);
6027 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
6028 if (north_info.raised == MagickFalse)
6029 if (slider_info.id > 0)
6035 state|=RedrawListState;
6037 if (south_info.raised == MagickFalse)
6038 if (slider_info.id < fonts)
6044 state|=RedrawListState;
6046 if (event.type != ButtonRelease)
6053 if (MatteIsActive(slider_info,event.xbutton))
6058 slider_info.active=MagickTrue;
6061 if (MatteIsActive(north_info,event.xbutton))
6062 if (slider_info.id > 0)
6067 north_info.raised=MagickFalse;
6069 state|=RedrawListState;
6072 if (MatteIsActive(south_info,event.xbutton))
6073 if (slider_info.id < fonts)
6078 south_info.raised=MagickFalse;
6080 state|=RedrawListState;
6083 if (MatteIsActive(scroll_info,event.xbutton))
6088 if (event.xbutton.y < slider_info.y)
6089 slider_info.id-=(visible_fonts-1);
6091 slider_info.id+=(visible_fonts-1);
6092 state|=RedrawListState;
6095 if (MatteIsActive(list_info,event.xbutton))
6101 User pressed list matte.
6103 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
6104 selection_info.height;
6105 if (id >= (int) fonts)
6107 (void) CopyMagickString(reply_info.text,fontlist[id],MaxTextExtent);
6108 reply_info.highlight=MagickFalse;
6109 reply_info.marker=reply_info.text;
6110 reply_info.cursor=reply_info.text+Extent(reply_info.text);
6111 XDrawMatteText(display,&windows->widget,&reply_info);
6112 state|=RedrawActionState;
6113 if (id == list_info.id)
6115 (void) CopyMagickString(glob_pattern,reply_info.text,
6117 state|=UpdateListState;
6119 selection_info.id=(~0);
6121 state|=RedrawListState;
6124 if (MatteIsActive(back_info,event.xbutton))
6127 User pressed Back button.
6129 back_info.raised=MagickFalse;
6130 XDrawBeveledButton(display,&windows->widget,&back_info);
6133 if (MatteIsActive(reset_info,event.xbutton))
6136 User pressed Reset button.
6138 reset_info.raised=MagickFalse;
6139 XDrawBeveledButton(display,&windows->widget,&reset_info);
6142 if (MatteIsActive(action_info,event.xbutton))
6145 User pressed action button.
6147 action_info.raised=MagickFalse;
6148 XDrawBeveledButton(display,&windows->widget,&action_info);
6151 if (MatteIsActive(cancel_info,event.xbutton))
6154 User pressed Cancel button.
6156 cancel_info.raised=MagickFalse;
6157 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6160 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
6162 if (event.xbutton.button != Button2)
6168 Move text cursor to position of button press.
6170 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
6171 for (i=1; i <= Extent(reply_info.marker); i++)
6172 if (XTextWidth(font_info,reply_info.marker,i) > x)
6174 reply_info.cursor=reply_info.marker+i-1;
6175 if (event.xbutton.time > (click_time+DoubleClick))
6176 reply_info.highlight=MagickFalse;
6180 Become the XA_PRIMARY selection owner.
6182 (void) CopyMagickString(primary_selection,reply_info.text,
6184 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
6185 event.xbutton.time);
6186 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
6187 windows->widget.id ? MagickTrue : MagickFalse;
6189 XDrawMatteText(display,&windows->widget,&reply_info);
6190 click_time=event.xbutton.time;
6194 Request primary selection.
6196 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
6197 windows->widget.id,event.xbutton.time);
6202 if (windows->widget.mapped == MagickFalse)
6204 if (north_info.raised == MagickFalse)
6207 User released up button.
6209 delay=SuspendTime << 2;
6210 north_info.raised=MagickTrue;
6211 XDrawTriangleNorth(display,&windows->widget,&north_info);
6213 if (south_info.raised == MagickFalse)
6216 User released down button.
6218 delay=SuspendTime << 2;
6219 south_info.raised=MagickTrue;
6220 XDrawTriangleSouth(display,&windows->widget,&south_info);
6222 if (slider_info.active)
6225 Stop tracking slider.
6227 slider_info.active=MagickFalse;
6230 if (back_info.raised == MagickFalse)
6232 if (event.xbutton.window == windows->widget.id)
6233 if (MatteIsActive(back_info,event.xbutton))
6235 (void) CopyMagickString(glob_pattern,back_pattern,
6237 state|=UpdateListState;
6239 back_info.raised=MagickTrue;
6240 XDrawBeveledButton(display,&windows->widget,&back_info);
6242 if (reset_info.raised == MagickFalse)
6244 if (event.xbutton.window == windows->widget.id)
6245 if (MatteIsActive(reset_info,event.xbutton))
6247 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6248 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
6249 state|=UpdateListState;
6251 reset_info.raised=MagickTrue;
6252 XDrawBeveledButton(display,&windows->widget,&reset_info);
6254 if (action_info.raised == MagickFalse)
6256 if (event.xbutton.window == windows->widget.id)
6258 if (MatteIsActive(action_info,event.xbutton))
6260 if (*reply_info.text == '\0')
6261 (void) XBell(display,0);
6266 action_info.raised=MagickTrue;
6267 XDrawBeveledButton(display,&windows->widget,&action_info);
6269 if (cancel_info.raised == MagickFalse)
6271 if (event.xbutton.window == windows->widget.id)
6272 if (MatteIsActive(cancel_info,event.xbutton))
6274 *reply_info.text='\0';
6277 cancel_info.raised=MagickTrue;
6278 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6285 If client window delete message, exit.
6287 if (event.xclient.message_type != windows->wm_protocols)
6289 if (*event.xclient.data.l == (int) windows->wm_take_focus)
6291 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
6292 (Time) event.xclient.data.l[1]);
6295 if (*event.xclient.data.l != (int) windows->wm_delete_window)
6297 if (event.xclient.window == windows->widget.id)
6299 *reply_info.text='\0';
6305 case ConfigureNotify:
6308 Update widget configuration.
6310 if (event.xconfigure.window != windows->widget.id)
6312 if ((event.xconfigure.width == (int) windows->widget.width) &&
6313 (event.xconfigure.height == (int) windows->widget.height))
6315 windows->widget.width=(unsigned int)
6316 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
6317 windows->widget.height=(unsigned int)
6318 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
6319 state|=UpdateConfigurationState;
6324 if (event.xcrossing.window != windows->widget.id)
6326 state&=(~InactiveWidgetState);
6331 if (event.xexpose.window != windows->widget.id)
6333 if (event.xexpose.count != 0)
6335 state|=RedrawWidgetState;
6341 command[MaxTextExtent];
6350 Respond to a user key press.
6352 if (event.xkey.window != windows->widget.id)
6354 length=XLookupString((XKeyEvent *) &event.xkey,command,
6355 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6356 *(command+length)='\0';
6357 if (AreaIsActive(scroll_info,event.xkey))
6362 switch ((int) key_symbol)
6385 slider_info.id-=visible_fonts;
6391 slider_info.id+=visible_fonts;
6397 slider_info.id=fonts;
6401 state|=RedrawListState;
6404 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
6407 Read new font or glob patterm.
6409 if (*reply_info.text == '\0')
6411 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6412 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
6413 state|=UpdateListState;
6416 if (key_symbol == XK_Control_L)
6418 state|=ControlState;
6421 if (state & ControlState)
6422 switch ((int) key_symbol)
6428 Erase the entire line of text.
6430 *reply_info.text='\0';
6431 reply_info.cursor=reply_info.text;
6432 reply_info.marker=reply_info.text;
6433 reply_info.highlight=MagickFalse;
6439 XEditText(display,&reply_info,key_symbol,command,state);
6440 XDrawMatteText(display,&windows->widget,&reply_info);
6441 state|=JumpListState;
6447 command[MaxTextExtent];
6453 Respond to a user key release.
6455 if (event.xkey.window != windows->widget.id)
6457 (void) XLookupString((XKeyEvent *) &event.xkey,command,
6458 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6459 if (key_symbol == XK_Control_L)
6460 state&=(~ControlState);
6465 if (event.xcrossing.window != windows->widget.id)
6467 state|=InactiveWidgetState;
6479 Discard pending button motion events.
6481 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
6482 if (slider_info.active)
6487 slider_info.y=event.xmotion.y-
6488 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
6489 if (slider_info.y < slider_info.min_y)
6490 slider_info.y=slider_info.min_y;
6491 if (slider_info.y > slider_info.max_y)
6492 slider_info.y=slider_info.max_y;
6494 if (slider_info.y != slider_info.min_y)
6495 slider_info.id=(fonts*(slider_info.y-slider_info.min_y+1))/
6496 (slider_info.max_y-slider_info.min_y+1);
6497 state|=RedrawListState;
6500 if (state & InactiveWidgetState)
6502 if (back_info.raised == MatteIsActive(back_info,event.xmotion))
6505 Back button status changed.
6507 back_info.raised=!back_info.raised;
6508 XDrawBeveledButton(display,&windows->widget,&back_info);
6511 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
6514 Reset button status changed.
6516 reset_info.raised=!reset_info.raised;
6517 XDrawBeveledButton(display,&windows->widget,&reset_info);
6520 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
6523 Action button status changed.
6525 action_info.raised=action_info.raised == MagickFalse ?
6526 MagickTrue : MagickFalse;
6527 XDrawBeveledButton(display,&windows->widget,&action_info);
6530 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
6533 Cancel button status changed.
6535 cancel_info.raised=cancel_info.raised == MagickFalse ?
6536 MagickTrue : MagickFalse;
6537 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6542 case SelectionClear:
6544 reply_info.highlight=MagickFalse;
6545 XDrawMatteText(display,&windows->widget,&reply_info);
6548 case SelectionNotify:
6564 Obtain response from primary selection.
6566 if (event.xselection.property == (Atom) None)
6568 status=XGetWindowProperty(display,event.xselection.requestor,
6569 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
6570 &format,&length,&after,&data);
6571 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
6574 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
6575 (void) XBell(display,0);
6579 Insert primary selection in reply text.
6581 *(data+length)='\0';
6582 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
6584 XDrawMatteText(display,&windows->widget,&reply_info);
6585 state|=JumpListState;
6586 state|=RedrawActionState;
6588 (void) XFree((void *) data);
6591 case SelectionRequest:
6596 XSelectionRequestEvent
6600 Set XA_PRIMARY selection.
6602 request=(&(event.xselectionrequest));
6603 (void) XChangeProperty(request->display,request->requestor,
6604 request->property,request->target,8,PropModeReplace,
6605 (unsigned char *) primary_selection,Extent(primary_selection));
6606 notify.type=SelectionNotify;
6607 notify.display=request->display;
6608 notify.requestor=request->requestor;
6609 notify.selection=request->selection;
6610 notify.target=request->target;
6611 notify.time=request->time;
6612 if (request->property == None)
6613 notify.property=request->target;
6615 notify.property=request->property;
6616 (void) XSendEvent(request->display,request->requestor,False,0,
6617 (XEvent *) ¬ify);
6622 } while ((state & ExitState) == 0);
6623 XSetCursorState(display,windows,MagickFalse);
6624 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
6625 XCheckRefreshWindows(display,windows);
6629 (void) XFreeFontNames(listhead);
6630 fontlist=(char **) RelinquishMagickMemory(fontlist);
6634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6638 % X I n f o W i d g e t %
6642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6644 % XInfoWidget() displays text in the Info widget. The purpose is to inform
6645 % the user that what activity is currently being performed (e.g. reading
6646 % an image, rotating an image, etc.).
6648 % The format of the XInfoWidget method is:
6650 % void XInfoWidget(Display *display,XWindows *windows,const char *activity)
6652 % A description of each parameter follows:
6654 % o display: Specifies a connection to an X server; returned from
6657 % o window: Specifies a pointer to a XWindows structure.
6659 % o activity: This character string reflects the current activity and is
6660 % displayed in the Info widget.
6663 MagickPrivate void XInfoWidget(Display *display,XWindows *windows,
6664 const char *activity)
6680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
6681 assert(display != (Display *) NULL);
6682 assert(windows != (XWindows *) NULL);
6683 assert(activity != (char *) NULL);
6684 font_info=windows->info.font_info;
6685 width=WidgetTextWidth(font_info,(char *) activity)+((3*QuantumMargin) >> 1)+4;
6686 height=(unsigned int) (((6*(font_info->ascent+font_info->descent)) >> 2)+4);
6687 if ((windows->info.width != width) || (windows->info.height != height))
6690 Size Info widget to accommodate the activity text.
6692 windows->info.width=width;
6693 windows->info.height=height;
6694 window_changes.width=(int) width;
6695 window_changes.height=(int) height;
6696 (void) XReconfigureWMWindow(display,windows->info.id,windows->info.screen,
6697 (unsigned int) (CWWidth | CWHeight),&window_changes);
6699 if (windows->info.mapped == MagickFalse)
6701 (void) XMapRaised(display,windows->info.id);
6702 windows->info.mapped=MagickTrue;
6705 Initialize Info matte information.
6707 height=(unsigned int) (font_info->ascent+font_info->descent);
6708 XGetWidgetInfo(activity,&monitor_info);
6709 monitor_info.bevel_width--;
6710 margin=monitor_info.bevel_width+((windows->info.height-height) >> 1)-2;
6711 monitor_info.center=MagickFalse;
6712 monitor_info.x=(int) margin;
6713 monitor_info.y=(int) margin;
6714 monitor_info.width=windows->info.width-(margin << 1);
6715 monitor_info.height=windows->info.height-(margin << 1)+1;
6719 monitor_info.raised=MagickFalse;
6720 XDrawBeveledMatte(display,&windows->info,&monitor_info);
6721 monitor_info.raised=MagickTrue;
6722 XDrawWidgetText(display,&windows->info,&monitor_info);
6726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6730 % X L i s t B r o w s e r W i d g e t %
6734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6736 % XListBrowserWidget() displays a List Browser widget with a query to the
6737 % user. The user keys a reply or select a reply from the list. Finally, the
6738 % user presses the Action or Cancel button to exit. The typed text is
6739 % returned as the reply function parameter.
6741 % The format of the XListBrowserWidget method is:
6743 % void XListBrowserWidget(Display *display,XWindows *windows,
6744 % XWindowInfo *window_info,const char **list,const char *action,
6745 % const char *query,char *reply)
6747 % A description of each parameter follows:
6749 % o display: Specifies a connection to an X server; returned from
6752 % o window: Specifies a pointer to a XWindows structure.
6754 % o list: Specifies a pointer to an array of strings. The user can
6755 % select from these strings as a possible reply value.
6757 % o action: Specifies a pointer to the action of this widget.
6759 % o query: Specifies a pointer to the query to present to the user.
6761 % o reply: the response from the user is returned in this parameter.
6764 MagickPrivate void XListBrowserWidget(Display *display,XWindows *windows,
6765 XWindowInfo *window_info,const char **list,const char *action,
6766 const char *query,char *reply)
6768 #define CancelButtonText "Cancel"
6771 primary_selection[MaxTextExtent];
6779 static MagickStatusType
6780 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
6822 Count the number of entries in the list.
6824 assert(display != (Display *) NULL);
6825 assert(windows != (XWindows *) NULL);
6826 assert(window_info != (XWindowInfo *) NULL);
6827 assert(list != (const char **) NULL);
6828 assert(action != (char *) NULL);
6829 assert(query != (char *) NULL);
6830 assert(reply != (char *) NULL);
6831 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
6832 XSetCursorState(display,windows,MagickTrue);
6833 XCheckRefreshWindows(display,windows);
6834 if (list == (const char **) NULL)
6836 XNoticeWidget(display,windows,"No text to browse:",(char *) NULL);
6839 for (entries=0; ; entries++)
6840 if (list[entries] == (char *) NULL)
6843 Determine Font Browser widget attributes.
6845 font_info=window_info->font_info;
6846 text_width=WidgetTextWidth(font_info,(char *) query);
6847 for (i=0; i < (int) entries; i++)
6848 if (WidgetTextWidth(font_info,(char *) list[i]) > text_width)
6849 text_width=WidgetTextWidth(font_info,(char *) list[i]);
6850 width=WidgetTextWidth(font_info,(char *) action);
6851 if (WidgetTextWidth(font_info,CancelButtonText) > width)
6852 width=WidgetTextWidth(font_info,CancelButtonText);
6853 width+=QuantumMargin;
6854 height=(unsigned int) (font_info->ascent+font_info->descent);
6856 Position List Browser widget.
6858 window_info->width=(unsigned int) MagickMin((int) text_width,(int)
6859 MaxTextWidth)+((9*QuantumMargin) >> 1);
6860 window_info->min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
6861 if (window_info->width < window_info->min_width)
6862 window_info->width=window_info->min_width;
6863 window_info->height=(unsigned int)
6864 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
6865 window_info->min_height=(unsigned int)
6866 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
6867 if (window_info->height < window_info->min_height)
6868 window_info->height=window_info->min_height;
6869 XConstrainWindowPosition(display,window_info);
6871 Map List Browser widget.
6873 (void) CopyMagickString(window_info->name,"Browse",MaxTextExtent);
6874 status=XStringListToTextProperty(&window_info->name,1,&window_name);
6875 if (status != False)
6877 XSetWMName(display,window_info->id,&window_name);
6878 XSetWMIconName(display,windows->widget.id,&window_name);
6879 (void) XFree((void *) window_name.value);
6881 window_changes.width=(int) window_info->width;
6882 window_changes.height=(int) window_info->height;
6883 window_changes.x=window_info->x;
6884 window_changes.y=window_info->y;
6885 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,mask,
6887 (void) XMapRaised(display,window_info->id);
6888 window_info->mapped=MagickFalse;
6890 Respond to X events.
6892 XGetWidgetInfo((char *) NULL,&slider_info);
6893 XGetWidgetInfo((char *) NULL,&north_info);
6894 XGetWidgetInfo((char *) NULL,&south_info);
6895 XGetWidgetInfo((char *) NULL,&expose_info);
6897 delay=SuspendTime << 2;
6898 state=UpdateConfigurationState;
6901 if (state & UpdateConfigurationState)
6907 Initialize button information.
6909 XGetWidgetInfo(CancelButtonText,&cancel_info);
6910 cancel_info.width=width;
6911 cancel_info.height=(unsigned int) ((3*height) >> 1);
6913 (window_info->width-cancel_info.width-QuantumMargin-2);
6915 (window_info->height-cancel_info.height-QuantumMargin);
6916 XGetWidgetInfo(action,&action_info);
6917 action_info.width=width;
6918 action_info.height=(unsigned int) ((3*height) >> 1);
6919 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
6920 (action_info.bevel_width << 1));
6921 action_info.y=cancel_info.y;
6923 Initialize reply information.
6925 XGetWidgetInfo(reply,&reply_info);
6926 reply_info.raised=MagickFalse;
6927 reply_info.bevel_width--;
6928 reply_info.width=window_info->width-((4*QuantumMargin) >> 1);
6929 reply_info.height=height << 1;
6930 reply_info.x=QuantumMargin;
6931 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
6933 Initialize scroll information.
6935 XGetWidgetInfo((char *) NULL,&scroll_info);
6936 scroll_info.bevel_width--;
6937 scroll_info.width=height;
6938 scroll_info.height=(unsigned int)
6939 (reply_info.y-((6*QuantumMargin) >> 1)-height);
6940 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
6941 scroll_info.y=((5*QuantumMargin) >> 1)+height-reply_info.bevel_width;
6942 scroll_info.raised=MagickFalse;
6943 scroll_info.trough=MagickTrue;
6944 north_info=scroll_info;
6945 north_info.raised=MagickTrue;
6946 north_info.width-=(north_info.bevel_width << 1);
6947 north_info.height=north_info.width-1;
6948 north_info.x+=north_info.bevel_width;
6949 north_info.y+=north_info.bevel_width;
6950 south_info=north_info;
6951 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
6954 slider_info=north_info;
6956 slider_info.width-=2;
6957 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
6958 slider_info.bevel_width+2;
6959 slider_info.height=scroll_info.height-((slider_info.min_y-
6960 scroll_info.y+1) << 1)+4;
6961 visible_entries=scroll_info.height/(height+(height >> 3));
6962 if (entries > visible_entries)
6963 slider_info.height=(visible_entries*slider_info.height)/entries;
6964 slider_info.max_y=south_info.y-south_info.bevel_width-
6965 slider_info.bevel_width-2;
6966 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
6967 slider_info.y=slider_info.min_y;
6968 expose_info=scroll_info;
6969 expose_info.y=slider_info.y;
6971 Initialize list information.
6973 XGetWidgetInfo((char *) NULL,&list_info);
6974 list_info.raised=MagickFalse;
6975 list_info.bevel_width--;
6976 list_info.width=(unsigned int)
6977 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
6978 list_info.height=scroll_info.height;
6979 list_info.x=reply_info.x;
6980 list_info.y=scroll_info.y;
6981 if (window_info->mapped == MagickFalse)
6982 for (i=0; i < (int) entries; i++)
6983 if (LocaleCompare(list[i],reply) == 0)
6986 slider_info.id=i-(visible_entries >> 1);
6987 if (slider_info.id < 0)
6991 Initialize text information.
6993 XGetWidgetInfo(query,&text_info);
6994 text_info.width=reply_info.width;
6995 text_info.height=height;
6996 text_info.x=list_info.x-(QuantumMargin >> 1);
6997 text_info.y=QuantumMargin;
6999 Initialize selection information.
7001 XGetWidgetInfo((char *) NULL,&selection_info);
7002 selection_info.center=MagickFalse;
7003 selection_info.width=list_info.width;
7004 selection_info.height=(unsigned int) ((9*height) >> 3);
7005 selection_info.x=list_info.x;
7006 state&=(~UpdateConfigurationState);
7008 if (state & RedrawWidgetState)
7011 Redraw List Browser window.
7013 XDrawWidgetText(display,window_info,&text_info);
7014 XDrawBeveledMatte(display,window_info,&list_info);
7015 XDrawBeveledMatte(display,window_info,&scroll_info);
7016 XDrawTriangleNorth(display,window_info,&north_info);
7017 XDrawBeveledButton(display,window_info,&slider_info);
7018 XDrawTriangleSouth(display,window_info,&south_info);
7019 XDrawBeveledMatte(display,window_info,&reply_info);
7020 XDrawMatteText(display,window_info,&reply_info);
7021 XDrawBeveledButton(display,window_info,&action_info);
7022 XDrawBeveledButton(display,window_info,&cancel_info);
7023 XHighlightWidget(display,window_info,BorderOffset,BorderOffset);
7024 selection_info.id=(~0);
7025 state|=RedrawActionState;
7026 state|=RedrawListState;
7027 state&=(~RedrawWidgetState);
7029 if (state & RedrawListState)
7032 Determine slider id and position.
7034 if (slider_info.id >= (int) (entries-visible_entries))
7035 slider_info.id=(int) (entries-visible_entries);
7036 if ((slider_info.id < 0) || (entries <= visible_entries))
7038 slider_info.y=slider_info.min_y;
7041 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/entries;
7042 if (slider_info.id != selection_info.id)
7045 Redraw scroll bar and file names.
7047 selection_info.id=slider_info.id;
7048 selection_info.y=list_info.y+(height >> 3)+2;
7049 for (i=0; i < (int) visible_entries; i++)
7051 selection_info.raised=(slider_info.id+i) != list_info.id ?
7052 MagickTrue : MagickFalse;
7053 selection_info.text=(char *) NULL;
7054 if ((slider_info.id+i) < (int) entries)
7055 selection_info.text=(char *) list[slider_info.id+i];
7056 XDrawWidgetText(display,window_info,&selection_info);
7057 selection_info.y+=(int) selection_info.height;
7062 if (slider_info.y > expose_info.y)
7064 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
7065 expose_info.y=slider_info.y-expose_info.height-
7066 slider_info.bevel_width-1;
7070 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
7071 expose_info.y=slider_info.y+slider_info.height+
7072 slider_info.bevel_width+1;
7074 XDrawTriangleNorth(display,window_info,&north_info);
7075 XDrawMatte(display,window_info,&expose_info);
7076 XDrawBeveledButton(display,window_info,&slider_info);
7077 XDrawTriangleSouth(display,window_info,&south_info);
7078 expose_info.y=slider_info.y;
7080 state&=(~RedrawListState);
7083 Wait for next event.
7085 if (north_info.raised && south_info.raised)
7086 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7090 Brief delay before advancing scroll bar.
7092 XDelay(display,delay);
7094 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
7095 if (north_info.raised == MagickFalse)
7096 if (slider_info.id > 0)
7102 state|=RedrawListState;
7104 if (south_info.raised == MagickFalse)
7105 if (slider_info.id < (int) entries)
7111 state|=RedrawListState;
7113 if (event.type != ButtonRelease)
7120 if (MatteIsActive(slider_info,event.xbutton))
7125 slider_info.active=MagickTrue;
7128 if (MatteIsActive(north_info,event.xbutton))
7129 if (slider_info.id > 0)
7134 north_info.raised=MagickFalse;
7136 state|=RedrawListState;
7139 if (MatteIsActive(south_info,event.xbutton))
7140 if (slider_info.id < (int) entries)
7145 south_info.raised=MagickFalse;
7147 state|=RedrawListState;
7150 if (MatteIsActive(scroll_info,event.xbutton))
7155 if (event.xbutton.y < slider_info.y)
7156 slider_info.id-=(visible_entries-1);
7158 slider_info.id+=(visible_entries-1);
7159 state|=RedrawListState;
7162 if (MatteIsActive(list_info,event.xbutton))
7168 User pressed list matte.
7170 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
7171 selection_info.height;
7172 if (id >= (int) entries)
7174 (void) CopyMagickString(reply_info.text,list[id],MaxTextExtent);
7175 reply_info.highlight=MagickFalse;
7176 reply_info.marker=reply_info.text;
7177 reply_info.cursor=reply_info.text+Extent(reply_info.text);
7178 XDrawMatteText(display,window_info,&reply_info);
7179 selection_info.id=(~0);
7180 if (id == list_info.id)
7182 action_info.raised=MagickFalse;
7183 XDrawBeveledButton(display,window_info,&action_info);
7187 state|=RedrawListState;
7190 if (MatteIsActive(action_info,event.xbutton))
7193 User pressed action button.
7195 action_info.raised=MagickFalse;
7196 XDrawBeveledButton(display,window_info,&action_info);
7199 if (MatteIsActive(cancel_info,event.xbutton))
7202 User pressed Cancel button.
7204 cancel_info.raised=MagickFalse;
7205 XDrawBeveledButton(display,window_info,&cancel_info);
7208 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7210 if (event.xbutton.button != Button2)
7216 Move text cursor to position of button press.
7218 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
7219 for (i=1; i <= Extent(reply_info.marker); i++)
7220 if (XTextWidth(font_info,reply_info.marker,i) > x)
7222 reply_info.cursor=reply_info.marker+i-1;
7223 if (event.xbutton.time > (click_time+DoubleClick))
7224 reply_info.highlight=MagickFalse;
7228 Become the XA_PRIMARY selection owner.
7230 (void) CopyMagickString(primary_selection,reply_info.text,
7232 (void) XSetSelectionOwner(display,XA_PRIMARY,window_info->id,
7233 event.xbutton.time);
7234 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
7235 window_info->id ? MagickTrue : MagickFalse;
7237 XDrawMatteText(display,window_info,&reply_info);
7238 click_time=event.xbutton.time;
7242 Request primary selection.
7244 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
7245 window_info->id,event.xbutton.time);
7250 if (window_info->mapped == MagickFalse)
7252 if (north_info.raised == MagickFalse)
7255 User released up button.
7257 delay=SuspendTime << 2;
7258 north_info.raised=MagickTrue;
7259 XDrawTriangleNorth(display,window_info,&north_info);
7261 if (south_info.raised == MagickFalse)
7264 User released down button.
7266 delay=SuspendTime << 2;
7267 south_info.raised=MagickTrue;
7268 XDrawTriangleSouth(display,window_info,&south_info);
7270 if (slider_info.active)
7273 Stop tracking slider.
7275 slider_info.active=MagickFalse;
7278 if (action_info.raised == MagickFalse)
7280 if (event.xbutton.window == window_info->id)
7282 if (MatteIsActive(action_info,event.xbutton))
7284 if (*reply_info.text == '\0')
7285 (void) XBell(display,0);
7290 action_info.raised=MagickTrue;
7291 XDrawBeveledButton(display,window_info,&action_info);
7293 if (cancel_info.raised == MagickFalse)
7295 if (event.xbutton.window == window_info->id)
7296 if (MatteIsActive(cancel_info,event.xbutton))
7298 *reply_info.text='\0';
7301 cancel_info.raised=MagickTrue;
7302 XDrawBeveledButton(display,window_info,&cancel_info);
7304 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7311 If client window delete message, exit.
7313 if (event.xclient.message_type != windows->wm_protocols)
7315 if (*event.xclient.data.l == (int) windows->wm_take_focus)
7317 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
7318 (Time) event.xclient.data.l[1]);
7321 if (*event.xclient.data.l != (int) windows->wm_delete_window)
7323 if (event.xclient.window == window_info->id)
7325 *reply_info.text='\0';
7331 case ConfigureNotify:
7334 Update widget configuration.
7336 if (event.xconfigure.window != window_info->id)
7338 if ((event.xconfigure.width == (int) window_info->width) &&
7339 (event.xconfigure.height == (int) window_info->height))
7341 window_info->width=(unsigned int)
7342 MagickMax(event.xconfigure.width,(int) window_info->min_width);
7343 window_info->height=(unsigned int)
7344 MagickMax(event.xconfigure.height,(int) window_info->min_height);
7345 state|=UpdateConfigurationState;
7350 if (event.xcrossing.window != window_info->id)
7352 state&=(~InactiveWidgetState);
7357 if (event.xexpose.window != window_info->id)
7359 if (event.xexpose.count != 0)
7361 state|=RedrawWidgetState;
7367 command[MaxTextExtent];
7376 Respond to a user key press.
7378 if (event.xkey.window != window_info->id)
7380 length=XLookupString((XKeyEvent *) &event.xkey,command,
7381 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7382 *(command+length)='\0';
7383 if (AreaIsActive(scroll_info,event.xkey))
7388 switch ((int) key_symbol)
7411 slider_info.id-=visible_entries;
7417 slider_info.id+=visible_entries;
7423 slider_info.id=(int) entries;
7427 state|=RedrawListState;
7430 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
7435 if (*reply_info.text == '\0')
7437 action_info.raised=MagickFalse;
7438 XDrawBeveledButton(display,window_info,&action_info);
7442 if (key_symbol == XK_Control_L)
7444 state|=ControlState;
7447 if (state & ControlState)
7448 switch ((int) key_symbol)
7454 Erase the entire line of text.
7456 *reply_info.text='\0';
7457 reply_info.cursor=reply_info.text;
7458 reply_info.marker=reply_info.text;
7459 reply_info.highlight=MagickFalse;
7465 XEditText(display,&reply_info,key_symbol,command,state);
7466 XDrawMatteText(display,window_info,&reply_info);
7472 command[MaxTextExtent];
7478 Respond to a user key release.
7480 if (event.xkey.window != window_info->id)
7482 (void) XLookupString((XKeyEvent *) &event.xkey,command,
7483 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7484 if (key_symbol == XK_Control_L)
7485 state&=(~ControlState);
7490 if (event.xcrossing.window != window_info->id)
7492 state|=InactiveWidgetState;
7504 Discard pending button motion events.
7506 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7507 if (slider_info.active)
7512 slider_info.y=event.xmotion.y-
7513 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
7514 if (slider_info.y < slider_info.min_y)
7515 slider_info.y=slider_info.min_y;
7516 if (slider_info.y > slider_info.max_y)
7517 slider_info.y=slider_info.max_y;
7519 if (slider_info.y != slider_info.min_y)
7520 slider_info.id=(int) ((entries*(slider_info.y-
7521 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
7522 state|=RedrawListState;
7525 if (state & InactiveWidgetState)
7527 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
7530 Action button status changed.
7532 action_info.raised=action_info.raised == MagickFalse ?
7533 MagickTrue : MagickFalse;
7534 XDrawBeveledButton(display,window_info,&action_info);
7537 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
7540 Cancel button status changed.
7542 cancel_info.raised=cancel_info.raised == MagickFalse ?
7543 MagickTrue : MagickFalse;
7544 XDrawBeveledButton(display,window_info,&cancel_info);
7549 case SelectionClear:
7551 reply_info.highlight=MagickFalse;
7552 XDrawMatteText(display,window_info,&reply_info);
7555 case SelectionNotify:
7571 Obtain response from primary selection.
7573 if (event.xselection.property == (Atom) None)
7575 status=XGetWindowProperty(display,
7576 event.xselection.requestor,event.xselection.property,0L,2047L,
7577 MagickTrue,XA_STRING,&type,&format,&length,&after,&data);
7578 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
7581 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
7582 (void) XBell(display,0);
7586 Insert primary selection in reply text.
7588 *(data+length)='\0';
7589 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
7591 XDrawMatteText(display,window_info,&reply_info);
7592 state|=RedrawActionState;
7594 (void) XFree((void *) data);
7597 case SelectionRequest:
7602 XSelectionRequestEvent
7605 if (reply_info.highlight == MagickFalse)
7608 Set primary selection.
7610 request=(&(event.xselectionrequest));
7611 (void) XChangeProperty(request->display,request->requestor,
7612 request->property,request->target,8,PropModeReplace,
7613 (unsigned char *) primary_selection,Extent(primary_selection));
7614 notify.type=SelectionNotify;
7615 notify.send_event=MagickTrue;
7616 notify.display=request->display;
7617 notify.requestor=request->requestor;
7618 notify.selection=request->selection;
7619 notify.target=request->target;
7620 notify.time=request->time;
7621 if (request->property == None)
7622 notify.property=request->target;
7624 notify.property=request->property;
7625 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
7626 (XEvent *) ¬ify);
7631 } while ((state & ExitState) == 0);
7632 XSetCursorState(display,windows,MagickFalse);
7633 (void) XWithdrawWindow(display,window_info->id,window_info->screen);
7634 XCheckRefreshWindows(display,windows);
7638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7642 % X M e n u W i d g e t %
7646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7648 % XMenuWidget() maps a menu and returns the command pointed to by the user
7649 % when the button is released.
7651 % The format of the XMenuWidget method is:
7653 % int XMenuWidget(Display *display,XWindows *windows,const char *title,
7654 % const char **selections,char *item)
7656 % A description of each parameter follows:
7658 % o selection_number: Specifies the number of the selection that the
7661 % o display: Specifies a connection to an X server; returned from
7664 % o window: Specifies a pointer to a XWindows structure.
7666 % o title: Specifies a character string that describes the menu selections.
7668 % o selections: Specifies a pointer to one or more strings that comprise
7669 % the choices in the menu.
7671 % o item: Specifies a character array. The item selected from the menu
7675 MagickPrivate int XMenuWidget(Display *display,XWindows *windows,
7676 const char *title,const char **selections,char *item)
7702 XSetWindowAttributes
7714 Determine Menu widget attributes.
7716 assert(display != (Display *) NULL);
7717 assert(windows != (XWindows *) NULL);
7718 assert(title != (char *) NULL);
7719 assert(selections != (const char **) NULL);
7720 assert(item != (char *) NULL);
7721 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
7722 font_info=windows->widget.font_info;
7723 windows->widget.width=submenu_info.active == 0 ?
7724 WidgetTextWidth(font_info,(char *) title) : 0;
7725 for (id=0; selections[id] != (char *) NULL; id++)
7727 width=WidgetTextWidth(font_info,(char *) selections[id]);
7728 if (width > windows->widget.width)
7729 windows->widget.width=width;
7731 number_selections=(unsigned int) id;
7732 XGetWidgetInfo((char *) NULL,&menu_info);
7733 title_height=(unsigned int) (submenu_info.active == 0 ?
7734 (3*(font_info->descent+font_info->ascent) >> 1)+5 : 2);
7735 width=WidgetTextWidth(font_info,(char *) title);
7736 height=(unsigned int) ((3*(font_info->ascent+font_info->descent)) >> 1);
7738 Position Menu widget.
7740 windows->widget.width+=QuantumMargin+(menu_info.bevel_width << 1);
7741 top_offset=title_height+menu_info.bevel_width-1;
7742 windows->widget.height=top_offset+number_selections*height+4;
7743 windows->widget.min_width=windows->widget.width;
7744 windows->widget.min_height=windows->widget.height;
7745 XQueryPosition(display,windows->widget.root,&x,&y);
7746 windows->widget.x=x-(QuantumMargin >> 1);
7747 if (submenu_info.active != 0)
7750 windows->command.x+windows->command.width-QuantumMargin;
7751 toggle_info.raised=MagickTrue;
7752 XDrawTriangleEast(display,&windows->command,&toggle_info);
7754 windows->widget.y=submenu_info.active == 0 ? y-(int)
7755 ((3*title_height) >> 2) : y;
7756 if (submenu_info.active != 0)
7757 windows->widget.y=windows->command.y+submenu_info.y;
7758 XConstrainWindowPosition(display,&windows->widget);
7762 window_attributes.override_redirect=MagickTrue;
7763 (void) XChangeWindowAttributes(display,windows->widget.id,
7764 (size_t) CWOverrideRedirect,&window_attributes);
7765 window_changes.width=(int) windows->widget.width;
7766 window_changes.height=(int) windows->widget.height;
7767 window_changes.x=windows->widget.x;
7768 window_changes.y=windows->widget.y;
7769 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
7770 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
7771 (void) XMapRaised(display,windows->widget.id);
7772 windows->widget.mapped=MagickFalse;
7774 Respond to X events.
7776 selection_info.height=height;
7777 cursor=XCreateFontCursor(display,XC_right_ptr);
7778 (void) XCheckDefineCursor(display,windows->image.id,cursor);
7779 (void) XCheckDefineCursor(display,windows->command.id,cursor);
7780 (void) XCheckDefineCursor(display,windows->widget.id,cursor);
7781 state=UpdateConfigurationState;
7784 if (state & UpdateConfigurationState)
7787 Initialize selection information.
7789 XGetWidgetInfo((char *) NULL,&menu_info);
7790 menu_info.bevel_width--;
7791 menu_info.width=windows->widget.width-((menu_info.bevel_width) << 1);
7792 menu_info.height=windows->widget.height-((menu_info.bevel_width) << 1);
7793 menu_info.x=(int) menu_info.bevel_width;
7794 menu_info.y=(int) menu_info.bevel_width;
7795 XGetWidgetInfo((char *) NULL,&selection_info);
7796 selection_info.center=MagickFalse;
7797 selection_info.width=menu_info.width;
7798 selection_info.height=height;
7799 selection_info.x=menu_info.x;
7800 highlight_info=selection_info;
7801 highlight_info.bevel_width--;
7802 highlight_info.width-=(highlight_info.bevel_width << 1);
7803 highlight_info.height-=(highlight_info.bevel_width << 1);
7804 highlight_info.x+=highlight_info.bevel_width;
7805 state&=(~UpdateConfigurationState);
7807 if (state & RedrawWidgetState)
7812 if (submenu_info.active == 0)
7814 y=(int) title_height;
7815 XSetBevelColor(display,&windows->widget,MagickFalse);
7816 (void) XDrawLine(display,windows->widget.id,
7817 windows->widget.widget_context,selection_info.x,y-1,
7818 (int) selection_info.width,y-1);
7819 XSetBevelColor(display,&windows->widget,MagickTrue);
7820 (void) XDrawLine(display,windows->widget.id,
7821 windows->widget.widget_context,selection_info.x,y,
7822 (int) selection_info.width,y);
7823 (void) XSetFillStyle(display,windows->widget.widget_context,
7827 Draw menu selections.
7829 selection_info.center=MagickTrue;
7830 selection_info.y=(int) menu_info.bevel_width;
7831 selection_info.text=(char *) title;
7832 if (submenu_info.active == 0)
7833 XDrawWidgetText(display,&windows->widget,&selection_info);
7834 selection_info.center=MagickFalse;
7835 selection_info.y=(int) top_offset;
7836 for (id=0; id < (int) number_selections; id++)
7838 selection_info.text=(char *) selections[id];
7839 XDrawWidgetText(display,&windows->widget,&selection_info);
7840 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7841 if (id == selection_info.id)
7842 XDrawBevel(display,&windows->widget,&highlight_info);
7843 selection_info.y+=(int) selection_info.height;
7845 XDrawBevel(display,&windows->widget,&menu_info);
7846 state&=(~RedrawWidgetState);
7848 if (number_selections > 2)
7853 y=(int) (top_offset+selection_info.height*(number_selections-1));
7854 XSetBevelColor(display,&windows->widget,MagickFalse);
7855 (void) XDrawLine(display,windows->widget.id,
7856 windows->widget.widget_context,selection_info.x,y-1,
7857 (int) selection_info.width,y-1);
7858 XSetBevelColor(display,&windows->widget,MagickTrue);
7859 (void) XDrawLine(display,windows->widget.id,
7860 windows->widget.widget_context,selection_info.x,y,
7861 (int) selection_info.width,y);
7862 (void) XSetFillStyle(display,windows->widget.widget_context,FillSolid);
7865 Wait for next event.
7867 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7872 if (event.xbutton.window != windows->widget.id)
7877 if (event.xbutton.window == windows->command.id)
7878 (void) XPutBackEvent(display,&event);
7879 selection_info.id=(~0);
7884 state&=(~InactiveWidgetState);
7885 id=(event.xbutton.y-top_offset)/(int) selection_info.height;
7886 selection_info.id=id;
7887 if ((id < 0) || (id >= (int) number_selections))
7890 Highlight this selection.
7892 selection_info.y=(int) (top_offset+id*selection_info.height);
7893 selection_info.text=(char *) selections[id];
7894 XDrawWidgetText(display,&windows->widget,&selection_info);
7895 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7896 XDrawBevel(display,&windows->widget,&highlight_info);
7901 if (windows->widget.mapped == MagickFalse)
7903 if (event.xbutton.window == windows->command.id)
7904 if ((state & InactiveWidgetState) == 0)
7909 XSetCursorState(display,windows,MagickFalse);
7914 case ConfigureNotify:
7917 Update widget configuration.
7919 if (event.xconfigure.window != windows->widget.id)
7921 if ((event.xconfigure.width == (int) windows->widget.width) &&
7922 (event.xconfigure.height == (int) windows->widget.height))
7924 windows->widget.width=(unsigned int)
7925 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
7926 windows->widget.height=(unsigned int)
7927 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
7928 state|=UpdateConfigurationState;
7933 if (event.xcrossing.window != windows->widget.id)
7935 if (event.xcrossing.state == 0)
7937 state&=(~InactiveWidgetState);
7938 id=((event.xcrossing.y-top_offset)/(int) selection_info.height);
7939 if ((selection_info.id >= 0) &&
7940 (selection_info.id < (int) number_selections))
7943 Unhighlight last selection.
7945 if (id == selection_info.id)
7947 selection_info.y=(int)
7948 (top_offset+selection_info.id*selection_info.height);
7949 selection_info.text=(char *) selections[selection_info.id];
7950 XDrawWidgetText(display,&windows->widget,&selection_info);
7952 if ((id < 0) || (id >= (int) number_selections))
7955 Highlight this selection.
7957 selection_info.id=id;
7958 selection_info.y=(int)
7959 (top_offset+selection_info.id*selection_info.height);
7960 selection_info.text=(char *) selections[selection_info.id];
7961 XDrawWidgetText(display,&windows->widget,&selection_info);
7962 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7963 XDrawBevel(display,&windows->widget,&highlight_info);
7968 if (event.xexpose.window != windows->widget.id)
7970 if (event.xexpose.count != 0)
7972 state|=RedrawWidgetState;
7977 if (event.xcrossing.window != windows->widget.id)
7979 state|=InactiveWidgetState;
7980 id=selection_info.id;
7981 if ((id < 0) || (id >= (int) number_selections))
7984 Unhighlight last selection.
7986 selection_info.y=(int) (top_offset+id*selection_info.height);
7987 selection_info.id=(~0);
7988 selection_info.text=(char *) selections[id];
7989 XDrawWidgetText(display,&windows->widget,&selection_info);
7995 Discard pending button motion events.
7997 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7998 if (submenu_info.active != 0)
7999 if (event.xmotion.window == windows->command.id)
8001 if ((state & InactiveWidgetState) == 0)
8003 if (MatteIsActive(submenu_info,event.xmotion) == MagickFalse)
8005 selection_info.id=(~0);
8012 if (WindowIsActive(windows->command,event.xmotion))
8014 selection_info.id=(~0);
8020 if (event.xmotion.window != windows->widget.id)
8022 if (state & InactiveWidgetState)
8024 id=(event.xmotion.y-top_offset)/(int) selection_info.height;
8025 if ((selection_info.id >= 0) &&
8026 (selection_info.id < (int) number_selections))
8029 Unhighlight last selection.
8031 if (id == selection_info.id)
8033 selection_info.y=(int)
8034 (top_offset+selection_info.id*selection_info.height);
8035 selection_info.text=(char *) selections[selection_info.id];
8036 XDrawWidgetText(display,&windows->widget,&selection_info);
8038 selection_info.id=id;
8039 if ((id < 0) || (id >= (int) number_selections))
8042 Highlight this selection.
8044 selection_info.y=(int) (top_offset+id*selection_info.height);
8045 selection_info.text=(char *) selections[id];
8046 XDrawWidgetText(display,&windows->widget,&selection_info);
8047 highlight_info.y=selection_info.y+highlight_info.bevel_width;
8048 XDrawBevel(display,&windows->widget,&highlight_info);
8054 } while ((state & ExitState) == 0);
8055 (void) XFreeCursor(display,cursor);
8056 window_attributes.override_redirect=MagickFalse;
8057 (void) XChangeWindowAttributes(display,windows->widget.id,
8058 (size_t) CWOverrideRedirect,&window_attributes);
8059 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8060 XCheckRefreshWindows(display,windows);
8061 if (submenu_info.active != 0)
8063 submenu_info.active=MagickFalse;
8064 toggle_info.raised=MagickFalse;
8065 XDrawTriangleEast(display,&windows->command,&toggle_info);
8067 if ((selection_info.id < 0) || (selection_info.id >= (int) number_selections))
8069 (void) CopyMagickString(item,selections[selection_info.id],MaxTextExtent);
8070 return(selection_info.id);
8074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8078 % X N o t i c e W i d g e t %
8082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8084 % XNoticeWidget() displays a Notice widget with a notice to the user. The
8085 % function returns when the user presses the "Dismiss" button.
8087 % The format of the XNoticeWidget method is:
8089 % void XNoticeWidget(Display *display,XWindows *windows,
8090 % const char *reason,const char *description)
8092 % A description of each parameter follows:
8094 % o display: Specifies a connection to an X server; returned from
8097 % o window: Specifies a pointer to a XWindows structure.
8099 % o reason: Specifies the message to display before terminating the
8102 % o description: Specifies any description to the message.
8105 MagickPrivate void XNoticeWidget(Display *display,XWindows *windows,
8106 const char *reason,const char *description)
8108 #define DismissButtonText "Dismiss"
8147 Determine Notice widget attributes.
8149 assert(display != (Display *) NULL);
8150 assert(windows != (XWindows *) NULL);
8151 assert(reason != (char *) NULL);
8152 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
8153 XDelay(display,SuspendTime << 3); /* avoid surpise with delay */
8154 XSetCursorState(display,windows,MagickTrue);
8155 XCheckRefreshWindows(display,windows);
8156 font_info=windows->widget.font_info;
8157 width=WidgetTextWidth(font_info,DismissButtonText);
8158 text=GetLocaleExceptionMessage(XServerError,reason);
8159 if (text != (char *) NULL)
8160 if (WidgetTextWidth(font_info,(char *) text) > width)
8161 width=WidgetTextWidth(font_info,(char *) text);
8162 if (description != (char *) NULL)
8164 text=GetLocaleExceptionMessage(XServerError,description);
8165 if (text != (char *) NULL)
8166 if (WidgetTextWidth(font_info,(char *) text) > width)
8167 width=WidgetTextWidth(font_info,(char *) text);
8169 height=(unsigned int) (font_info->ascent+font_info->descent);
8171 Position Notice widget.
8173 windows->widget.width=width+4*QuantumMargin;
8174 windows->widget.min_width=width+QuantumMargin;
8175 if (windows->widget.width < windows->widget.min_width)
8176 windows->widget.width=windows->widget.min_width;
8177 windows->widget.height=(unsigned int) (12*height);
8178 windows->widget.min_height=(unsigned int) (7*height);
8179 if (windows->widget.height < windows->widget.min_height)
8180 windows->widget.height=windows->widget.min_height;
8181 XConstrainWindowPosition(display,&windows->widget);
8185 (void) CopyMagickString(windows->widget.name,"Notice",MaxTextExtent);
8186 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8187 if (status != False)
8189 XSetWMName(display,windows->widget.id,&window_name);
8190 XSetWMIconName(display,windows->widget.id,&window_name);
8191 (void) XFree((void *) window_name.value);
8193 window_changes.width=(int) windows->widget.width;
8194 window_changes.height=(int) windows->widget.height;
8195 window_changes.x=windows->widget.x;
8196 window_changes.y=windows->widget.y;
8197 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8198 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8199 (void) XMapRaised(display,windows->widget.id);
8200 windows->widget.mapped=MagickFalse;
8201 (void) XBell(display,0);
8203 Respond to X events.
8205 timer=time((time_t *) NULL)+Timeout;
8206 state=UpdateConfigurationState;
8209 if (time((time_t *) NULL) > timer)
8211 if (state & UpdateConfigurationState)
8214 Initialize Dismiss button information.
8216 XGetWidgetInfo(DismissButtonText,&dismiss_info);
8217 dismiss_info.width=(unsigned int) QuantumMargin+
8218 WidgetTextWidth(font_info,DismissButtonText);
8219 dismiss_info.height=(unsigned int) ((3*height) >> 1);
8220 dismiss_info.x=(int)
8221 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
8222 dismiss_info.y=(int)
8223 (windows->widget.height-(dismiss_info.height << 1));
8224 state&=(~UpdateConfigurationState);
8226 if (state & RedrawWidgetState)
8229 Redraw Notice widget.
8231 width=WidgetTextWidth(font_info,(char *) reason);
8232 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8233 y=(int) ((windows->widget.height >> 1)-(height << 1));
8234 (void) XDrawString(display,windows->widget.id,
8235 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
8236 if (description != (char *) NULL)
8238 width=WidgetTextWidth(font_info,(char *) description);
8239 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8241 (void) XDrawString(display,windows->widget.id,
8242 windows->widget.annotate_context,x,y,(char *) description,
8243 Extent(description));
8245 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8246 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8247 state&=(~RedrawWidgetState);
8250 Wait for next event.
8252 if (XCheckIfEvent(display,&event,XScreenEvent,(char *) windows) == MagickFalse)
8255 Do not block if delay > 0.
8257 XDelay(display,SuspendTime << 2);
8264 if (MatteIsActive(dismiss_info,event.xbutton))
8267 User pressed Dismiss button.
8269 dismiss_info.raised=MagickFalse;
8270 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8277 if (windows->widget.mapped == MagickFalse)
8279 if (dismiss_info.raised == MagickFalse)
8281 if (event.xbutton.window == windows->widget.id)
8282 if (MatteIsActive(dismiss_info,event.xbutton))
8284 dismiss_info.raised=MagickTrue;
8285 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8292 If client window delete message, exit.
8294 if (event.xclient.message_type != windows->wm_protocols)
8296 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8298 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8299 (Time) event.xclient.data.l[1]);
8302 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8304 if (event.xclient.window == windows->widget.id)
8311 case ConfigureNotify:
8314 Update widget configuration.
8316 if (event.xconfigure.window != windows->widget.id)
8318 if ((event.xconfigure.width == (int) windows->widget.width) &&
8319 (event.xconfigure.height == (int) windows->widget.height))
8321 windows->widget.width=(unsigned int)
8322 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8323 windows->widget.height=(unsigned int)
8324 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8325 state|=UpdateConfigurationState;
8330 if (event.xcrossing.window != windows->widget.id)
8332 state&=(~InactiveWidgetState);
8337 if (event.xexpose.window != windows->widget.id)
8339 if (event.xexpose.count != 0)
8341 state|=RedrawWidgetState;
8347 command[MaxTextExtent];
8353 Respond to a user key press.
8355 if (event.xkey.window != windows->widget.id)
8357 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8358 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8359 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8361 dismiss_info.raised=MagickFalse;
8362 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8370 if (event.xcrossing.window != windows->widget.id)
8372 state|=InactiveWidgetState;
8378 Discard pending button motion events.
8380 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8381 if (state & InactiveWidgetState)
8383 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
8386 Dismiss button status changed.
8388 dismiss_info.raised=
8389 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8390 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8398 } while ((state & ExitState) == 0);
8399 XSetCursorState(display,windows,MagickFalse);
8400 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8401 XCheckRefreshWindows(display,windows);
8405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8409 % X P r e f e r e n c e s W i d g e t %
8413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8415 % XPreferencesWidget() displays a Preferences widget with program preferences.
8416 % If the user presses the Apply button, the preferences are stored in a
8417 % configuration file in the users' home directory.
8419 % The format of the XPreferencesWidget method is:
8421 % MagickBooleanType XPreferencesWidget(Display *display,
8422 % XResourceInfo *resource_info,XWindows *windows)
8424 % A description of each parameter follows:
8426 % o display: Specifies a connection to an X server; returned from
8429 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8431 % o window: Specifies a pointer to a XWindows structure.
8434 MagickPrivate MagickBooleanType XPreferencesWidget(Display *display,
8435 XResourceInfo *resource_info,XWindows *windows)
8437 #define ApplyButtonText "Apply"
8438 #define CacheButtonText "%lu mega-bytes of memory in the undo edit cache "
8439 #define CancelButtonText "Cancel"
8440 #define NumberPreferences 8
8445 "display image centered on a backdrop",
8446 "confirm on program exit",
8447 "confirm on image edits",
8448 "correct image for display gamma",
8449 "display warning messages",
8450 "apply Floyd/Steinberg error diffusion to image",
8451 "use a shared colormap for colormapped X visuals",
8452 "display images as an X server pixmap"
8456 cache[MaxTextExtent];
8489 preferences_info[NumberPreferences];
8495 Determine Preferences widget attributes.
8497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8498 assert(display != (Display *) NULL);
8499 assert(resource_info != (XResourceInfo *) NULL);
8500 assert(windows != (XWindows *) NULL);
8501 XCheckRefreshWindows(display,windows);
8502 font_info=windows->widget.font_info;
8503 text_width=WidgetTextWidth(font_info,CacheButtonText);
8504 for (i=0; i < NumberPreferences; i++)
8505 if (WidgetTextWidth(font_info,(char *) Preferences[i]) > text_width)
8506 text_width=WidgetTextWidth(font_info,(char *) Preferences[i]);
8507 width=WidgetTextWidth(font_info,ApplyButtonText);
8508 if (WidgetTextWidth(font_info,CancelButtonText) > width)
8509 width=WidgetTextWidth(font_info,CancelButtonText);
8510 width+=(unsigned int) QuantumMargin;
8511 height=(unsigned int) (font_info->ascent+font_info->descent);
8513 Position Preferences widget.
8515 windows->widget.width=(unsigned int) (MagickMax((int) (width << 1),
8516 (int) text_width)+6*QuantumMargin);
8517 windows->widget.min_width=(width << 1)+QuantumMargin;
8518 if (windows->widget.width < windows->widget.min_width)
8519 windows->widget.width=windows->widget.min_width;
8520 windows->widget.height=(unsigned int)
8521 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8522 windows->widget.min_height=(unsigned int)
8523 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8524 if (windows->widget.height < windows->widget.min_height)
8525 windows->widget.height=windows->widget.min_height;
8526 XConstrainWindowPosition(display,&windows->widget);
8528 Map Preferences widget.
8530 (void) CopyMagickString(windows->widget.name,"Preferences",MaxTextExtent);
8531 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8532 if (status != False)
8534 XSetWMName(display,windows->widget.id,&window_name);
8535 XSetWMIconName(display,windows->widget.id,&window_name);
8536 (void) XFree((void *) window_name.value);
8538 window_changes.width=(int) windows->widget.width;
8539 window_changes.height=(int) windows->widget.height;
8540 window_changes.x=windows->widget.x;
8541 window_changes.y=windows->widget.y;
8542 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8543 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8544 (void) XMapRaised(display,windows->widget.id);
8545 windows->widget.mapped=MagickFalse;
8547 Respond to X events.
8549 state=UpdateConfigurationState;
8550 XSetCursorState(display,windows,MagickTrue);
8553 if (state & UpdateConfigurationState)
8556 Initialize button information.
8558 XGetWidgetInfo(CancelButtonText,&cancel_info);
8559 cancel_info.width=width;
8560 cancel_info.height=(unsigned int) (3*height) >> 1;
8561 cancel_info.x=(int) windows->widget.width-cancel_info.width-
8562 (QuantumMargin << 1);
8563 cancel_info.y=(int) windows->widget.height-
8564 cancel_info.height-QuantumMargin;
8565 XGetWidgetInfo(ApplyButtonText,&apply_info);
8566 apply_info.width=width;
8567 apply_info.height=(unsigned int) (3*height) >> 1;
8568 apply_info.x=QuantumMargin << 1;
8569 apply_info.y=cancel_info.y;
8570 y=(int) (height << 1);
8571 for (i=0; i < NumberPreferences; i++)
8573 XGetWidgetInfo(Preferences[i],&preferences_info[i]);
8574 preferences_info[i].bevel_width--;
8575 preferences_info[i].width=(unsigned int) QuantumMargin >> 1;
8576 preferences_info[i].height=(unsigned int) QuantumMargin >> 1;
8577 preferences_info[i].x=QuantumMargin << 1;
8578 preferences_info[i].y=y;
8579 y+=height+(QuantumMargin >> 1);
8581 preferences_info[0].raised=resource_info->backdrop ==
8582 MagickFalse ? MagickTrue : MagickFalse;
8583 preferences_info[1].raised=resource_info->confirm_exit ==
8584 MagickFalse ? MagickTrue : MagickFalse;
8585 preferences_info[2].raised=resource_info->confirm_edit ==
8586 MagickFalse ? MagickTrue : MagickFalse;
8587 preferences_info[3].raised=resource_info->gamma_correct ==
8588 MagickFalse ? MagickTrue : MagickFalse;
8589 preferences_info[4].raised=resource_info->display_warnings ==
8590 MagickFalse ? MagickTrue : MagickFalse;
8591 preferences_info[5].raised=resource_info->quantize_info->dither ==
8592 MagickFalse ? MagickTrue : MagickFalse;
8593 preferences_info[6].raised=resource_info->colormap !=
8594 SharedColormap ? MagickTrue : MagickFalse;
8595 preferences_info[7].raised=resource_info->use_pixmap ==
8596 MagickFalse ? MagickTrue : MagickFalse;
8597 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8598 (unsigned long) resource_info->undo_cache);
8599 XGetWidgetInfo(cache,&cache_info);
8600 cache_info.bevel_width--;
8601 cache_info.width=(unsigned int) QuantumMargin >> 1;
8602 cache_info.height=(unsigned int) QuantumMargin >> 1;
8603 cache_info.x=QuantumMargin << 1;
8605 state&=(~UpdateConfigurationState);
8607 if (state & RedrawWidgetState)
8610 Redraw Preferences widget.
8612 XDrawBeveledButton(display,&windows->widget,&apply_info);
8613 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8614 for (i=0; i < NumberPreferences; i++)
8615 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8616 XDrawTriangleEast(display,&windows->widget,&cache_info);
8617 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8618 state&=(~RedrawWidgetState);
8621 Wait for next event.
8623 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
8628 if (MatteIsActive(apply_info,event.xbutton))
8631 User pressed Apply button.
8633 apply_info.raised=MagickFalse;
8634 XDrawBeveledButton(display,&windows->widget,&apply_info);
8637 if (MatteIsActive(cancel_info,event.xbutton))
8640 User pressed Cancel button.
8642 cancel_info.raised=MagickFalse;
8643 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8646 for (i=0; i < NumberPreferences; i++)
8647 if (MatteIsActive(preferences_info[i],event.xbutton))
8650 User pressed a Preferences button.
8652 preferences_info[i].raised=preferences_info[i].raised ==
8653 MagickFalse ? MagickTrue : MagickFalse;
8654 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8657 if (MatteIsActive(cache_info,event.xbutton))
8660 User pressed Cache button.
8662 x=cache_info.x+cache_info.width+cache_info.bevel_width+
8663 (QuantumMargin >> 1);
8664 y=cache_info.y+((cache_info.height-height) >> 1);
8665 width=WidgetTextWidth(font_info,cache);
8666 (void) XClearArea(display,windows->widget.id,x,y,width,height,
8668 resource_info->undo_cache<<=1;
8669 if (resource_info->undo_cache > 256)
8670 resource_info->undo_cache=1;
8671 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8672 (unsigned long) resource_info->undo_cache);
8673 cache_info.raised=MagickFalse;
8674 XDrawTriangleEast(display,&windows->widget,&cache_info);
8681 if (windows->widget.mapped == MagickFalse)
8683 if (apply_info.raised == MagickFalse)
8685 if (event.xbutton.window == windows->widget.id)
8686 if (MatteIsActive(apply_info,event.xbutton))
8688 apply_info.raised=MagickTrue;
8689 XDrawBeveledButton(display,&windows->widget,&apply_info);
8690 apply_info.raised=MagickFalse;
8692 if (cancel_info.raised == MagickFalse)
8694 if (event.xbutton.window == windows->widget.id)
8695 if (MatteIsActive(cancel_info,event.xbutton))
8697 cancel_info.raised=MagickTrue;
8698 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8700 if (cache_info.raised == MagickFalse)
8702 cache_info.raised=MagickTrue;
8703 XDrawTriangleEast(display,&windows->widget,&cache_info);
8710 If client window delete message, exit.
8712 if (event.xclient.message_type != windows->wm_protocols)
8714 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8716 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8717 (Time) event.xclient.data.l[1]);
8720 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8722 if (event.xclient.window == windows->widget.id)
8729 case ConfigureNotify:
8732 Update widget configuration.
8734 if (event.xconfigure.window != windows->widget.id)
8736 if ((event.xconfigure.width == (int) windows->widget.width) &&
8737 (event.xconfigure.height == (int) windows->widget.height))
8739 windows->widget.width=(unsigned int)
8740 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8741 windows->widget.height=(unsigned int)
8742 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8743 state|=UpdateConfigurationState;
8748 if (event.xcrossing.window != windows->widget.id)
8750 state&=(~InactiveWidgetState);
8755 if (event.xexpose.window != windows->widget.id)
8757 if (event.xexpose.count != 0)
8759 state|=RedrawWidgetState;
8765 command[MaxTextExtent];
8771 Respond to a user key press.
8773 if (event.xkey.window != windows->widget.id)
8775 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8776 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8777 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8779 apply_info.raised=MagickFalse;
8780 XDrawBeveledButton(display,&windows->widget,&apply_info);
8788 if (event.xcrossing.window != windows->widget.id)
8790 state|=InactiveWidgetState;
8796 Discard pending button motion events.
8798 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8799 if (state & InactiveWidgetState)
8801 if (apply_info.raised == MatteIsActive(apply_info,event.xmotion))
8804 Apply button status changed.
8807 apply_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8808 XDrawBeveledButton(display,&windows->widget,&apply_info);
8811 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
8814 Cancel button status changed.
8817 cancel_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8818 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8826 } while ((state & ExitState) == 0);
8827 XSetCursorState(display,windows,MagickFalse);
8828 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8829 XCheckRefreshWindows(display,windows);
8830 if (apply_info.raised)
8831 return(MagickFalse);
8833 Save user preferences to the client configuration file.
8835 resource_info->backdrop=
8836 preferences_info[0].raised == MagickFalse ? MagickTrue : MagickFalse;
8837 resource_info->confirm_exit=
8838 preferences_info[1].raised == MagickFalse ? MagickTrue : MagickFalse;
8839 resource_info->confirm_edit=
8840 preferences_info[2].raised == MagickFalse ? MagickTrue : MagickFalse;
8841 resource_info->gamma_correct=
8842 preferences_info[3].raised == MagickFalse ? MagickTrue : MagickFalse;
8843 resource_info->display_warnings=
8844 preferences_info[4].raised == MagickFalse ? MagickTrue : MagickFalse;
8845 resource_info->quantize_info->dither=
8846 preferences_info[5].raised == MagickFalse ? MagickTrue : MagickFalse;
8847 resource_info->colormap=SharedColormap;
8848 if (preferences_info[6].raised)
8849 resource_info->colormap=PrivateColormap;
8850 resource_info->use_pixmap=
8851 preferences_info[7].raised == MagickFalse ? MagickTrue : MagickFalse;
8852 XUserPreferences(resource_info);
8857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8861 % X P r o g r e s s M o n i t o r W i d g e t %
8865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8867 % XProgressMonitorWidget() displays the progress a task is making in
8868 % completing a task. A span of zero toggles the active status. An inactive
8869 % state disables the progress monitor.
8871 % The format of the XProgressMonitorWidget method is:
8873 % void XProgressMonitorWidget(Display *display,XWindows *windows,
8874 % const char *task,const MagickOffsetType offset,
8875 % const MagickSizeType span)
8877 % A description of each parameter follows:
8879 % o display: Specifies a connection to an X server; returned from
8882 % o window: Specifies a pointer to a XWindows structure.
8884 % o task: Identifies the task in progress.
8886 % o offset: Specifies the offset position within the span which represents
8887 % how much progress has been made in completing a task.
8889 % o span: Specifies the span relative to completing a task.
8892 MagickPrivate void XProgressMonitorWidget(Display *display,XWindows *windows,
8893 const char *task,const MagickOffsetType offset,const MagickSizeType span)
8901 assert(display != (Display *) NULL);
8902 assert(windows != (XWindows *) NULL);
8903 assert(task != (const char *) NULL);
8904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",task);
8908 Update image windows if there is a pending expose event.
8910 while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
8911 (void) XCommandWidget(display,windows,(const char **) NULL,&event);
8912 while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
8913 XRefreshWindow(display,&windows->image,&event);
8914 while (XCheckTypedWindowEvent(display,windows->info.id,Expose,&event))
8915 if (monitor_info.text != (char *) NULL)
8916 XInfoWidget(display,windows,monitor_info.text);
8918 Draw progress monitor bar to represent percent completion of a task.
8920 if ((windows->info.mapped == MagickFalse) || (task != monitor_info.text))
8921 XInfoWidget(display,windows,task);
8922 width=(unsigned int) (((offset+1)*(windows->info.width-
8923 (2*monitor_info.x)))/span);
8924 if (width < monitor_info.width)
8926 monitor_info.raised=MagickTrue;
8927 XDrawWidgetText(display,&windows->info,&monitor_info);
8928 monitor_info.raised=MagickFalse;
8930 monitor_info.width=width;
8931 XDrawWidgetText(display,&windows->info,&monitor_info);
8932 (void) XFlush(display);
8936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8940 % X T e x t V i e w W i d g e t %
8944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8946 % XTextViewWidget() displays text in a Text View widget.
8948 % The format of the XTextViewWidget method is:
8950 % void XTextViewWidget(Display *display,const XResourceInfo *resource_info,
8951 % XWindows *windows,const MagickBooleanType mono,const char *title,
8952 % const char **textlist)
8954 % A description of each parameter follows:
8956 % o display: Specifies a connection to an X server; returned from
8959 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8961 % o window: Specifies a pointer to a XWindows structure.
8963 % o mono: Use mono-spaced font when displaying text.
8965 % o title: This character string is displayed at the top of the widget
8968 % o textlist: This string list is displayed within the Text View widget.
8971 MagickPrivate void XTextViewWidget(Display *display,
8972 const XResourceInfo *resource_info,XWindows *windows,
8973 const MagickBooleanType mono,const char *title,const char **textlist)
8975 #define DismissButtonText "Dismiss"
8978 primary_selection[MaxTextExtent];
8983 static MagickStatusType
8984 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
9024 Convert text string to a text list.
9026 assert(display != (Display *) NULL);
9027 assert(resource_info != (XResourceInfo *) NULL);
9028 assert(windows != (XWindows *) NULL);
9029 assert(title != (const char *) NULL);
9030 assert(textlist != (const char **) NULL);
9031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
9032 XSetCursorState(display,windows,MagickTrue);
9033 XCheckRefreshWindows(display,windows);
9034 if (textlist == (const char **) NULL)
9036 XNoticeWidget(display,windows,"No text to view:",(char *) NULL);
9040 Determine Text View widget attributes.
9042 font_info=windows->widget.font_info;
9043 text_info=(XFontStruct *) NULL;
9044 if (mono != MagickFalse)
9045 text_info=XBestFont(display,resource_info,MagickTrue);
9046 if (text_info == (XFontStruct *) NULL)
9047 text_info=windows->widget.font_info;
9049 for (i=0; textlist[i] != (char *) NULL; i++)
9050 if (WidgetTextWidth(text_info,(char *) textlist[i]) > text_width)
9051 text_width=(unsigned int) XTextWidth(text_info,(char *) textlist[i],
9052 MagickMin(Extent(textlist[i]),160));
9053 lines=(unsigned int) i;
9054 width=WidgetTextWidth(font_info,DismissButtonText);
9055 width+=QuantumMargin;
9056 height=(unsigned int) (text_info->ascent+text_info->descent);
9058 Position Text View widget.
9060 windows->widget.width=(unsigned int) (MagickMin((int) text_width,
9061 (int) MaxTextWidth)+5*QuantumMargin);
9062 windows->widget.min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
9063 if (windows->widget.width < windows->widget.min_width)
9064 windows->widget.width=windows->widget.min_width;
9065 windows->widget.height=(unsigned int) (MagickMin(MagickMax((int) lines,3),32)*
9066 height+((13*height) >> 1)+((9*QuantumMargin) >> 1));
9067 windows->widget.min_height=(unsigned int) (3*height+((13*height) >> 1)+((9*
9068 QuantumMargin) >> 1));
9069 if (windows->widget.height < windows->widget.min_height)
9070 windows->widget.height=windows->widget.min_height;
9071 XConstrainWindowPosition(display,&windows->widget);
9073 Map Text View widget.
9075 (void) CopyMagickString(windows->widget.name,title,MaxTextExtent);
9076 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
9077 if (status != False)
9079 XSetWMName(display,windows->widget.id,&window_name);
9080 XSetWMIconName(display,windows->widget.id,&window_name);
9081 (void) XFree((void *) window_name.value);
9083 window_changes.width=(int) windows->widget.width;
9084 window_changes.height=(int) windows->widget.height;
9085 window_changes.x=windows->widget.x;
9086 window_changes.y=windows->widget.y;
9087 (void) XReconfigureWMWindow(display,windows->widget.id,
9088 windows->widget.screen,(unsigned int) mask,&window_changes);
9089 (void) XMapRaised(display,windows->widget.id);
9090 windows->widget.mapped=MagickFalse;
9092 Respond to X events.
9094 XGetWidgetInfo((char *) NULL,&slider_info);
9095 XGetWidgetInfo((char *) NULL,&north_info);
9096 XGetWidgetInfo((char *) NULL,&south_info);
9097 XGetWidgetInfo((char *) NULL,&expose_info);
9099 delay=SuspendTime << 2;
9100 height=(unsigned int) (font_info->ascent+font_info->descent);
9101 state=UpdateConfigurationState;
9104 if (state & UpdateConfigurationState)
9110 Initialize button information.
9112 XGetWidgetInfo(DismissButtonText,&dismiss_info);
9113 dismiss_info.width=width;
9114 dismiss_info.height=(unsigned int) ((3*height) >> 1);
9115 dismiss_info.x=(int) windows->widget.width-dismiss_info.width-
9117 dismiss_info.y=(int) windows->widget.height-dismiss_info.height-
9120 Initialize scroll information.
9122 XGetWidgetInfo((char *) NULL,&scroll_info);
9123 scroll_info.bevel_width--;
9124 scroll_info.width=height;
9125 scroll_info.height=(unsigned int) (dismiss_info.y-((5*QuantumMargin) >>
9127 scroll_info.x=(int) windows->widget.width-QuantumMargin-
9129 scroll_info.y=(3*QuantumMargin) >> 1;
9130 scroll_info.raised=MagickFalse;
9131 scroll_info.trough=MagickTrue;
9132 north_info=scroll_info;
9133 north_info.raised=MagickTrue;
9134 north_info.width-=(north_info.bevel_width << 1);
9135 north_info.height=north_info.width-1;
9136 north_info.x+=north_info.bevel_width;
9137 north_info.y+=north_info.bevel_width;
9138 south_info=north_info;
9139 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
9142 slider_info=north_info;
9144 slider_info.width-=2;
9145 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
9146 slider_info.bevel_width+2;
9147 slider_info.height=scroll_info.height-((slider_info.min_y-
9148 scroll_info.y+1) << 1)+4;
9149 visible_lines=scroll_info.height/(text_info->ascent+text_info->descent+
9150 ((text_info->ascent+text_info->descent) >> 3));
9151 if (lines > visible_lines)
9152 slider_info.height=(unsigned int) (visible_lines*slider_info.height)/
9154 slider_info.max_y=south_info.y-south_info.bevel_width-
9155 slider_info.bevel_width-2;
9156 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
9157 slider_info.y=slider_info.min_y;
9158 expose_info=scroll_info;
9159 expose_info.y=slider_info.y;
9161 Initialize list information.
9163 XGetWidgetInfo((char *) NULL,&list_info);
9164 list_info.raised=MagickFalse;
9165 list_info.bevel_width--;
9166 list_info.width=(unsigned int) scroll_info.x-((3*QuantumMargin) >> 1);
9167 list_info.height=scroll_info.height;
9168 list_info.x=QuantumMargin;
9169 list_info.y=scroll_info.y;
9171 Initialize selection information.
9173 XGetWidgetInfo((char *) NULL,&selection_info);
9174 selection_info.center=MagickFalse;
9175 selection_info.width=list_info.width;
9176 selection_info.height=(unsigned int)
9177 (9*(text_info->ascent+text_info->descent)) >> 3;
9178 selection_info.x=list_info.x;
9179 state&=(~UpdateConfigurationState);
9181 if (state & RedrawWidgetState)
9184 Redraw Text View window.
9186 XDrawBeveledMatte(display,&windows->widget,&list_info);
9187 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
9188 XDrawTriangleNorth(display,&windows->widget,&north_info);
9189 XDrawBeveledButton(display,&windows->widget,&slider_info);
9190 XDrawTriangleSouth(display,&windows->widget,&south_info);
9191 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9192 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
9193 selection_info.id=(~0);
9194 state|=RedrawListState;
9195 state&=(~RedrawWidgetState);
9197 if (state & RedrawListState)
9200 Determine slider id and position.
9202 if (slider_info.id >= (int) (lines-visible_lines))
9203 slider_info.id=(int) lines-visible_lines;
9204 if ((slider_info.id < 0) || (lines <= visible_lines))
9206 slider_info.y=slider_info.min_y;
9209 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/lines;
9210 if (slider_info.id != selection_info.id)
9213 Redraw scroll bar and text.
9215 windows->widget.font_info=text_info;
9216 (void) XSetFont(display,windows->widget.annotate_context,
9218 (void) XSetFont(display,windows->widget.highlight_context,
9220 selection_info.id=slider_info.id;
9221 selection_info.y=list_info.y+(height >> 3)+2;
9222 for (i=0; i < (int) visible_lines; i++)
9224 selection_info.raised=
9225 (slider_info.id+i) != list_info.id ? MagickTrue : MagickFalse;
9226 selection_info.text=(char *) NULL;
9227 if ((slider_info.id+i) < (int) lines)
9228 selection_info.text=(char *) textlist[slider_info.id+i];
9229 XDrawWidgetText(display,&windows->widget,&selection_info);
9230 selection_info.y+=(int) selection_info.height;
9232 windows->widget.font_info=font_info;
9233 (void) XSetFont(display,windows->widget.annotate_context,
9235 (void) XSetFont(display,windows->widget.highlight_context,
9240 if (slider_info.y > expose_info.y)
9242 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
9243 expose_info.y=slider_info.y-expose_info.height-
9244 slider_info.bevel_width-1;
9248 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
9249 expose_info.y=slider_info.y+slider_info.height+
9250 slider_info.bevel_width+1;
9252 XDrawTriangleNorth(display,&windows->widget,&north_info);
9253 XDrawMatte(display,&windows->widget,&expose_info);
9254 XDrawBeveledButton(display,&windows->widget,&slider_info);
9255 XDrawTriangleSouth(display,&windows->widget,&south_info);
9256 expose_info.y=slider_info.y;
9258 state&=(~RedrawListState);
9261 Wait for next event.
9263 if (north_info.raised && south_info.raised)
9264 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
9268 Brief delay before advancing scroll bar.
9270 XDelay(display,delay);
9272 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
9273 if (north_info.raised == MagickFalse)
9274 if (slider_info.id > 0)
9280 state|=RedrawListState;
9282 if (south_info.raised == MagickFalse)
9283 if (slider_info.id < (int) lines)
9289 state|=RedrawListState;
9291 if (event.type != ButtonRelease)
9298 if (MatteIsActive(slider_info,event.xbutton))
9303 slider_info.active=MagickTrue;
9306 if (MatteIsActive(north_info,event.xbutton))
9307 if (slider_info.id > 0)
9312 north_info.raised=MagickFalse;
9314 state|=RedrawListState;
9317 if (MatteIsActive(south_info,event.xbutton))
9318 if (slider_info.id < (int) lines)
9323 south_info.raised=MagickFalse;
9325 state|=RedrawListState;
9328 if (MatteIsActive(scroll_info,event.xbutton))
9333 if (event.xbutton.y < slider_info.y)
9334 slider_info.id-=(visible_lines-1);
9336 slider_info.id+=(visible_lines-1);
9337 state|=RedrawListState;
9340 if (MatteIsActive(dismiss_info,event.xbutton))
9343 User pressed Dismiss button.
9345 dismiss_info.raised=MagickFalse;
9346 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9349 if (MatteIsActive(list_info,event.xbutton))
9358 User pressed list matte.
9360 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
9361 selection_info.height;
9362 if (id >= (int) lines)
9364 if (id != list_info.id)
9367 click_time=event.xbutton.time;
9371 if (event.xbutton.time >= (click_time+DoubleClick))
9373 click_time=event.xbutton.time;
9376 click_time=event.xbutton.time;
9378 Become the XA_PRIMARY selection owner.
9380 (void) CopyMagickString(primary_selection,textlist[list_info.id],
9382 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
9383 event.xbutton.time);
9384 if (XGetSelectionOwner(display,XA_PRIMARY) != windows->widget.id)
9386 selection_info.id=(~0);
9388 state|=RedrawListState;
9395 if (windows->widget.mapped == MagickFalse)
9397 if (north_info.raised == MagickFalse)
9400 User released up button.
9402 delay=SuspendTime << 2;
9403 north_info.raised=MagickTrue;
9404 XDrawTriangleNorth(display,&windows->widget,&north_info);
9406 if (south_info.raised == MagickFalse)
9409 User released down button.
9411 delay=SuspendTime << 2;
9412 south_info.raised=MagickTrue;
9413 XDrawTriangleSouth(display,&windows->widget,&south_info);
9415 if (slider_info.active)
9418 Stop tracking slider.
9420 slider_info.active=MagickFalse;
9423 if (dismiss_info.raised == MagickFalse)
9425 if (event.xbutton.window == windows->widget.id)
9426 if (MatteIsActive(dismiss_info,event.xbutton))
9428 dismiss_info.raised=MagickTrue;
9429 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9436 If client window delete message, exit.
9438 if (event.xclient.message_type != windows->wm_protocols)
9440 if (*event.xclient.data.l == (int) windows->wm_take_focus)
9442 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
9443 (Time) event.xclient.data.l[1]);
9446 if (*event.xclient.data.l != (int) windows->wm_delete_window)
9448 if (event.xclient.window == windows->widget.id)
9455 case ConfigureNotify:
9458 Update widget configuration.
9460 if (event.xconfigure.window != windows->widget.id)
9462 if ((event.xconfigure.width == (int) windows->widget.width) &&
9463 (event.xconfigure.height == (int) windows->widget.height))
9465 windows->widget.width=(unsigned int)
9466 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
9467 windows->widget.height=(unsigned int)
9468 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
9469 state|=UpdateConfigurationState;
9474 if (event.xcrossing.window != windows->widget.id)
9476 state&=(~InactiveWidgetState);
9481 if (event.xexpose.window != windows->widget.id)
9483 if (event.xexpose.count != 0)
9485 state|=RedrawWidgetState;
9491 command[MaxTextExtent];
9500 Respond to a user key press.
9502 if (event.xkey.window != windows->widget.id)
9504 length=XLookupString((XKeyEvent *) &event.xkey,command,
9505 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9506 *(command+length)='\0';
9507 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
9509 dismiss_info.raised=MagickFalse;
9510 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9514 if (AreaIsActive(scroll_info,event.xkey))
9519 switch ((int) key_symbol)
9542 slider_info.id-=visible_lines;
9548 slider_info.id+=visible_lines;
9554 slider_info.id=(int) lines;
9558 state|=RedrawListState;
9567 if (event.xcrossing.window != windows->widget.id)
9569 state|=InactiveWidgetState;
9581 Discard pending button motion events.
9583 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9584 if (slider_info.active)
9589 slider_info.y=event.xmotion.y-
9590 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
9591 if (slider_info.y < slider_info.min_y)
9592 slider_info.y=slider_info.min_y;
9593 if (slider_info.y > slider_info.max_y)
9594 slider_info.y=slider_info.max_y;
9596 if (slider_info.y != slider_info.min_y)
9597 slider_info.id=(int) (lines*(slider_info.y-slider_info.min_y+1))/
9598 (slider_info.max_y-slider_info.min_y+1);
9599 state|=RedrawListState;
9602 if (state & InactiveWidgetState)
9604 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
9607 Dismiss button status changed.
9609 dismiss_info.raised=
9610 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
9611 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9616 case SelectionClear:
9619 selection_info.id=(~0);
9620 state|=RedrawListState;
9623 case SelectionRequest:
9628 XSelectionRequestEvent
9631 if (list_info.id == (~0))
9634 Set primary selection.
9636 request=(&(event.xselectionrequest));
9637 (void) XChangeProperty(request->display,request->requestor,
9638 request->property,request->target,8,PropModeReplace,
9639 (unsigned char *) primary_selection,Extent(primary_selection));
9640 notify.type=SelectionNotify;
9641 notify.send_event=MagickTrue;
9642 notify.display=request->display;
9643 notify.requestor=request->requestor;
9644 notify.selection=request->selection;
9645 notify.target=request->target;
9646 notify.time=request->time;
9647 if (request->property == None)
9648 notify.property=request->target;
9650 notify.property=request->property;
9651 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
9652 (XEvent *) ¬ify);
9657 } while ((state & ExitState) == 0);
9658 if (text_info != windows->widget.font_info)
9659 (void) XFreeFont(display,text_info);
9660 XSetCursorState(display,windows,MagickFalse);
9661 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
9662 XCheckRefreshWindows(display,windows);