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-2011 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 "magick/studio.h"
44 #include "magick/color.h"
45 #include "magick/color-private.h"
46 #include "magick/exception.h"
47 #include "magick/exception-private.h"
48 #include "magick/image.h"
49 #include "magick/magick.h"
50 #include "magick/memory_.h"
51 #include "magick/PreRvIcccm.h"
52 #include "magick/string_.h"
53 #include "magick/token.h"
54 #include "magick/utility.h"
55 #include "magick/xwindow-private.h"
56 #include "magick/widget.h"
58 #if defined(MAGICKCORE_X11_DELEGATE)
63 #define AreaIsActive(matte_info,position) ( \
64 ((position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
65 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
66 ? MagickTrue : MagickFalse)
67 #define Extent(s) ((int) strlen(s))
68 #define MatteIsActive(matte_info,position) ( \
69 ((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \
70 (position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
71 (position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) && \
72 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
73 ? MagickTrue : MagickFalse)
74 #define MaxTextWidth ((unsigned int) (255*XTextWidth(font_info,"_",1)))
75 #define MinTextWidth (26*XTextWidth(font_info,"_",1))
76 #define QuantumMargin MagickMax(font_info->max_bounds.width,12)
77 #define WidgetTextWidth(font_info,text) \
78 ((unsigned int) XTextWidth(font_info,text,Extent(text)))
79 #define WindowIsActive(window_info,position) ( \
80 ((position.x >= 0) && (position.y >= 0) && \
81 (position.x < (int) window_info.width) && \
82 (position.y < (int) window_info.height)) ? MagickTrue : MagickFalse)
89 ControlState = 0x0001,
90 InactiveWidgetState = 0x0004,
91 JumpListState = 0x0008,
92 RedrawActionState = 0x0010,
93 RedrawListState = 0x0020,
94 RedrawWidgetState = 0x0040,
95 UpdateListState = 0x0100
101 typedef struct _XWidgetInfo
131 Variable declarations.
136 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
137 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
141 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
142 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
144 *selection_info = (XWidgetInfo *) NULL,
147 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
148 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
152 Constant declarations.
162 XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *),
163 XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType),
164 XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType),
165 XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType);
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % D e s t r o y X W i d g e t %
176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 % DestroyXWidget() destroys resources associated with the X widget.
180 % The format of the DestroyXWidget method is:
182 % void DestroyXWidget()
184 % A description of each parameter follows:
187 MagickExport void DestroyXWidget(void)
189 if (selection_info != (XWidgetInfo *) NULL)
190 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 + X D r a w B e v e l %
202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 % XDrawBevel() "sets off" an area with a highlighted upper and left bevel and
205 % a shadowed lower and right bevel. The highlighted and shadowed bevels
206 % create a 3-D effect.
208 % The format of the XDrawBevel function is:
210 % XDrawBevel(display,window_info,bevel_info)
212 % A description of each parameter follows:
214 % o display: Specifies a pointer to the Display structure; returned from
217 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
219 % o bevel_info: Specifies a pointer to a XWidgetInfo structure. It
220 % contains the extents of the bevel.
223 static void XDrawBevel(Display *display,const XWindowInfo *window_info,
224 const XWidgetInfo *bevel_info)
239 Draw upper and left beveled border.
242 y1=bevel_info->y+bevel_info->height;
243 x2=bevel_info->x+bevel_info->width;
245 bevel_width=bevel_info->bevel_width;
252 points[3].x=x2+bevel_width;
253 points[3].y=y2-bevel_width;
254 points[4].x=x1-bevel_width;
255 points[4].y=y2-bevel_width;
256 points[5].x=x1-bevel_width;
257 points[5].y=y1+bevel_width;
258 XSetBevelColor(display,window_info,bevel_info->raised);
259 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
260 points,6,Complex,CoordModeOrigin);
262 Draw lower and right beveled border.
270 points[3].x=x2+bevel_width;
271 points[3].y=y2-bevel_width;
272 points[4].x=x2+bevel_width;
273 points[4].y=y1+bevel_width;
274 points[5].x=x1-bevel_width;
275 points[5].y=y1+bevel_width;
276 XSetBevelColor(display,window_info,!bevel_info->raised);
277 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
278 points,6,Complex,CoordModeOrigin);
279 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287 + X D r a w B e v e l e d B u t t o n %
291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293 % XDrawBeveledButton() draws a button with a highlighted upper and left bevel
294 % and a shadowed lower and right bevel. The highlighted and shadowed bevels
295 % create a 3-D effect.
297 % The format of the XDrawBeveledButton function is:
299 % XDrawBeveledButton(display,window_info,button_info)
301 % A description of each parameter follows:
303 % o display: Specifies a pointer to the Display structure; returned from
306 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
308 % o button_info: Specifies a pointer to a XWidgetInfo structure. It
309 % contains the extents of the button.
313 static inline int MagickAbsoluteValue(const int x)
320 static inline int MagickMax(const int x,const int y)
327 static inline int MagickMin(const int x,const int y)
334 static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info,
335 const XWidgetInfo *button_info)
353 XDrawBevel(display,window_info,button_info);
354 XSetMatteColor(display,window_info,button_info->raised);
355 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
356 button_info->x,button_info->y,button_info->width,button_info->height);
357 x=button_info->x-button_info->bevel_width-1;
358 y=button_info->y-button_info->bevel_width-1;
359 (void) XSetForeground(display,window_info->widget_context,
360 window_info->pixel_info->trough_color.pixel);
361 if (button_info->raised || (window_info->depth == 1))
362 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
363 x,y,button_info->width+(button_info->bevel_width << 1)+1,
364 button_info->height+(button_info->bevel_width << 1)+1);
365 if (button_info->text == (char *) NULL)
370 crop_info.width=(unsigned short) button_info->width;
371 crop_info.height=(unsigned short) button_info->height;
372 crop_info.x=button_info->x;
373 crop_info.y=button_info->y;
377 font_info=window_info->font_info;
378 width=WidgetTextWidth(font_info,button_info->text);
379 x=button_info->x+(QuantumMargin >> 1);
380 if (button_info->center)
381 x=button_info->x+(button_info->width >> 1)-(width >> 1);
382 y=button_info->y+((button_info->height-
383 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
384 if ((int) button_info->width == (QuantumMargin >> 1))
387 Option button-- write label to right of button.
389 XSetTextColor(display,window_info,MagickTrue);
390 x=button_info->x+button_info->width+button_info->bevel_width+
391 (QuantumMargin >> 1);
392 (void) XDrawString(display,window_info->id,window_info->widget_context,
393 x,y,button_info->text,Extent(button_info->text));
396 (void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info,
398 XSetTextColor(display,window_info,button_info->raised);
399 (void) XDrawString(display,window_info->id,window_info->widget_context,x,y,
400 button_info->text,Extent(button_info->text));
401 (void) XSetClipMask(display,window_info->widget_context,None);
402 if (button_info->raised == MagickFalse)
403 XDelay(display,SuspendTime << 2);
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 + X D r a w B e v e l e d M a t t e %
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417 % XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and
418 % a highlighted lower and right bevel. The highlighted and shadowed bevels
419 % create a 3-D effect.
421 % The format of the XDrawBeveledMatte function is:
423 % XDrawBeveledMatte(display,window_info,matte_info)
425 % A description of each parameter follows:
427 % o display: Specifies a pointer to the Display structure; returned from
430 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
432 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
433 % contains the extents of the matte.
436 static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info,
437 const XWidgetInfo *matte_info)
442 XDrawBevel(display,window_info,matte_info);
443 XDrawMatte(display,window_info,matte_info);
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 + X D r a w M a t t e %
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 % XDrawMatte() fills a rectangular area with the matte color.
459 % The format of the XDrawMatte function is:
461 % XDrawMatte(display,window_info,matte_info)
463 % A description of each parameter follows:
465 % o display: Specifies a pointer to the Display structure; returned from
468 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
470 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
471 % contains the extents of the matte.
474 static void XDrawMatte(Display *display,const XWindowInfo *window_info,
475 const XWidgetInfo *matte_info)
480 if ((matte_info->trough == MagickFalse) || (window_info->depth == 1))
481 (void) XFillRectangle(display,window_info->id,
482 window_info->highlight_context,matte_info->x,matte_info->y,
483 matte_info->width,matte_info->height);
486 (void) XSetForeground(display,window_info->widget_context,
487 window_info->pixel_info->trough_color.pixel);
488 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
489 matte_info->x,matte_info->y,matte_info->width,matte_info->height);
494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498 + X D r a w M a t t e T e x t %
502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504 % XDrawMatteText() draws a matte with text. If the text exceeds the extents
505 % of the text, a portion of the text relative to the cursor is displayed.
507 % The format of the XDrawMatteText function is:
509 % XDrawMatteText(display,window_info,text_info)
511 % A description of each parameter follows:
513 % o display: Specifies a pointer to the Display structure; returned from
516 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
518 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
519 % contains the extents of the text.
522 static void XDrawMatteText(Display *display,const XWindowInfo *window_info,
523 XWidgetInfo *text_info)
549 XSetMatteColor(display,window_info,MagickFalse);
550 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
551 text_info->x,text_info->y,text_info->width,text_info->height);
552 if (text_info->text == (char *) NULL)
554 XSetTextColor(display,window_info,text_info->highlight);
555 font_info=window_info->font_info;
556 x=text_info->x+(QuantumMargin >> 2);
557 y=text_info->y+font_info->ascent+(text_info->height >> 2);
558 width=text_info->width-(QuantumMargin >> 1);
559 height=(unsigned int) (font_info->ascent+font_info->descent);
560 if (*text_info->text == '\0')
563 No text-- just draw cursor.
565 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
572 crop_info.width=(unsigned short) text_info->width;
573 crop_info.height=(unsigned short) text_info->height;
574 crop_info.x=text_info->x;
575 crop_info.y=text_info->y;
577 Determine beginning of the visible text.
579 if (text_info->cursor < text_info->marker)
580 text_info->marker=text_info->cursor;
583 text=text_info->marker;
584 if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) >
587 text=text_info->text;
588 for (i=0; i < Extent(text); i++)
590 n=XTextWidth(font_info,(char *) text+i,(int)
591 (text_info->cursor-text-i));
592 if (n <= (int) width)
595 text_info->marker=(char *) text+i;
599 Draw text and cursor.
601 if (text_info->highlight == MagickFalse)
603 (void) XSetClipRectangles(display,window_info->widget_context,0,0,
604 &crop_info,1,Unsorted);
605 (void) XDrawString(display,window_info->id,window_info->widget_context,
606 x,y,text_info->marker,Extent(text_info->marker));
607 (void) XSetClipMask(display,window_info->widget_context,None);
611 (void) XSetClipRectangles(display,window_info->annotate_context,0,0,
612 &crop_info,1,Unsorted);
613 width=WidgetTextWidth(font_info,text_info->marker);
614 (void) XFillRectangle(display,window_info->id,
615 window_info->annotate_context,x,y-font_info->ascent,width,height);
616 (void) XSetClipMask(display,window_info->annotate_context,None);
617 (void) XSetClipRectangles(display,window_info->highlight_context,0,0,
618 &crop_info,1,Unsorted);
619 (void) XDrawString(display,window_info->id,
620 window_info->highlight_context,x,y,text_info->marker,
621 Extent(text_info->marker));
622 (void) XSetClipMask(display,window_info->highlight_context,None);
624 x+=XTextWidth(font_info,text_info->marker,(int)
625 (text_info->cursor-text_info->marker));
626 (void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3,
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635 + X D r a w T r i a n g l e E a s t %
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641 % XDrawTriangleEast() draws a triangle with a highlighted left bevel and a
642 % shadowed right and lower bevel. The highlighted and shadowed bevels create
645 % The format of the XDrawTriangleEast function is:
647 % XDrawTriangleEast(display,window_info,triangle_info)
649 % A description of each parameter follows:
651 % o display: Specifies a pointer to the Display structure; returned from
654 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
656 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
657 % contains the extents of the triangle.
660 static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info,
661 const XWidgetInfo *triangle_info)
685 x2=triangle_info->x+triangle_info->width;
686 y2=triangle_info->y+(triangle_info->height >> 1);
688 y3=triangle_info->y+triangle_info->height;
689 bevel_width=triangle_info->bevel_width;
696 XSetMatteColor(display,window_info,triangle_info->raised);
697 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
698 points,3,Complex,CoordModeOrigin);
706 points[2].x=x3-bevel_width;
707 points[2].y=y3+bevel_width;
708 points[3].x=x2+bevel_width;
710 XSetBevelColor(display,window_info,!triangle_info->raised);
711 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
712 points,4,Complex,CoordModeOrigin);
720 points[2].x=x1-bevel_width+1;
721 points[2].y=y1-bevel_width;
722 points[3].x=x3-bevel_width+1;
723 points[3].y=y3+bevel_width;
724 XSetBevelColor(display,window_info,triangle_info->raised);
725 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
726 points,4,Complex,CoordModeOrigin);
734 points[2].x=x2+bevel_width;
736 points[3].x=x1-bevel_width;
737 points[3].y=y1-bevel_width;
738 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
739 points,4,Complex,CoordModeOrigin);
740 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
741 if (triangle_info->text == (char *) NULL)
744 Write label to right of triangle.
746 font_info=window_info->font_info;
747 XSetTextColor(display,window_info,MagickTrue);
748 x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+
749 (QuantumMargin >> 1);
750 y1=triangle_info->y+((triangle_info->height-
751 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
752 (void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1,
753 triangle_info->text,Extent(triangle_info->text));
757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
761 + X D r a w T r i a n g l e N o r t h %
765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 % XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a
768 % shadowed right and lower bevel. The highlighted and shadowed bevels create
771 % The format of the XDrawTriangleNorth function is:
773 % XDrawTriangleNorth(display,window_info,triangle_info)
775 % A description of each parameter follows:
777 % o display: Specifies a pointer to the Display structure; returned from
780 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
782 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
783 % contains the extents of the triangle.
786 static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info,
787 const XWidgetInfo *triangle_info)
807 y1=triangle_info->y+triangle_info->height;
808 x2=triangle_info->x+(triangle_info->width >> 1);
810 x3=triangle_info->x+triangle_info->width;
811 y3=triangle_info->y+triangle_info->height;
812 bevel_width=triangle_info->bevel_width;
819 XSetMatteColor(display,window_info,triangle_info->raised);
820 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
821 points,3,Complex,CoordModeOrigin);
830 points[2].y=y2-bevel_width-2;
831 points[3].x=x1-bevel_width-1;
832 points[3].y=y1+bevel_width;
833 XSetBevelColor(display,window_info,triangle_info->raised);
834 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
835 points,4,Complex,CoordModeOrigin);
843 points[2].x=x3+bevel_width;
844 points[2].y=y3+bevel_width;
846 points[3].y=y2-bevel_width;
847 XSetBevelColor(display,window_info,!triangle_info->raised);
848 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
849 points,4,Complex,CoordModeOrigin);
857 points[2].x=x1-bevel_width;
858 points[2].y=y1+bevel_width;
859 points[3].x=x3+bevel_width;
860 points[3].y=y3+bevel_width;
861 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
862 points,4,Complex,CoordModeOrigin);
863 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 + X D r a w T r i a n g l e S o u t h %
875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
877 % XDrawTriangleSouth() draws a border with a highlighted left and right bevel
878 % and a shadowed lower bevel. The highlighted and shadowed bevels create a
881 % The format of the XDrawTriangleSouth function is:
883 % XDrawTriangleSouth(display,window_info,triangle_info)
885 % A description of each parameter follows:
887 % o display: Specifies a pointer to the Display structure; returned from
890 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
892 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
893 % contains the extents of the triangle.
896 static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info,
897 const XWidgetInfo *triangle_info)
918 x2=triangle_info->x+(triangle_info->width >> 1);
919 y2=triangle_info->y+triangle_info->height;
920 x3=triangle_info->x+triangle_info->width;
922 bevel_width=triangle_info->bevel_width;
929 XSetMatteColor(display,window_info,triangle_info->raised);
930 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
931 points,3,Complex,CoordModeOrigin);
939 points[2].x=x1-bevel_width;
940 points[2].y=y1-bevel_width;
941 points[3].x=x3+bevel_width;
942 points[3].y=y3-bevel_width;
943 XSetBevelColor(display,window_info,triangle_info->raised);
944 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
945 points,4,Complex,CoordModeOrigin);
952 points[1].y=y3-bevel_width;
953 points[2].x=x3+bevel_width;
954 points[2].y=y3-bevel_width;
956 points[3].y=y2+bevel_width;
957 XSetBevelColor(display,window_info,!triangle_info->raised);
958 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
959 points,4,Complex,CoordModeOrigin);
968 points[2].y=y2+bevel_width;
969 points[3].x=x1-bevel_width;
970 points[3].y=y1-bevel_width;
971 XSetBevelColor(display,window_info,triangle_info->raised);
972 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
973 points,4,Complex,CoordModeOrigin);
974 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982 + X D r a w W i d g e t T e x t %
986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
988 % XDrawWidgetText() first clears the widget and draws a text string justifed
989 % left (or center) in the x-direction and centered within the y-direction.
991 % The format of the XDrawWidgetText function is:
993 % XDrawWidgetText(display,window_info,text_info)
995 % A description of each parameter follows:
997 % o display: Specifies a pointer to the Display structure; returned from
1000 % o window_info: Specifies a pointer to a XWindowText structure.
1002 % o text_info: Specifies a pointer to XWidgetInfo structure.
1005 static void XDrawWidgetText(Display *display,const XWindowInfo *window_info,
1006 XWidgetInfo *text_info)
1026 Clear the text area.
1028 widget_context=window_info->annotate_context;
1029 if (text_info->raised)
1030 (void) XClearArea(display,window_info->id,text_info->x,text_info->y,
1031 text_info->width,text_info->height,MagickFalse);
1034 (void) XFillRectangle(display,window_info->id,widget_context,text_info->x,
1035 text_info->y,text_info->width,text_info->height);
1036 widget_context=window_info->highlight_context;
1038 if (text_info->text == (char *) NULL)
1040 if (*text_info->text == '\0')
1043 Set cropping region.
1045 font_info=window_info->font_info;
1046 crop_info.width=(unsigned short) text_info->width;
1047 crop_info.height=(unsigned short) text_info->height;
1048 crop_info.x=text_info->x;
1049 crop_info.y=text_info->y;
1053 width=WidgetTextWidth(font_info,text_info->text);
1054 x=text_info->x+(QuantumMargin >> 1);
1055 if (text_info->center)
1056 x=text_info->x+(text_info->width >> 1)-(width >> 1);
1057 if (text_info->raised)
1058 if (width > (text_info->width-QuantumMargin))
1059 x+=(text_info->width-QuantumMargin-width);
1060 height=(unsigned int) (font_info->ascent+font_info->descent);
1061 y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent;
1062 (void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted);
1063 (void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text,
1064 Extent(text_info->text));
1065 (void) XSetClipMask(display,widget_context,None);
1066 if (x < text_info->x)
1067 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
1068 text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1);
1072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1076 + X E d i t T e x t %
1080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1082 % XEditText() edits a text string as indicated by the key symbol.
1084 % The format of the XEditText function is:
1086 % XEditText(display,text_info,key_symbol,text,state)
1088 % A description of each parameter follows:
1090 % o display: Specifies a connection to an X server; returned from
1093 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
1094 % contains the extents of the text.
1096 % o key_symbol: A X11 KeySym that indicates what editing function to
1097 % perform to the text.
1099 % o text: A character string to insert into the text.
1101 % o state: An size_t that indicates whether the key symbol is a
1102 % control character or not.
1105 static void XEditText(Display *display,XWidgetInfo *text_info,
1106 const KeySym key_symbol,char *text,const size_t state)
1108 switch ((int) key_symbol)
1113 if (text_info->highlight)
1116 Erase the entire line of text.
1118 *text_info->text='\0';
1119 text_info->cursor=text_info->text;
1120 text_info->marker=text_info->text;
1121 text_info->highlight=MagickFalse;
1124 Erase one character.
1126 if (text_info->cursor != text_info->text)
1128 text_info->cursor--;
1129 (void) CopyMagickString(text_info->cursor,text_info->cursor+1,
1131 text_info->highlight=MagickFalse;
1139 Move cursor one position left.
1141 if (text_info->cursor == text_info->text)
1143 text_info->cursor--;
1150 Move cursor one position right.
1152 if (text_info->cursor == (text_info->text+Extent(text_info->text)))
1154 text_info->cursor++;
1166 if (state & ControlState)
1170 if ((Extent(text_info->text)+1) >= (int) MaxTextExtent)
1171 (void) XBell(display,0);
1174 if (text_info->highlight)
1177 Erase the entire line of text.
1179 *text_info->text='\0';
1180 text_info->cursor=text_info->text;
1181 text_info->marker=text_info->text;
1182 text_info->highlight=MagickFalse;
1185 Insert a string into the text.
1187 q=text_info->text+Extent(text_info->text)+strlen(text);
1188 for (i=0; i <= Extent(text_info->cursor); i++)
1190 *q=(*(q-Extent(text)));
1194 for (i=0; i < Extent(text); i++)
1195 *text_info->cursor++=(*p++);
1203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 + X G e t W i d g e t I n f o %
1211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1213 % XGetWidgetInfo() initializes the XWidgetInfo structure.
1215 % The format of the XGetWidgetInfo function is:
1217 % XGetWidgetInfo(text,widget_info)
1219 % A description of each parameter follows:
1221 % o text: A string of characters associated with the widget.
1223 % o widget_info: Specifies a pointer to a X11 XWidgetInfo structure.
1226 static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info)
1229 Initialize widget info.
1231 widget_info->id=(~0);
1232 widget_info->bevel_width=3;
1233 widget_info->width=1;
1234 widget_info->height=1;
1237 widget_info->min_y=0;
1238 widget_info->max_y=0;
1239 widget_info->raised=MagickTrue;
1240 widget_info->active=MagickFalse;
1241 widget_info->center=MagickTrue;
1242 widget_info->trough=MagickFalse;
1243 widget_info->highlight=MagickFalse;
1244 widget_info->text=(char *) text;
1245 widget_info->cursor=(char *) text;
1246 if (text != (char *) NULL)
1247 widget_info->cursor+=Extent(text);
1248 widget_info->marker=(char *) text;
1252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1256 + X H i g h l i g h t W i d g e t %
1260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262 % XHighlightWidget() draws a highlighted border around a window.
1264 % The format of the XHighlightWidget function is:
1266 % XHighlightWidget(display,window_info,x,y)
1268 % A description of each parameter follows:
1270 % o display: Specifies a pointer to the Display structure; returned from
1273 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1275 % o x: Specifies an integer representing the rectangle offset in the
1278 % o y: Specifies an integer representing the rectangle offset in the
1282 static void XHighlightWidget(Display *display,const XWindowInfo *window_info,
1283 const int x,const int y)
1286 Draw the widget highlighting rectangle.
1288 XSetBevelColor(display,window_info,MagickTrue);
1289 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y,
1290 window_info->width-(x << 1),window_info->height-(y << 1));
1291 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1292 x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1);
1293 XSetBevelColor(display,window_info,MagickFalse);
1294 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1295 x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1));
1296 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
1300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304 + X S c r e e n E v e n t %
1308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1310 % XScreenEvent() returns MagickTrue if the any event on the X server queue is
1311 % associated with the widget window.
1313 % The format of the XScreenEvent function is:
1315 % int XScreenEvent(Display *display,XEvent *event,char *data)
1317 % A description of each parameter follows:
1319 % o display: Specifies a pointer to the Display structure; returned from
1322 % o event: Specifies a pointer to a X11 XEvent structure.
1324 % o data: Specifies a pointer to a XWindows structure.
1328 #if defined(__cplusplus) || defined(c_plusplus)
1332 static int XScreenEvent(Display *display,XEvent *event,char *data)
1337 windows=(XWindows *) data;
1338 if (event->xany.window == windows->popup.id)
1340 if (event->type == MapNotify)
1341 windows->popup.mapped=MagickTrue;
1342 if (event->type == UnmapNotify)
1343 windows->popup.mapped=MagickFalse;
1346 if (event->xany.window == windows->widget.id)
1348 if (event->type == MapNotify)
1349 windows->widget.mapped=MagickTrue;
1350 if (event->type == UnmapNotify)
1351 windows->widget.mapped=MagickFalse;
1354 switch (event->type)
1358 if ((event->xbutton.button == Button3) &&
1359 (event->xbutton.state & Mod1Mask))
1362 Convert Alt-Button3 to Button2.
1364 event->xbutton.button=Button2;
1365 event->xbutton.state&=(~Mod1Mask);
1371 if (event->xexpose.window == windows->image.id)
1373 XRefreshWindow(display,&windows->image,event);
1376 if (event->xexpose.window == windows->magnify.id)
1377 if (event->xexpose.count == 0)
1378 if (windows->magnify.mapped)
1380 XMakeMagnifyImage(display,windows);
1383 if (event->xexpose.window == windows->command.id)
1384 if (event->xexpose.count == 0)
1386 (void) XCommandWidget(display,windows,(const char **) NULL,event);
1394 Set input focus for backdrop window.
1396 if (event->xfocus.window == windows->image.id)
1397 (void) XSetInputFocus(display,windows->image.id,RevertToNone,
1405 case SelectionNotify:
1410 return(MagickFalse);
1413 #if defined(__cplusplus) || defined(c_plusplus)
1418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 + X S e t B e v e l C o l o r %
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428 % XSetBevelColor() sets the graphic context for drawing a beveled border.
1430 % The format of the XSetBevelColor function is:
1432 % XSetBevelColor(display,window_info,raised)
1434 % A description of each parameter follows:
1436 % o display: Specifies a pointer to the Display structure; returned from
1439 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1441 % o raised: A value other than zero indicates the color show be a
1442 % "highlight" color, otherwise the "shadow" color is set.
1445 static void XSetBevelColor(Display *display,const XWindowInfo *window_info,
1446 const MagickStatusType raised)
1448 if (window_info->depth == 1)
1456 (void) XSetBackground(display,window_info->widget_context,
1457 XBlackPixel(display,window_info->screen));
1458 (void) XSetForeground(display,window_info->widget_context,
1459 XWhitePixel(display,window_info->screen));
1460 (void) XSetFillStyle(display,window_info->widget_context,
1461 FillOpaqueStippled);
1462 stipple=window_info->highlight_stipple;
1463 if (raised == MagickFalse)
1464 stipple=window_info->shadow_stipple;
1465 (void) XSetStipple(display,window_info->widget_context,stipple);
1469 (void) XSetForeground(display,window_info->widget_context,
1470 window_info->pixel_info->highlight_color.pixel);
1472 (void) XSetForeground(display,window_info->widget_context,
1473 window_info->pixel_info->shadow_color.pixel);
1477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1481 + X S e t M a t t e C o l o r %
1485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1487 % XSetMatteColor() sets the graphic context for drawing the matte.
1489 % The format of the XSetMatteColor function is:
1491 % XSetMatteColor(display,window_info,raised)
1493 % A description of each parameter follows:
1495 % o display: Specifies a pointer to the Display structure; returned from
1498 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1500 % o raised: A value other than zero indicates the matte is active.
1503 static void XSetMatteColor(Display *display,const XWindowInfo *window_info,
1504 const MagickStatusType raised)
1506 if (window_info->depth == 1)
1512 (void) XSetForeground(display,window_info->widget_context,
1513 XWhitePixel(display,window_info->screen));
1515 (void) XSetForeground(display,window_info->widget_context,
1516 XBlackPixel(display,window_info->screen));
1520 (void) XSetForeground(display,window_info->widget_context,
1521 window_info->pixel_info->matte_color.pixel);
1523 (void) XSetForeground(display,window_info->widget_context,
1524 window_info->pixel_info->depth_color.pixel);
1528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1532 + X S e t T e x t C o l o r %
1536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1538 % XSetTextColor() sets the graphic context for drawing text on a matte.
1540 % The format of the XSetTextColor function is:
1542 % XSetTextColor(display,window_info,raised)
1544 % A description of each parameter follows:
1546 % o display: Specifies a pointer to the Display structure; returned from
1549 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1551 % o raised: A value other than zero indicates the color show be a
1552 % "highlight" color, otherwise the "shadow" color is set.
1555 static void XSetTextColor(Display *display,const XWindowInfo *window_info,
1556 const MagickStatusType raised)
1562 if (window_info->depth == 1)
1568 (void) XSetForeground(display,window_info->widget_context,
1569 XBlackPixel(display,window_info->screen));
1571 (void) XSetForeground(display,window_info->widget_context,
1572 XWhitePixel(display,window_info->screen));
1575 foreground=(ssize_t) XPixelIntensity(
1576 &window_info->pixel_info->foreground_color);
1577 matte=(ssize_t) XPixelIntensity(&window_info->pixel_info->matte_color);
1578 if (MagickAbsoluteValue((int) (foreground-matte)) > (65535L >> 3))
1579 (void) XSetForeground(display,window_info->widget_context,
1580 window_info->pixel_info->foreground_color.pixel);
1582 (void) XSetForeground(display,window_info->widget_context,
1583 window_info->pixel_info->background_color.pixel);
1587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1591 % X C o l o r B r o w s e r W i d g e t %
1595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597 % XColorBrowserWidget() displays a Color Browser widget with a color query
1598 % to the user. The user keys a reply and presses the Action or Cancel button
1599 % to exit. The typed text is returned as the reply function parameter.
1601 % The format of the XColorBrowserWidget method is:
1603 % void XColorBrowserWidget(Display *display,XWindows *windows,
1604 % const char *action,char *reply)
1606 % A description of each parameter follows:
1608 % o display: Specifies a connection to an X server; returned from
1611 % o window: Specifies a pointer to a XWindows structure.
1613 % o action: Specifies a pointer to the action of this widget.
1615 % o reply: the response from the user is returned in this parameter.
1618 MagickExport void XColorBrowserWidget(Display *display,XWindows *windows,
1619 const char *action,char *reply)
1621 #define CancelButtonText "Cancel"
1622 #define ColornameText "Name:"
1623 #define ColorPatternText "Pattern:"
1624 #define GrabButtonText "Grab"
1625 #define ResetButtonText "Reset"
1629 primary_selection[MaxTextExtent],
1630 reset_pattern[MaxTextExtent],
1631 text[MaxTextExtent];
1644 glob_pattern[MaxTextExtent] = "*";
1646 static MagickStatusType
1647 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
1695 Get color list and sort in ascending order.
1697 assert(display != (Display *) NULL);
1698 assert(windows != (XWindows *) NULL);
1699 assert(action != (char *) NULL);
1700 assert(reply != (char *) NULL);
1701 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
1702 XSetCursorState(display,windows,MagickTrue);
1703 XCheckRefreshWindows(display,windows);
1704 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
1705 exception=AcquireExceptionInfo();
1706 colorlist=GetColorList(glob_pattern,&colors,exception);
1707 if (colorlist == (char **) NULL)
1710 Pattern failed, obtain all the colors.
1712 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
1713 colorlist=GetColorList(glob_pattern,&colors,exception);
1714 if (colorlist == (char **) NULL)
1716 XNoticeWidget(display,windows,"Unable to obtain colors names:",
1718 (void) XDialogWidget(display,windows,action,"Enter color name:",
1724 Determine Color Browser widget attributes.
1726 font_info=windows->widget.font_info;
1728 for (i=0; i < (int) colors; i++)
1729 if (WidgetTextWidth(font_info,colorlist[i]) > text_width)
1730 text_width=WidgetTextWidth(font_info,colorlist[i]);
1731 width=WidgetTextWidth(font_info,(char *) action);
1732 if (WidgetTextWidth(font_info,CancelButtonText) > width)
1733 width=WidgetTextWidth(font_info,CancelButtonText);
1734 if (WidgetTextWidth(font_info,ResetButtonText) > width)
1735 width=WidgetTextWidth(font_info,ResetButtonText);
1736 if (WidgetTextWidth(font_info,GrabButtonText) > width)
1737 width=WidgetTextWidth(font_info,GrabButtonText);
1738 width+=QuantumMargin;
1739 if (WidgetTextWidth(font_info,ColorPatternText) > width)
1740 width=WidgetTextWidth(font_info,ColorPatternText);
1741 if (WidgetTextWidth(font_info,ColornameText) > width)
1742 width=WidgetTextWidth(font_info,ColornameText);
1743 height=(unsigned int) (font_info->ascent+font_info->descent);
1745 Position Color Browser widget.
1747 windows->widget.width=(unsigned int)
1748 (width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin);
1749 windows->widget.min_width=(unsigned int)
1750 (width+MinTextWidth+4*QuantumMargin);
1751 if (windows->widget.width < windows->widget.min_width)
1752 windows->widget.width=windows->widget.min_width;
1753 windows->widget.height=(unsigned int)
1754 ((81*height) >> 2)+((13*QuantumMargin) >> 1)+4;
1755 windows->widget.min_height=(unsigned int)
1756 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
1757 if (windows->widget.height < windows->widget.min_height)
1758 windows->widget.height=windows->widget.min_height;
1759 XConstrainWindowPosition(display,&windows->widget);
1761 Map Color Browser widget.
1763 (void) CopyMagickString(windows->widget.name,"Browse and Select a Color",
1765 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
1766 if (status != False)
1768 XSetWMName(display,windows->widget.id,&window_name);
1769 XSetWMIconName(display,windows->widget.id,&window_name);
1770 (void) XFree((void *) window_name.value);
1772 window_changes.width=(int) windows->widget.width;
1773 window_changes.height=(int) windows->widget.height;
1774 window_changes.x=windows->widget.x;
1775 window_changes.y=windows->widget.y;
1776 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
1777 mask,&window_changes);
1778 (void) XMapRaised(display,windows->widget.id);
1779 windows->widget.mapped=MagickFalse;
1781 Respond to X events.
1783 XGetWidgetInfo((char *) NULL,&slider_info);
1784 XGetWidgetInfo((char *) NULL,&north_info);
1785 XGetWidgetInfo((char *) NULL,&south_info);
1786 XGetWidgetInfo((char *) NULL,&expose_info);
1788 delay=SuspendTime << 2;
1789 state=UpdateConfigurationState;
1792 if (state & UpdateConfigurationState)
1798 Initialize button information.
1800 XGetWidgetInfo(CancelButtonText,&cancel_info);
1801 cancel_info.width=width;
1802 cancel_info.height=(unsigned int) ((3*height) >> 1);
1804 (windows->widget.width-cancel_info.width-QuantumMargin-2);
1806 (windows->widget.height-cancel_info.height-QuantumMargin);
1807 XGetWidgetInfo(action,&action_info);
1808 action_info.width=width;
1809 action_info.height=(unsigned int) ((3*height) >> 1);
1810 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
1811 (action_info.bevel_width << 1));
1812 action_info.y=cancel_info.y;
1813 XGetWidgetInfo(GrabButtonText,&grab_info);
1814 grab_info.width=width;
1815 grab_info.height=(unsigned int) ((3*height) >> 1);
1816 grab_info.x=QuantumMargin;
1817 grab_info.y=((5*QuantumMargin) >> 1)+height;
1818 XGetWidgetInfo(ResetButtonText,&reset_info);
1819 reset_info.width=width;
1820 reset_info.height=(unsigned int) ((3*height) >> 1);
1821 reset_info.x=QuantumMargin;
1822 reset_info.y=grab_info.y+grab_info.height+QuantumMargin;
1824 Initialize reply information.
1826 XGetWidgetInfo(reply,&reply_info);
1827 reply_info.raised=MagickFalse;
1828 reply_info.bevel_width--;
1829 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
1830 reply_info.height=height << 1;
1831 reply_info.x=(int) (width+(QuantumMargin << 1));
1832 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
1834 Initialize mode information.
1836 XGetWidgetInfo((char *) NULL,&mode_info);
1837 mode_info.active=MagickTrue;
1838 mode_info.bevel_width=0;
1839 mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1));
1840 mode_info.height=action_info.height;
1841 mode_info.x=QuantumMargin;
1842 mode_info.y=action_info.y;
1844 Initialize scroll information.
1846 XGetWidgetInfo((char *) NULL,&scroll_info);
1847 scroll_info.bevel_width--;
1848 scroll_info.width=height;
1849 scroll_info.height=(unsigned int) (reply_info.y-grab_info.y-
1850 (QuantumMargin >> 1));
1851 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
1852 scroll_info.y=grab_info.y-reply_info.bevel_width;
1853 scroll_info.raised=MagickFalse;
1854 scroll_info.trough=MagickTrue;
1855 north_info=scroll_info;
1856 north_info.raised=MagickTrue;
1857 north_info.width-=(north_info.bevel_width << 1);
1858 north_info.height=north_info.width-1;
1859 north_info.x+=north_info.bevel_width;
1860 north_info.y+=north_info.bevel_width;
1861 south_info=north_info;
1862 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
1865 slider_info=north_info;
1867 slider_info.width-=2;
1868 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
1869 slider_info.bevel_width+2;
1870 slider_info.height=scroll_info.height-((slider_info.min_y-
1871 scroll_info.y+1) << 1)+4;
1872 visible_colors=scroll_info.height/(height+(height >> 3));
1873 if (colors > visible_colors)
1874 slider_info.height=(unsigned int)
1875 ((visible_colors*slider_info.height)/colors);
1876 slider_info.max_y=south_info.y-south_info.bevel_width-
1877 slider_info.bevel_width-2;
1878 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
1879 slider_info.y=slider_info.min_y;
1880 expose_info=scroll_info;
1881 expose_info.y=slider_info.y;
1883 Initialize list information.
1885 XGetWidgetInfo((char *) NULL,&list_info);
1886 list_info.raised=MagickFalse;
1887 list_info.bevel_width--;
1888 list_info.width=(unsigned int)
1889 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
1890 list_info.height=scroll_info.height;
1891 list_info.x=reply_info.x;
1892 list_info.y=scroll_info.y;
1893 if (windows->widget.mapped == MagickFalse)
1894 state|=JumpListState;
1896 Initialize text information.
1899 XGetWidgetInfo(text,&text_info);
1900 text_info.center=MagickFalse;
1901 text_info.width=reply_info.width;
1902 text_info.height=height;
1903 text_info.x=list_info.x-(QuantumMargin >> 1);
1904 text_info.y=QuantumMargin;
1906 Initialize selection information.
1908 XGetWidgetInfo((char *) NULL,&selection_info);
1909 selection_info.center=MagickFalse;
1910 selection_info.width=list_info.width;
1911 selection_info.height=(unsigned int) ((9*height) >> 3);
1912 selection_info.x=list_info.x;
1913 state&=(~UpdateConfigurationState);
1915 if (state & RedrawWidgetState)
1918 Redraw Color Browser window.
1921 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
1922 (void) XDrawString(display,windows->widget.id,
1923 windows->widget.annotate_context,x,y,ColorPatternText,
1924 Extent(ColorPatternText));
1925 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
1926 XDrawWidgetText(display,&windows->widget,&text_info);
1927 XDrawBeveledButton(display,&windows->widget,&grab_info);
1928 XDrawBeveledButton(display,&windows->widget,&reset_info);
1929 XDrawBeveledMatte(display,&windows->widget,&list_info);
1930 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
1931 XDrawTriangleNorth(display,&windows->widget,&north_info);
1932 XDrawBeveledButton(display,&windows->widget,&slider_info);
1933 XDrawTriangleSouth(display,&windows->widget,&south_info);
1935 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
1936 (void) XDrawString(display,windows->widget.id,
1937 windows->widget.annotate_context,x,y,ColornameText,
1938 Extent(ColornameText));
1939 XDrawBeveledMatte(display,&windows->widget,&reply_info);
1940 XDrawMatteText(display,&windows->widget,&reply_info);
1941 XDrawBeveledButton(display,&windows->widget,&action_info);
1942 XDrawBeveledButton(display,&windows->widget,&cancel_info);
1943 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
1944 selection_info.id=(~0);
1945 state|=RedrawActionState;
1946 state|=RedrawListState;
1947 state&=(~RedrawWidgetState);
1949 if (state & UpdateListState)
1957 status=XParseColor(display,windows->widget.map_info->colormap,
1958 glob_pattern,&color);
1959 if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL))
1962 Reply is a single color name-- exit.
1964 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
1965 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1966 action_info.raised=MagickFalse;
1967 XDrawBeveledButton(display,&windows->widget,&action_info);
1973 checklist=GetColorList(glob_pattern,&number_colors,exception);
1974 if (number_colors == 0)
1976 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1977 (void) XBell(display,0);
1981 for (i=0; i < (int) colors; i++)
1982 colorlist[i]=DestroyString(colorlist[i]);
1983 if (colorlist != (char **) NULL)
1984 colorlist=(char **) RelinquishMagickMemory(colorlist);
1985 colorlist=checklist;
1986 colors=number_colors;
1989 Sort color list in ascending order.
1992 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
1993 if (colors > visible_colors)
1994 slider_info.height=(unsigned int)
1995 ((visible_colors*slider_info.height)/colors);
1996 slider_info.max_y=south_info.y-south_info.bevel_width-
1997 slider_info.bevel_width-2;
1999 slider_info.y=slider_info.min_y;
2000 expose_info.y=slider_info.y;
2001 selection_info.id=(~0);
2003 state|=RedrawListState;
2005 Redraw color name & reply.
2007 *reply_info.text='\0';
2008 reply_info.cursor=reply_info.text;
2009 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
2010 XDrawWidgetText(display,&windows->widget,&text_info);
2011 XDrawMatteText(display,&windows->widget,&reply_info);
2012 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
2013 XDrawTriangleNorth(display,&windows->widget,&north_info);
2014 XDrawBeveledButton(display,&windows->widget,&slider_info);
2015 XDrawTriangleSouth(display,&windows->widget,&south_info);
2016 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
2017 state&=(~UpdateListState);
2019 if (state & JumpListState)
2022 Jump scroll to match user color.
2025 for (i=0; i < (int) colors; i++)
2026 if (LocaleCompare(colorlist[i],reply) >= 0)
2028 list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0;
2031 if ((i < slider_info.id) ||
2032 (i >= (int) (slider_info.id+visible_colors)))
2033 slider_info.id=i-(visible_colors >> 1);
2034 selection_info.id=(~0);
2035 state|=RedrawListState;
2036 state&=(~JumpListState);
2038 if (state & RedrawListState)
2041 Determine slider id and position.
2043 if (slider_info.id >= (int) (colors-visible_colors))
2044 slider_info.id=(int) (colors-visible_colors);
2045 if ((slider_info.id < 0) || (colors <= visible_colors))
2047 slider_info.y=slider_info.min_y;
2049 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
2050 slider_info.min_y+1)/colors);
2051 if (slider_info.id != selection_info.id)
2054 Redraw scroll bar and file names.
2056 selection_info.id=slider_info.id;
2057 selection_info.y=list_info.y+(height >> 3)+2;
2058 for (i=0; i < (int) visible_colors; i++)
2060 selection_info.raised=(slider_info.id+i) != list_info.id ?
2061 MagickTrue : MagickFalse;
2062 selection_info.text=(char *) NULL;
2063 if ((slider_info.id+i) < (int) colors)
2064 selection_info.text=colorlist[slider_info.id+i];
2065 XDrawWidgetText(display,&windows->widget,&selection_info);
2066 selection_info.y+=(int) selection_info.height;
2071 if (slider_info.y > expose_info.y)
2073 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
2074 expose_info.y=slider_info.y-expose_info.height-
2075 slider_info.bevel_width-1;
2079 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
2080 expose_info.y=slider_info.y+slider_info.height+
2081 slider_info.bevel_width+1;
2083 XDrawTriangleNorth(display,&windows->widget,&north_info);
2084 XDrawMatte(display,&windows->widget,&expose_info);
2085 XDrawBeveledButton(display,&windows->widget,&slider_info);
2086 XDrawTriangleSouth(display,&windows->widget,&south_info);
2087 expose_info.y=slider_info.y;
2089 state&=(~RedrawListState);
2091 if (state & RedrawActionState)
2094 colorname[MaxTextExtent];
2097 Display the selected color in a drawing area.
2099 color=windows->widget.pixel_info->matte_color;
2100 (void) XParseColor(display,windows->widget.map_info->colormap,
2101 reply_info.text,&windows->widget.pixel_info->matte_color);
2102 XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL,
2103 (unsigned int) windows->widget.visual_info->colormap_size,
2104 &windows->widget.pixel_info->matte_color);
2105 mode_info.text=colorname;
2106 (void) FormatMagickString(mode_info.text,MaxTextExtent,"#%02x%02x%02x",
2107 windows->widget.pixel_info->matte_color.red,
2108 windows->widget.pixel_info->matte_color.green,
2109 windows->widget.pixel_info->matte_color.blue);
2110 XDrawBeveledButton(display,&windows->widget,&mode_info);
2111 windows->widget.pixel_info->matte_color=color;
2112 state&=(~RedrawActionState);
2115 Wait for next event.
2117 if (north_info.raised && south_info.raised)
2118 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
2122 Brief delay before advancing scroll bar.
2124 XDelay(display,delay);
2126 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
2127 if (north_info.raised == MagickFalse)
2128 if (slider_info.id > 0)
2134 state|=RedrawListState;
2136 if (south_info.raised == MagickFalse)
2137 if (slider_info.id < (int) colors)
2143 state|=RedrawListState;
2145 if (event.type != ButtonRelease)
2152 if (MatteIsActive(slider_info,event.xbutton))
2157 slider_info.active=MagickTrue;
2160 if (MatteIsActive(north_info,event.xbutton))
2161 if (slider_info.id > 0)
2166 north_info.raised=MagickFalse;
2168 state|=RedrawListState;
2171 if (MatteIsActive(south_info,event.xbutton))
2172 if (slider_info.id < (int) colors)
2177 south_info.raised=MagickFalse;
2179 state|=RedrawListState;
2182 if (MatteIsActive(scroll_info,event.xbutton))
2187 if (event.xbutton.y < slider_info.y)
2188 slider_info.id-=(visible_colors-1);
2190 slider_info.id+=(visible_colors-1);
2191 state|=RedrawListState;
2194 if (MatteIsActive(list_info,event.xbutton))
2200 User pressed list matte.
2202 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
2203 selection_info.height;
2204 if (id >= (int) colors)
2206 (void) CopyMagickString(reply_info.text,colorlist[id],
2208 reply_info.highlight=MagickFalse;
2209 reply_info.marker=reply_info.text;
2210 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2211 XDrawMatteText(display,&windows->widget,&reply_info);
2212 state|=RedrawActionState;
2213 if (id == list_info.id)
2215 (void) CopyMagickString(glob_pattern,reply_info.text,
2217 state|=UpdateListState;
2219 selection_info.id=(~0);
2221 state|=RedrawListState;
2224 if (MatteIsActive(grab_info,event.xbutton))
2227 User pressed Grab button.
2229 grab_info.raised=MagickFalse;
2230 XDrawBeveledButton(display,&windows->widget,&grab_info);
2233 if (MatteIsActive(reset_info,event.xbutton))
2236 User pressed Reset button.
2238 reset_info.raised=MagickFalse;
2239 XDrawBeveledButton(display,&windows->widget,&reset_info);
2242 if (MatteIsActive(mode_info,event.xbutton))
2245 User pressed mode button.
2247 (void) CopyMagickString(reply_info.text,mode_info.text,
2249 (void) CopyMagickString(primary_selection,reply_info.text,
2251 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2252 event.xbutton.time);
2253 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2254 windows->widget.id ? MagickTrue : MagickFalse;
2255 reply_info.marker=reply_info.text;
2256 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2257 XDrawMatteText(display,&windows->widget,&reply_info);
2260 if (MatteIsActive(action_info,event.xbutton))
2263 User pressed action button.
2265 action_info.raised=MagickFalse;
2266 XDrawBeveledButton(display,&windows->widget,&action_info);
2269 if (MatteIsActive(cancel_info,event.xbutton))
2272 User pressed Cancel button.
2274 cancel_info.raised=MagickFalse;
2275 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2278 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2280 if (event.xbutton.button != Button2)
2286 Move text cursor to position of button press.
2288 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
2289 for (i=1; i <= Extent(reply_info.marker); i++)
2290 if (XTextWidth(font_info,reply_info.marker,i) > x)
2292 reply_info.cursor=reply_info.marker+i-1;
2293 if (event.xbutton.time > (click_time+DoubleClick))
2294 reply_info.highlight=MagickFalse;
2298 Become the XA_PRIMARY selection owner.
2300 (void) CopyMagickString(primary_selection,reply_info.text,
2302 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2303 event.xbutton.time);
2304 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2305 windows->widget.id ? MagickTrue : MagickFalse;
2307 XDrawMatteText(display,&windows->widget,&reply_info);
2308 click_time=event.xbutton.time;
2312 Request primary selection.
2314 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2315 windows->widget.id,event.xbutton.time);
2320 if (windows->widget.mapped == MagickFalse)
2322 if (north_info.raised == MagickFalse)
2325 User released up button.
2327 delay=SuspendTime << 2;
2328 north_info.raised=MagickTrue;
2329 XDrawTriangleNorth(display,&windows->widget,&north_info);
2331 if (south_info.raised == MagickFalse)
2334 User released down button.
2336 delay=SuspendTime << 2;
2337 south_info.raised=MagickTrue;
2338 XDrawTriangleSouth(display,&windows->widget,&south_info);
2340 if (slider_info.active)
2343 Stop tracking slider.
2345 slider_info.active=MagickFalse;
2348 if (grab_info.raised == MagickFalse)
2350 if (event.xbutton.window == windows->widget.id)
2351 if (MatteIsActive(grab_info,event.xbutton))
2354 Select a pen color from the X server.
2356 (void) XGetWindowColor(display,windows,reply_info.text);
2357 reply_info.marker=reply_info.text;
2358 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2359 XDrawMatteText(display,&windows->widget,&reply_info);
2360 state|=RedrawActionState;
2362 grab_info.raised=MagickTrue;
2363 XDrawBeveledButton(display,&windows->widget,&grab_info);
2365 if (reset_info.raised == MagickFalse)
2367 if (event.xbutton.window == windows->widget.id)
2368 if (MatteIsActive(reset_info,event.xbutton))
2370 (void) CopyMagickString(glob_pattern,reset_pattern,
2372 state|=UpdateListState;
2374 reset_info.raised=MagickTrue;
2375 XDrawBeveledButton(display,&windows->widget,&reset_info);
2377 if (action_info.raised == MagickFalse)
2379 if (event.xbutton.window == windows->widget.id)
2381 if (MatteIsActive(action_info,event.xbutton))
2383 if (*reply_info.text == '\0')
2384 (void) XBell(display,0);
2389 action_info.raised=MagickTrue;
2390 XDrawBeveledButton(display,&windows->widget,&action_info);
2392 if (cancel_info.raised == MagickFalse)
2394 if (event.xbutton.window == windows->widget.id)
2395 if (MatteIsActive(cancel_info,event.xbutton))
2397 *reply_info.text='\0';
2400 cancel_info.raised=MagickTrue;
2401 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2403 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2410 If client window delete message, exit.
2412 if (event.xclient.message_type != windows->wm_protocols)
2414 if (*event.xclient.data.l == (int) windows->wm_take_focus)
2416 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2417 (Time) event.xclient.data.l[1]);
2420 if (*event.xclient.data.l != (int) windows->wm_delete_window)
2422 if (event.xclient.window == windows->widget.id)
2424 *reply_info.text='\0';
2430 case ConfigureNotify:
2433 Update widget configuration.
2435 if (event.xconfigure.window != windows->widget.id)
2437 if ((event.xconfigure.width == (int) windows->widget.width) &&
2438 (event.xconfigure.height == (int) windows->widget.height))
2440 windows->widget.width=(unsigned int)
2441 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
2442 windows->widget.height=(unsigned int)
2443 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
2444 state|=UpdateConfigurationState;
2449 if (event.xcrossing.window != windows->widget.id)
2451 state&=(~InactiveWidgetState);
2456 if (event.xexpose.window != windows->widget.id)
2458 if (event.xexpose.count != 0)
2460 state|=RedrawWidgetState;
2466 command[MaxTextExtent];
2475 Respond to a user key press.
2477 if (event.xkey.window != windows->widget.id)
2479 length=XLookupString((XKeyEvent *) &event.xkey,command,
2480 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2481 *(command+length)='\0';
2482 if (AreaIsActive(scroll_info,event.xkey))
2487 switch ((int) key_symbol)
2510 slider_info.id-=visible_colors;
2516 slider_info.id+=visible_colors;
2522 slider_info.id=(int) colors;
2526 state|=RedrawListState;
2529 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
2532 Read new color or glob patterm.
2534 if (*reply_info.text == '\0')
2536 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
2537 state|=UpdateListState;
2540 if (key_symbol == XK_Control_L)
2542 state|=ControlState;
2545 if (state & ControlState)
2546 switch ((int) key_symbol)
2552 Erase the entire line of text.
2554 *reply_info.text='\0';
2555 reply_info.cursor=reply_info.text;
2556 reply_info.marker=reply_info.text;
2557 reply_info.highlight=MagickFalse;
2563 XEditText(display,&reply_info,key_symbol,command,state);
2564 XDrawMatteText(display,&windows->widget,&reply_info);
2565 state|=JumpListState;
2566 status=XParseColor(display,windows->widget.map_info->colormap,
2567 reply_info.text,&color);
2568 if (status != False)
2569 state|=RedrawActionState;
2575 command[MaxTextExtent];
2581 Respond to a user key release.
2583 if (event.xkey.window != windows->widget.id)
2585 (void) XLookupString((XKeyEvent *) &event.xkey,command,
2586 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2587 if (key_symbol == XK_Control_L)
2588 state&=(~ControlState);
2593 if (event.xcrossing.window != windows->widget.id)
2595 state|=InactiveWidgetState;
2607 Discard pending button motion events.
2609 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
2610 if (slider_info.active)
2615 slider_info.y=event.xmotion.y-
2616 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
2617 if (slider_info.y < slider_info.min_y)
2618 slider_info.y=slider_info.min_y;
2619 if (slider_info.y > slider_info.max_y)
2620 slider_info.y=slider_info.max_y;
2622 if (slider_info.y != slider_info.min_y)
2623 slider_info.id=(int) ((colors*(slider_info.y-
2624 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
2625 state|=RedrawListState;
2628 if (state & InactiveWidgetState)
2630 if (grab_info.raised == MatteIsActive(grab_info,event.xmotion))
2633 Grab button status changed.
2635 grab_info.raised=!grab_info.raised;
2636 XDrawBeveledButton(display,&windows->widget,&grab_info);
2639 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
2642 Reset button status changed.
2644 reset_info.raised=!reset_info.raised;
2645 XDrawBeveledButton(display,&windows->widget,&reset_info);
2648 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
2651 Action button status changed.
2653 action_info.raised=action_info.raised == MagickFalse ?
2654 MagickTrue : MagickFalse;
2655 XDrawBeveledButton(display,&windows->widget,&action_info);
2658 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
2661 Cancel button status changed.
2663 cancel_info.raised=cancel_info.raised == MagickFalse ?
2664 MagickTrue : MagickFalse;
2665 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2670 case SelectionClear:
2672 reply_info.highlight=MagickFalse;
2673 XDrawMatteText(display,&windows->widget,&reply_info);
2676 case SelectionNotify:
2692 Obtain response from primary selection.
2694 if (event.xselection.property == (Atom) None)
2696 status=XGetWindowProperty(display,event.xselection.requestor,
2697 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
2698 &format,&length,&after,&data);
2699 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2702 if ((Extent(reply_info.text)+length) >= MaxTextExtent)
2703 (void) XBell(display,0);
2707 Insert primary selection in reply text.
2709 *(data+length)='\0';
2710 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
2712 XDrawMatteText(display,&windows->widget,&reply_info);
2713 state|=JumpListState;
2714 state|=RedrawActionState;
2716 (void) XFree((void *) data);
2719 case SelectionRequest:
2724 XSelectionRequestEvent
2727 if (reply_info.highlight == MagickFalse)
2730 Set primary selection.
2732 request=(&(event.xselectionrequest));
2733 (void) XChangeProperty(request->display,request->requestor,
2734 request->property,request->target,8,PropModeReplace,
2735 (unsigned char *) primary_selection,Extent(primary_selection));
2736 notify.type=SelectionNotify;
2737 notify.send_event=MagickTrue;
2738 notify.display=request->display;
2739 notify.requestor=request->requestor;
2740 notify.selection=request->selection;
2741 notify.target=request->target;
2742 notify.time=request->time;
2743 if (request->property == None)
2744 notify.property=request->target;
2746 notify.property=request->property;
2747 (void) XSendEvent(request->display,request->requestor,False,
2748 NoEventMask,(XEvent *) ¬ify);
2753 } while ((state & ExitState) == 0);
2754 XSetCursorState(display,windows,MagickFalse);
2755 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
2756 XCheckRefreshWindows(display,windows);
2760 for (i=0; i < (int) colors; i++)
2761 colorlist[i]=DestroyString(colorlist[i]);
2762 if (colorlist != (char **) NULL)
2763 colorlist=(char **) RelinquishMagickMemory(colorlist);
2764 exception=DestroyExceptionInfo(exception);
2765 if ((*reply == '\0') || (strchr(reply,'-') != (char *) NULL))
2767 status=XParseColor(display,windows->widget.map_info->colormap,reply,&color);
2768 if (status != False)
2770 XNoticeWidget(display,windows,"Color is unknown to X server:",reply);
2771 (void) CopyMagickString(reply,"gray",MaxTextExtent);
2775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2779 % X C o m m a n d W i d g e t %
2783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2785 % XCommandWidget() maps a menu and returns the command pointed to by the user
2786 % when the button is released.
2788 % The format of the XCommandWidget method is:
2790 % int XCommandWidget(Display *display,XWindows *windows,
2791 % const char **selections,XEvent *event)
2793 % A description of each parameter follows:
2795 % o selection_number: Specifies the number of the selection that the
2798 % o display: Specifies a connection to an X server; returned from
2801 % o window: Specifies a pointer to a XWindows structure.
2803 % o selections: Specifies a pointer to one or more strings that comprise
2804 % the choices in the menu.
2806 % o event: Specifies a pointer to a X11 XEvent structure.
2809 MagickExport int XCommandWidget(Display *display,XWindows *windows,
2810 const char **selections,XEvent *event)
2812 #define tile_width 112
2813 #define tile_height 70
2815 static const unsigned char
2818 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2819 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2820 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
2822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2823 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
2824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2825 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2826 0x00, 0x00, 0x1e, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2827 0x00, 0x00, 0x00, 0x00, 0x1e, 0xbc, 0x9f, 0x03, 0x00, 0x3e, 0x00, 0xc0,
2828 0x1f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x0f, 0x80, 0x3f,
2829 0x00, 0xf0, 0x1f, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x1f,
2830 0xe0, 0x3f, 0x00, 0xfc, 0x1f, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc,
2831 0xff, 0x1f, 0xf0, 0x3f, 0x00, 0xfe, 0x1f, 0xf8, 0x0f, 0x00, 0x00, 0x00,
2832 0x1e, 0xfc, 0xfc, 0x3f, 0xf8, 0x3f, 0x00, 0xff, 0x1e, 0xfc, 0x0f, 0x00,
2833 0x00, 0x00, 0x1e, 0x7c, 0xfc, 0x3e, 0xf8, 0x3c, 0x80, 0x1f, 0x1e, 0x7c,
2834 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 0xc0, 0x0f,
2835 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c,
2836 0xc0, 0x07, 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c,
2837 0x7c, 0x7c, 0xc0, 0x0f, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78,
2838 0x78, 0x3c, 0xfc, 0x7c, 0x80, 0x7f, 0x1e, 0x7c, 0x00, 0x00, 0x00, 0x00,
2839 0x1e, 0xf8, 0x78, 0x7c, 0xf8, 0xff, 0x00, 0xff, 0x1f, 0xf8, 0xff, 0x00,
2840 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xfe, 0x1f, 0xf8,
2841 0xff, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xf8,
2842 0x1f, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xc0, 0xef,
2843 0x07, 0xe0, 0x1f, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0x70, 0x40, 0x78,
2844 0x00, 0xc7, 0x07, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00,
2845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
2846 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
2848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
2849 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2850 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2851 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2852 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
2853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00,
2854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
2855 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
2856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2857 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00,
2858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
2859 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2860 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2861 0x60, 0x00, 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2862 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2863 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00,
2864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0x9f, 0x7f, 0x00,
2865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0xdf,
2866 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00,
2867 0xe0, 0xdf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0c,
2868 0x78, 0x30, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
2869 0x00, 0x0f, 0xf8, 0x70, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x1f, 0x00, 0xe0,
2870 0x0f, 0x1e, 0x80, 0x0f, 0xf8, 0x78, 0xf0, 0xfd, 0xf9, 0x00, 0xc0, 0x1f,
2871 0x00, 0xf8, 0x0f, 0x00, 0xe0, 0x1f, 0xf8, 0x7c, 0xf0, 0xfc, 0xf9, 0x00,
2872 0xf0, 0x1f, 0x00, 0xfe, 0x0f, 0x00, 0xf0, 0x07, 0xf8, 0x3e, 0xf8, 0xfc,
2873 0xf0, 0x01, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x1e, 0xf0, 0x03, 0xf8, 0x3f,
2874 0xf8, 0xf8, 0xf0, 0x01, 0xfc, 0x1f, 0x80, 0x7f, 0x0f, 0x1e, 0xf8, 0x00,
2875 0xf8, 0x1f, 0x78, 0x18, 0xf0, 0x01, 0x7c, 0x1e, 0xc0, 0x0f, 0x0f, 0x1e,
2876 0x7c, 0x00, 0xf0, 0x0f, 0x78, 0x00, 0xf0, 0x01, 0x3e, 0x1e, 0xe0, 0x07,
2877 0x0f, 0x1e, 0x7c, 0x00, 0xf0, 0x07, 0x7c, 0x00, 0xe0, 0x01, 0x3e, 0x1e,
2878 0xe0, 0x03, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x0f, 0x7c, 0x00, 0xe0, 0x03,
2879 0x3e, 0x3e, 0xe0, 0x07, 0x0f, 0x1e, 0x1e, 0x00, 0xf0, 0x1f, 0x3c, 0x00,
2880 0xe0, 0x03, 0x7e, 0x3e, 0xc0, 0x3f, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x1f,
2881 0x3e, 0x00, 0xe0, 0x03, 0xfc, 0x7f, 0x80, 0xff, 0x0f, 0x1e, 0xfc, 0x00,
2882 0xf0, 0x3e, 0x3e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xff, 0x0f, 0x1e,
2883 0xfc, 0x07, 0xf0, 0x7c, 0x1e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xfc,
2884 0x0f, 0x1e, 0xf8, 0x1f, 0xf0, 0xf8, 0x1e, 0x00, 0xc0, 0x03, 0xe0, 0xf7,
2885 0x03, 0xf0, 0x0f, 0x1e, 0xe0, 0x3f, 0xf0, 0x78, 0x1c, 0x00, 0x80, 0x03,
2886 0x80, 0xe3, 0x03, 0x00, 0x0f, 0x1e, 0xc0, 0x3f, 0xf0, 0x30, 0x00, 0x00,
2887 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x3e, 0x00, 0x00,
2888 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x10,
2889 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00,
2890 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
2891 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2892 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2893 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2894 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
2896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
2897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
2898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2899 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2921 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2922 assert(display != (Display *) NULL);
2923 assert(windows != (XWindows *) NULL);
2924 font_info=windows->command.font_info;
2925 height=(unsigned int) (font_info->ascent+font_info->descent);
2928 if (event == (XEvent *) NULL)
2940 Determine command window attributes.
2942 assert(selections != (const char **) NULL);
2943 windows->command.width=0;
2944 for (i=0; selections[i] != (char *) NULL; i++)
2946 width=WidgetTextWidth(font_info,(char *) selections[i]);
2947 if (width > windows->command.width)
2948 windows->command.width=width;
2950 number_selections=(unsigned int) i;
2951 windows->command.width+=3*QuantumMargin+10;
2952 if ((int) windows->command.width < (tile_width+QuantumMargin+10))
2953 windows->command.width=(unsigned int) (tile_width+QuantumMargin+10);
2954 windows->command.height=(unsigned int) (number_selections*
2955 (((3*height) >> 1)+10)+tile_height+20);
2956 windows->command.min_width=windows->command.width;
2957 windows->command.min_height=windows->command.height;
2958 XConstrainWindowPosition(display,&windows->command);
2959 if (windows->command.id != (Window) NULL)
2965 Reconfigure command window.
2967 status=XStringListToTextProperty(&windows->command.name,1,
2969 if (status != False)
2971 XSetWMName(display,windows->command.id,&window_name);
2972 XSetWMIconName(display,windows->command.id,&window_name);
2973 (void) XFree((void *) window_name.value);
2975 window_changes.width=(int) windows->command.width;
2976 window_changes.height=(int) windows->command.height;
2977 (void) XReconfigureWMWindow(display,windows->command.id,
2978 windows->command.screen,(unsigned int) (CWWidth | CWHeight),
2982 Allocate selection info memory.
2984 if (selection_info != (XWidgetInfo *) NULL)
2985 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
2986 selection_info=(XWidgetInfo *) AcquireQuantumMemory(number_selections,
2987 sizeof(*selection_info));
2988 if (selection_info == (XWidgetInfo *) NULL)
2990 ThrowXWindowFatalException(ResourceLimitError,
2991 "MemoryAllocationFailed","...");
2994 state|=UpdateConfigurationState | RedrawWidgetState;
2997 Wait for next event.
2999 if (event != (XEvent *) NULL)
3000 switch (event->type)
3004 for (i=0; i < (int) number_selections; i++)
3006 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3008 if (i >= (int) windows->command.data)
3010 selection_info[i].raised=MagickFalse;
3011 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3014 submenu_info=selection_info[i];
3015 submenu_info.active=MagickTrue;
3017 submenu_info.y+(submenu_info.height >> 1)-(toggle_info.height >> 1);
3019 (void) XCheckWindowEvent(display,windows->widget.id,LeaveWindowMask,
3027 for (i=0; i < (int) number_selections; i++)
3029 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3032 if (id >= (int) windows->command.data)
3034 selection_info[id].raised=MagickTrue;
3035 XDrawBeveledButton(display,&windows->command,&selection_info[id]);
3045 If client window delete message, withdraw command widget.
3047 if (event->xclient.message_type != windows->wm_protocols)
3049 if (*event->xclient.data.l != (int) windows->wm_delete_window)
3051 (void) XWithdrawWindow(display,windows->command.id,
3052 windows->command.screen);
3055 case ConfigureNotify:
3058 Update widget configuration.
3060 if (event->xconfigure.window != windows->command.id)
3062 if (event->xconfigure.send_event != 0)
3064 windows->command.x=event->xconfigure.x;
3065 windows->command.y=event->xconfigure.y;
3067 if ((event->xconfigure.width == (int) windows->command.width) &&
3068 (event->xconfigure.height == (int) windows->command.height))
3070 windows->command.width=(unsigned int)
3071 MagickMax(event->xconfigure.width,(int) windows->command.min_width);
3072 windows->command.height=(unsigned int)
3073 MagickMax(event->xconfigure.height,(int) windows->command.min_height);
3074 state|=UpdateConfigurationState;
3079 if (event->xexpose.window != windows->command.id)
3081 if (event->xexpose.count != 0)
3083 state|=RedrawWidgetState;
3089 Return the ID of the highlighted menu entry.
3093 for (i=0; i < (int) number_selections; i++)
3095 if (i >= (int) windows->command.data)
3097 if (selection_info[i].raised ==
3098 MatteIsActive(selection_info[i],event->xmotion))
3101 Button status changed.
3103 selection_info[i].raised=!selection_info[i].raised;
3104 XDrawBeveledButton(display,&windows->command,
3105 &selection_info[i]);
3109 if (MatteIsActive(selection_info[i],event->xmotion) == MagickFalse)
3111 submenu_info=selection_info[i];
3112 submenu_info.active=MagickTrue;
3113 toggle_info.raised=MagickTrue;
3114 toggle_info.y=submenu_info.y+(submenu_info.height >> 1)-
3115 (toggle_info.height >> 1);
3116 XDrawTriangleEast(display,&windows->command,&toggle_info);
3119 XDelay(display,SuspendTime);
3120 if (XCheckMaskEvent(display,ButtonMotionMask,event) == MagickFalse)
3122 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
3123 toggle_info.raised=MagickFalse;
3124 if (windows->command.data != 0)
3125 XDrawTriangleEast(display,&windows->command,&toggle_info);
3131 windows->command.mapped=MagickTrue;
3136 windows->command.mapped=MagickFalse;
3142 if (state & UpdateConfigurationState)
3145 Initialize button information.
3147 assert(selections != (const char **) NULL);
3149 for (i=0; i < (int) number_selections; i++)
3151 XGetWidgetInfo(selections[i],&selection_info[i]);
3152 selection_info[i].center=MagickFalse;
3153 selection_info[i].bevel_width--;
3154 selection_info[i].height=(unsigned int) ((3*height) >> 1);
3155 selection_info[i].x=(QuantumMargin >> 1)+4;
3156 selection_info[i].width=(unsigned int)
3157 (windows->command.width-(selection_info[i].x << 1));
3158 selection_info[i].y=y;
3159 y+=selection_info[i].height+(selection_info[i].bevel_width << 1)+6;
3161 XGetWidgetInfo((char *) NULL,&toggle_info);
3162 toggle_info.bevel_width--;
3163 toggle_info.width=(unsigned int)
3164 (((5*height) >> 3)-(toggle_info.bevel_width << 1));
3165 toggle_info.height=toggle_info.width;
3166 toggle_info.x=selection_info[0].x+selection_info[0].width-
3167 toggle_info.width-(QuantumMargin >> 1);
3168 if (windows->command.mapped)
3169 (void) XClearWindow(display,windows->command.id);
3171 if (state & RedrawWidgetState)
3177 Draw command buttons.
3179 tile_pixmap=XCreatePixmapFromBitmapData(display,windows->command.id,
3180 (char *) tile_bits,tile_width,tile_height,1L,0L,1);
3181 if (tile_pixmap != (Pixmap) NULL)
3183 (void) XCopyPlane(display,tile_pixmap,windows->command.id,
3184 windows->command.annotate_context,0,0,tile_width,tile_height,
3185 (int) ((windows->command.width-tile_width) >> 1),10,1L);
3186 (void) XFreePixmap(display,tile_pixmap);
3188 for (i=0; i < (int) number_selections; i++)
3190 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3191 if (i >= (int) windows->command.data)
3193 toggle_info.raised=i == id ? MagickTrue : MagickFalse;
3194 toggle_info.y=selection_info[i].y+
3195 (selection_info[i].height >> 1)-(toggle_info.height >> 1);
3196 XDrawTriangleEast(display,&windows->command,&toggle_info);
3198 XHighlightWidget(display,&windows->command,BorderOffset,BorderOffset);
3204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3208 % X C o n f i r m W i d g e t %
3212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3214 % XConfirmWidget() displays a Confirm widget with a notice to the user. The
3215 % function returns -1 if Dismiss is pressed, 0 for Cancel, and 1 for Yes.
3217 % The format of the XConfirmWidget method is:
3219 % int XConfirmWidget(Display *display,XWindows *windows,
3220 % const char *reason,const char *description)
3222 % A description of each parameter follows:
3224 % o display: Specifies a connection to an X server; returned from
3227 % o window: Specifies a pointer to a XWindows structure.
3229 % o reason: Specifies the message to display before terminating the
3232 % o description: Specifies any description to the message.
3235 MagickExport int XConfirmWidget(Display *display,XWindows *windows,
3236 const char *reason,const char *description)
3238 #define CancelButtonText "Cancel"
3239 #define DismissButtonText "Dismiss"
3240 #define YesButtonText "Yes"
3275 Determine Confirm widget attributes.
3277 assert(display != (Display *) NULL);
3278 assert(windows != (XWindows *) NULL);
3279 assert(reason != (char *) NULL);
3280 assert(description != (char *) NULL);
3281 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
3282 XCheckRefreshWindows(display,windows);
3283 font_info=windows->widget.font_info;
3284 width=WidgetTextWidth(font_info,CancelButtonText);
3285 if (WidgetTextWidth(font_info,DismissButtonText) > width)
3286 width=WidgetTextWidth(font_info,DismissButtonText);
3287 if (WidgetTextWidth(font_info,YesButtonText) > width)
3288 width=WidgetTextWidth(font_info,YesButtonText);
3290 if (description != (char *) NULL)
3291 if (WidgetTextWidth(font_info,(char *) description) > width)
3292 width=WidgetTextWidth(font_info,(char *) description);
3293 height=(unsigned int) (font_info->ascent+font_info->descent);
3295 Position Confirm widget.
3297 windows->widget.width=(unsigned int) (width+9*QuantumMargin);
3298 windows->widget.min_width=(unsigned int) (9*QuantumMargin+
3299 WidgetTextWidth(font_info,CancelButtonText)+
3300 WidgetTextWidth(font_info,DismissButtonText)+
3301 WidgetTextWidth(font_info,YesButtonText));
3302 if (windows->widget.width < windows->widget.min_width)
3303 windows->widget.width=windows->widget.min_width;
3304 windows->widget.height=(unsigned int) (12*height);
3305 windows->widget.min_height=(unsigned int) (7*height);
3306 if (windows->widget.height < windows->widget.min_height)
3307 windows->widget.height=windows->widget.min_height;
3308 XConstrainWindowPosition(display,&windows->widget);
3312 (void) CopyMagickString(windows->widget.name,"Confirm",MaxTextExtent);
3313 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3314 if (status != False)
3316 XSetWMName(display,windows->widget.id,&window_name);
3317 XSetWMIconName(display,windows->widget.id,&window_name);
3318 (void) XFree((void *) window_name.value);
3320 window_changes.width=(int) windows->widget.width;
3321 window_changes.height=(int) windows->widget.height;
3322 window_changes.x=windows->widget.x;
3323 window_changes.y=windows->widget.y;
3324 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3325 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3326 (void) XMapRaised(display,windows->widget.id);
3327 windows->widget.mapped=MagickFalse;
3329 Respond to X events.
3332 state=UpdateConfigurationState;
3333 XSetCursorState(display,windows,MagickTrue);
3336 if (state & UpdateConfigurationState)
3339 Initialize button information.
3341 XGetWidgetInfo(CancelButtonText,&cancel_info);
3342 cancel_info.width=(unsigned int) QuantumMargin+
3343 WidgetTextWidth(font_info,CancelButtonText);
3344 cancel_info.height=(unsigned int) ((3*height) >> 1);
3345 cancel_info.x=(int) (windows->widget.width-cancel_info.width-
3347 cancel_info.y=(int) (windows->widget.height-(cancel_info.height << 1));
3348 dismiss_info=cancel_info;
3349 dismiss_info.text=(char *) DismissButtonText;
3350 if (LocaleCompare(description,"Do you want to save it") == 0)
3351 dismiss_info.text=(char *) "Don't Save";
3352 dismiss_info.width=(unsigned int) QuantumMargin+
3353 WidgetTextWidth(font_info,dismiss_info.text);
3354 dismiss_info.x=(int)
3355 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
3356 yes_info=cancel_info;
3357 yes_info.text=(char *) YesButtonText;
3358 if (LocaleCompare(description,"Do you want to save it") == 0)
3359 yes_info.text=(char *) "Save";
3360 yes_info.width=(unsigned int) QuantumMargin+
3361 WidgetTextWidth(font_info,yes_info.text);
3362 if (yes_info.width < cancel_info.width)
3363 yes_info.width=cancel_info.width;
3364 yes_info.x=QuantumMargin;
3365 state&=(~UpdateConfigurationState);
3367 if (state & RedrawWidgetState)
3370 Redraw Confirm widget.
3372 width=WidgetTextWidth(font_info,(char *) reason);
3373 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3374 y=(int) ((windows->widget.height >> 1)-(height << 1));
3375 (void) XDrawString(display,windows->widget.id,
3376 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
3377 if (description != (char *) NULL)
3380 question[MaxTextExtent];
3382 (void) CopyMagickString(question,description,MaxTextExtent);
3383 (void) ConcatenateMagickString(question,"?",MaxTextExtent);
3384 width=WidgetTextWidth(font_info,question);
3385 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3387 (void) XDrawString(display,windows->widget.id,
3388 windows->widget.annotate_context,x,y,question,Extent(question));
3390 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3391 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3392 XDrawBeveledButton(display,&windows->widget,&yes_info);
3393 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3394 state&=(~RedrawWidgetState);
3397 Wait for next event.
3399 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3404 if (MatteIsActive(cancel_info,event.xbutton))
3407 User pressed No button.
3409 cancel_info.raised=MagickFalse;
3410 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3413 if (MatteIsActive(dismiss_info,event.xbutton))
3416 User pressed Dismiss button.
3418 dismiss_info.raised=MagickFalse;
3419 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3422 if (MatteIsActive(yes_info,event.xbutton))
3425 User pressed Yes button.
3427 yes_info.raised=MagickFalse;
3428 XDrawBeveledButton(display,&windows->widget,&yes_info);
3435 if (windows->widget.mapped == MagickFalse)
3437 if (cancel_info.raised == MagickFalse)
3439 if (event.xbutton.window == windows->widget.id)
3440 if (MatteIsActive(cancel_info,event.xbutton))
3445 cancel_info.raised=MagickTrue;
3446 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3448 if (dismiss_info.raised == MagickFalse)
3450 if (event.xbutton.window == windows->widget.id)
3451 if (MatteIsActive(dismiss_info,event.xbutton))
3456 dismiss_info.raised=MagickTrue;
3457 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3459 if (yes_info.raised == MagickFalse)
3461 if (event.xbutton.window == windows->widget.id)
3462 if (MatteIsActive(yes_info,event.xbutton))
3467 yes_info.raised=MagickTrue;
3468 XDrawBeveledButton(display,&windows->widget,&yes_info);
3475 If client window delete message, exit.
3477 if (event.xclient.message_type != windows->wm_protocols)
3479 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3481 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3482 (Time) event.xclient.data.l[1]);
3485 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3487 if (event.xclient.window == windows->widget.id)
3494 case ConfigureNotify:
3497 Update widget configuration.
3499 if (event.xconfigure.window != windows->widget.id)
3501 if ((event.xconfigure.width == (int) windows->widget.width) &&
3502 (event.xconfigure.height == (int) windows->widget.height))
3504 windows->widget.width=(unsigned int)
3505 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3506 windows->widget.height=(unsigned int)
3507 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3508 state|=UpdateConfigurationState;
3513 if (event.xcrossing.window != windows->widget.id)
3515 state&=(~InactiveWidgetState);
3520 if (event.xexpose.window != windows->widget.id)
3522 if (event.xexpose.count != 0)
3524 state|=RedrawWidgetState;
3530 command[MaxTextExtent];
3536 Respond to a user key press.
3538 if (event.xkey.window != windows->widget.id)
3540 (void) XLookupString((XKeyEvent *) &event.xkey,command,
3541 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3542 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
3544 yes_info.raised=MagickFalse;
3545 XDrawBeveledButton(display,&windows->widget,&yes_info);
3554 if (event.xcrossing.window != windows->widget.id)
3556 state|=InactiveWidgetState;
3562 Discard pending button motion events.
3564 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
3565 if (state & InactiveWidgetState)
3567 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
3570 Cancel button status changed.
3572 cancel_info.raised=cancel_info.raised == MagickFalse ?
3573 MagickTrue : MagickFalse;
3574 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3577 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
3580 Dismiss button status changed.
3582 dismiss_info.raised=cancel_info.raised == MagickFalse ?
3583 MagickTrue : MagickFalse;
3584 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3587 if (yes_info.raised == MatteIsActive(yes_info,event.xmotion))
3590 Yes button status changed.
3592 yes_info.raised=yes_info.raised == MagickFalse ?
3593 MagickTrue : MagickFalse;
3594 XDrawBeveledButton(display,&windows->widget,&yes_info);
3602 } while ((state & ExitState) == 0);
3603 XSetCursorState(display,windows,MagickFalse);
3604 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
3605 XCheckRefreshWindows(display,windows);
3610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3614 % X D i a l o g W i d g e t %
3618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3620 % XDialogWidget() displays a Dialog widget with a query to the user. The user
3621 % keys a reply and presses the Ok or Cancel button to exit. The typed text is
3622 % returned as the reply function parameter.
3624 % The format of the XDialogWidget method is:
3626 % int XDialogWidget(Display *display,XWindows *windows,const char *action,
3627 % const char *query,char *reply)
3629 % A description of each parameter follows:
3631 % o display: Specifies a connection to an X server; returned from
3634 % o window: Specifies a pointer to a XWindows structure.
3636 % o action: Specifies a pointer to the action of this widget.
3638 % o query: Specifies a pointer to the query to present to the user.
3640 % o reply: the response from the user is returned in this parameter.
3643 MagickExport int XDialogWidget(Display *display,XWindows *windows,
3644 const char *action,const char *query,char *reply)
3646 #define CancelButtonText "Cancel"
3649 primary_selection[MaxTextExtent];
3657 static MagickBooleanType
3658 raised = MagickFalse;
3691 Determine Dialog widget attributes.
3693 assert(display != (Display *) NULL);
3694 assert(windows != (XWindows *) NULL);
3695 assert(action != (char *) NULL);
3696 assert(query != (char *) NULL);
3697 assert(reply != (char *) NULL);
3698 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
3699 XCheckRefreshWindows(display,windows);
3700 font_info=windows->widget.font_info;
3701 width=WidgetTextWidth(font_info,(char *) action);
3702 if (WidgetTextWidth(font_info,CancelButtonText) > width)
3703 width=WidgetTextWidth(font_info,CancelButtonText);
3704 width+=(3*QuantumMargin) >> 1;
3705 height=(unsigned int) (font_info->ascent+font_info->descent);
3707 Position Dialog widget.
3709 windows->widget.width=(unsigned int) MagickMax((int) (2*width),(int)
3710 WidgetTextWidth(font_info,(char *) query));
3711 if (windows->widget.width < WidgetTextWidth(font_info,reply))
3712 windows->widget.width=WidgetTextWidth(font_info,reply);
3713 windows->widget.width+=6*QuantumMargin;
3714 windows->widget.min_width=(unsigned int)
3715 (width+28*XTextWidth(font_info,"#",1)+4*QuantumMargin);
3716 if (windows->widget.width < windows->widget.min_width)
3717 windows->widget.width=windows->widget.min_width;
3718 windows->widget.height=(unsigned int) (7*height+(QuantumMargin << 1));
3719 windows->widget.min_height=windows->widget.height;
3720 if (windows->widget.height < windows->widget.min_height)
3721 windows->widget.height=windows->widget.min_height;
3722 XConstrainWindowPosition(display,&windows->widget);
3726 (void) CopyMagickString(windows->widget.name,"Dialog",MaxTextExtent);
3727 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3728 if (status != False)
3730 XSetWMName(display,windows->widget.id,&window_name);
3731 XSetWMIconName(display,windows->widget.id,&window_name);
3732 (void) XFree((void *) window_name.value);
3734 window_changes.width=(int) windows->widget.width;
3735 window_changes.height=(int) windows->widget.height;
3736 window_changes.x=windows->widget.x;
3737 window_changes.y=windows->widget.y;
3738 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3739 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3740 (void) XMapRaised(display,windows->widget.id);
3741 windows->widget.mapped=MagickFalse;
3743 Respond to X events.
3745 anomaly=(LocaleCompare(action,"Background") == 0) ||
3746 (LocaleCompare(action,"New") == 0) ||
3747 (LocaleCompare(action,"Quantize") == 0) ||
3748 (LocaleCompare(action,"Resize") == 0) ||
3749 (LocaleCompare(action,"Save") == 0) ||
3750 (LocaleCompare(action,"Shade") == 0);
3751 state=UpdateConfigurationState;
3752 XSetCursorState(display,windows,MagickTrue);
3755 if (state & UpdateConfigurationState)
3758 Initialize button information.
3760 XGetWidgetInfo(CancelButtonText,&cancel_info);
3761 cancel_info.width=width;
3762 cancel_info.height=(unsigned int) ((3*height) >> 1);
3764 (windows->widget.width-cancel_info.width-((3*QuantumMargin) >> 1));
3766 (windows->widget.height-cancel_info.height-((3*QuantumMargin) >> 1));
3767 XGetWidgetInfo(action,&action_info);
3768 action_info.width=width;
3769 action_info.height=(unsigned int) ((3*height) >> 1);
3770 action_info.x=cancel_info.x-(cancel_info.width+QuantumMargin+
3771 (action_info.bevel_width << 1));
3772 action_info.y=cancel_info.y;
3774 Initialize reply information.
3776 XGetWidgetInfo(reply,&reply_info);
3777 reply_info.raised=MagickFalse;
3778 reply_info.bevel_width--;
3779 reply_info.width=windows->widget.width-(3*QuantumMargin);
3780 reply_info.height=height << 1;
3781 reply_info.x=(3*QuantumMargin) >> 1;
3782 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
3784 Initialize option information.
3786 XGetWidgetInfo("Dither",&special_info);
3787 special_info.raised=raised;
3788 special_info.bevel_width--;
3789 special_info.width=(unsigned int) QuantumMargin >> 1;
3790 special_info.height=(unsigned int) QuantumMargin >> 1;
3791 special_info.x=reply_info.x;
3792 special_info.y=action_info.y+action_info.height-special_info.height;
3793 if (LocaleCompare(action,"Background") == 0)
3794 special_info.text=(char *) "Backdrop";
3795 if (LocaleCompare(action,"New") == 0)
3796 special_info.text=(char *) "Gradation";
3797 if (LocaleCompare(action,"Resize") == 0)
3798 special_info.text=(char *) "Constrain ratio";
3799 if (LocaleCompare(action,"Save") == 0)
3800 special_info.text=(char *) "Non-progressive";
3801 if (LocaleCompare(action,"Shade") == 0)
3802 special_info.text=(char *) "Color shading";
3804 Initialize text information.
3806 XGetWidgetInfo(query,&text_info);
3807 text_info.width=reply_info.width;
3808 text_info.height=height;
3809 text_info.x=reply_info.x-(QuantumMargin >> 1);
3810 text_info.y=QuantumMargin;
3811 text_info.center=MagickFalse;
3812 state&=(~UpdateConfigurationState);
3814 if (state & RedrawWidgetState)
3817 Redraw Dialog widget.
3819 XDrawWidgetText(display,&windows->widget,&text_info);
3820 XDrawBeveledMatte(display,&windows->widget,&reply_info);
3821 XDrawMatteText(display,&windows->widget,&reply_info);
3823 XDrawBeveledButton(display,&windows->widget,&special_info);
3824 XDrawBeveledButton(display,&windows->widget,&action_info);
3825 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3826 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3827 state&=(~RedrawWidgetState);
3830 Wait for next event.
3832 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3838 if (MatteIsActive(special_info,event.xbutton))
3841 Option button status changed.
3843 special_info.raised=!special_info.raised;
3844 XDrawBeveledButton(display,&windows->widget,&special_info);
3847 if (MatteIsActive(action_info,event.xbutton))
3850 User pressed Action button.
3852 action_info.raised=MagickFalse;
3853 XDrawBeveledButton(display,&windows->widget,&action_info);
3856 if (MatteIsActive(cancel_info,event.xbutton))
3859 User pressed Cancel button.
3861 cancel_info.raised=MagickFalse;
3862 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3865 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
3867 if (event.xbutton.button != Button2)
3873 Move text cursor to position of button press.
3875 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
3876 for (i=1; i <= Extent(reply_info.marker); i++)
3877 if (XTextWidth(font_info,reply_info.marker,i) > x)
3879 reply_info.cursor=reply_info.marker+i-1;
3880 if (event.xbutton.time > (click_time+DoubleClick))
3881 reply_info.highlight=MagickFalse;
3885 Become the XA_PRIMARY selection owner.
3887 (void) CopyMagickString(primary_selection,reply_info.text,
3889 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
3890 event.xbutton.time);
3891 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
3892 windows->widget.id ? MagickTrue : MagickFalse;
3894 XDrawMatteText(display,&windows->widget,&reply_info);
3895 click_time=event.xbutton.time;
3899 Request primary selection.
3901 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
3902 windows->widget.id,event.xbutton.time);
3907 if (windows->widget.mapped == MagickFalse)
3909 if (action_info.raised == MagickFalse)
3911 if (event.xbutton.window == windows->widget.id)
3912 if (MatteIsActive(action_info,event.xbutton))
3914 action_info.raised=MagickTrue;
3915 XDrawBeveledButton(display,&windows->widget,&action_info);
3917 if (cancel_info.raised == MagickFalse)
3919 if (event.xbutton.window == windows->widget.id)
3920 if (MatteIsActive(cancel_info,event.xbutton))
3922 *reply_info.text='\0';
3925 cancel_info.raised=MagickTrue;
3926 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3933 If client window delete message, exit.
3935 if (event.xclient.message_type != windows->wm_protocols)
3937 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3939 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3940 (Time) event.xclient.data.l[1]);
3943 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3945 if (event.xclient.window == windows->widget.id)
3947 *reply_info.text='\0';
3953 case ConfigureNotify:
3956 Update widget configuration.
3958 if (event.xconfigure.window != windows->widget.id)
3960 if ((event.xconfigure.width == (int) windows->widget.width) &&
3961 (event.xconfigure.height == (int) windows->widget.height))
3963 windows->widget.width=(unsigned int)
3964 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3965 windows->widget.height=(unsigned int)
3966 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3967 state|=UpdateConfigurationState;
3972 if (event.xcrossing.window != windows->widget.id)
3974 state&=(~InactiveWidgetState);
3979 if (event.xexpose.window != windows->widget.id)
3981 if (event.xexpose.count != 0)
3983 state|=RedrawWidgetState;
3989 command[MaxTextExtent];
3998 Respond to a user key press.
4000 if (event.xkey.window != windows->widget.id)
4002 length=XLookupString((XKeyEvent *) &event.xkey,command,
4003 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4004 *(command+length)='\0';
4005 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
4007 action_info.raised=MagickFalse;
4008 XDrawBeveledButton(display,&windows->widget,&action_info);
4012 if (key_symbol == XK_Control_L)
4014 state|=ControlState;
4017 if (state & ControlState)
4018 switch ((int) key_symbol)
4024 Erase the entire line of text.
4026 *reply_info.text='\0';
4027 reply_info.cursor=reply_info.text;
4028 reply_info.marker=reply_info.text;
4029 reply_info.highlight=MagickFalse;
4035 XEditText(display,&reply_info,key_symbol,command,state);
4036 XDrawMatteText(display,&windows->widget,&reply_info);
4042 command[MaxTextExtent];
4048 Respond to a user key release.
4050 if (event.xkey.window != windows->widget.id)
4052 (void) XLookupString((XKeyEvent *) &event.xkey,command,
4053 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4054 if (key_symbol == XK_Control_L)
4055 state&=(~ControlState);
4060 if (event.xcrossing.window != windows->widget.id)
4062 state|=InactiveWidgetState;
4068 Discard pending button motion events.
4070 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
4071 if (state & InactiveWidgetState)
4073 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
4076 Action button status changed.
4078 action_info.raised=action_info.raised == MagickFalse ?
4079 MagickTrue : MagickFalse;
4080 XDrawBeveledButton(display,&windows->widget,&action_info);
4083 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
4086 Cancel button status changed.
4088 cancel_info.raised=cancel_info.raised == MagickFalse ?
4089 MagickTrue : MagickFalse;
4090 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4095 case SelectionClear:
4097 reply_info.highlight=MagickFalse;
4098 XDrawMatteText(display,&windows->widget,&reply_info);
4101 case SelectionNotify:
4117 Obtain response from primary selection.
4119 if (event.xselection.property == (Atom) None)
4121 status=XGetWindowProperty(display,event.xselection.requestor,
4122 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
4123 &format,&length,&after,&data);
4124 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
4127 if ((Extent(reply_info.text)+length) >= MaxTextExtent)
4128 (void) XBell(display,0);
4132 Insert primary selection in reply text.
4134 *(data+length)='\0';
4135 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
4137 XDrawMatteText(display,&windows->widget,&reply_info);
4139 (void) XFree((void *) data);
4142 case SelectionRequest:
4147 XSelectionRequestEvent
4150 if (reply_info.highlight == MagickFalse)
4153 Set primary selection.
4155 request=(&(event.xselectionrequest));
4156 (void) XChangeProperty(request->display,request->requestor,
4157 request->property,request->target,8,PropModeReplace,
4158 (unsigned char *) primary_selection,Extent(primary_selection));
4159 notify.type=SelectionNotify;
4160 notify.display=request->display;
4161 notify.requestor=request->requestor;
4162 notify.selection=request->selection;
4163 notify.target=request->target;
4164 notify.time=request->time;
4165 if (request->property == None)
4166 notify.property=request->target;
4168 notify.property=request->property;
4169 (void) XSendEvent(request->display,request->requestor,False,0,
4170 (XEvent *) ¬ify);
4175 } while ((state & ExitState) == 0);
4176 XSetCursorState(display,windows,MagickFalse);
4177 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
4178 XCheckRefreshWindows(display,windows);
4180 if (special_info.raised)
4183 return(raised == MagickFalse);
4187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4191 % X F i l e B r o w s e r W i d g e t %
4195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4197 % XFileBrowserWidget() displays a File Browser widget with a file query to the
4198 % user. The user keys a reply and presses the Action or Cancel button to
4199 % exit. The typed text is returned as the reply function parameter.
4201 % The format of the XFileBrowserWidget method is:
4203 % void XFileBrowserWidget(Display *display,XWindows *windows,
4204 % const char *action,char *reply)
4206 % A description of each parameter follows:
4208 % o display: Specifies a connection to an X server; returned from
4211 % o window: Specifies a pointer to a XWindows structure.
4213 % o action: Specifies a pointer to the action of this widget.
4215 % o reply: the response from the user is returned in this parameter.
4218 MagickExport void XFileBrowserWidget(Display *display,XWindows *windows,
4219 const char *action,char *reply)
4221 #define CancelButtonText "Cancel"
4222 #define DirectoryText "Directory:"
4223 #define FilenameText "File name:"
4224 #define GrabButtonText "Grab"
4225 #define FormatButtonText "Format"
4226 #define HomeButtonText "Home"
4227 #define UpButtonText "Up"
4232 home_directory[MaxTextExtent],
4233 primary_selection[MaxTextExtent],
4234 text[MaxTextExtent],
4235 working_path[MaxTextExtent];
4245 glob_pattern[MaxTextExtent] = "*",
4246 format[MaxTextExtent] = "miff";
4248 static MagickStatusType
4249 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
4295 Read filelist from current directory.
4297 assert(display != (Display *) NULL);
4298 assert(windows != (XWindows *) NULL);
4299 assert(action != (char *) NULL);
4300 assert(reply != (char *) NULL);
4301 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
4302 XSetCursorState(display,windows,MagickTrue);
4303 XCheckRefreshWindows(display,windows);
4304 cwd=getcwd(home_directory,MaxTextExtent);
4305 (void) CopyMagickString(working_path,home_directory,MaxTextExtent);
4306 filelist=ListFiles(working_path,glob_pattern,&files);
4307 if (filelist == (char **) NULL)
4310 Directory read failed.
4312 XNoticeWidget(display,windows,"Unable to read directory:",working_path);
4313 (void) XDialogWidget(display,windows,action,"Enter filename:",reply);
4317 Determine File Browser widget attributes.
4319 font_info=windows->widget.font_info;
4321 for (i=0; i < (ssize_t) files; i++)
4322 if (WidgetTextWidth(font_info,filelist[i]) > text_width)
4323 text_width=WidgetTextWidth(font_info,filelist[i]);
4324 width=WidgetTextWidth(font_info,(char *) action);
4325 if (WidgetTextWidth(font_info,GrabButtonText) > width)
4326 width=WidgetTextWidth(font_info,GrabButtonText);
4327 if (WidgetTextWidth(font_info,FormatButtonText) > width)
4328 width=WidgetTextWidth(font_info,FormatButtonText);
4329 if (WidgetTextWidth(font_info,CancelButtonText) > width)
4330 width=WidgetTextWidth(font_info,CancelButtonText);
4331 if (WidgetTextWidth(font_info,HomeButtonText) > width)
4332 width=WidgetTextWidth(font_info,HomeButtonText);
4333 if (WidgetTextWidth(font_info,UpButtonText) > width)
4334 width=WidgetTextWidth(font_info,UpButtonText);
4335 width+=QuantumMargin;
4336 if (WidgetTextWidth(font_info,DirectoryText) > width)
4337 width=WidgetTextWidth(font_info,DirectoryText);
4338 if (WidgetTextWidth(font_info,FilenameText) > width)
4339 width=WidgetTextWidth(font_info,FilenameText);
4340 height=(unsigned int) (font_info->ascent+font_info->descent);
4342 Position File Browser widget.
4344 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
4346 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
4347 if (windows->widget.width < windows->widget.min_width)
4348 windows->widget.width=windows->widget.min_width;
4349 windows->widget.height=(unsigned int)
4350 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
4351 windows->widget.min_height=(unsigned int)
4352 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
4353 if (windows->widget.height < windows->widget.min_height)
4354 windows->widget.height=windows->widget.min_height;
4355 XConstrainWindowPosition(display,&windows->widget);
4357 Map File Browser widget.
4359 (void) CopyMagickString(windows->widget.name,"Browse and Select a File",
4361 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
4362 if (status != False)
4364 XSetWMName(display,windows->widget.id,&window_name);
4365 XSetWMIconName(display,windows->widget.id,&window_name);
4366 (void) XFree((void *) window_name.value);
4368 window_changes.width=(int) windows->widget.width;
4369 window_changes.height=(int) windows->widget.height;
4370 window_changes.x=windows->widget.x;
4371 window_changes.y=windows->widget.y;
4372 (void) XReconfigureWMWindow(display,windows->widget.id,
4373 windows->widget.screen,mask,&window_changes);
4374 (void) XMapRaised(display,windows->widget.id);
4375 windows->widget.mapped=MagickFalse;
4377 Respond to X events.
4379 XGetWidgetInfo((char *) NULL,&slider_info);
4380 XGetWidgetInfo((char *) NULL,&north_info);
4381 XGetWidgetInfo((char *) NULL,&south_info);
4382 XGetWidgetInfo((char *) NULL,&expose_info);
4384 anomaly=(LocaleCompare(action,"Composite") == 0) ||
4385 (LocaleCompare(action,"Open") == 0) || (LocaleCompare(action,"Map") == 0);
4387 delay=SuspendTime << 2;
4388 state=UpdateConfigurationState;
4391 if (state & UpdateConfigurationState)
4397 Initialize button information.
4399 XGetWidgetInfo(CancelButtonText,&cancel_info);
4400 cancel_info.width=width;
4401 cancel_info.height=(unsigned int) ((3*height) >> 1);
4403 (windows->widget.width-cancel_info.width-QuantumMargin-2);
4405 (windows->widget.height-cancel_info.height-QuantumMargin);
4406 XGetWidgetInfo(action,&action_info);
4407 action_info.width=width;
4408 action_info.height=(unsigned int) ((3*height) >> 1);
4409 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
4410 (action_info.bevel_width << 1));
4411 action_info.y=cancel_info.y;
4412 XGetWidgetInfo(GrabButtonText,&special_info);
4413 special_info.width=width;
4414 special_info.height=(unsigned int) ((3*height) >> 1);
4415 special_info.x=action_info.x-(action_info.width+(QuantumMargin >> 1)+
4416 (special_info.bevel_width << 1));
4417 special_info.y=action_info.y;
4418 if (anomaly == MagickFalse)
4423 special_info.text=(char *) FormatButtonText;
4424 p=reply+Extent(reply)-1;
4425 while ((p > (reply+1)) && (*(p-1) != '.'))
4427 if ((p > (reply+1)) && (*(p-1) == '.'))
4428 (void) CopyMagickString(format,p,MaxTextExtent);
4430 XGetWidgetInfo(UpButtonText,&up_info);
4431 up_info.width=width;
4432 up_info.height=(unsigned int) ((3*height) >> 1);
4433 up_info.x=QuantumMargin;
4434 up_info.y=((5*QuantumMargin) >> 1)+height;
4435 XGetWidgetInfo(HomeButtonText,&home_info);
4436 home_info.width=width;
4437 home_info.height=(unsigned int) ((3*height) >> 1);
4438 home_info.x=QuantumMargin;
4439 home_info.y=up_info.y+up_info.height+QuantumMargin;
4441 Initialize reply information.
4443 XGetWidgetInfo(reply,&reply_info);
4444 reply_info.raised=MagickFalse;
4445 reply_info.bevel_width--;
4446 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
4447 reply_info.height=height << 1;
4448 reply_info.x=(int) (width+(QuantumMargin << 1));
4449 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
4451 Initialize scroll information.
4453 XGetWidgetInfo((char *) NULL,&scroll_info);
4454 scroll_info.bevel_width--;
4455 scroll_info.width=height;
4456 scroll_info.height=(unsigned int)
4457 (reply_info.y-up_info.y-(QuantumMargin >> 1));
4458 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
4459 scroll_info.y=up_info.y-reply_info.bevel_width;
4460 scroll_info.raised=MagickFalse;
4461 scroll_info.trough=MagickTrue;
4462 north_info=scroll_info;
4463 north_info.raised=MagickTrue;
4464 north_info.width-=(north_info.bevel_width << 1);
4465 north_info.height=north_info.width-1;
4466 north_info.x+=north_info.bevel_width;
4467 north_info.y+=north_info.bevel_width;
4468 south_info=north_info;
4469 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
4472 slider_info=north_info;
4474 slider_info.width-=2;
4475 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
4476 slider_info.bevel_width+2;
4477 slider_info.height=scroll_info.height-((slider_info.min_y-
4478 scroll_info.y+1) << 1)+4;
4479 visible_files=scroll_info.height/(height+(height >> 3));
4480 if (files > visible_files)
4481 slider_info.height=(unsigned int)
4482 ((visible_files*slider_info.height)/files);
4483 slider_info.max_y=south_info.y-south_info.bevel_width-
4484 slider_info.bevel_width-2;
4485 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
4486 slider_info.y=slider_info.min_y;
4487 expose_info=scroll_info;
4488 expose_info.y=slider_info.y;
4490 Initialize list information.
4492 XGetWidgetInfo((char *) NULL,&list_info);
4493 list_info.raised=MagickFalse;
4494 list_info.bevel_width--;
4495 list_info.width=(unsigned int)
4496 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
4497 list_info.height=scroll_info.height;
4498 list_info.x=reply_info.x;
4499 list_info.y=scroll_info.y;
4500 if (windows->widget.mapped == MagickFalse)
4501 state|=JumpListState;
4503 Initialize text information.
4506 XGetWidgetInfo(text,&text_info);
4507 text_info.center=MagickFalse;
4508 text_info.width=reply_info.width;
4509 text_info.height=height;
4510 text_info.x=list_info.x-(QuantumMargin >> 1);
4511 text_info.y=QuantumMargin;
4513 Initialize selection information.
4515 XGetWidgetInfo((char *) NULL,&selection_info);
4516 selection_info.center=MagickFalse;
4517 selection_info.width=list_info.width;
4518 selection_info.height=(unsigned int) ((9*height) >> 3);
4519 selection_info.x=list_info.x;
4520 state&=(~UpdateConfigurationState);
4522 if (state & RedrawWidgetState)
4525 Redraw File Browser window.
4528 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
4529 (void) XDrawString(display,windows->widget.id,
4530 windows->widget.annotate_context,x,y,DirectoryText,
4531 Extent(DirectoryText));
4532 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4533 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4535 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4537 XDrawWidgetText(display,&windows->widget,&text_info);
4538 XDrawBeveledButton(display,&windows->widget,&up_info);
4539 XDrawBeveledButton(display,&windows->widget,&home_info);
4540 XDrawBeveledMatte(display,&windows->widget,&list_info);
4541 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4542 XDrawTriangleNorth(display,&windows->widget,&north_info);
4543 XDrawBeveledButton(display,&windows->widget,&slider_info);
4544 XDrawTriangleSouth(display,&windows->widget,&south_info);
4546 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
4547 (void) XDrawString(display,windows->widget.id,
4548 windows->widget.annotate_context,x,y,FilenameText,
4549 Extent(FilenameText));
4550 XDrawBeveledMatte(display,&windows->widget,&reply_info);
4551 XDrawMatteText(display,&windows->widget,&reply_info);
4552 XDrawBeveledButton(display,&windows->widget,&special_info);
4553 XDrawBeveledButton(display,&windows->widget,&action_info);
4554 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4555 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4556 selection_info.id=(~0);
4557 state|=RedrawListState;
4558 state&=(~RedrawWidgetState);
4560 if (state & UpdateListState)
4571 checklist=ListFiles(working_path,glob_pattern,&number_files);
4572 if (checklist == (char **) NULL)
4575 Reply is a filename, exit.
4577 action_info.raised=MagickFalse;
4578 XDrawBeveledButton(display,&windows->widget,&action_info);
4581 for (i=0; i < (ssize_t) files; i++)
4582 filelist[i]=DestroyString(filelist[i]);
4583 if (filelist != (char **) NULL)
4584 filelist=(char **) RelinquishMagickMemory(filelist);
4591 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
4592 if (files > visible_files)
4593 slider_info.height=(unsigned int)
4594 ((visible_files*slider_info.height)/files);
4595 slider_info.max_y=south_info.y-south_info.bevel_width-
4596 slider_info.bevel_width-2;
4598 slider_info.y=slider_info.min_y;
4599 expose_info.y=slider_info.y;
4600 selection_info.id=(~0);
4602 state|=RedrawListState;
4604 Redraw directory name & reply.
4606 if (IsGlob(reply_info.text) == MagickFalse)
4608 *reply_info.text='\0';
4609 reply_info.cursor=reply_info.text;
4611 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4612 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4614 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4616 XDrawWidgetText(display,&windows->widget,&text_info);
4617 XDrawMatteText(display,&windows->widget,&reply_info);
4618 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4619 XDrawTriangleNorth(display,&windows->widget,&north_info);
4620 XDrawBeveledButton(display,&windows->widget,&slider_info);
4621 XDrawTriangleSouth(display,&windows->widget,&south_info);
4622 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4623 state&=(~UpdateListState);
4625 if (state & JumpListState)
4628 Jump scroll to match user filename.
4631 for (i=0; i < (ssize_t) files; i++)
4632 if (LocaleCompare(filelist[i],reply) >= 0)
4635 (LocaleCompare(filelist[i],reply) == 0 ? i : ~0);
4638 if ((i < (ssize_t) slider_info.id) ||
4639 (i >= (ssize_t) (slider_info.id+visible_files)))
4640 slider_info.id=(int) i-(visible_files >> 1);
4641 selection_info.id=(~0);
4642 state|=RedrawListState;
4643 state&=(~JumpListState);
4645 if (state & RedrawListState)
4648 Determine slider id and position.
4650 if (slider_info.id >= (int) (files-visible_files))
4651 slider_info.id=(int) (files-visible_files);
4652 if ((slider_info.id < 0) || (files <= visible_files))
4654 slider_info.y=slider_info.min_y;
4656 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
4657 slider_info.min_y+1)/files);
4658 if (slider_info.id != selection_info.id)
4661 Redraw scroll bar and file names.
4663 selection_info.id=slider_info.id;
4664 selection_info.y=list_info.y+(height >> 3)+2;
4665 for (i=0; i < (ssize_t) visible_files; i++)
4667 selection_info.raised=(int) (slider_info.id+i) != list_info.id ?
4668 MagickTrue : MagickFalse;
4669 selection_info.text=(char *) NULL;
4670 if ((slider_info.id+i) < (ssize_t) files)
4671 selection_info.text=filelist[slider_info.id+i];
4672 XDrawWidgetText(display,&windows->widget,&selection_info);
4673 selection_info.y+=(int) selection_info.height;
4678 if (slider_info.y > expose_info.y)
4680 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
4681 expose_info.y=slider_info.y-expose_info.height-
4682 slider_info.bevel_width-1;
4686 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
4687 expose_info.y=slider_info.y+slider_info.height+
4688 slider_info.bevel_width+1;
4690 XDrawTriangleNorth(display,&windows->widget,&north_info);
4691 XDrawMatte(display,&windows->widget,&expose_info);
4692 XDrawBeveledButton(display,&windows->widget,&slider_info);
4693 XDrawTriangleSouth(display,&windows->widget,&south_info);
4694 expose_info.y=slider_info.y;
4696 state&=(~RedrawListState);
4699 Wait for next event.
4701 if (north_info.raised && south_info.raised)
4702 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
4706 Brief delay before advancing scroll bar.
4708 XDelay(display,delay);
4710 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
4711 if (north_info.raised == MagickFalse)
4712 if (slider_info.id > 0)
4718 state|=RedrawListState;
4720 if (south_info.raised == MagickFalse)
4721 if (slider_info.id < (int) files)
4727 state|=RedrawListState;
4729 if (event.type != ButtonRelease)
4736 if (MatteIsActive(slider_info,event.xbutton))
4741 slider_info.active=MagickTrue;
4744 if (MatteIsActive(north_info,event.xbutton))
4745 if (slider_info.id > 0)
4750 north_info.raised=MagickFalse;
4752 state|=RedrawListState;
4755 if (MatteIsActive(south_info,event.xbutton))
4756 if (slider_info.id < (int) files)
4761 south_info.raised=MagickFalse;
4763 state|=RedrawListState;
4766 if (MatteIsActive(scroll_info,event.xbutton))
4771 if (event.xbutton.y < slider_info.y)
4772 slider_info.id-=(visible_files-1);
4774 slider_info.id+=(visible_files-1);
4775 state|=RedrawListState;
4778 if (MatteIsActive(list_info,event.xbutton))
4784 User pressed file matte.
4786 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
4787 selection_info.height;
4788 if (id >= (int) files)
4790 (void) CopyMagickString(reply_info.text,filelist[id],MaxTextExtent);
4791 reply_info.highlight=MagickFalse;
4792 reply_info.marker=reply_info.text;
4793 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4794 XDrawMatteText(display,&windows->widget,&reply_info);
4795 if (id == list_info.id)
4800 p=reply_info.text+strlen(reply_info.text)-1;
4801 if (*p == *DirectorySeparator)
4802 ChopPathComponents(reply_info.text,1);
4803 (void) ConcatenateMagickString(working_path,DirectorySeparator,
4805 (void) ConcatenateMagickString(working_path,reply_info.text,
4808 state|=UpdateListState;
4810 selection_info.id=(~0);
4812 state|=RedrawListState;
4815 if (MatteIsActive(up_info,event.xbutton))
4818 User pressed Up button.
4820 up_info.raised=MagickFalse;
4821 XDrawBeveledButton(display,&windows->widget,&up_info);
4824 if (MatteIsActive(home_info,event.xbutton))
4827 User pressed Home button.
4829 home_info.raised=MagickFalse;
4830 XDrawBeveledButton(display,&windows->widget,&home_info);
4833 if (MatteIsActive(special_info,event.xbutton))
4836 User pressed Special button.
4838 special_info.raised=MagickFalse;
4839 XDrawBeveledButton(display,&windows->widget,&special_info);
4842 if (MatteIsActive(action_info,event.xbutton))
4845 User pressed action button.
4847 action_info.raised=MagickFalse;
4848 XDrawBeveledButton(display,&windows->widget,&action_info);
4851 if (MatteIsActive(cancel_info,event.xbutton))
4854 User pressed Cancel button.
4856 cancel_info.raised=MagickFalse;
4857 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4860 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
4862 if (event.xbutton.button != Button2)
4868 Move text cursor to position of button press.
4870 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
4871 for (i=1; i <= (ssize_t) Extent(reply_info.marker); i++)
4872 if (XTextWidth(font_info,reply_info.marker,(int) i) > x)
4874 reply_info.cursor=reply_info.marker+i-1;
4875 if (event.xbutton.time > (click_time+DoubleClick))
4876 reply_info.highlight=MagickFalse;
4880 Become the XA_PRIMARY selection owner.
4882 (void) CopyMagickString(primary_selection,reply_info.text,
4884 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
4885 event.xbutton.time);
4886 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
4887 windows->widget.id ? MagickTrue : MagickFalse;
4889 XDrawMatteText(display,&windows->widget,&reply_info);
4890 click_time=event.xbutton.time;
4894 Request primary selection.
4896 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
4897 windows->widget.id,event.xbutton.time);
4902 if (windows->widget.mapped == MagickFalse)
4904 if (north_info.raised == MagickFalse)
4907 User released up button.
4909 delay=SuspendTime << 2;
4910 north_info.raised=MagickTrue;
4911 XDrawTriangleNorth(display,&windows->widget,&north_info);
4913 if (south_info.raised == MagickFalse)
4916 User released down button.
4918 delay=SuspendTime << 2;
4919 south_info.raised=MagickTrue;
4920 XDrawTriangleSouth(display,&windows->widget,&south_info);
4922 if (slider_info.active)
4925 Stop tracking slider.
4927 slider_info.active=MagickFalse;
4930 if (up_info.raised == MagickFalse)
4932 if (event.xbutton.window == windows->widget.id)
4933 if (MatteIsActive(up_info,event.xbutton))
4935 ChopPathComponents(working_path,1);
4936 if (*working_path == '\0')
4937 (void) CopyMagickString(working_path,DirectorySeparator,
4939 state|=UpdateListState;
4941 up_info.raised=MagickTrue;
4942 XDrawBeveledButton(display,&windows->widget,&up_info);
4944 if (home_info.raised == MagickFalse)
4946 if (event.xbutton.window == windows->widget.id)
4947 if (MatteIsActive(home_info,event.xbutton))
4949 (void) CopyMagickString(working_path,home_directory,
4951 state|=UpdateListState;
4953 home_info.raised=MagickTrue;
4954 XDrawBeveledButton(display,&windows->widget,&home_info);
4956 if (special_info.raised == MagickFalse)
4958 if (anomaly == MagickFalse)
4970 Let user select image format.
4972 exception=AcquireExceptionInfo();
4973 formats=GetMagickList("*",&number_formats,exception);
4974 exception=DestroyExceptionInfo(exception);
4975 (void) XCheckDefineCursor(display,windows->widget.id,
4976 windows->widget.busy_cursor);
4977 windows->popup.x=windows->widget.x+60;
4978 windows->popup.y=windows->widget.y+60;
4979 XListBrowserWidget(display,windows,&windows->popup,
4980 (const char **) formats,"Select","Select image format type:",
4982 XSetCursorState(display,windows,MagickTrue);
4983 (void) XCheckDefineCursor(display,windows->widget.id,
4984 windows->widget.cursor);
4985 LocaleLower(format);
4986 AppendImageFormat(format,reply_info.text);
4987 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4988 XDrawMatteText(display,&windows->widget,&reply_info);
4989 special_info.raised=MagickTrue;
4990 XDrawBeveledButton(display,&windows->widget,&special_info);
4991 for (i=0; i < (ssize_t) number_formats; i++)
4992 formats[i]=DestroyString(formats[i]);
4993 formats=(char **) RelinquishMagickMemory(formats);
4996 if (event.xbutton.window == windows->widget.id)
4997 if (MatteIsActive(special_info,event.xbutton))
4999 (void) CopyMagickString(working_path,"x:",MaxTextExtent);
5002 special_info.raised=MagickTrue;
5003 XDrawBeveledButton(display,&windows->widget,&special_info);
5005 if (action_info.raised == MagickFalse)
5007 if (event.xbutton.window == windows->widget.id)
5009 if (MatteIsActive(action_info,event.xbutton))
5011 if (*reply_info.text == '\0')
5012 (void) XBell(display,0);
5017 action_info.raised=MagickTrue;
5018 XDrawBeveledButton(display,&windows->widget,&action_info);
5020 if (cancel_info.raised == MagickFalse)
5022 if (event.xbutton.window == windows->widget.id)
5023 if (MatteIsActive(cancel_info,event.xbutton))
5025 *reply_info.text='\0';
5029 cancel_info.raised=MagickTrue;
5030 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5037 If client window delete message, exit.
5039 if (event.xclient.message_type != windows->wm_protocols)
5041 if (*event.xclient.data.l == (int) windows->wm_take_focus)
5043 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
5044 (Time) event.xclient.data.l[1]);
5047 if (*event.xclient.data.l != (int) windows->wm_delete_window)
5049 if (event.xclient.window == windows->widget.id)
5051 *reply_info.text='\0';
5057 case ConfigureNotify:
5060 Update widget configuration.
5062 if (event.xconfigure.window != windows->widget.id)
5064 if ((event.xconfigure.width == (int) windows->widget.width) &&
5065 (event.xconfigure.height == (int) windows->widget.height))
5067 windows->widget.width=(unsigned int)
5068 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
5069 windows->widget.height=(unsigned int)
5070 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
5071 state|=UpdateConfigurationState;
5076 if (event.xcrossing.window != windows->widget.id)
5078 state&=(~InactiveWidgetState);
5083 if (event.xexpose.window != windows->widget.id)
5085 if (event.xexpose.count != 0)
5087 state|=RedrawWidgetState;
5093 command[MaxTextExtent];
5102 Respond to a user key press.
5104 if (event.xkey.window != windows->widget.id)
5106 length=XLookupString((XKeyEvent *) &event.xkey,command,
5107 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5108 *(command+length)='\0';
5109 if (AreaIsActive(scroll_info,event.xkey))
5114 switch ((int) key_symbol)
5137 slider_info.id-=visible_files;
5143 slider_info.id+=visible_files;
5149 slider_info.id=(int) files;
5153 state|=RedrawListState;
5156 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
5159 Read new directory or glob patterm.
5161 if (*reply_info.text == '\0')
5163 if (IsGlob(reply_info.text))
5164 (void) CopyMagickString(glob_pattern,reply_info.text,
5168 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5170 (void) ConcatenateMagickString(working_path,reply_info.text,
5172 if (*working_path == '~')
5173 ExpandFilename(working_path);
5176 state|=UpdateListState;
5179 if (key_symbol == XK_Control_L)
5181 state|=ControlState;
5184 if (state & ControlState)
5185 switch ((int) key_symbol)
5191 Erase the entire line of text.
5193 *reply_info.text='\0';
5194 reply_info.cursor=reply_info.text;
5195 reply_info.marker=reply_info.text;
5196 reply_info.highlight=MagickFalse;
5202 XEditText(display,&reply_info,key_symbol,command,state);
5203 XDrawMatteText(display,&windows->widget,&reply_info);
5204 state|=JumpListState;
5210 command[MaxTextExtent];
5216 Respond to a user key release.
5218 if (event.xkey.window != windows->widget.id)
5220 (void) XLookupString((XKeyEvent *) &event.xkey,command,
5221 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5222 if (key_symbol == XK_Control_L)
5223 state&=(~ControlState);
5228 if (event.xcrossing.window != windows->widget.id)
5230 state|=InactiveWidgetState;
5242 Discard pending button motion events.
5244 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
5245 if (slider_info.active)
5250 slider_info.y=event.xmotion.y-
5251 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
5252 if (slider_info.y < slider_info.min_y)
5253 slider_info.y=slider_info.min_y;
5254 if (slider_info.y > slider_info.max_y)
5255 slider_info.y=slider_info.max_y;
5257 if (slider_info.y != slider_info.min_y)
5258 slider_info.id=(int) ((files*(slider_info.y-slider_info.min_y+1))/
5259 (slider_info.max_y-slider_info.min_y+1));
5260 state|=RedrawListState;
5263 if (state & InactiveWidgetState)
5265 if (up_info.raised == MatteIsActive(up_info,event.xmotion))
5268 Up button status changed.
5270 up_info.raised=!up_info.raised;
5271 XDrawBeveledButton(display,&windows->widget,&up_info);
5274 if (home_info.raised == MatteIsActive(home_info,event.xmotion))
5277 Home button status changed.
5279 home_info.raised=!home_info.raised;
5280 XDrawBeveledButton(display,&windows->widget,&home_info);
5283 if (special_info.raised == MatteIsActive(special_info,event.xmotion))
5286 Grab button status changed.
5288 special_info.raised=!special_info.raised;
5289 XDrawBeveledButton(display,&windows->widget,&special_info);
5292 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
5295 Action button status changed.
5297 action_info.raised=action_info.raised == MagickFalse ?
5298 MagickTrue : MagickFalse;
5299 XDrawBeveledButton(display,&windows->widget,&action_info);
5302 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
5305 Cancel button status changed.
5307 cancel_info.raised=cancel_info.raised == MagickFalse ?
5308 MagickTrue : MagickFalse;
5309 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5314 case SelectionClear:
5316 reply_info.highlight=MagickFalse;
5317 XDrawMatteText(display,&windows->widget,&reply_info);
5320 case SelectionNotify:
5336 Obtain response from primary selection.
5338 if (event.xselection.property == (Atom) None)
5340 status=XGetWindowProperty(display,event.xselection.requestor,
5341 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
5342 &format,&length,&after,&data);
5343 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
5346 if ((Extent(reply_info.text)+length) >= MaxTextExtent)
5347 (void) XBell(display,0);
5351 Insert primary selection in reply text.
5353 *(data+length)='\0';
5354 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
5356 XDrawMatteText(display,&windows->widget,&reply_info);
5357 state|=JumpListState;
5358 state|=RedrawActionState;
5360 (void) XFree((void *) data);
5363 case SelectionRequest:
5368 XSelectionRequestEvent
5371 if (reply_info.highlight == MagickFalse)
5374 Set primary selection.
5376 request=(&(event.xselectionrequest));
5377 (void) XChangeProperty(request->display,request->requestor,
5378 request->property,request->target,8,PropModeReplace,
5379 (unsigned char *) primary_selection,Extent(primary_selection));
5380 notify.type=SelectionNotify;
5381 notify.display=request->display;
5382 notify.requestor=request->requestor;
5383 notify.selection=request->selection;
5384 notify.target=request->target;
5385 notify.time=request->time;
5386 if (request->property == None)
5387 notify.property=request->target;
5389 notify.property=request->property;
5390 (void) XSendEvent(request->display,request->requestor,False,0,
5391 (XEvent *) ¬ify);
5396 } while ((state & ExitState) == 0);
5397 XSetCursorState(display,windows,MagickFalse);
5398 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
5399 XCheckRefreshWindows(display,windows);
5403 for (i=0; i < (ssize_t) files; i++)
5404 filelist[i]=DestroyString(filelist[i]);
5405 if (filelist != (char **) NULL)
5406 filelist=(char **) RelinquishMagickMemory(filelist);
5409 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5411 (void) ConcatenateMagickString(working_path,reply,MaxTextExtent);
5413 (void) CopyMagickString(reply,working_path,MaxTextExtent);
5415 ExpandFilename(reply);
5419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5423 % X F o n t B r o w s e r W i d g e t %
5427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5429 % XFontBrowserWidget() displays a Font Browser widget with a font query to the
5430 % user. The user keys a reply and presses the Action or Cancel button to
5431 % exit. The typed text is returned as the reply function parameter.
5433 % The format of the XFontBrowserWidget method is:
5435 % void XFontBrowserWidget(Display *display,XWindows *windows,
5436 % const char *action,char *reply)
5438 % A description of each parameter follows:
5440 % o display: Specifies a connection to an X server; returned from
5443 % o window: Specifies a pointer to a XWindows structure.
5445 % o action: Specifies a pointer to the action of this widget.
5447 % o reply: the response from the user is returned in this parameter.
5452 #if defined(__cplusplus) || defined(c_plusplus)
5456 static int FontCompare(const void *x,const void *y)
5462 p=(char *) *((char **) x);
5463 q=(char *) *((char **) y);
5464 while ((*p != '\0') && (*q != '\0') && (*p == *q))
5472 #if defined(__cplusplus) || defined(c_plusplus)
5476 MagickExport void XFontBrowserWidget(Display *display,XWindows *windows,
5477 const char *action,char *reply)
5479 #define BackButtonText "Back"
5480 #define CancelButtonText "Cancel"
5481 #define FontnameText "Name:"
5482 #define FontPatternText "Pattern:"
5483 #define ResetButtonText "Reset"
5486 back_pattern[MaxTextExtent],
5489 primary_selection[MaxTextExtent],
5490 reset_pattern[MaxTextExtent],
5491 text[MaxTextExtent];
5502 glob_pattern[MaxTextExtent] = "*";
5504 static MagickStatusType
5505 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
5549 Get font list and sort in ascending order.
5551 assert(display != (Display *) NULL);
5552 assert(windows != (XWindows *) NULL);
5553 assert(action != (char *) NULL);
5554 assert(reply != (char *) NULL);
5555 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
5556 XSetCursorState(display,windows,MagickTrue);
5557 XCheckRefreshWindows(display,windows);
5558 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
5559 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
5560 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5564 Pattern failed, obtain all the fonts.
5566 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5568 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
5569 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5570 if (fontlist == (char **) NULL)
5572 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5578 Sort font list in ascending order.
5581 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,sizeof(*fontlist));
5582 if (fontlist == (char **) NULL)
5584 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5585 "UnableToViewFonts");
5588 for (i=0; i < fonts; i++)
5589 fontlist[i]=listhead[i];
5590 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5592 Determine Font Browser widget attributes.
5594 font_info=windows->widget.font_info;
5596 for (i=0; i < fonts; i++)
5597 if (WidgetTextWidth(font_info,fontlist[i]) > text_width)
5598 text_width=WidgetTextWidth(font_info,fontlist[i]);
5599 width=WidgetTextWidth(font_info,(char *) action);
5600 if (WidgetTextWidth(font_info,CancelButtonText) > width)
5601 width=WidgetTextWidth(font_info,CancelButtonText);
5602 if (WidgetTextWidth(font_info,ResetButtonText) > width)
5603 width=WidgetTextWidth(font_info,ResetButtonText);
5604 if (WidgetTextWidth(font_info,BackButtonText) > width)
5605 width=WidgetTextWidth(font_info,BackButtonText);
5606 width+=QuantumMargin;
5607 if (WidgetTextWidth(font_info,FontPatternText) > width)
5608 width=WidgetTextWidth(font_info,FontPatternText);
5609 if (WidgetTextWidth(font_info,FontnameText) > width)
5610 width=WidgetTextWidth(font_info,FontnameText);
5611 height=(unsigned int) (font_info->ascent+font_info->descent);
5613 Position Font Browser widget.
5615 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
5617 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
5618 if (windows->widget.width < windows->widget.min_width)
5619 windows->widget.width=windows->widget.min_width;
5620 windows->widget.height=(unsigned int)
5621 (((85*height) >> 2)+((13*QuantumMargin) >> 1)+4);
5622 windows->widget.min_height=(unsigned int)
5623 (((27*height) >> 1)+((13*QuantumMargin) >> 1)+4);
5624 if (windows->widget.height < windows->widget.min_height)
5625 windows->widget.height=windows->widget.min_height;
5626 XConstrainWindowPosition(display,&windows->widget);
5628 Map Font Browser widget.
5630 (void) CopyMagickString(windows->widget.name,"Browse and Select a Font",
5632 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
5633 if (status != False)
5635 XSetWMName(display,windows->widget.id,&window_name);
5636 XSetWMIconName(display,windows->widget.id,&window_name);
5637 (void) XFree((void *) window_name.value);
5639 window_changes.width=(int) windows->widget.width;
5640 window_changes.height=(int) windows->widget.height;
5641 window_changes.x=windows->widget.x;
5642 window_changes.y=windows->widget.y;
5643 (void) XReconfigureWMWindow(display,windows->widget.id,
5644 windows->widget.screen,mask,&window_changes);
5645 (void) XMapRaised(display,windows->widget.id);
5646 windows->widget.mapped=MagickFalse;
5648 Respond to X events.
5650 XGetWidgetInfo((char *) NULL,&slider_info);
5651 XGetWidgetInfo((char *) NULL,&north_info);
5652 XGetWidgetInfo((char *) NULL,&south_info);
5653 XGetWidgetInfo((char *) NULL,&expose_info);
5655 delay=SuspendTime << 2;
5656 state=UpdateConfigurationState;
5659 if (state & UpdateConfigurationState)
5665 Initialize button information.
5667 XGetWidgetInfo(CancelButtonText,&cancel_info);
5668 cancel_info.width=width;
5669 cancel_info.height=(unsigned int) ((3*height) >> 1);
5671 (windows->widget.width-cancel_info.width-QuantumMargin-2);
5673 (windows->widget.height-cancel_info.height-QuantumMargin);
5674 XGetWidgetInfo(action,&action_info);
5675 action_info.width=width;
5676 action_info.height=(unsigned int) ((3*height) >> 1);
5677 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
5678 (action_info.bevel_width << 1));
5679 action_info.y=cancel_info.y;
5680 XGetWidgetInfo(BackButtonText,&back_info);
5681 back_info.width=width;
5682 back_info.height=(unsigned int) ((3*height) >> 1);
5683 back_info.x=QuantumMargin;
5684 back_info.y=((5*QuantumMargin) >> 1)+height;
5685 XGetWidgetInfo(ResetButtonText,&reset_info);
5686 reset_info.width=width;
5687 reset_info.height=(unsigned int) ((3*height) >> 1);
5688 reset_info.x=QuantumMargin;
5689 reset_info.y=back_info.y+back_info.height+QuantumMargin;
5691 Initialize reply information.
5693 XGetWidgetInfo(reply,&reply_info);
5694 reply_info.raised=MagickFalse;
5695 reply_info.bevel_width--;
5696 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
5697 reply_info.height=height << 1;
5698 reply_info.x=(int) (width+(QuantumMargin << 1));
5699 reply_info.y=action_info.y-(action_info.height << 1)-QuantumMargin;
5701 Initialize mode information.
5703 XGetWidgetInfo(reply,&mode_info);
5704 mode_info.bevel_width=0;
5705 mode_info.width=(unsigned int)
5706 (action_info.x-reply_info.x-QuantumMargin);
5707 mode_info.height=action_info.height << 1;
5708 mode_info.x=reply_info.x;
5709 mode_info.y=action_info.y-action_info.height+action_info.bevel_width;
5711 Initialize scroll information.
5713 XGetWidgetInfo((char *) NULL,&scroll_info);
5714 scroll_info.bevel_width--;
5715 scroll_info.width=height;
5716 scroll_info.height=(unsigned int)
5717 (reply_info.y-back_info.y-(QuantumMargin >> 1));
5718 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
5719 scroll_info.y=back_info.y-reply_info.bevel_width;
5720 scroll_info.raised=MagickFalse;
5721 scroll_info.trough=MagickTrue;
5722 north_info=scroll_info;
5723 north_info.raised=MagickTrue;
5724 north_info.width-=(north_info.bevel_width << 1);
5725 north_info.height=north_info.width-1;
5726 north_info.x+=north_info.bevel_width;
5727 north_info.y+=north_info.bevel_width;
5728 south_info=north_info;
5729 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
5732 slider_info=north_info;
5734 slider_info.width-=2;
5735 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
5736 slider_info.bevel_width+2;
5737 slider_info.height=scroll_info.height-((slider_info.min_y-
5738 scroll_info.y+1) << 1)+4;
5739 visible_fonts=scroll_info.height/(height+(height >> 3));
5740 if (fonts > (int) visible_fonts)
5741 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5742 slider_info.max_y=south_info.y-south_info.bevel_width-
5743 slider_info.bevel_width-2;
5744 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
5745 slider_info.y=slider_info.min_y;
5746 expose_info=scroll_info;
5747 expose_info.y=slider_info.y;
5749 Initialize list information.
5751 XGetWidgetInfo((char *) NULL,&list_info);
5752 list_info.raised=MagickFalse;
5753 list_info.bevel_width--;
5754 list_info.width=(unsigned int)
5755 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
5756 list_info.height=scroll_info.height;
5757 list_info.x=reply_info.x;
5758 list_info.y=scroll_info.y;
5759 if (windows->widget.mapped == MagickFalse)
5760 state|=JumpListState;
5762 Initialize text information.
5765 XGetWidgetInfo(text,&text_info);
5766 text_info.center=MagickFalse;
5767 text_info.width=reply_info.width;
5768 text_info.height=height;
5769 text_info.x=list_info.x-(QuantumMargin >> 1);
5770 text_info.y=QuantumMargin;
5772 Initialize selection information.
5774 XGetWidgetInfo((char *) NULL,&selection_info);
5775 selection_info.center=MagickFalse;
5776 selection_info.width=list_info.width;
5777 selection_info.height=(unsigned int) ((9*height) >> 3);
5778 selection_info.x=list_info.x;
5779 state&=(~UpdateConfigurationState);
5781 if (state & RedrawWidgetState)
5784 Redraw Font Browser window.
5787 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
5788 (void) XDrawString(display,windows->widget.id,
5789 windows->widget.annotate_context,x,y,FontPatternText,
5790 Extent(FontPatternText));
5791 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5792 XDrawWidgetText(display,&windows->widget,&text_info);
5793 XDrawBeveledButton(display,&windows->widget,&back_info);
5794 XDrawBeveledButton(display,&windows->widget,&reset_info);
5795 XDrawBeveledMatte(display,&windows->widget,&list_info);
5796 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5797 XDrawTriangleNorth(display,&windows->widget,&north_info);
5798 XDrawBeveledButton(display,&windows->widget,&slider_info);
5799 XDrawTriangleSouth(display,&windows->widget,&south_info);
5801 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
5802 (void) XDrawString(display,windows->widget.id,
5803 windows->widget.annotate_context,x,y,FontnameText,
5804 Extent(FontnameText));
5805 XDrawBeveledMatte(display,&windows->widget,&reply_info);
5806 XDrawMatteText(display,&windows->widget,&reply_info);
5807 XDrawBeveledButton(display,&windows->widget,&action_info);
5808 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5809 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5810 selection_info.id=(~0);
5811 state|=RedrawActionState;
5812 state|=RedrawListState;
5813 state&=(~RedrawWidgetState);
5815 if (state & UpdateListState)
5826 checklist=XListFonts(display,glob_pattern,32767,&number_fonts);
5827 if (checklist == (char **) NULL)
5829 if ((strchr(glob_pattern,'*') == (char *) NULL) &&
5830 (strchr(glob_pattern,'?') == (char *) NULL))
5833 Might be a scaleable font-- exit.
5835 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
5836 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5837 action_info.raised=MagickFalse;
5838 XDrawBeveledButton(display,&windows->widget,&action_info);
5841 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5842 (void) XBell(display,0);
5845 if (number_fonts == 1)
5848 Reply is a single font name-- exit.
5850 (void) CopyMagickString(reply,checklist[0],MaxTextExtent);
5851 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5852 (void) XFreeFontNames(checklist);
5853 action_info.raised=MagickFalse;
5854 XDrawBeveledButton(display,&windows->widget,&action_info);
5859 (void) XFreeFontNames(listhead);
5860 fontlist=(char **) RelinquishMagickMemory(fontlist);
5865 Sort font list in ascending order.
5868 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,
5870 if (fontlist == (char **) NULL)
5872 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5873 "UnableToViewFonts");
5876 for (i=0; i < fonts; i++)
5877 fontlist[i]=listhead[i];
5878 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5880 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
5881 if (fonts > (int) visible_fonts)
5882 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5883 slider_info.max_y=south_info.y-south_info.bevel_width-
5884 slider_info.bevel_width-2;
5886 slider_info.y=slider_info.min_y;
5887 expose_info.y=slider_info.y;
5888 selection_info.id=(~0);
5890 state|=RedrawListState;
5892 Redraw font name & reply.
5894 *reply_info.text='\0';
5895 reply_info.cursor=reply_info.text;
5896 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5897 XDrawWidgetText(display,&windows->widget,&text_info);
5898 XDrawMatteText(display,&windows->widget,&reply_info);
5899 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5900 XDrawTriangleNorth(display,&windows->widget,&north_info);
5901 XDrawBeveledButton(display,&windows->widget,&slider_info);
5902 XDrawTriangleSouth(display,&windows->widget,&south_info);
5903 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5904 state&=(~UpdateListState);
5906 if (state & JumpListState)
5909 Jump scroll to match user font.
5912 for (i=0; i < fonts; i++)
5913 if (LocaleCompare(fontlist[i],reply) >= 0)
5915 list_info.id=LocaleCompare(fontlist[i],reply) == 0 ? i : ~0;
5918 if ((i < slider_info.id) || (i >= (int) (slider_info.id+visible_fonts)))
5919 slider_info.id=i-(visible_fonts >> 1);
5920 selection_info.id=(~0);
5921 state|=RedrawListState;
5922 state&=(~JumpListState);
5924 if (state & RedrawListState)
5927 Determine slider id and position.
5929 if (slider_info.id >= (int) (fonts-visible_fonts))
5930 slider_info.id=fonts-visible_fonts;
5931 if ((slider_info.id < 0) || (fonts <= (int) visible_fonts))
5933 slider_info.y=slider_info.min_y;
5936 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/fonts;
5937 if (slider_info.id != selection_info.id)
5940 Redraw scroll bar and file names.
5942 selection_info.id=slider_info.id;
5943 selection_info.y=list_info.y+(height >> 3)+2;
5944 for (i=0; i < (int) visible_fonts; i++)
5946 selection_info.raised=(slider_info.id+i) != list_info.id ?
5947 MagickTrue : MagickFalse;
5948 selection_info.text=(char *) NULL;
5949 if ((slider_info.id+i) < fonts)
5950 selection_info.text=fontlist[slider_info.id+i];
5951 XDrawWidgetText(display,&windows->widget,&selection_info);
5952 selection_info.y+=(int) selection_info.height;
5957 if (slider_info.y > expose_info.y)
5959 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
5960 expose_info.y=slider_info.y-expose_info.height-
5961 slider_info.bevel_width-1;
5965 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
5966 expose_info.y=slider_info.y+slider_info.height+
5967 slider_info.bevel_width+1;
5969 XDrawTriangleNorth(display,&windows->widget,&north_info);
5970 XDrawMatte(display,&windows->widget,&expose_info);
5971 XDrawBeveledButton(display,&windows->widget,&slider_info);
5972 XDrawTriangleSouth(display,&windows->widget,&south_info);
5973 expose_info.y=slider_info.y;
5975 state&=(~RedrawListState);
5977 if (state & RedrawActionState)
5983 Display the selected font in a drawing area.
5985 save_info=windows->widget.font_info;
5986 font_info=XLoadQueryFont(display,reply_info.text);
5987 if (font_info != (XFontStruct *) NULL)
5989 windows->widget.font_info=font_info;
5990 (void) XSetFont(display,windows->widget.widget_context,
5993 XDrawBeveledButton(display,&windows->widget,&mode_info);
5994 windows->widget.font_info=save_info;
5995 if (font_info != (XFontStruct *) NULL)
5997 (void) XSetFont(display,windows->widget.widget_context,
5998 windows->widget.font_info->fid);
5999 (void) XFreeFont(display,font_info);
6001 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
6002 XDrawMatteText(display,&windows->widget,&reply_info);
6003 state&=(~RedrawActionState);
6006 Wait for next event.
6008 if (north_info.raised && south_info.raised)
6009 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
6013 Brief delay before advancing scroll bar.
6015 XDelay(display,delay);
6017 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
6018 if (north_info.raised == MagickFalse)
6019 if (slider_info.id > 0)
6025 state|=RedrawListState;
6027 if (south_info.raised == MagickFalse)
6028 if (slider_info.id < fonts)
6034 state|=RedrawListState;
6036 if (event.type != ButtonRelease)
6043 if (MatteIsActive(slider_info,event.xbutton))
6048 slider_info.active=MagickTrue;
6051 if (MatteIsActive(north_info,event.xbutton))
6052 if (slider_info.id > 0)
6057 north_info.raised=MagickFalse;
6059 state|=RedrawListState;
6062 if (MatteIsActive(south_info,event.xbutton))
6063 if (slider_info.id < fonts)
6068 south_info.raised=MagickFalse;
6070 state|=RedrawListState;
6073 if (MatteIsActive(scroll_info,event.xbutton))
6078 if (event.xbutton.y < slider_info.y)
6079 slider_info.id-=(visible_fonts-1);
6081 slider_info.id+=(visible_fonts-1);
6082 state|=RedrawListState;
6085 if (MatteIsActive(list_info,event.xbutton))
6091 User pressed list matte.
6093 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
6094 selection_info.height;
6095 if (id >= (int) fonts)
6097 (void) CopyMagickString(reply_info.text,fontlist[id],MaxTextExtent);
6098 reply_info.highlight=MagickFalse;
6099 reply_info.marker=reply_info.text;
6100 reply_info.cursor=reply_info.text+Extent(reply_info.text);
6101 XDrawMatteText(display,&windows->widget,&reply_info);
6102 state|=RedrawActionState;
6103 if (id == list_info.id)
6105 (void) CopyMagickString(glob_pattern,reply_info.text,
6107 state|=UpdateListState;
6109 selection_info.id=(~0);
6111 state|=RedrawListState;
6114 if (MatteIsActive(back_info,event.xbutton))
6117 User pressed Back button.
6119 back_info.raised=MagickFalse;
6120 XDrawBeveledButton(display,&windows->widget,&back_info);
6123 if (MatteIsActive(reset_info,event.xbutton))
6126 User pressed Reset button.
6128 reset_info.raised=MagickFalse;
6129 XDrawBeveledButton(display,&windows->widget,&reset_info);
6132 if (MatteIsActive(action_info,event.xbutton))
6135 User pressed action button.
6137 action_info.raised=MagickFalse;
6138 XDrawBeveledButton(display,&windows->widget,&action_info);
6141 if (MatteIsActive(cancel_info,event.xbutton))
6144 User pressed Cancel button.
6146 cancel_info.raised=MagickFalse;
6147 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6150 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
6152 if (event.xbutton.button != Button2)
6158 Move text cursor to position of button press.
6160 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
6161 for (i=1; i <= Extent(reply_info.marker); i++)
6162 if (XTextWidth(font_info,reply_info.marker,i) > x)
6164 reply_info.cursor=reply_info.marker+i-1;
6165 if (event.xbutton.time > (click_time+DoubleClick))
6166 reply_info.highlight=MagickFalse;
6170 Become the XA_PRIMARY selection owner.
6172 (void) CopyMagickString(primary_selection,reply_info.text,
6174 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
6175 event.xbutton.time);
6176 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
6177 windows->widget.id ? MagickTrue : MagickFalse;
6179 XDrawMatteText(display,&windows->widget,&reply_info);
6180 click_time=event.xbutton.time;
6184 Request primary selection.
6186 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
6187 windows->widget.id,event.xbutton.time);
6192 if (windows->widget.mapped == MagickFalse)
6194 if (north_info.raised == MagickFalse)
6197 User released up button.
6199 delay=SuspendTime << 2;
6200 north_info.raised=MagickTrue;
6201 XDrawTriangleNorth(display,&windows->widget,&north_info);
6203 if (south_info.raised == MagickFalse)
6206 User released down button.
6208 delay=SuspendTime << 2;
6209 south_info.raised=MagickTrue;
6210 XDrawTriangleSouth(display,&windows->widget,&south_info);
6212 if (slider_info.active)
6215 Stop tracking slider.
6217 slider_info.active=MagickFalse;
6220 if (back_info.raised == MagickFalse)
6222 if (event.xbutton.window == windows->widget.id)
6223 if (MatteIsActive(back_info,event.xbutton))
6225 (void) CopyMagickString(glob_pattern,back_pattern,
6227 state|=UpdateListState;
6229 back_info.raised=MagickTrue;
6230 XDrawBeveledButton(display,&windows->widget,&back_info);
6232 if (reset_info.raised == MagickFalse)
6234 if (event.xbutton.window == windows->widget.id)
6235 if (MatteIsActive(reset_info,event.xbutton))
6237 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6238 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
6239 state|=UpdateListState;
6241 reset_info.raised=MagickTrue;
6242 XDrawBeveledButton(display,&windows->widget,&reset_info);
6244 if (action_info.raised == MagickFalse)
6246 if (event.xbutton.window == windows->widget.id)
6248 if (MatteIsActive(action_info,event.xbutton))
6250 if (*reply_info.text == '\0')
6251 (void) XBell(display,0);
6256 action_info.raised=MagickTrue;
6257 XDrawBeveledButton(display,&windows->widget,&action_info);
6259 if (cancel_info.raised == MagickFalse)
6261 if (event.xbutton.window == windows->widget.id)
6262 if (MatteIsActive(cancel_info,event.xbutton))
6264 *reply_info.text='\0';
6267 cancel_info.raised=MagickTrue;
6268 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6275 If client window delete message, exit.
6277 if (event.xclient.message_type != windows->wm_protocols)
6279 if (*event.xclient.data.l == (int) windows->wm_take_focus)
6281 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
6282 (Time) event.xclient.data.l[1]);
6285 if (*event.xclient.data.l != (int) windows->wm_delete_window)
6287 if (event.xclient.window == windows->widget.id)
6289 *reply_info.text='\0';
6295 case ConfigureNotify:
6298 Update widget configuration.
6300 if (event.xconfigure.window != windows->widget.id)
6302 if ((event.xconfigure.width == (int) windows->widget.width) &&
6303 (event.xconfigure.height == (int) windows->widget.height))
6305 windows->widget.width=(unsigned int)
6306 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
6307 windows->widget.height=(unsigned int)
6308 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
6309 state|=UpdateConfigurationState;
6314 if (event.xcrossing.window != windows->widget.id)
6316 state&=(~InactiveWidgetState);
6321 if (event.xexpose.window != windows->widget.id)
6323 if (event.xexpose.count != 0)
6325 state|=RedrawWidgetState;
6331 command[MaxTextExtent];
6340 Respond to a user key press.
6342 if (event.xkey.window != windows->widget.id)
6344 length=XLookupString((XKeyEvent *) &event.xkey,command,
6345 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6346 *(command+length)='\0';
6347 if (AreaIsActive(scroll_info,event.xkey))
6352 switch ((int) key_symbol)
6375 slider_info.id-=visible_fonts;
6381 slider_info.id+=visible_fonts;
6387 slider_info.id=fonts;
6391 state|=RedrawListState;
6394 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
6397 Read new font or glob patterm.
6399 if (*reply_info.text == '\0')
6401 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6402 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
6403 state|=UpdateListState;
6406 if (key_symbol == XK_Control_L)
6408 state|=ControlState;
6411 if (state & ControlState)
6412 switch ((int) key_symbol)
6418 Erase the entire line of text.
6420 *reply_info.text='\0';
6421 reply_info.cursor=reply_info.text;
6422 reply_info.marker=reply_info.text;
6423 reply_info.highlight=MagickFalse;
6429 XEditText(display,&reply_info,key_symbol,command,state);
6430 XDrawMatteText(display,&windows->widget,&reply_info);
6431 state|=JumpListState;
6437 command[MaxTextExtent];
6443 Respond to a user key release.
6445 if (event.xkey.window != windows->widget.id)
6447 (void) XLookupString((XKeyEvent *) &event.xkey,command,
6448 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6449 if (key_symbol == XK_Control_L)
6450 state&=(~ControlState);
6455 if (event.xcrossing.window != windows->widget.id)
6457 state|=InactiveWidgetState;
6469 Discard pending button motion events.
6471 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
6472 if (slider_info.active)
6477 slider_info.y=event.xmotion.y-
6478 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
6479 if (slider_info.y < slider_info.min_y)
6480 slider_info.y=slider_info.min_y;
6481 if (slider_info.y > slider_info.max_y)
6482 slider_info.y=slider_info.max_y;
6484 if (slider_info.y != slider_info.min_y)
6485 slider_info.id=(fonts*(slider_info.y-slider_info.min_y+1))/
6486 (slider_info.max_y-slider_info.min_y+1);
6487 state|=RedrawListState;
6490 if (state & InactiveWidgetState)
6492 if (back_info.raised == MatteIsActive(back_info,event.xmotion))
6495 Back button status changed.
6497 back_info.raised=!back_info.raised;
6498 XDrawBeveledButton(display,&windows->widget,&back_info);
6501 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
6504 Reset button status changed.
6506 reset_info.raised=!reset_info.raised;
6507 XDrawBeveledButton(display,&windows->widget,&reset_info);
6510 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
6513 Action button status changed.
6515 action_info.raised=action_info.raised == MagickFalse ?
6516 MagickTrue : MagickFalse;
6517 XDrawBeveledButton(display,&windows->widget,&action_info);
6520 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
6523 Cancel button status changed.
6525 cancel_info.raised=cancel_info.raised == MagickFalse ?
6526 MagickTrue : MagickFalse;
6527 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6532 case SelectionClear:
6534 reply_info.highlight=MagickFalse;
6535 XDrawMatteText(display,&windows->widget,&reply_info);
6538 case SelectionNotify:
6554 Obtain response from primary selection.
6556 if (event.xselection.property == (Atom) None)
6558 status=XGetWindowProperty(display,event.xselection.requestor,
6559 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
6560 &format,&length,&after,&data);
6561 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
6564 if ((Extent(reply_info.text)+length) >= MaxTextExtent)
6565 (void) XBell(display,0);
6569 Insert primary selection in reply text.
6571 *(data+length)='\0';
6572 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
6574 XDrawMatteText(display,&windows->widget,&reply_info);
6575 state|=JumpListState;
6576 state|=RedrawActionState;
6578 (void) XFree((void *) data);
6581 case SelectionRequest:
6586 XSelectionRequestEvent
6590 Set XA_PRIMARY selection.
6592 request=(&(event.xselectionrequest));
6593 (void) XChangeProperty(request->display,request->requestor,
6594 request->property,request->target,8,PropModeReplace,
6595 (unsigned char *) primary_selection,Extent(primary_selection));
6596 notify.type=SelectionNotify;
6597 notify.display=request->display;
6598 notify.requestor=request->requestor;
6599 notify.selection=request->selection;
6600 notify.target=request->target;
6601 notify.time=request->time;
6602 if (request->property == None)
6603 notify.property=request->target;
6605 notify.property=request->property;
6606 (void) XSendEvent(request->display,request->requestor,False,0,
6607 (XEvent *) ¬ify);
6612 } while ((state & ExitState) == 0);
6613 XSetCursorState(display,windows,MagickFalse);
6614 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
6615 XCheckRefreshWindows(display,windows);
6619 (void) XFreeFontNames(listhead);
6620 fontlist=(char **) RelinquishMagickMemory(fontlist);
6624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6628 % X I n f o W i d g e t %
6632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6634 % XInfoWidget() displays text in the Info widget. The purpose is to inform
6635 % the user that what activity is currently being performed (e.g. reading
6636 % an image, rotating an image, etc.).
6638 % The format of the XInfoWidget method is:
6640 % void XInfoWidget(Display *display,XWindows *windows,const char *activity)
6642 % A description of each parameter follows:
6644 % o display: Specifies a connection to an X server; returned from
6647 % o window: Specifies a pointer to a XWindows structure.
6649 % o activity: This character string reflects the current activity and is
6650 % displayed in the Info widget.
6653 MagickExport void XInfoWidget(Display *display,XWindows *windows,
6654 const char *activity)
6670 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
6671 assert(display != (Display *) NULL);
6672 assert(windows != (XWindows *) NULL);
6673 assert(activity != (char *) NULL);
6674 font_info=windows->info.font_info;
6675 width=WidgetTextWidth(font_info,(char *) activity)+((3*QuantumMargin) >> 1)+4;
6676 height=(unsigned int) (((6*(font_info->ascent+font_info->descent)) >> 2)+4);
6677 if ((windows->info.width != width) || (windows->info.height != height))
6680 Size Info widget to accommodate the activity text.
6682 windows->info.width=width;
6683 windows->info.height=height;
6684 window_changes.width=(int) width;
6685 window_changes.height=(int) height;
6686 (void) XReconfigureWMWindow(display,windows->info.id,windows->info.screen,
6687 (unsigned int) (CWWidth | CWHeight),&window_changes);
6689 if (windows->info.mapped == MagickFalse)
6691 (void) XMapRaised(display,windows->info.id);
6692 windows->info.mapped=MagickTrue;
6695 Initialize Info matte information.
6697 height=(unsigned int) (font_info->ascent+font_info->descent);
6698 XGetWidgetInfo(activity,&monitor_info);
6699 monitor_info.bevel_width--;
6700 margin=monitor_info.bevel_width+((windows->info.height-height) >> 1)-2;
6701 monitor_info.center=MagickFalse;
6702 monitor_info.x=(int) margin;
6703 monitor_info.y=(int) margin;
6704 monitor_info.width=windows->info.width-(margin << 1);
6705 monitor_info.height=windows->info.height-(margin << 1)+1;
6709 monitor_info.raised=MagickFalse;
6710 XDrawBeveledMatte(display,&windows->info,&monitor_info);
6711 monitor_info.raised=MagickTrue;
6712 XDrawWidgetText(display,&windows->info,&monitor_info);
6716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6720 % X L i s t B r o w s e r W i d g e t %
6724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6726 % XListBrowserWidget() displays a List Browser widget with a query to the
6727 % user. The user keys a reply or select a reply from the list. Finally, the
6728 % user presses the Action or Cancel button to exit. The typed text is
6729 % returned as the reply function parameter.
6731 % The format of the XListBrowserWidget method is:
6733 % void XListBrowserWidget(Display *display,XWindows *windows,
6734 % XWindowInfo *window_info,const char **list,const char *action,
6735 % const char *query,char *reply)
6737 % A description of each parameter follows:
6739 % o display: Specifies a connection to an X server; returned from
6742 % o window: Specifies a pointer to a XWindows structure.
6744 % o list: Specifies a pointer to an array of strings. The user can
6745 % select from these strings as a possible reply value.
6747 % o action: Specifies a pointer to the action of this widget.
6749 % o query: Specifies a pointer to the query to present to the user.
6751 % o reply: the response from the user is returned in this parameter.
6754 MagickExport void XListBrowserWidget(Display *display,XWindows *windows,
6755 XWindowInfo *window_info,const char **list,const char *action,
6756 const char *query,char *reply)
6758 #define CancelButtonText "Cancel"
6761 primary_selection[MaxTextExtent];
6769 static MagickStatusType
6770 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
6812 Count the number of entries in the list.
6814 assert(display != (Display *) NULL);
6815 assert(windows != (XWindows *) NULL);
6816 assert(window_info != (XWindowInfo *) NULL);
6817 assert(list != (const char **) NULL);
6818 assert(action != (char *) NULL);
6819 assert(query != (char *) NULL);
6820 assert(reply != (char *) NULL);
6821 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
6822 XSetCursorState(display,windows,MagickTrue);
6823 XCheckRefreshWindows(display,windows);
6824 if (list == (const char **) NULL)
6826 XNoticeWidget(display,windows,"No text to browse:",(char *) NULL);
6829 for (entries=0; ; entries++)
6830 if (list[entries] == (char *) NULL)
6833 Determine Font Browser widget attributes.
6835 font_info=window_info->font_info;
6836 text_width=WidgetTextWidth(font_info,(char *) query);
6837 for (i=0; i < (int) entries; i++)
6838 if (WidgetTextWidth(font_info,(char *) list[i]) > text_width)
6839 text_width=WidgetTextWidth(font_info,(char *) list[i]);
6840 width=WidgetTextWidth(font_info,(char *) action);
6841 if (WidgetTextWidth(font_info,CancelButtonText) > width)
6842 width=WidgetTextWidth(font_info,CancelButtonText);
6843 width+=QuantumMargin;
6844 height=(unsigned int) (font_info->ascent+font_info->descent);
6846 Position List Browser widget.
6848 window_info->width=(unsigned int) MagickMin((int) text_width,(int)
6849 MaxTextWidth)+((9*QuantumMargin) >> 1);
6850 window_info->min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
6851 if (window_info->width < window_info->min_width)
6852 window_info->width=window_info->min_width;
6853 window_info->height=(unsigned int)
6854 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
6855 window_info->min_height=(unsigned int)
6856 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
6857 if (window_info->height < window_info->min_height)
6858 window_info->height=window_info->min_height;
6859 XConstrainWindowPosition(display,window_info);
6861 Map List Browser widget.
6863 (void) CopyMagickString(window_info->name,"Browse",MaxTextExtent);
6864 status=XStringListToTextProperty(&window_info->name,1,&window_name);
6865 if (status != False)
6867 XSetWMName(display,window_info->id,&window_name);
6868 XSetWMIconName(display,windows->widget.id,&window_name);
6869 (void) XFree((void *) window_name.value);
6871 window_changes.width=(int) window_info->width;
6872 window_changes.height=(int) window_info->height;
6873 window_changes.x=window_info->x;
6874 window_changes.y=window_info->y;
6875 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,mask,
6877 (void) XMapRaised(display,window_info->id);
6878 window_info->mapped=MagickFalse;
6880 Respond to X events.
6882 XGetWidgetInfo((char *) NULL,&slider_info);
6883 XGetWidgetInfo((char *) NULL,&north_info);
6884 XGetWidgetInfo((char *) NULL,&south_info);
6885 XGetWidgetInfo((char *) NULL,&expose_info);
6887 delay=SuspendTime << 2;
6888 state=UpdateConfigurationState;
6891 if (state & UpdateConfigurationState)
6897 Initialize button information.
6899 XGetWidgetInfo(CancelButtonText,&cancel_info);
6900 cancel_info.width=width;
6901 cancel_info.height=(unsigned int) ((3*height) >> 1);
6903 (window_info->width-cancel_info.width-QuantumMargin-2);
6905 (window_info->height-cancel_info.height-QuantumMargin);
6906 XGetWidgetInfo(action,&action_info);
6907 action_info.width=width;
6908 action_info.height=(unsigned int) ((3*height) >> 1);
6909 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
6910 (action_info.bevel_width << 1));
6911 action_info.y=cancel_info.y;
6913 Initialize reply information.
6915 XGetWidgetInfo(reply,&reply_info);
6916 reply_info.raised=MagickFalse;
6917 reply_info.bevel_width--;
6918 reply_info.width=window_info->width-((4*QuantumMargin) >> 1);
6919 reply_info.height=height << 1;
6920 reply_info.x=QuantumMargin;
6921 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
6923 Initialize scroll information.
6925 XGetWidgetInfo((char *) NULL,&scroll_info);
6926 scroll_info.bevel_width--;
6927 scroll_info.width=height;
6928 scroll_info.height=(unsigned int)
6929 (reply_info.y-((6*QuantumMargin) >> 1)-height);
6930 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
6931 scroll_info.y=((5*QuantumMargin) >> 1)+height-reply_info.bevel_width;
6932 scroll_info.raised=MagickFalse;
6933 scroll_info.trough=MagickTrue;
6934 north_info=scroll_info;
6935 north_info.raised=MagickTrue;
6936 north_info.width-=(north_info.bevel_width << 1);
6937 north_info.height=north_info.width-1;
6938 north_info.x+=north_info.bevel_width;
6939 north_info.y+=north_info.bevel_width;
6940 south_info=north_info;
6941 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
6944 slider_info=north_info;
6946 slider_info.width-=2;
6947 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
6948 slider_info.bevel_width+2;
6949 slider_info.height=scroll_info.height-((slider_info.min_y-
6950 scroll_info.y+1) << 1)+4;
6951 visible_entries=scroll_info.height/(height+(height >> 3));
6952 if (entries > visible_entries)
6953 slider_info.height=(visible_entries*slider_info.height)/entries;
6954 slider_info.max_y=south_info.y-south_info.bevel_width-
6955 slider_info.bevel_width-2;
6956 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
6957 slider_info.y=slider_info.min_y;
6958 expose_info=scroll_info;
6959 expose_info.y=slider_info.y;
6961 Initialize list information.
6963 XGetWidgetInfo((char *) NULL,&list_info);
6964 list_info.raised=MagickFalse;
6965 list_info.bevel_width--;
6966 list_info.width=(unsigned int)
6967 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
6968 list_info.height=scroll_info.height;
6969 list_info.x=reply_info.x;
6970 list_info.y=scroll_info.y;
6971 if (window_info->mapped == MagickFalse)
6972 for (i=0; i < (int) entries; i++)
6973 if (LocaleCompare(list[i],reply) == 0)
6976 slider_info.id=i-(visible_entries >> 1);
6977 if (slider_info.id < 0)
6981 Initialize text information.
6983 XGetWidgetInfo(query,&text_info);
6984 text_info.width=reply_info.width;
6985 text_info.height=height;
6986 text_info.x=list_info.x-(QuantumMargin >> 1);
6987 text_info.y=QuantumMargin;
6989 Initialize selection information.
6991 XGetWidgetInfo((char *) NULL,&selection_info);
6992 selection_info.center=MagickFalse;
6993 selection_info.width=list_info.width;
6994 selection_info.height=(unsigned int) ((9*height) >> 3);
6995 selection_info.x=list_info.x;
6996 state&=(~UpdateConfigurationState);
6998 if (state & RedrawWidgetState)
7001 Redraw List Browser window.
7003 XDrawWidgetText(display,window_info,&text_info);
7004 XDrawBeveledMatte(display,window_info,&list_info);
7005 XDrawBeveledMatte(display,window_info,&scroll_info);
7006 XDrawTriangleNorth(display,window_info,&north_info);
7007 XDrawBeveledButton(display,window_info,&slider_info);
7008 XDrawTriangleSouth(display,window_info,&south_info);
7009 XDrawBeveledMatte(display,window_info,&reply_info);
7010 XDrawMatteText(display,window_info,&reply_info);
7011 XDrawBeveledButton(display,window_info,&action_info);
7012 XDrawBeveledButton(display,window_info,&cancel_info);
7013 XHighlightWidget(display,window_info,BorderOffset,BorderOffset);
7014 selection_info.id=(~0);
7015 state|=RedrawActionState;
7016 state|=RedrawListState;
7017 state&=(~RedrawWidgetState);
7019 if (state & RedrawListState)
7022 Determine slider id and position.
7024 if (slider_info.id >= (int) (entries-visible_entries))
7025 slider_info.id=(int) (entries-visible_entries);
7026 if ((slider_info.id < 0) || (entries <= visible_entries))
7028 slider_info.y=slider_info.min_y;
7031 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/entries;
7032 if (slider_info.id != selection_info.id)
7035 Redraw scroll bar and file names.
7037 selection_info.id=slider_info.id;
7038 selection_info.y=list_info.y+(height >> 3)+2;
7039 for (i=0; i < (int) visible_entries; i++)
7041 selection_info.raised=(slider_info.id+i) != list_info.id ?
7042 MagickTrue : MagickFalse;
7043 selection_info.text=(char *) NULL;
7044 if ((slider_info.id+i) < (int) entries)
7045 selection_info.text=(char *) list[slider_info.id+i];
7046 XDrawWidgetText(display,window_info,&selection_info);
7047 selection_info.y+=(int) selection_info.height;
7052 if (slider_info.y > expose_info.y)
7054 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
7055 expose_info.y=slider_info.y-expose_info.height-
7056 slider_info.bevel_width-1;
7060 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
7061 expose_info.y=slider_info.y+slider_info.height+
7062 slider_info.bevel_width+1;
7064 XDrawTriangleNorth(display,window_info,&north_info);
7065 XDrawMatte(display,window_info,&expose_info);
7066 XDrawBeveledButton(display,window_info,&slider_info);
7067 XDrawTriangleSouth(display,window_info,&south_info);
7068 expose_info.y=slider_info.y;
7070 state&=(~RedrawListState);
7073 Wait for next event.
7075 if (north_info.raised && south_info.raised)
7076 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7080 Brief delay before advancing scroll bar.
7082 XDelay(display,delay);
7084 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
7085 if (north_info.raised == MagickFalse)
7086 if (slider_info.id > 0)
7092 state|=RedrawListState;
7094 if (south_info.raised == MagickFalse)
7095 if (slider_info.id < (int) entries)
7101 state|=RedrawListState;
7103 if (event.type != ButtonRelease)
7110 if (MatteIsActive(slider_info,event.xbutton))
7115 slider_info.active=MagickTrue;
7118 if (MatteIsActive(north_info,event.xbutton))
7119 if (slider_info.id > 0)
7124 north_info.raised=MagickFalse;
7126 state|=RedrawListState;
7129 if (MatteIsActive(south_info,event.xbutton))
7130 if (slider_info.id < (int) entries)
7135 south_info.raised=MagickFalse;
7137 state|=RedrawListState;
7140 if (MatteIsActive(scroll_info,event.xbutton))
7145 if (event.xbutton.y < slider_info.y)
7146 slider_info.id-=(visible_entries-1);
7148 slider_info.id+=(visible_entries-1);
7149 state|=RedrawListState;
7152 if (MatteIsActive(list_info,event.xbutton))
7158 User pressed list matte.
7160 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
7161 selection_info.height;
7162 if (id >= (int) entries)
7164 (void) CopyMagickString(reply_info.text,list[id],MaxTextExtent);
7165 reply_info.highlight=MagickFalse;
7166 reply_info.marker=reply_info.text;
7167 reply_info.cursor=reply_info.text+Extent(reply_info.text);
7168 XDrawMatteText(display,window_info,&reply_info);
7169 selection_info.id=(~0);
7170 if (id == list_info.id)
7172 action_info.raised=MagickFalse;
7173 XDrawBeveledButton(display,window_info,&action_info);
7177 state|=RedrawListState;
7180 if (MatteIsActive(action_info,event.xbutton))
7183 User pressed action button.
7185 action_info.raised=MagickFalse;
7186 XDrawBeveledButton(display,window_info,&action_info);
7189 if (MatteIsActive(cancel_info,event.xbutton))
7192 User pressed Cancel button.
7194 cancel_info.raised=MagickFalse;
7195 XDrawBeveledButton(display,window_info,&cancel_info);
7198 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7200 if (event.xbutton.button != Button2)
7206 Move text cursor to position of button press.
7208 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
7209 for (i=1; i <= Extent(reply_info.marker); i++)
7210 if (XTextWidth(font_info,reply_info.marker,i) > x)
7212 reply_info.cursor=reply_info.marker+i-1;
7213 if (event.xbutton.time > (click_time+DoubleClick))
7214 reply_info.highlight=MagickFalse;
7218 Become the XA_PRIMARY selection owner.
7220 (void) CopyMagickString(primary_selection,reply_info.text,
7222 (void) XSetSelectionOwner(display,XA_PRIMARY,window_info->id,
7223 event.xbutton.time);
7224 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
7225 window_info->id ? MagickTrue : MagickFalse;
7227 XDrawMatteText(display,window_info,&reply_info);
7228 click_time=event.xbutton.time;
7232 Request primary selection.
7234 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
7235 window_info->id,event.xbutton.time);
7240 if (window_info->mapped == MagickFalse)
7242 if (north_info.raised == MagickFalse)
7245 User released up button.
7247 delay=SuspendTime << 2;
7248 north_info.raised=MagickTrue;
7249 XDrawTriangleNorth(display,window_info,&north_info);
7251 if (south_info.raised == MagickFalse)
7254 User released down button.
7256 delay=SuspendTime << 2;
7257 south_info.raised=MagickTrue;
7258 XDrawTriangleSouth(display,window_info,&south_info);
7260 if (slider_info.active)
7263 Stop tracking slider.
7265 slider_info.active=MagickFalse;
7268 if (action_info.raised == MagickFalse)
7270 if (event.xbutton.window == window_info->id)
7272 if (MatteIsActive(action_info,event.xbutton))
7274 if (*reply_info.text == '\0')
7275 (void) XBell(display,0);
7280 action_info.raised=MagickTrue;
7281 XDrawBeveledButton(display,window_info,&action_info);
7283 if (cancel_info.raised == MagickFalse)
7285 if (event.xbutton.window == window_info->id)
7286 if (MatteIsActive(cancel_info,event.xbutton))
7288 *reply_info.text='\0';
7291 cancel_info.raised=MagickTrue;
7292 XDrawBeveledButton(display,window_info,&cancel_info);
7294 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7301 If client window delete message, exit.
7303 if (event.xclient.message_type != windows->wm_protocols)
7305 if (*event.xclient.data.l == (int) windows->wm_take_focus)
7307 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
7308 (Time) event.xclient.data.l[1]);
7311 if (*event.xclient.data.l != (int) windows->wm_delete_window)
7313 if (event.xclient.window == window_info->id)
7315 *reply_info.text='\0';
7321 case ConfigureNotify:
7324 Update widget configuration.
7326 if (event.xconfigure.window != window_info->id)
7328 if ((event.xconfigure.width == (int) window_info->width) &&
7329 (event.xconfigure.height == (int) window_info->height))
7331 window_info->width=(unsigned int)
7332 MagickMax(event.xconfigure.width,(int) window_info->min_width);
7333 window_info->height=(unsigned int)
7334 MagickMax(event.xconfigure.height,(int) window_info->min_height);
7335 state|=UpdateConfigurationState;
7340 if (event.xcrossing.window != window_info->id)
7342 state&=(~InactiveWidgetState);
7347 if (event.xexpose.window != window_info->id)
7349 if (event.xexpose.count != 0)
7351 state|=RedrawWidgetState;
7357 command[MaxTextExtent];
7366 Respond to a user key press.
7368 if (event.xkey.window != window_info->id)
7370 length=XLookupString((XKeyEvent *) &event.xkey,command,
7371 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7372 *(command+length)='\0';
7373 if (AreaIsActive(scroll_info,event.xkey))
7378 switch ((int) key_symbol)
7401 slider_info.id-=visible_entries;
7407 slider_info.id+=visible_entries;
7413 slider_info.id=(int) entries;
7417 state|=RedrawListState;
7420 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
7425 if (*reply_info.text == '\0')
7427 action_info.raised=MagickFalse;
7428 XDrawBeveledButton(display,window_info,&action_info);
7432 if (key_symbol == XK_Control_L)
7434 state|=ControlState;
7437 if (state & ControlState)
7438 switch ((int) key_symbol)
7444 Erase the entire line of text.
7446 *reply_info.text='\0';
7447 reply_info.cursor=reply_info.text;
7448 reply_info.marker=reply_info.text;
7449 reply_info.highlight=MagickFalse;
7455 XEditText(display,&reply_info,key_symbol,command,state);
7456 XDrawMatteText(display,window_info,&reply_info);
7462 command[MaxTextExtent];
7468 Respond to a user key release.
7470 if (event.xkey.window != window_info->id)
7472 (void) XLookupString((XKeyEvent *) &event.xkey,command,
7473 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7474 if (key_symbol == XK_Control_L)
7475 state&=(~ControlState);
7480 if (event.xcrossing.window != window_info->id)
7482 state|=InactiveWidgetState;
7494 Discard pending button motion events.
7496 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7497 if (slider_info.active)
7502 slider_info.y=event.xmotion.y-
7503 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
7504 if (slider_info.y < slider_info.min_y)
7505 slider_info.y=slider_info.min_y;
7506 if (slider_info.y > slider_info.max_y)
7507 slider_info.y=slider_info.max_y;
7509 if (slider_info.y != slider_info.min_y)
7510 slider_info.id=(int) ((entries*(slider_info.y-
7511 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
7512 state|=RedrawListState;
7515 if (state & InactiveWidgetState)
7517 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
7520 Action button status changed.
7522 action_info.raised=action_info.raised == MagickFalse ?
7523 MagickTrue : MagickFalse;
7524 XDrawBeveledButton(display,window_info,&action_info);
7527 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
7530 Cancel button status changed.
7532 cancel_info.raised=cancel_info.raised == MagickFalse ?
7533 MagickTrue : MagickFalse;
7534 XDrawBeveledButton(display,window_info,&cancel_info);
7539 case SelectionClear:
7541 reply_info.highlight=MagickFalse;
7542 XDrawMatteText(display,window_info,&reply_info);
7545 case SelectionNotify:
7561 Obtain response from primary selection.
7563 if (event.xselection.property == (Atom) None)
7565 status=XGetWindowProperty(display,
7566 event.xselection.requestor,event.xselection.property,0L,2047L,
7567 MagickTrue,XA_STRING,&type,&format,&length,&after,&data);
7568 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
7571 if ((Extent(reply_info.text)+length) >= MaxTextExtent)
7572 (void) XBell(display,0);
7576 Insert primary selection in reply text.
7578 *(data+length)='\0';
7579 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
7581 XDrawMatteText(display,window_info,&reply_info);
7582 state|=RedrawActionState;
7584 (void) XFree((void *) data);
7587 case SelectionRequest:
7592 XSelectionRequestEvent
7595 if (reply_info.highlight == MagickFalse)
7598 Set primary selection.
7600 request=(&(event.xselectionrequest));
7601 (void) XChangeProperty(request->display,request->requestor,
7602 request->property,request->target,8,PropModeReplace,
7603 (unsigned char *) primary_selection,Extent(primary_selection));
7604 notify.type=SelectionNotify;
7605 notify.send_event=MagickTrue;
7606 notify.display=request->display;
7607 notify.requestor=request->requestor;
7608 notify.selection=request->selection;
7609 notify.target=request->target;
7610 notify.time=request->time;
7611 if (request->property == None)
7612 notify.property=request->target;
7614 notify.property=request->property;
7615 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
7616 (XEvent *) ¬ify);
7621 } while ((state & ExitState) == 0);
7622 XSetCursorState(display,windows,MagickFalse);
7623 (void) XWithdrawWindow(display,window_info->id,window_info->screen);
7624 XCheckRefreshWindows(display,windows);
7628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7632 % X M e n u W i d g e t %
7636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7638 % XMenuWidget() maps a menu and returns the command pointed to by the user
7639 % when the button is released.
7641 % The format of the XMenuWidget method is:
7643 % int XMenuWidget(Display *display,XWindows *windows,const char *title,
7644 % const char **selections,char *item)
7646 % A description of each parameter follows:
7648 % o selection_number: Specifies the number of the selection that the
7651 % o display: Specifies a connection to an X server; returned from
7654 % o window: Specifies a pointer to a XWindows structure.
7656 % o title: Specifies a character string that describes the menu selections.
7658 % o selections: Specifies a pointer to one or more strings that comprise
7659 % the choices in the menu.
7661 % o item: Specifies a character array. The item selected from the menu
7665 MagickExport int XMenuWidget(Display *display,XWindows *windows,
7666 const char *title,const char **selections,char *item)
7692 XSetWindowAttributes
7704 Determine Menu widget attributes.
7706 assert(display != (Display *) NULL);
7707 assert(windows != (XWindows *) NULL);
7708 assert(title != (char *) NULL);
7709 assert(selections != (const char **) NULL);
7710 assert(item != (char *) NULL);
7711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
7712 font_info=windows->widget.font_info;
7713 windows->widget.width=submenu_info.active == 0 ?
7714 WidgetTextWidth(font_info,(char *) title) : 0;
7715 for (id=0; selections[id] != (char *) NULL; id++)
7717 width=WidgetTextWidth(font_info,(char *) selections[id]);
7718 if (width > windows->widget.width)
7719 windows->widget.width=width;
7721 number_selections=(unsigned int) id;
7722 XGetWidgetInfo((char *) NULL,&menu_info);
7723 title_height=(unsigned int) (submenu_info.active == 0 ?
7724 (3*(font_info->descent+font_info->ascent) >> 1)+5 : 2);
7725 width=WidgetTextWidth(font_info,(char *) title);
7726 height=(unsigned int) ((3*(font_info->ascent+font_info->descent)) >> 1);
7728 Position Menu widget.
7730 windows->widget.width+=QuantumMargin+(menu_info.bevel_width << 1);
7731 top_offset=title_height+menu_info.bevel_width-1;
7732 windows->widget.height=top_offset+number_selections*height+4;
7733 windows->widget.min_width=windows->widget.width;
7734 windows->widget.min_height=windows->widget.height;
7735 XQueryPosition(display,windows->widget.root,&x,&y);
7736 windows->widget.x=x-(QuantumMargin >> 1);
7737 if (submenu_info.active != 0)
7740 windows->command.x+windows->command.width-QuantumMargin;
7741 toggle_info.raised=MagickTrue;
7742 XDrawTriangleEast(display,&windows->command,&toggle_info);
7744 windows->widget.y=submenu_info.active == 0 ? y-(int)
7745 ((3*title_height) >> 2) : y;
7746 if (submenu_info.active != 0)
7747 windows->widget.y=windows->command.y+submenu_info.y;
7748 XConstrainWindowPosition(display,&windows->widget);
7752 window_attributes.override_redirect=MagickTrue;
7753 (void) XChangeWindowAttributes(display,windows->widget.id,
7754 (size_t) CWOverrideRedirect,&window_attributes);
7755 window_changes.width=(int) windows->widget.width;
7756 window_changes.height=(int) windows->widget.height;
7757 window_changes.x=windows->widget.x;
7758 window_changes.y=windows->widget.y;
7759 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
7760 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
7761 (void) XMapRaised(display,windows->widget.id);
7762 windows->widget.mapped=MagickFalse;
7764 Respond to X events.
7766 selection_info.height=height;
7767 cursor=XCreateFontCursor(display,XC_right_ptr);
7768 (void) XCheckDefineCursor(display,windows->image.id,cursor);
7769 (void) XCheckDefineCursor(display,windows->command.id,cursor);
7770 (void) XCheckDefineCursor(display,windows->widget.id,cursor);
7771 state=UpdateConfigurationState;
7774 if (state & UpdateConfigurationState)
7777 Initialize selection information.
7779 XGetWidgetInfo((char *) NULL,&menu_info);
7780 menu_info.bevel_width--;
7781 menu_info.width=windows->widget.width-((menu_info.bevel_width) << 1);
7782 menu_info.height=windows->widget.height-((menu_info.bevel_width) << 1);
7783 menu_info.x=(int) menu_info.bevel_width;
7784 menu_info.y=(int) menu_info.bevel_width;
7785 XGetWidgetInfo((char *) NULL,&selection_info);
7786 selection_info.center=MagickFalse;
7787 selection_info.width=menu_info.width;
7788 selection_info.height=height;
7789 selection_info.x=menu_info.x;
7790 highlight_info=selection_info;
7791 highlight_info.bevel_width--;
7792 highlight_info.width-=(highlight_info.bevel_width << 1);
7793 highlight_info.height-=(highlight_info.bevel_width << 1);
7794 highlight_info.x+=highlight_info.bevel_width;
7795 state&=(~UpdateConfigurationState);
7797 if (state & RedrawWidgetState)
7802 if (submenu_info.active == 0)
7804 y=(int) title_height;
7805 XSetBevelColor(display,&windows->widget,MagickFalse);
7806 (void) XDrawLine(display,windows->widget.id,
7807 windows->widget.widget_context,selection_info.x,y-1,
7808 (int) selection_info.width,y-1);
7809 XSetBevelColor(display,&windows->widget,MagickTrue);
7810 (void) XDrawLine(display,windows->widget.id,
7811 windows->widget.widget_context,selection_info.x,y,
7812 (int) selection_info.width,y);
7813 (void) XSetFillStyle(display,windows->widget.widget_context,
7817 Draw menu selections.
7819 selection_info.center=MagickTrue;
7820 selection_info.y=(int) menu_info.bevel_width;
7821 selection_info.text=(char *) title;
7822 if (submenu_info.active == 0)
7823 XDrawWidgetText(display,&windows->widget,&selection_info);
7824 selection_info.center=MagickFalse;
7825 selection_info.y=(int) top_offset;
7826 for (id=0; id < (int) number_selections; id++)
7828 selection_info.text=(char *) selections[id];
7829 XDrawWidgetText(display,&windows->widget,&selection_info);
7830 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7831 if (id == selection_info.id)
7832 XDrawBevel(display,&windows->widget,&highlight_info);
7833 selection_info.y+=(int) selection_info.height;
7835 XDrawBevel(display,&windows->widget,&menu_info);
7836 state&=(~RedrawWidgetState);
7838 if (number_selections > 2)
7843 y=(int) (top_offset+selection_info.height*(number_selections-1));
7844 XSetBevelColor(display,&windows->widget,MagickFalse);
7845 (void) XDrawLine(display,windows->widget.id,
7846 windows->widget.widget_context,selection_info.x,y-1,
7847 (int) selection_info.width,y-1);
7848 XSetBevelColor(display,&windows->widget,MagickTrue);
7849 (void) XDrawLine(display,windows->widget.id,
7850 windows->widget.widget_context,selection_info.x,y,
7851 (int) selection_info.width,y);
7852 (void) XSetFillStyle(display,windows->widget.widget_context,FillSolid);
7855 Wait for next event.
7857 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7862 if (event.xbutton.window != windows->widget.id)
7867 if (event.xbutton.window == windows->command.id)
7868 (void) XPutBackEvent(display,&event);
7869 selection_info.id=(~0);
7874 state&=(~InactiveWidgetState);
7875 id=(event.xbutton.y-top_offset)/(int) selection_info.height;
7876 selection_info.id=id;
7877 if ((id < 0) || (id >= (int) number_selections))
7880 Highlight this selection.
7882 selection_info.y=(int) (top_offset+id*selection_info.height);
7883 selection_info.text=(char *) selections[id];
7884 XDrawWidgetText(display,&windows->widget,&selection_info);
7885 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7886 XDrawBevel(display,&windows->widget,&highlight_info);
7891 if (windows->widget.mapped == MagickFalse)
7893 if (event.xbutton.window == windows->command.id)
7894 if ((state & InactiveWidgetState) == 0)
7899 XSetCursorState(display,windows,MagickFalse);
7904 case ConfigureNotify:
7907 Update widget configuration.
7909 if (event.xconfigure.window != windows->widget.id)
7911 if ((event.xconfigure.width == (int) windows->widget.width) &&
7912 (event.xconfigure.height == (int) windows->widget.height))
7914 windows->widget.width=(unsigned int)
7915 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
7916 windows->widget.height=(unsigned int)
7917 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
7918 state|=UpdateConfigurationState;
7923 if (event.xcrossing.window != windows->widget.id)
7925 if (event.xcrossing.state == 0)
7927 state&=(~InactiveWidgetState);
7928 id=((event.xcrossing.y-top_offset)/(int) selection_info.height);
7929 if ((selection_info.id >= 0) &&
7930 (selection_info.id < (int) number_selections))
7933 Unhighlight last selection.
7935 if (id == selection_info.id)
7937 selection_info.y=(int)
7938 (top_offset+selection_info.id*selection_info.height);
7939 selection_info.text=(char *) selections[selection_info.id];
7940 XDrawWidgetText(display,&windows->widget,&selection_info);
7942 if ((id < 0) || (id >= (int) number_selections))
7945 Highlight this selection.
7947 selection_info.id=id;
7948 selection_info.y=(int)
7949 (top_offset+selection_info.id*selection_info.height);
7950 selection_info.text=(char *) selections[selection_info.id];
7951 XDrawWidgetText(display,&windows->widget,&selection_info);
7952 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7953 XDrawBevel(display,&windows->widget,&highlight_info);
7958 if (event.xexpose.window != windows->widget.id)
7960 if (event.xexpose.count != 0)
7962 state|=RedrawWidgetState;
7967 if (event.xcrossing.window != windows->widget.id)
7969 state|=InactiveWidgetState;
7970 id=selection_info.id;
7971 if ((id < 0) || (id >= (int) number_selections))
7974 Unhighlight last selection.
7976 selection_info.y=(int) (top_offset+id*selection_info.height);
7977 selection_info.id=(~0);
7978 selection_info.text=(char *) selections[id];
7979 XDrawWidgetText(display,&windows->widget,&selection_info);
7985 Discard pending button motion events.
7987 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7988 if (submenu_info.active != 0)
7989 if (event.xmotion.window == windows->command.id)
7991 if ((state & InactiveWidgetState) == 0)
7993 if (MatteIsActive(submenu_info,event.xmotion) == MagickFalse)
7995 selection_info.id=(~0);
8002 if (WindowIsActive(windows->command,event.xmotion))
8004 selection_info.id=(~0);
8010 if (event.xmotion.window != windows->widget.id)
8012 if (state & InactiveWidgetState)
8014 id=(event.xmotion.y-top_offset)/(int) selection_info.height;
8015 if ((selection_info.id >= 0) &&
8016 (selection_info.id < (int) number_selections))
8019 Unhighlight last selection.
8021 if (id == selection_info.id)
8023 selection_info.y=(int)
8024 (top_offset+selection_info.id*selection_info.height);
8025 selection_info.text=(char *) selections[selection_info.id];
8026 XDrawWidgetText(display,&windows->widget,&selection_info);
8028 selection_info.id=id;
8029 if ((id < 0) || (id >= (int) number_selections))
8032 Highlight this selection.
8034 selection_info.y=(int) (top_offset+id*selection_info.height);
8035 selection_info.text=(char *) selections[id];
8036 XDrawWidgetText(display,&windows->widget,&selection_info);
8037 highlight_info.y=selection_info.y+highlight_info.bevel_width;
8038 XDrawBevel(display,&windows->widget,&highlight_info);
8044 } while ((state & ExitState) == 0);
8045 (void) XFreeCursor(display,cursor);
8046 window_attributes.override_redirect=MagickFalse;
8047 (void) XChangeWindowAttributes(display,windows->widget.id,
8048 (size_t) CWOverrideRedirect,&window_attributes);
8049 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8050 XCheckRefreshWindows(display,windows);
8051 if (submenu_info.active != 0)
8053 submenu_info.active=MagickFalse;
8054 toggle_info.raised=MagickFalse;
8055 XDrawTriangleEast(display,&windows->command,&toggle_info);
8057 if ((selection_info.id < 0) || (selection_info.id >= (int) number_selections))
8059 (void) CopyMagickString(item,selections[selection_info.id],MaxTextExtent);
8060 return(selection_info.id);
8064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8068 % X N o t i c e W i d g e t %
8072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8074 % XNoticeWidget() displays a Notice widget with a notice to the user. The
8075 % function returns when the user presses the "Dismiss" button.
8077 % The format of the XNoticeWidget method is:
8079 % void XNoticeWidget(Display *display,XWindows *windows,
8080 % const char *reason,const char *description)
8082 % A description of each parameter follows:
8084 % o display: Specifies a connection to an X server; returned from
8087 % o window: Specifies a pointer to a XWindows structure.
8089 % o reason: Specifies the message to display before terminating the
8092 % o description: Specifies any description to the message.
8095 MagickExport void XNoticeWidget(Display *display,XWindows *windows,
8096 const char *reason,const char *description)
8098 #define DismissButtonText "Dismiss"
8137 Determine Notice widget attributes.
8139 assert(display != (Display *) NULL);
8140 assert(windows != (XWindows *) NULL);
8141 assert(reason != (char *) NULL);
8142 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
8143 XDelay(display,SuspendTime << 3); /* avoid surpise with delay */
8144 XSetCursorState(display,windows,MagickTrue);
8145 XCheckRefreshWindows(display,windows);
8146 font_info=windows->widget.font_info;
8147 width=WidgetTextWidth(font_info,DismissButtonText);
8148 text=GetLocaleExceptionMessage(XServerError,reason);
8149 if (text != (char *) NULL)
8150 if (WidgetTextWidth(font_info,(char *) text) > width)
8151 width=WidgetTextWidth(font_info,(char *) text);
8152 if (description != (char *) NULL)
8154 text=GetLocaleExceptionMessage(XServerError,description);
8155 if (text != (char *) NULL)
8156 if (WidgetTextWidth(font_info,(char *) text) > width)
8157 width=WidgetTextWidth(font_info,(char *) text);
8159 height=(unsigned int) (font_info->ascent+font_info->descent);
8161 Position Notice widget.
8163 windows->widget.width=width+4*QuantumMargin;
8164 windows->widget.min_width=width+QuantumMargin;
8165 if (windows->widget.width < windows->widget.min_width)
8166 windows->widget.width=windows->widget.min_width;
8167 windows->widget.height=(unsigned int) (12*height);
8168 windows->widget.min_height=(unsigned int) (7*height);
8169 if (windows->widget.height < windows->widget.min_height)
8170 windows->widget.height=windows->widget.min_height;
8171 XConstrainWindowPosition(display,&windows->widget);
8175 (void) CopyMagickString(windows->widget.name,"Notice",MaxTextExtent);
8176 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8177 if (status != False)
8179 XSetWMName(display,windows->widget.id,&window_name);
8180 XSetWMIconName(display,windows->widget.id,&window_name);
8181 (void) XFree((void *) window_name.value);
8183 window_changes.width=(int) windows->widget.width;
8184 window_changes.height=(int) windows->widget.height;
8185 window_changes.x=windows->widget.x;
8186 window_changes.y=windows->widget.y;
8187 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8188 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8189 (void) XMapRaised(display,windows->widget.id);
8190 windows->widget.mapped=MagickFalse;
8191 (void) XBell(display,0);
8193 Respond to X events.
8195 timer=time((time_t *) NULL)+Timeout;
8196 state=UpdateConfigurationState;
8199 if (time((time_t *) NULL) > timer)
8201 if (state & UpdateConfigurationState)
8204 Initialize Dismiss button information.
8206 XGetWidgetInfo(DismissButtonText,&dismiss_info);
8207 dismiss_info.width=(unsigned int) QuantumMargin+
8208 WidgetTextWidth(font_info,DismissButtonText);
8209 dismiss_info.height=(unsigned int) ((3*height) >> 1);
8210 dismiss_info.x=(int)
8211 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
8212 dismiss_info.y=(int)
8213 (windows->widget.height-(dismiss_info.height << 1));
8214 state&=(~UpdateConfigurationState);
8216 if (state & RedrawWidgetState)
8219 Redraw Notice widget.
8221 width=WidgetTextWidth(font_info,(char *) reason);
8222 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8223 y=(int) ((windows->widget.height >> 1)-(height << 1));
8224 (void) XDrawString(display,windows->widget.id,
8225 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
8226 if (description != (char *) NULL)
8228 width=WidgetTextWidth(font_info,(char *) description);
8229 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8231 (void) XDrawString(display,windows->widget.id,
8232 windows->widget.annotate_context,x,y,(char *) description,
8233 Extent(description));
8235 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8236 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8237 state&=(~RedrawWidgetState);
8240 Wait for next event.
8242 if (XCheckIfEvent(display,&event,XScreenEvent,(char *) windows) == MagickFalse)
8245 Do not block if delay > 0.
8247 XDelay(display,SuspendTime << 2);
8254 if (MatteIsActive(dismiss_info,event.xbutton))
8257 User pressed Dismiss button.
8259 dismiss_info.raised=MagickFalse;
8260 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8267 if (windows->widget.mapped == MagickFalse)
8269 if (dismiss_info.raised == MagickFalse)
8271 if (event.xbutton.window == windows->widget.id)
8272 if (MatteIsActive(dismiss_info,event.xbutton))
8274 dismiss_info.raised=MagickTrue;
8275 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8282 If client window delete message, exit.
8284 if (event.xclient.message_type != windows->wm_protocols)
8286 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8288 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8289 (Time) event.xclient.data.l[1]);
8292 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8294 if (event.xclient.window == windows->widget.id)
8301 case ConfigureNotify:
8304 Update widget configuration.
8306 if (event.xconfigure.window != windows->widget.id)
8308 if ((event.xconfigure.width == (int) windows->widget.width) &&
8309 (event.xconfigure.height == (int) windows->widget.height))
8311 windows->widget.width=(unsigned int)
8312 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8313 windows->widget.height=(unsigned int)
8314 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8315 state|=UpdateConfigurationState;
8320 if (event.xcrossing.window != windows->widget.id)
8322 state&=(~InactiveWidgetState);
8327 if (event.xexpose.window != windows->widget.id)
8329 if (event.xexpose.count != 0)
8331 state|=RedrawWidgetState;
8337 command[MaxTextExtent];
8343 Respond to a user key press.
8345 if (event.xkey.window != windows->widget.id)
8347 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8348 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8349 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8351 dismiss_info.raised=MagickFalse;
8352 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8360 if (event.xcrossing.window != windows->widget.id)
8362 state|=InactiveWidgetState;
8368 Discard pending button motion events.
8370 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8371 if (state & InactiveWidgetState)
8373 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
8376 Dismiss button status changed.
8378 dismiss_info.raised=
8379 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8380 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8388 } while ((state & ExitState) == 0);
8389 XSetCursorState(display,windows,MagickFalse);
8390 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8391 XCheckRefreshWindows(display,windows);
8395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8399 % X P r e f e r e n c e s W i d g e t %
8403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8405 % XPreferencesWidget() displays a Preferences widget with program preferences.
8406 % If the user presses the Apply button, the preferences are stored in a
8407 % configuration file in the users' home directory.
8409 % The format of the XPreferencesWidget method is:
8411 % MagickBooleanType XPreferencesWidget(Display *display,
8412 % XResourceInfo *resource_info,XWindows *windows)
8414 % A description of each parameter follows:
8416 % o display: Specifies a connection to an X server; returned from
8419 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8421 % o window: Specifies a pointer to a XWindows structure.
8424 MagickExport MagickBooleanType XPreferencesWidget(Display *display,
8425 XResourceInfo *resource_info,XWindows *windows)
8427 #define ApplyButtonText "Apply"
8428 #define CacheButtonText "%lu mega-bytes of memory in the undo edit cache "
8429 #define CancelButtonText "Cancel"
8430 #define NumberPreferences 8
8435 "display image centered on a backdrop",
8436 "confirm on program exit",
8437 "confirm on image edits",
8438 "correct image for display gamma",
8439 "display warning messages",
8440 "apply Floyd/Steinberg error diffusion to image",
8441 "use a shared colormap for colormapped X visuals",
8442 "display images as an X server pixmap"
8446 cache[MaxTextExtent];
8479 preferences_info[NumberPreferences];
8485 Determine Preferences widget attributes.
8487 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8488 assert(display != (Display *) NULL);
8489 assert(resource_info != (XResourceInfo *) NULL);
8490 assert(windows != (XWindows *) NULL);
8491 XCheckRefreshWindows(display,windows);
8492 font_info=windows->widget.font_info;
8493 text_width=WidgetTextWidth(font_info,CacheButtonText);
8494 for (i=0; i < NumberPreferences; i++)
8495 if (WidgetTextWidth(font_info,(char *) Preferences[i]) > text_width)
8496 text_width=WidgetTextWidth(font_info,(char *) Preferences[i]);
8497 width=WidgetTextWidth(font_info,ApplyButtonText);
8498 if (WidgetTextWidth(font_info,CancelButtonText) > width)
8499 width=WidgetTextWidth(font_info,CancelButtonText);
8500 width+=(unsigned int) QuantumMargin;
8501 height=(unsigned int) (font_info->ascent+font_info->descent);
8503 Position Preferences widget.
8505 windows->widget.width=(unsigned int) (MagickMax((int) (width << 1),
8506 (int) text_width)+6*QuantumMargin);
8507 windows->widget.min_width=(width << 1)+QuantumMargin;
8508 if (windows->widget.width < windows->widget.min_width)
8509 windows->widget.width=windows->widget.min_width;
8510 windows->widget.height=(unsigned int)
8511 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8512 windows->widget.min_height=(unsigned int)
8513 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8514 if (windows->widget.height < windows->widget.min_height)
8515 windows->widget.height=windows->widget.min_height;
8516 XConstrainWindowPosition(display,&windows->widget);
8518 Map Preferences widget.
8520 (void) CopyMagickString(windows->widget.name,"Preferences",MaxTextExtent);
8521 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8522 if (status != False)
8524 XSetWMName(display,windows->widget.id,&window_name);
8525 XSetWMIconName(display,windows->widget.id,&window_name);
8526 (void) XFree((void *) window_name.value);
8528 window_changes.width=(int) windows->widget.width;
8529 window_changes.height=(int) windows->widget.height;
8530 window_changes.x=windows->widget.x;
8531 window_changes.y=windows->widget.y;
8532 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8533 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8534 (void) XMapRaised(display,windows->widget.id);
8535 windows->widget.mapped=MagickFalse;
8537 Respond to X events.
8539 state=UpdateConfigurationState;
8540 XSetCursorState(display,windows,MagickTrue);
8543 if (state & UpdateConfigurationState)
8546 Initialize button information.
8548 XGetWidgetInfo(CancelButtonText,&cancel_info);
8549 cancel_info.width=width;
8550 cancel_info.height=(unsigned int) (3*height) >> 1;
8551 cancel_info.x=(int) windows->widget.width-cancel_info.width-
8552 (QuantumMargin << 1);
8553 cancel_info.y=(int) windows->widget.height-
8554 cancel_info.height-QuantumMargin;
8555 XGetWidgetInfo(ApplyButtonText,&apply_info);
8556 apply_info.width=width;
8557 apply_info.height=(unsigned int) (3*height) >> 1;
8558 apply_info.x=QuantumMargin << 1;
8559 apply_info.y=cancel_info.y;
8560 y=(int) (height << 1);
8561 for (i=0; i < NumberPreferences; i++)
8563 XGetWidgetInfo(Preferences[i],&preferences_info[i]);
8564 preferences_info[i].bevel_width--;
8565 preferences_info[i].width=(unsigned int) QuantumMargin >> 1;
8566 preferences_info[i].height=(unsigned int) QuantumMargin >> 1;
8567 preferences_info[i].x=QuantumMargin << 1;
8568 preferences_info[i].y=y;
8569 y+=height+(QuantumMargin >> 1);
8571 preferences_info[0].raised=resource_info->backdrop ==
8572 MagickFalse ? MagickTrue : MagickFalse;
8573 preferences_info[1].raised=resource_info->confirm_exit ==
8574 MagickFalse ? MagickTrue : MagickFalse;
8575 preferences_info[2].raised=resource_info->confirm_edit ==
8576 MagickFalse ? MagickTrue : MagickFalse;
8577 preferences_info[3].raised=resource_info->gamma_correct ==
8578 MagickFalse ? MagickTrue : MagickFalse;
8579 preferences_info[4].raised=resource_info->display_warnings ==
8580 MagickFalse ? MagickTrue : MagickFalse;
8581 preferences_info[5].raised=resource_info->quantize_info->dither ==
8582 MagickFalse ? MagickTrue : MagickFalse;
8583 preferences_info[6].raised=resource_info->colormap !=
8584 SharedColormap ? MagickTrue : MagickFalse;
8585 preferences_info[7].raised=resource_info->use_pixmap ==
8586 MagickFalse ? MagickTrue : MagickFalse;
8587 (void) FormatMagickString(cache,MaxTextExtent,CacheButtonText,
8588 (unsigned long) resource_info->undo_cache);
8589 XGetWidgetInfo(cache,&cache_info);
8590 cache_info.bevel_width--;
8591 cache_info.width=(unsigned int) QuantumMargin >> 1;
8592 cache_info.height=(unsigned int) QuantumMargin >> 1;
8593 cache_info.x=QuantumMargin << 1;
8595 state&=(~UpdateConfigurationState);
8597 if (state & RedrawWidgetState)
8600 Redraw Preferences widget.
8602 XDrawBeveledButton(display,&windows->widget,&apply_info);
8603 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8604 for (i=0; i < NumberPreferences; i++)
8605 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8606 XDrawTriangleEast(display,&windows->widget,&cache_info);
8607 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8608 state&=(~RedrawWidgetState);
8611 Wait for next event.
8613 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
8618 if (MatteIsActive(apply_info,event.xbutton))
8621 User pressed Apply button.
8623 apply_info.raised=MagickFalse;
8624 XDrawBeveledButton(display,&windows->widget,&apply_info);
8627 if (MatteIsActive(cancel_info,event.xbutton))
8630 User pressed Cancel button.
8632 cancel_info.raised=MagickFalse;
8633 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8636 for (i=0; i < NumberPreferences; i++)
8637 if (MatteIsActive(preferences_info[i],event.xbutton))
8640 User pressed a Preferences button.
8642 preferences_info[i].raised=preferences_info[i].raised ==
8643 MagickFalse ? MagickTrue : MagickFalse;
8644 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8647 if (MatteIsActive(cache_info,event.xbutton))
8650 User pressed Cache button.
8652 x=cache_info.x+cache_info.width+cache_info.bevel_width+
8653 (QuantumMargin >> 1);
8654 y=cache_info.y+((cache_info.height-height) >> 1);
8655 width=WidgetTextWidth(font_info,cache);
8656 (void) XClearArea(display,windows->widget.id,x,y,width,height,
8658 resource_info->undo_cache<<=1;
8659 if (resource_info->undo_cache > 256)
8660 resource_info->undo_cache=1;
8661 (void) FormatMagickString(cache,MaxTextExtent,CacheButtonText,
8662 (unsigned long) resource_info->undo_cache);
8663 cache_info.raised=MagickFalse;
8664 XDrawTriangleEast(display,&windows->widget,&cache_info);
8671 if (windows->widget.mapped == MagickFalse)
8673 if (apply_info.raised == MagickFalse)
8675 if (event.xbutton.window == windows->widget.id)
8676 if (MatteIsActive(apply_info,event.xbutton))
8678 apply_info.raised=MagickTrue;
8679 XDrawBeveledButton(display,&windows->widget,&apply_info);
8680 apply_info.raised=MagickFalse;
8682 if (cancel_info.raised == MagickFalse)
8684 if (event.xbutton.window == windows->widget.id)
8685 if (MatteIsActive(cancel_info,event.xbutton))
8687 cancel_info.raised=MagickTrue;
8688 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8690 if (cache_info.raised == MagickFalse)
8692 cache_info.raised=MagickTrue;
8693 XDrawTriangleEast(display,&windows->widget,&cache_info);
8700 If client window delete message, exit.
8702 if (event.xclient.message_type != windows->wm_protocols)
8704 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8706 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8707 (Time) event.xclient.data.l[1]);
8710 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8712 if (event.xclient.window == windows->widget.id)
8719 case ConfigureNotify:
8722 Update widget configuration.
8724 if (event.xconfigure.window != windows->widget.id)
8726 if ((event.xconfigure.width == (int) windows->widget.width) &&
8727 (event.xconfigure.height == (int) windows->widget.height))
8729 windows->widget.width=(unsigned int)
8730 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8731 windows->widget.height=(unsigned int)
8732 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8733 state|=UpdateConfigurationState;
8738 if (event.xcrossing.window != windows->widget.id)
8740 state&=(~InactiveWidgetState);
8745 if (event.xexpose.window != windows->widget.id)
8747 if (event.xexpose.count != 0)
8749 state|=RedrawWidgetState;
8755 command[MaxTextExtent];
8761 Respond to a user key press.
8763 if (event.xkey.window != windows->widget.id)
8765 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8766 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8767 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8769 apply_info.raised=MagickFalse;
8770 XDrawBeveledButton(display,&windows->widget,&apply_info);
8778 if (event.xcrossing.window != windows->widget.id)
8780 state|=InactiveWidgetState;
8786 Discard pending button motion events.
8788 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8789 if (state & InactiveWidgetState)
8791 if (apply_info.raised == MatteIsActive(apply_info,event.xmotion))
8794 Apply button status changed.
8797 apply_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8798 XDrawBeveledButton(display,&windows->widget,&apply_info);
8801 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
8804 Cancel button status changed.
8807 cancel_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8808 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8816 } while ((state & ExitState) == 0);
8817 XSetCursorState(display,windows,MagickFalse);
8818 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8819 XCheckRefreshWindows(display,windows);
8820 if (apply_info.raised)
8821 return(MagickFalse);
8823 Save user preferences to the client configuration file.
8825 resource_info->backdrop=
8826 preferences_info[0].raised == MagickFalse ? MagickTrue : MagickFalse;
8827 resource_info->confirm_exit=
8828 preferences_info[1].raised == MagickFalse ? MagickTrue : MagickFalse;
8829 resource_info->confirm_edit=
8830 preferences_info[2].raised == MagickFalse ? MagickTrue : MagickFalse;
8831 resource_info->gamma_correct=
8832 preferences_info[3].raised == MagickFalse ? MagickTrue : MagickFalse;
8833 resource_info->display_warnings=
8834 preferences_info[4].raised == MagickFalse ? MagickTrue : MagickFalse;
8835 resource_info->quantize_info->dither=
8836 preferences_info[5].raised == MagickFalse ? MagickTrue : MagickFalse;
8837 resource_info->colormap=SharedColormap;
8838 if (preferences_info[6].raised)
8839 resource_info->colormap=PrivateColormap;
8840 resource_info->use_pixmap=
8841 preferences_info[7].raised == MagickFalse ? MagickTrue : MagickFalse;
8842 XUserPreferences(resource_info);
8847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8851 % X P r o g r e s s M o n i t o r W i d g e t %
8855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8857 % XProgressMonitorWidget() displays the progress a task is making in
8858 % completing a task. A span of zero toggles the active status. An inactive
8859 % state disables the progress monitor.
8861 % The format of the XProgressMonitorWidget method is:
8863 % void XProgressMonitorWidget(Display *display,XWindows *windows,
8864 % const char *task,const MagickOffsetType offset,
8865 % const MagickSizeType span)
8867 % A description of each parameter follows:
8869 % o display: Specifies a connection to an X server; returned from
8872 % o window: Specifies a pointer to a XWindows structure.
8874 % o task: Identifies the task in progress.
8876 % o offset: Specifies the offset position within the span which represents
8877 % how much progress has been made in completing a task.
8879 % o span: Specifies the span relative to completing a task.
8882 MagickExport void XProgressMonitorWidget(Display *display,XWindows *windows,
8883 const char *task,const MagickOffsetType offset,const MagickSizeType span)
8891 assert(display != (Display *) NULL);
8892 assert(windows != (XWindows *) NULL);
8893 assert(task != (const char *) NULL);
8894 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",task);
8898 Update image windows if there is a pending expose event.
8900 while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
8901 (void) XCommandWidget(display,windows,(const char **) NULL,&event);
8902 while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
8903 XRefreshWindow(display,&windows->image,&event);
8904 while (XCheckTypedWindowEvent(display,windows->info.id,Expose,&event))
8905 if (monitor_info.text != (char *) NULL)
8906 XInfoWidget(display,windows,monitor_info.text);
8908 Draw progress monitor bar to represent percent completion of a task.
8910 if ((windows->info.mapped == MagickFalse) || (task != monitor_info.text))
8911 XInfoWidget(display,windows,task);
8912 width=(unsigned int) (((offset+1)*(windows->info.width-
8913 (2*monitor_info.x)))/span);
8914 if (width < monitor_info.width)
8916 monitor_info.raised=MagickTrue;
8917 XDrawWidgetText(display,&windows->info,&monitor_info);
8918 monitor_info.raised=MagickFalse;
8920 monitor_info.width=width;
8921 XDrawWidgetText(display,&windows->info,&monitor_info);
8922 (void) XFlush(display);
8926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8930 % X T e x t V i e w W i d g e t %
8934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8936 % XTextViewWidget() displays text in a Text View widget.
8938 % The format of the XTextViewWidget method is:
8940 % void XTextViewWidget(Display *display,const XResourceInfo *resource_info,
8941 % XWindows *windows,const MagickBooleanType mono,const char *title,
8942 % const char **textlist)
8944 % A description of each parameter follows:
8946 % o display: Specifies a connection to an X server; returned from
8949 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8951 % o window: Specifies a pointer to a XWindows structure.
8953 % o mono: Use mono-spaced font when displaying text.
8955 % o title: This character string is displayed at the top of the widget
8958 % o textlist: This string list is displayed within the Text View widget.
8961 MagickExport void XTextViewWidget(Display *display,
8962 const XResourceInfo *resource_info,XWindows *windows,
8963 const MagickBooleanType mono,const char *title,const char **textlist)
8965 #define DismissButtonText "Dismiss"
8968 primary_selection[MaxTextExtent];
8973 static MagickStatusType
8974 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
9014 Convert text string to a text list.
9016 assert(display != (Display *) NULL);
9017 assert(resource_info != (XResourceInfo *) NULL);
9018 assert(windows != (XWindows *) NULL);
9019 assert(title != (const char *) NULL);
9020 assert(textlist != (const char **) NULL);
9021 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
9022 XSetCursorState(display,windows,MagickTrue);
9023 XCheckRefreshWindows(display,windows);
9024 if (textlist == (const char **) NULL)
9026 XNoticeWidget(display,windows,"No text to view:",(char *) NULL);
9030 Determine Text View widget attributes.
9032 font_info=windows->widget.font_info;
9033 text_info=(XFontStruct *) NULL;
9034 if (mono != MagickFalse)
9035 text_info=XBestFont(display,resource_info,MagickTrue);
9036 if (text_info == (XFontStruct *) NULL)
9037 text_info=windows->widget.font_info;
9039 for (i=0; textlist[i] != (char *) NULL; i++)
9040 if (WidgetTextWidth(text_info,(char *) textlist[i]) > text_width)
9041 text_width=(unsigned int) XTextWidth(text_info,(char *) textlist[i],
9042 MagickMin(Extent(textlist[i]),160));
9043 lines=(unsigned int) i;
9044 width=WidgetTextWidth(font_info,DismissButtonText);
9045 width+=QuantumMargin;
9046 height=(unsigned int) (text_info->ascent+text_info->descent);
9048 Position Text View widget.
9050 windows->widget.width=(unsigned int) (MagickMin((int) text_width,
9051 (int) MaxTextWidth)+5*QuantumMargin);
9052 windows->widget.min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
9053 if (windows->widget.width < windows->widget.min_width)
9054 windows->widget.width=windows->widget.min_width;
9055 windows->widget.height=(unsigned int) (MagickMin(MagickMax((int) lines,3),32)*
9056 height+((13*height) >> 1)+((9*QuantumMargin) >> 1));
9057 windows->widget.min_height=(unsigned int) (3*height+((13*height) >> 1)+((9*
9058 QuantumMargin) >> 1));
9059 if (windows->widget.height < windows->widget.min_height)
9060 windows->widget.height=windows->widget.min_height;
9061 XConstrainWindowPosition(display,&windows->widget);
9063 Map Text View widget.
9065 (void) CopyMagickString(windows->widget.name,title,MaxTextExtent);
9066 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
9067 if (status != False)
9069 XSetWMName(display,windows->widget.id,&window_name);
9070 XSetWMIconName(display,windows->widget.id,&window_name);
9071 (void) XFree((void *) window_name.value);
9073 window_changes.width=(int) windows->widget.width;
9074 window_changes.height=(int) windows->widget.height;
9075 window_changes.x=windows->widget.x;
9076 window_changes.y=windows->widget.y;
9077 (void) XReconfigureWMWindow(display,windows->widget.id,
9078 windows->widget.screen,(unsigned int) mask,&window_changes);
9079 (void) XMapRaised(display,windows->widget.id);
9080 windows->widget.mapped=MagickFalse;
9082 Respond to X events.
9084 XGetWidgetInfo((char *) NULL,&slider_info);
9085 XGetWidgetInfo((char *) NULL,&north_info);
9086 XGetWidgetInfo((char *) NULL,&south_info);
9087 XGetWidgetInfo((char *) NULL,&expose_info);
9089 delay=SuspendTime << 2;
9090 height=(unsigned int) (font_info->ascent+font_info->descent);
9091 state=UpdateConfigurationState;
9094 if (state & UpdateConfigurationState)
9100 Initialize button information.
9102 XGetWidgetInfo(DismissButtonText,&dismiss_info);
9103 dismiss_info.width=width;
9104 dismiss_info.height=(unsigned int) ((3*height) >> 1);
9105 dismiss_info.x=(int) windows->widget.width-dismiss_info.width-
9107 dismiss_info.y=(int) windows->widget.height-dismiss_info.height-
9110 Initialize scroll information.
9112 XGetWidgetInfo((char *) NULL,&scroll_info);
9113 scroll_info.bevel_width--;
9114 scroll_info.width=height;
9115 scroll_info.height=(unsigned int) (dismiss_info.y-((5*QuantumMargin) >>
9117 scroll_info.x=(int) windows->widget.width-QuantumMargin-
9119 scroll_info.y=(3*QuantumMargin) >> 1;
9120 scroll_info.raised=MagickFalse;
9121 scroll_info.trough=MagickTrue;
9122 north_info=scroll_info;
9123 north_info.raised=MagickTrue;
9124 north_info.width-=(north_info.bevel_width << 1);
9125 north_info.height=north_info.width-1;
9126 north_info.x+=north_info.bevel_width;
9127 north_info.y+=north_info.bevel_width;
9128 south_info=north_info;
9129 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
9132 slider_info=north_info;
9134 slider_info.width-=2;
9135 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
9136 slider_info.bevel_width+2;
9137 slider_info.height=scroll_info.height-((slider_info.min_y-
9138 scroll_info.y+1) << 1)+4;
9139 visible_lines=scroll_info.height/(text_info->ascent+text_info->descent+
9140 ((text_info->ascent+text_info->descent) >> 3));
9141 if (lines > visible_lines)
9142 slider_info.height=(unsigned int) (visible_lines*slider_info.height)/
9144 slider_info.max_y=south_info.y-south_info.bevel_width-
9145 slider_info.bevel_width-2;
9146 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
9147 slider_info.y=slider_info.min_y;
9148 expose_info=scroll_info;
9149 expose_info.y=slider_info.y;
9151 Initialize list information.
9153 XGetWidgetInfo((char *) NULL,&list_info);
9154 list_info.raised=MagickFalse;
9155 list_info.bevel_width--;
9156 list_info.width=(unsigned int) scroll_info.x-((3*QuantumMargin) >> 1);
9157 list_info.height=scroll_info.height;
9158 list_info.x=QuantumMargin;
9159 list_info.y=scroll_info.y;
9161 Initialize selection information.
9163 XGetWidgetInfo((char *) NULL,&selection_info);
9164 selection_info.center=MagickFalse;
9165 selection_info.width=list_info.width;
9166 selection_info.height=(unsigned int)
9167 (9*(text_info->ascent+text_info->descent)) >> 3;
9168 selection_info.x=list_info.x;
9169 state&=(~UpdateConfigurationState);
9171 if (state & RedrawWidgetState)
9174 Redraw Text View window.
9176 XDrawBeveledMatte(display,&windows->widget,&list_info);
9177 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
9178 XDrawTriangleNorth(display,&windows->widget,&north_info);
9179 XDrawBeveledButton(display,&windows->widget,&slider_info);
9180 XDrawTriangleSouth(display,&windows->widget,&south_info);
9181 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9182 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
9183 selection_info.id=(~0);
9184 state|=RedrawListState;
9185 state&=(~RedrawWidgetState);
9187 if (state & RedrawListState)
9190 Determine slider id and position.
9192 if (slider_info.id >= (int) (lines-visible_lines))
9193 slider_info.id=(int) lines-visible_lines;
9194 if ((slider_info.id < 0) || (lines <= visible_lines))
9196 slider_info.y=slider_info.min_y;
9199 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/lines;
9200 if (slider_info.id != selection_info.id)
9203 Redraw scroll bar and text.
9205 windows->widget.font_info=text_info;
9206 (void) XSetFont(display,windows->widget.annotate_context,
9208 (void) XSetFont(display,windows->widget.highlight_context,
9210 selection_info.id=slider_info.id;
9211 selection_info.y=list_info.y+(height >> 3)+2;
9212 for (i=0; i < (int) visible_lines; i++)
9214 selection_info.raised=
9215 (slider_info.id+i) != list_info.id ? MagickTrue : MagickFalse;
9216 selection_info.text=(char *) NULL;
9217 if ((slider_info.id+i) < (int) lines)
9218 selection_info.text=(char *) textlist[slider_info.id+i];
9219 XDrawWidgetText(display,&windows->widget,&selection_info);
9220 selection_info.y+=(int) selection_info.height;
9222 windows->widget.font_info=font_info;
9223 (void) XSetFont(display,windows->widget.annotate_context,
9225 (void) XSetFont(display,windows->widget.highlight_context,
9230 if (slider_info.y > expose_info.y)
9232 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
9233 expose_info.y=slider_info.y-expose_info.height-
9234 slider_info.bevel_width-1;
9238 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
9239 expose_info.y=slider_info.y+slider_info.height+
9240 slider_info.bevel_width+1;
9242 XDrawTriangleNorth(display,&windows->widget,&north_info);
9243 XDrawMatte(display,&windows->widget,&expose_info);
9244 XDrawBeveledButton(display,&windows->widget,&slider_info);
9245 XDrawTriangleSouth(display,&windows->widget,&south_info);
9246 expose_info.y=slider_info.y;
9248 state&=(~RedrawListState);
9251 Wait for next event.
9253 if (north_info.raised && south_info.raised)
9254 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
9258 Brief delay before advancing scroll bar.
9260 XDelay(display,delay);
9262 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
9263 if (north_info.raised == MagickFalse)
9264 if (slider_info.id > 0)
9270 state|=RedrawListState;
9272 if (south_info.raised == MagickFalse)
9273 if (slider_info.id < (int) lines)
9279 state|=RedrawListState;
9281 if (event.type != ButtonRelease)
9288 if (MatteIsActive(slider_info,event.xbutton))
9293 slider_info.active=MagickTrue;
9296 if (MatteIsActive(north_info,event.xbutton))
9297 if (slider_info.id > 0)
9302 north_info.raised=MagickFalse;
9304 state|=RedrawListState;
9307 if (MatteIsActive(south_info,event.xbutton))
9308 if (slider_info.id < (int) lines)
9313 south_info.raised=MagickFalse;
9315 state|=RedrawListState;
9318 if (MatteIsActive(scroll_info,event.xbutton))
9323 if (event.xbutton.y < slider_info.y)
9324 slider_info.id-=(visible_lines-1);
9326 slider_info.id+=(visible_lines-1);
9327 state|=RedrawListState;
9330 if (MatteIsActive(dismiss_info,event.xbutton))
9333 User pressed Dismiss button.
9335 dismiss_info.raised=MagickFalse;
9336 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9339 if (MatteIsActive(list_info,event.xbutton))
9348 User pressed list matte.
9350 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
9351 selection_info.height;
9352 if (id >= (int) lines)
9354 if (id != list_info.id)
9357 click_time=event.xbutton.time;
9361 if (event.xbutton.time >= (click_time+DoubleClick))
9363 click_time=event.xbutton.time;
9366 click_time=event.xbutton.time;
9368 Become the XA_PRIMARY selection owner.
9370 (void) CopyMagickString(primary_selection,textlist[list_info.id],
9372 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
9373 event.xbutton.time);
9374 if (XGetSelectionOwner(display,XA_PRIMARY) != windows->widget.id)
9376 selection_info.id=(~0);
9378 state|=RedrawListState;
9385 if (windows->widget.mapped == MagickFalse)
9387 if (north_info.raised == MagickFalse)
9390 User released up button.
9392 delay=SuspendTime << 2;
9393 north_info.raised=MagickTrue;
9394 XDrawTriangleNorth(display,&windows->widget,&north_info);
9396 if (south_info.raised == MagickFalse)
9399 User released down button.
9401 delay=SuspendTime << 2;
9402 south_info.raised=MagickTrue;
9403 XDrawTriangleSouth(display,&windows->widget,&south_info);
9405 if (slider_info.active)
9408 Stop tracking slider.
9410 slider_info.active=MagickFalse;
9413 if (dismiss_info.raised == MagickFalse)
9415 if (event.xbutton.window == windows->widget.id)
9416 if (MatteIsActive(dismiss_info,event.xbutton))
9418 dismiss_info.raised=MagickTrue;
9419 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9426 If client window delete message, exit.
9428 if (event.xclient.message_type != windows->wm_protocols)
9430 if (*event.xclient.data.l == (int) windows->wm_take_focus)
9432 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
9433 (Time) event.xclient.data.l[1]);
9436 if (*event.xclient.data.l != (int) windows->wm_delete_window)
9438 if (event.xclient.window == windows->widget.id)
9445 case ConfigureNotify:
9448 Update widget configuration.
9450 if (event.xconfigure.window != windows->widget.id)
9452 if ((event.xconfigure.width == (int) windows->widget.width) &&
9453 (event.xconfigure.height == (int) windows->widget.height))
9455 windows->widget.width=(unsigned int)
9456 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
9457 windows->widget.height=(unsigned int)
9458 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
9459 state|=UpdateConfigurationState;
9464 if (event.xcrossing.window != windows->widget.id)
9466 state&=(~InactiveWidgetState);
9471 if (event.xexpose.window != windows->widget.id)
9473 if (event.xexpose.count != 0)
9475 state|=RedrawWidgetState;
9481 command[MaxTextExtent];
9490 Respond to a user key press.
9492 if (event.xkey.window != windows->widget.id)
9494 length=XLookupString((XKeyEvent *) &event.xkey,command,
9495 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9496 *(command+length)='\0';
9497 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
9499 dismiss_info.raised=MagickFalse;
9500 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9504 if (AreaIsActive(scroll_info,event.xkey))
9509 switch ((int) key_symbol)
9532 slider_info.id-=visible_lines;
9538 slider_info.id+=visible_lines;
9544 slider_info.id=(int) lines;
9548 state|=RedrawListState;
9557 if (event.xcrossing.window != windows->widget.id)
9559 state|=InactiveWidgetState;
9571 Discard pending button motion events.
9573 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9574 if (slider_info.active)
9579 slider_info.y=event.xmotion.y-
9580 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
9581 if (slider_info.y < slider_info.min_y)
9582 slider_info.y=slider_info.min_y;
9583 if (slider_info.y > slider_info.max_y)
9584 slider_info.y=slider_info.max_y;
9586 if (slider_info.y != slider_info.min_y)
9587 slider_info.id=(int) (lines*(slider_info.y-slider_info.min_y+1))/
9588 (slider_info.max_y-slider_info.min_y+1);
9589 state|=RedrawListState;
9592 if (state & InactiveWidgetState)
9594 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
9597 Dismiss button status changed.
9599 dismiss_info.raised=
9600 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
9601 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9606 case SelectionClear:
9609 selection_info.id=(~0);
9610 state|=RedrawListState;
9613 case SelectionRequest:
9618 XSelectionRequestEvent
9621 if (list_info.id == (~0))
9624 Set primary selection.
9626 request=(&(event.xselectionrequest));
9627 (void) XChangeProperty(request->display,request->requestor,
9628 request->property,request->target,8,PropModeReplace,
9629 (unsigned char *) primary_selection,Extent(primary_selection));
9630 notify.type=SelectionNotify;
9631 notify.send_event=MagickTrue;
9632 notify.display=request->display;
9633 notify.requestor=request->requestor;
9634 notify.selection=request->selection;
9635 notify.target=request->target;
9636 notify.time=request->time;
9637 if (request->property == None)
9638 notify.property=request->target;
9640 notify.property=request->property;
9641 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
9642 (XEvent *) ¬ify);
9647 } while ((state & ExitState) == 0);
9648 if (text_info != windows->widget.font_info)
9649 (void) XFreeFont(display,text_info);
9650 XSetCursorState(display,windows,MagickFalse);
9651 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
9652 XCheckRefreshWindows(display,windows);