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 "MagickCore/studio.h"
44 #include "MagickCore/color.h"
45 #include "MagickCore/color-private.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/magick.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/PreRvIcccm.h"
52 #include "MagickCore/string_.h"
53 #include "MagickCore/token.h"
54 #include "MagickCore/utility.h"
55 #include "MagickCore/xwindow-private.h"
56 #include "MagickCore/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) FormatLocaleString(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-1))
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-1))
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 directory=getcwd(home_directory,MaxTextExtent);
4306 (void) CopyMagickString(working_path,home_directory,MaxTextExtent);
4307 filelist=ListFiles(working_path,glob_pattern,&files);
4308 if (filelist == (char **) NULL)
4311 Directory read failed.
4313 XNoticeWidget(display,windows,"Unable to read directory:",working_path);
4314 (void) XDialogWidget(display,windows,action,"Enter filename:",reply);
4318 Determine File Browser widget attributes.
4320 font_info=windows->widget.font_info;
4322 for (i=0; i < (ssize_t) files; i++)
4323 if (WidgetTextWidth(font_info,filelist[i]) > text_width)
4324 text_width=WidgetTextWidth(font_info,filelist[i]);
4325 width=WidgetTextWidth(font_info,(char *) action);
4326 if (WidgetTextWidth(font_info,GrabButtonText) > width)
4327 width=WidgetTextWidth(font_info,GrabButtonText);
4328 if (WidgetTextWidth(font_info,FormatButtonText) > width)
4329 width=WidgetTextWidth(font_info,FormatButtonText);
4330 if (WidgetTextWidth(font_info,CancelButtonText) > width)
4331 width=WidgetTextWidth(font_info,CancelButtonText);
4332 if (WidgetTextWidth(font_info,HomeButtonText) > width)
4333 width=WidgetTextWidth(font_info,HomeButtonText);
4334 if (WidgetTextWidth(font_info,UpButtonText) > width)
4335 width=WidgetTextWidth(font_info,UpButtonText);
4336 width+=QuantumMargin;
4337 if (WidgetTextWidth(font_info,DirectoryText) > width)
4338 width=WidgetTextWidth(font_info,DirectoryText);
4339 if (WidgetTextWidth(font_info,FilenameText) > width)
4340 width=WidgetTextWidth(font_info,FilenameText);
4341 height=(unsigned int) (font_info->ascent+font_info->descent);
4343 Position File Browser widget.
4345 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
4347 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
4348 if (windows->widget.width < windows->widget.min_width)
4349 windows->widget.width=windows->widget.min_width;
4350 windows->widget.height=(unsigned int)
4351 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
4352 windows->widget.min_height=(unsigned int)
4353 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
4354 if (windows->widget.height < windows->widget.min_height)
4355 windows->widget.height=windows->widget.min_height;
4356 XConstrainWindowPosition(display,&windows->widget);
4358 Map File Browser widget.
4360 (void) CopyMagickString(windows->widget.name,"Browse and Select a File",
4362 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
4363 if (status != False)
4365 XSetWMName(display,windows->widget.id,&window_name);
4366 XSetWMIconName(display,windows->widget.id,&window_name);
4367 (void) XFree((void *) window_name.value);
4369 window_changes.width=(int) windows->widget.width;
4370 window_changes.height=(int) windows->widget.height;
4371 window_changes.x=windows->widget.x;
4372 window_changes.y=windows->widget.y;
4373 (void) XReconfigureWMWindow(display,windows->widget.id,
4374 windows->widget.screen,mask,&window_changes);
4375 (void) XMapRaised(display,windows->widget.id);
4376 windows->widget.mapped=MagickFalse;
4378 Respond to X events.
4380 XGetWidgetInfo((char *) NULL,&slider_info);
4381 XGetWidgetInfo((char *) NULL,&north_info);
4382 XGetWidgetInfo((char *) NULL,&south_info);
4383 XGetWidgetInfo((char *) NULL,&expose_info);
4385 anomaly=(LocaleCompare(action,"Composite") == 0) ||
4386 (LocaleCompare(action,"Open") == 0) || (LocaleCompare(action,"Map") == 0);
4388 delay=SuspendTime << 2;
4389 state=UpdateConfigurationState;
4392 if (state & UpdateConfigurationState)
4398 Initialize button information.
4400 XGetWidgetInfo(CancelButtonText,&cancel_info);
4401 cancel_info.width=width;
4402 cancel_info.height=(unsigned int) ((3*height) >> 1);
4404 (windows->widget.width-cancel_info.width-QuantumMargin-2);
4406 (windows->widget.height-cancel_info.height-QuantumMargin);
4407 XGetWidgetInfo(action,&action_info);
4408 action_info.width=width;
4409 action_info.height=(unsigned int) ((3*height) >> 1);
4410 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
4411 (action_info.bevel_width << 1));
4412 action_info.y=cancel_info.y;
4413 XGetWidgetInfo(GrabButtonText,&special_info);
4414 special_info.width=width;
4415 special_info.height=(unsigned int) ((3*height) >> 1);
4416 special_info.x=action_info.x-(action_info.width+(QuantumMargin >> 1)+
4417 (special_info.bevel_width << 1));
4418 special_info.y=action_info.y;
4419 if (anomaly == MagickFalse)
4424 special_info.text=(char *) FormatButtonText;
4425 p=reply+Extent(reply)-1;
4426 while ((p > (reply+1)) && (*(p-1) != '.'))
4428 if ((p > (reply+1)) && (*(p-1) == '.'))
4429 (void) CopyMagickString(format,p,MaxTextExtent);
4431 XGetWidgetInfo(UpButtonText,&up_info);
4432 up_info.width=width;
4433 up_info.height=(unsigned int) ((3*height) >> 1);
4434 up_info.x=QuantumMargin;
4435 up_info.y=((5*QuantumMargin) >> 1)+height;
4436 XGetWidgetInfo(HomeButtonText,&home_info);
4437 home_info.width=width;
4438 home_info.height=(unsigned int) ((3*height) >> 1);
4439 home_info.x=QuantumMargin;
4440 home_info.y=up_info.y+up_info.height+QuantumMargin;
4442 Initialize reply information.
4444 XGetWidgetInfo(reply,&reply_info);
4445 reply_info.raised=MagickFalse;
4446 reply_info.bevel_width--;
4447 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
4448 reply_info.height=height << 1;
4449 reply_info.x=(int) (width+(QuantumMargin << 1));
4450 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
4452 Initialize scroll information.
4454 XGetWidgetInfo((char *) NULL,&scroll_info);
4455 scroll_info.bevel_width--;
4456 scroll_info.width=height;
4457 scroll_info.height=(unsigned int)
4458 (reply_info.y-up_info.y-(QuantumMargin >> 1));
4459 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
4460 scroll_info.y=up_info.y-reply_info.bevel_width;
4461 scroll_info.raised=MagickFalse;
4462 scroll_info.trough=MagickTrue;
4463 north_info=scroll_info;
4464 north_info.raised=MagickTrue;
4465 north_info.width-=(north_info.bevel_width << 1);
4466 north_info.height=north_info.width-1;
4467 north_info.x+=north_info.bevel_width;
4468 north_info.y+=north_info.bevel_width;
4469 south_info=north_info;
4470 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
4473 slider_info=north_info;
4475 slider_info.width-=2;
4476 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
4477 slider_info.bevel_width+2;
4478 slider_info.height=scroll_info.height-((slider_info.min_y-
4479 scroll_info.y+1) << 1)+4;
4480 visible_files=scroll_info.height/(height+(height >> 3));
4481 if (files > visible_files)
4482 slider_info.height=(unsigned int)
4483 ((visible_files*slider_info.height)/files);
4484 slider_info.max_y=south_info.y-south_info.bevel_width-
4485 slider_info.bevel_width-2;
4486 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
4487 slider_info.y=slider_info.min_y;
4488 expose_info=scroll_info;
4489 expose_info.y=slider_info.y;
4491 Initialize list information.
4493 XGetWidgetInfo((char *) NULL,&list_info);
4494 list_info.raised=MagickFalse;
4495 list_info.bevel_width--;
4496 list_info.width=(unsigned int)
4497 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
4498 list_info.height=scroll_info.height;
4499 list_info.x=reply_info.x;
4500 list_info.y=scroll_info.y;
4501 if (windows->widget.mapped == MagickFalse)
4502 state|=JumpListState;
4504 Initialize text information.
4507 XGetWidgetInfo(text,&text_info);
4508 text_info.center=MagickFalse;
4509 text_info.width=reply_info.width;
4510 text_info.height=height;
4511 text_info.x=list_info.x-(QuantumMargin >> 1);
4512 text_info.y=QuantumMargin;
4514 Initialize selection information.
4516 XGetWidgetInfo((char *) NULL,&selection_info);
4517 selection_info.center=MagickFalse;
4518 selection_info.width=list_info.width;
4519 selection_info.height=(unsigned int) ((9*height) >> 3);
4520 selection_info.x=list_info.x;
4521 state&=(~UpdateConfigurationState);
4523 if (state & RedrawWidgetState)
4526 Redraw File Browser window.
4529 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
4530 (void) XDrawString(display,windows->widget.id,
4531 windows->widget.annotate_context,x,y,DirectoryText,
4532 Extent(DirectoryText));
4533 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4534 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4536 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4538 XDrawWidgetText(display,&windows->widget,&text_info);
4539 XDrawBeveledButton(display,&windows->widget,&up_info);
4540 XDrawBeveledButton(display,&windows->widget,&home_info);
4541 XDrawBeveledMatte(display,&windows->widget,&list_info);
4542 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4543 XDrawTriangleNorth(display,&windows->widget,&north_info);
4544 XDrawBeveledButton(display,&windows->widget,&slider_info);
4545 XDrawTriangleSouth(display,&windows->widget,&south_info);
4547 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
4548 (void) XDrawString(display,windows->widget.id,
4549 windows->widget.annotate_context,x,y,FilenameText,
4550 Extent(FilenameText));
4551 XDrawBeveledMatte(display,&windows->widget,&reply_info);
4552 XDrawMatteText(display,&windows->widget,&reply_info);
4553 XDrawBeveledButton(display,&windows->widget,&special_info);
4554 XDrawBeveledButton(display,&windows->widget,&action_info);
4555 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4556 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4557 selection_info.id=(~0);
4558 state|=RedrawListState;
4559 state&=(~RedrawWidgetState);
4561 if (state & UpdateListState)
4572 checklist=ListFiles(working_path,glob_pattern,&number_files);
4573 if (checklist == (char **) NULL)
4576 Reply is a filename, exit.
4578 action_info.raised=MagickFalse;
4579 XDrawBeveledButton(display,&windows->widget,&action_info);
4582 for (i=0; i < (ssize_t) files; i++)
4583 filelist[i]=DestroyString(filelist[i]);
4584 if (filelist != (char **) NULL)
4585 filelist=(char **) RelinquishMagickMemory(filelist);
4592 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
4593 if (files > visible_files)
4594 slider_info.height=(unsigned int)
4595 ((visible_files*slider_info.height)/files);
4596 slider_info.max_y=south_info.y-south_info.bevel_width-
4597 slider_info.bevel_width-2;
4599 slider_info.y=slider_info.min_y;
4600 expose_info.y=slider_info.y;
4601 selection_info.id=(~0);
4603 state|=RedrawListState;
4605 Redraw directory name & reply.
4607 if (IsGlob(reply_info.text) == MagickFalse)
4609 *reply_info.text='\0';
4610 reply_info.cursor=reply_info.text;
4612 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4613 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4615 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4617 XDrawWidgetText(display,&windows->widget,&text_info);
4618 XDrawMatteText(display,&windows->widget,&reply_info);
4619 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4620 XDrawTriangleNorth(display,&windows->widget,&north_info);
4621 XDrawBeveledButton(display,&windows->widget,&slider_info);
4622 XDrawTriangleSouth(display,&windows->widget,&south_info);
4623 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4624 state&=(~UpdateListState);
4626 if (state & JumpListState)
4629 Jump scroll to match user filename.
4632 for (i=0; i < (ssize_t) files; i++)
4633 if (LocaleCompare(filelist[i],reply) >= 0)
4636 (LocaleCompare(filelist[i],reply) == 0 ? i : ~0);
4639 if ((i < (ssize_t) slider_info.id) ||
4640 (i >= (ssize_t) (slider_info.id+visible_files)))
4641 slider_info.id=(int) i-(visible_files >> 1);
4642 selection_info.id=(~0);
4643 state|=RedrawListState;
4644 state&=(~JumpListState);
4646 if (state & RedrawListState)
4649 Determine slider id and position.
4651 if (slider_info.id >= (int) (files-visible_files))
4652 slider_info.id=(int) (files-visible_files);
4653 if ((slider_info.id < 0) || (files <= visible_files))
4655 slider_info.y=slider_info.min_y;
4657 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
4658 slider_info.min_y+1)/files);
4659 if (slider_info.id != selection_info.id)
4662 Redraw scroll bar and file names.
4664 selection_info.id=slider_info.id;
4665 selection_info.y=list_info.y+(height >> 3)+2;
4666 for (i=0; i < (ssize_t) visible_files; i++)
4668 selection_info.raised=(int) (slider_info.id+i) != list_info.id ?
4669 MagickTrue : MagickFalse;
4670 selection_info.text=(char *) NULL;
4671 if ((slider_info.id+i) < (ssize_t) files)
4672 selection_info.text=filelist[slider_info.id+i];
4673 XDrawWidgetText(display,&windows->widget,&selection_info);
4674 selection_info.y+=(int) selection_info.height;
4679 if (slider_info.y > expose_info.y)
4681 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
4682 expose_info.y=slider_info.y-expose_info.height-
4683 slider_info.bevel_width-1;
4687 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
4688 expose_info.y=slider_info.y+slider_info.height+
4689 slider_info.bevel_width+1;
4691 XDrawTriangleNorth(display,&windows->widget,&north_info);
4692 XDrawMatte(display,&windows->widget,&expose_info);
4693 XDrawBeveledButton(display,&windows->widget,&slider_info);
4694 XDrawTriangleSouth(display,&windows->widget,&south_info);
4695 expose_info.y=slider_info.y;
4697 state&=(~RedrawListState);
4700 Wait for next event.
4702 if (north_info.raised && south_info.raised)
4703 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
4707 Brief delay before advancing scroll bar.
4709 XDelay(display,delay);
4711 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
4712 if (north_info.raised == MagickFalse)
4713 if (slider_info.id > 0)
4719 state|=RedrawListState;
4721 if (south_info.raised == MagickFalse)
4722 if (slider_info.id < (int) files)
4728 state|=RedrawListState;
4730 if (event.type != ButtonRelease)
4737 if (MatteIsActive(slider_info,event.xbutton))
4742 slider_info.active=MagickTrue;
4745 if (MatteIsActive(north_info,event.xbutton))
4746 if (slider_info.id > 0)
4751 north_info.raised=MagickFalse;
4753 state|=RedrawListState;
4756 if (MatteIsActive(south_info,event.xbutton))
4757 if (slider_info.id < (int) files)
4762 south_info.raised=MagickFalse;
4764 state|=RedrawListState;
4767 if (MatteIsActive(scroll_info,event.xbutton))
4772 if (event.xbutton.y < slider_info.y)
4773 slider_info.id-=(visible_files-1);
4775 slider_info.id+=(visible_files-1);
4776 state|=RedrawListState;
4779 if (MatteIsActive(list_info,event.xbutton))
4785 User pressed file matte.
4787 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
4788 selection_info.height;
4789 if (id >= (int) files)
4791 (void) CopyMagickString(reply_info.text,filelist[id],MaxTextExtent);
4792 reply_info.highlight=MagickFalse;
4793 reply_info.marker=reply_info.text;
4794 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4795 XDrawMatteText(display,&windows->widget,&reply_info);
4796 if (id == list_info.id)
4801 p=reply_info.text+strlen(reply_info.text)-1;
4802 if (*p == *DirectorySeparator)
4803 ChopPathComponents(reply_info.text,1);
4804 (void) ConcatenateMagickString(working_path,DirectorySeparator,
4806 (void) ConcatenateMagickString(working_path,reply_info.text,
4809 state|=UpdateListState;
4811 selection_info.id=(~0);
4813 state|=RedrawListState;
4816 if (MatteIsActive(up_info,event.xbutton))
4819 User pressed Up button.
4821 up_info.raised=MagickFalse;
4822 XDrawBeveledButton(display,&windows->widget,&up_info);
4825 if (MatteIsActive(home_info,event.xbutton))
4828 User pressed Home button.
4830 home_info.raised=MagickFalse;
4831 XDrawBeveledButton(display,&windows->widget,&home_info);
4834 if (MatteIsActive(special_info,event.xbutton))
4837 User pressed Special button.
4839 special_info.raised=MagickFalse;
4840 XDrawBeveledButton(display,&windows->widget,&special_info);
4843 if (MatteIsActive(action_info,event.xbutton))
4846 User pressed action button.
4848 action_info.raised=MagickFalse;
4849 XDrawBeveledButton(display,&windows->widget,&action_info);
4852 if (MatteIsActive(cancel_info,event.xbutton))
4855 User pressed Cancel button.
4857 cancel_info.raised=MagickFalse;
4858 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4861 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
4863 if (event.xbutton.button != Button2)
4869 Move text cursor to position of button press.
4871 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
4872 for (i=1; i <= (ssize_t) Extent(reply_info.marker); i++)
4873 if (XTextWidth(font_info,reply_info.marker,(int) i) > x)
4875 reply_info.cursor=reply_info.marker+i-1;
4876 if (event.xbutton.time > (click_time+DoubleClick))
4877 reply_info.highlight=MagickFalse;
4881 Become the XA_PRIMARY selection owner.
4883 (void) CopyMagickString(primary_selection,reply_info.text,
4885 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
4886 event.xbutton.time);
4887 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
4888 windows->widget.id ? MagickTrue : MagickFalse;
4890 XDrawMatteText(display,&windows->widget,&reply_info);
4891 click_time=event.xbutton.time;
4895 Request primary selection.
4897 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
4898 windows->widget.id,event.xbutton.time);
4903 if (windows->widget.mapped == MagickFalse)
4905 if (north_info.raised == MagickFalse)
4908 User released up button.
4910 delay=SuspendTime << 2;
4911 north_info.raised=MagickTrue;
4912 XDrawTriangleNorth(display,&windows->widget,&north_info);
4914 if (south_info.raised == MagickFalse)
4917 User released down button.
4919 delay=SuspendTime << 2;
4920 south_info.raised=MagickTrue;
4921 XDrawTriangleSouth(display,&windows->widget,&south_info);
4923 if (slider_info.active)
4926 Stop tracking slider.
4928 slider_info.active=MagickFalse;
4931 if (up_info.raised == MagickFalse)
4933 if (event.xbutton.window == windows->widget.id)
4934 if (MatteIsActive(up_info,event.xbutton))
4936 ChopPathComponents(working_path,1);
4937 if (*working_path == '\0')
4938 (void) CopyMagickString(working_path,DirectorySeparator,
4940 state|=UpdateListState;
4942 up_info.raised=MagickTrue;
4943 XDrawBeveledButton(display,&windows->widget,&up_info);
4945 if (home_info.raised == MagickFalse)
4947 if (event.xbutton.window == windows->widget.id)
4948 if (MatteIsActive(home_info,event.xbutton))
4950 (void) CopyMagickString(working_path,home_directory,
4952 state|=UpdateListState;
4954 home_info.raised=MagickTrue;
4955 XDrawBeveledButton(display,&windows->widget,&home_info);
4957 if (special_info.raised == MagickFalse)
4959 if (anomaly == MagickFalse)
4971 Let user select image format.
4973 exception=AcquireExceptionInfo();
4974 formats=GetMagickList("*",&number_formats,exception);
4975 exception=DestroyExceptionInfo(exception);
4976 (void) XCheckDefineCursor(display,windows->widget.id,
4977 windows->widget.busy_cursor);
4978 windows->popup.x=windows->widget.x+60;
4979 windows->popup.y=windows->widget.y+60;
4980 XListBrowserWidget(display,windows,&windows->popup,
4981 (const char **) formats,"Select","Select image format type:",
4983 XSetCursorState(display,windows,MagickTrue);
4984 (void) XCheckDefineCursor(display,windows->widget.id,
4985 windows->widget.cursor);
4986 LocaleLower(format);
4987 AppendImageFormat(format,reply_info.text);
4988 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4989 XDrawMatteText(display,&windows->widget,&reply_info);
4990 special_info.raised=MagickTrue;
4991 XDrawBeveledButton(display,&windows->widget,&special_info);
4992 for (i=0; i < (ssize_t) number_formats; i++)
4993 formats[i]=DestroyString(formats[i]);
4994 formats=(char **) RelinquishMagickMemory(formats);
4997 if (event.xbutton.window == windows->widget.id)
4998 if (MatteIsActive(special_info,event.xbutton))
5000 (void) CopyMagickString(working_path,"x:",MaxTextExtent);
5003 special_info.raised=MagickTrue;
5004 XDrawBeveledButton(display,&windows->widget,&special_info);
5006 if (action_info.raised == MagickFalse)
5008 if (event.xbutton.window == windows->widget.id)
5010 if (MatteIsActive(action_info,event.xbutton))
5012 if (*reply_info.text == '\0')
5013 (void) XBell(display,0);
5018 action_info.raised=MagickTrue;
5019 XDrawBeveledButton(display,&windows->widget,&action_info);
5021 if (cancel_info.raised == MagickFalse)
5023 if (event.xbutton.window == windows->widget.id)
5024 if (MatteIsActive(cancel_info,event.xbutton))
5026 *reply_info.text='\0';
5030 cancel_info.raised=MagickTrue;
5031 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5038 If client window delete message, exit.
5040 if (event.xclient.message_type != windows->wm_protocols)
5042 if (*event.xclient.data.l == (int) windows->wm_take_focus)
5044 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
5045 (Time) event.xclient.data.l[1]);
5048 if (*event.xclient.data.l != (int) windows->wm_delete_window)
5050 if (event.xclient.window == windows->widget.id)
5052 *reply_info.text='\0';
5058 case ConfigureNotify:
5061 Update widget configuration.
5063 if (event.xconfigure.window != windows->widget.id)
5065 if ((event.xconfigure.width == (int) windows->widget.width) &&
5066 (event.xconfigure.height == (int) windows->widget.height))
5068 windows->widget.width=(unsigned int)
5069 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
5070 windows->widget.height=(unsigned int)
5071 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
5072 state|=UpdateConfigurationState;
5077 if (event.xcrossing.window != windows->widget.id)
5079 state&=(~InactiveWidgetState);
5084 if (event.xexpose.window != windows->widget.id)
5086 if (event.xexpose.count != 0)
5088 state|=RedrawWidgetState;
5094 command[MaxTextExtent];
5103 Respond to a user key press.
5105 if (event.xkey.window != windows->widget.id)
5107 length=XLookupString((XKeyEvent *) &event.xkey,command,
5108 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5109 *(command+length)='\0';
5110 if (AreaIsActive(scroll_info,event.xkey))
5115 switch ((int) key_symbol)
5138 slider_info.id-=visible_files;
5144 slider_info.id+=visible_files;
5150 slider_info.id=(int) files;
5154 state|=RedrawListState;
5157 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
5160 Read new directory or glob patterm.
5162 if (*reply_info.text == '\0')
5164 if (IsGlob(reply_info.text))
5165 (void) CopyMagickString(glob_pattern,reply_info.text,
5169 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5171 (void) ConcatenateMagickString(working_path,reply_info.text,
5173 if (*working_path == '~')
5174 ExpandFilename(working_path);
5177 state|=UpdateListState;
5180 if (key_symbol == XK_Control_L)
5182 state|=ControlState;
5185 if (state & ControlState)
5186 switch ((int) key_symbol)
5192 Erase the entire line of text.
5194 *reply_info.text='\0';
5195 reply_info.cursor=reply_info.text;
5196 reply_info.marker=reply_info.text;
5197 reply_info.highlight=MagickFalse;
5203 XEditText(display,&reply_info,key_symbol,command,state);
5204 XDrawMatteText(display,&windows->widget,&reply_info);
5205 state|=JumpListState;
5211 command[MaxTextExtent];
5217 Respond to a user key release.
5219 if (event.xkey.window != windows->widget.id)
5221 (void) XLookupString((XKeyEvent *) &event.xkey,command,
5222 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5223 if (key_symbol == XK_Control_L)
5224 state&=(~ControlState);
5229 if (event.xcrossing.window != windows->widget.id)
5231 state|=InactiveWidgetState;
5243 Discard pending button motion events.
5245 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
5246 if (slider_info.active)
5251 slider_info.y=event.xmotion.y-
5252 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
5253 if (slider_info.y < slider_info.min_y)
5254 slider_info.y=slider_info.min_y;
5255 if (slider_info.y > slider_info.max_y)
5256 slider_info.y=slider_info.max_y;
5258 if (slider_info.y != slider_info.min_y)
5259 slider_info.id=(int) ((files*(slider_info.y-slider_info.min_y+1))/
5260 (slider_info.max_y-slider_info.min_y+1));
5261 state|=RedrawListState;
5264 if (state & InactiveWidgetState)
5266 if (up_info.raised == MatteIsActive(up_info,event.xmotion))
5269 Up button status changed.
5271 up_info.raised=!up_info.raised;
5272 XDrawBeveledButton(display,&windows->widget,&up_info);
5275 if (home_info.raised == MatteIsActive(home_info,event.xmotion))
5278 Home button status changed.
5280 home_info.raised=!home_info.raised;
5281 XDrawBeveledButton(display,&windows->widget,&home_info);
5284 if (special_info.raised == MatteIsActive(special_info,event.xmotion))
5287 Grab button status changed.
5289 special_info.raised=!special_info.raised;
5290 XDrawBeveledButton(display,&windows->widget,&special_info);
5293 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
5296 Action button status changed.
5298 action_info.raised=action_info.raised == MagickFalse ?
5299 MagickTrue : MagickFalse;
5300 XDrawBeveledButton(display,&windows->widget,&action_info);
5303 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
5306 Cancel button status changed.
5308 cancel_info.raised=cancel_info.raised == MagickFalse ?
5309 MagickTrue : MagickFalse;
5310 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5315 case SelectionClear:
5317 reply_info.highlight=MagickFalse;
5318 XDrawMatteText(display,&windows->widget,&reply_info);
5321 case SelectionNotify:
5337 Obtain response from primary selection.
5339 if (event.xselection.property == (Atom) None)
5341 status=XGetWindowProperty(display,event.xselection.requestor,
5342 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
5343 &format,&length,&after,&data);
5344 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
5347 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
5348 (void) XBell(display,0);
5352 Insert primary selection in reply text.
5354 *(data+length)='\0';
5355 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
5357 XDrawMatteText(display,&windows->widget,&reply_info);
5358 state|=JumpListState;
5359 state|=RedrawActionState;
5361 (void) XFree((void *) data);
5364 case SelectionRequest:
5369 XSelectionRequestEvent
5372 if (reply_info.highlight == MagickFalse)
5375 Set primary selection.
5377 request=(&(event.xselectionrequest));
5378 (void) XChangeProperty(request->display,request->requestor,
5379 request->property,request->target,8,PropModeReplace,
5380 (unsigned char *) primary_selection,Extent(primary_selection));
5381 notify.type=SelectionNotify;
5382 notify.display=request->display;
5383 notify.requestor=request->requestor;
5384 notify.selection=request->selection;
5385 notify.target=request->target;
5386 notify.time=request->time;
5387 if (request->property == None)
5388 notify.property=request->target;
5390 notify.property=request->property;
5391 (void) XSendEvent(request->display,request->requestor,False,0,
5392 (XEvent *) ¬ify);
5397 } while ((state & ExitState) == 0);
5398 XSetCursorState(display,windows,MagickFalse);
5399 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
5400 XCheckRefreshWindows(display,windows);
5404 for (i=0; i < (ssize_t) files; i++)
5405 filelist[i]=DestroyString(filelist[i]);
5406 if (filelist != (char **) NULL)
5407 filelist=(char **) RelinquishMagickMemory(filelist);
5410 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5412 (void) ConcatenateMagickString(working_path,reply,MaxTextExtent);
5414 (void) CopyMagickString(reply,working_path,MaxTextExtent);
5416 ExpandFilename(reply);
5420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5424 % X F o n t B r o w s e r W i d g e t %
5428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5430 % XFontBrowserWidget() displays a Font Browser widget with a font query to the
5431 % user. The user keys a reply and presses the Action or Cancel button to
5432 % exit. The typed text is returned as the reply function parameter.
5434 % The format of the XFontBrowserWidget method is:
5436 % void XFontBrowserWidget(Display *display,XWindows *windows,
5437 % const char *action,char *reply)
5439 % A description of each parameter follows:
5441 % o display: Specifies a connection to an X server; returned from
5444 % o window: Specifies a pointer to a XWindows structure.
5446 % o action: Specifies a pointer to the action of this widget.
5448 % o reply: the response from the user is returned in this parameter.
5453 #if defined(__cplusplus) || defined(c_plusplus)
5457 static int FontCompare(const void *x,const void *y)
5463 p=(char *) *((char **) x);
5464 q=(char *) *((char **) y);
5465 while ((*p != '\0') && (*q != '\0') && (*p == *q))
5473 #if defined(__cplusplus) || defined(c_plusplus)
5477 MagickExport void XFontBrowserWidget(Display *display,XWindows *windows,
5478 const char *action,char *reply)
5480 #define BackButtonText "Back"
5481 #define CancelButtonText "Cancel"
5482 #define FontnameText "Name:"
5483 #define FontPatternText "Pattern:"
5484 #define ResetButtonText "Reset"
5487 back_pattern[MaxTextExtent],
5490 primary_selection[MaxTextExtent],
5491 reset_pattern[MaxTextExtent],
5492 text[MaxTextExtent];
5503 glob_pattern[MaxTextExtent] = "*";
5505 static MagickStatusType
5506 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
5550 Get font list and sort in ascending order.
5552 assert(display != (Display *) NULL);
5553 assert(windows != (XWindows *) NULL);
5554 assert(action != (char *) NULL);
5555 assert(reply != (char *) NULL);
5556 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
5557 XSetCursorState(display,windows,MagickTrue);
5558 XCheckRefreshWindows(display,windows);
5559 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
5560 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
5561 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5565 Pattern failed, obtain all the fonts.
5567 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5569 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
5570 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5571 if (fontlist == (char **) NULL)
5573 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5579 Sort font list in ascending order.
5582 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,sizeof(*fontlist));
5583 if (fontlist == (char **) NULL)
5585 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5586 "UnableToViewFonts");
5589 for (i=0; i < fonts; i++)
5590 fontlist[i]=listhead[i];
5591 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5593 Determine Font Browser widget attributes.
5595 font_info=windows->widget.font_info;
5597 for (i=0; i < fonts; i++)
5598 if (WidgetTextWidth(font_info,fontlist[i]) > text_width)
5599 text_width=WidgetTextWidth(font_info,fontlist[i]);
5600 width=WidgetTextWidth(font_info,(char *) action);
5601 if (WidgetTextWidth(font_info,CancelButtonText) > width)
5602 width=WidgetTextWidth(font_info,CancelButtonText);
5603 if (WidgetTextWidth(font_info,ResetButtonText) > width)
5604 width=WidgetTextWidth(font_info,ResetButtonText);
5605 if (WidgetTextWidth(font_info,BackButtonText) > width)
5606 width=WidgetTextWidth(font_info,BackButtonText);
5607 width+=QuantumMargin;
5608 if (WidgetTextWidth(font_info,FontPatternText) > width)
5609 width=WidgetTextWidth(font_info,FontPatternText);
5610 if (WidgetTextWidth(font_info,FontnameText) > width)
5611 width=WidgetTextWidth(font_info,FontnameText);
5612 height=(unsigned int) (font_info->ascent+font_info->descent);
5614 Position Font Browser widget.
5616 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
5618 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
5619 if (windows->widget.width < windows->widget.min_width)
5620 windows->widget.width=windows->widget.min_width;
5621 windows->widget.height=(unsigned int)
5622 (((85*height) >> 2)+((13*QuantumMargin) >> 1)+4);
5623 windows->widget.min_height=(unsigned int)
5624 (((27*height) >> 1)+((13*QuantumMargin) >> 1)+4);
5625 if (windows->widget.height < windows->widget.min_height)
5626 windows->widget.height=windows->widget.min_height;
5627 XConstrainWindowPosition(display,&windows->widget);
5629 Map Font Browser widget.
5631 (void) CopyMagickString(windows->widget.name,"Browse and Select a Font",
5633 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
5634 if (status != False)
5636 XSetWMName(display,windows->widget.id,&window_name);
5637 XSetWMIconName(display,windows->widget.id,&window_name);
5638 (void) XFree((void *) window_name.value);
5640 window_changes.width=(int) windows->widget.width;
5641 window_changes.height=(int) windows->widget.height;
5642 window_changes.x=windows->widget.x;
5643 window_changes.y=windows->widget.y;
5644 (void) XReconfigureWMWindow(display,windows->widget.id,
5645 windows->widget.screen,mask,&window_changes);
5646 (void) XMapRaised(display,windows->widget.id);
5647 windows->widget.mapped=MagickFalse;
5649 Respond to X events.
5651 XGetWidgetInfo((char *) NULL,&slider_info);
5652 XGetWidgetInfo((char *) NULL,&north_info);
5653 XGetWidgetInfo((char *) NULL,&south_info);
5654 XGetWidgetInfo((char *) NULL,&expose_info);
5656 delay=SuspendTime << 2;
5657 state=UpdateConfigurationState;
5660 if (state & UpdateConfigurationState)
5666 Initialize button information.
5668 XGetWidgetInfo(CancelButtonText,&cancel_info);
5669 cancel_info.width=width;
5670 cancel_info.height=(unsigned int) ((3*height) >> 1);
5672 (windows->widget.width-cancel_info.width-QuantumMargin-2);
5674 (windows->widget.height-cancel_info.height-QuantumMargin);
5675 XGetWidgetInfo(action,&action_info);
5676 action_info.width=width;
5677 action_info.height=(unsigned int) ((3*height) >> 1);
5678 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
5679 (action_info.bevel_width << 1));
5680 action_info.y=cancel_info.y;
5681 XGetWidgetInfo(BackButtonText,&back_info);
5682 back_info.width=width;
5683 back_info.height=(unsigned int) ((3*height) >> 1);
5684 back_info.x=QuantumMargin;
5685 back_info.y=((5*QuantumMargin) >> 1)+height;
5686 XGetWidgetInfo(ResetButtonText,&reset_info);
5687 reset_info.width=width;
5688 reset_info.height=(unsigned int) ((3*height) >> 1);
5689 reset_info.x=QuantumMargin;
5690 reset_info.y=back_info.y+back_info.height+QuantumMargin;
5692 Initialize reply information.
5694 XGetWidgetInfo(reply,&reply_info);
5695 reply_info.raised=MagickFalse;
5696 reply_info.bevel_width--;
5697 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
5698 reply_info.height=height << 1;
5699 reply_info.x=(int) (width+(QuantumMargin << 1));
5700 reply_info.y=action_info.y-(action_info.height << 1)-QuantumMargin;
5702 Initialize mode information.
5704 XGetWidgetInfo(reply,&mode_info);
5705 mode_info.bevel_width=0;
5706 mode_info.width=(unsigned int)
5707 (action_info.x-reply_info.x-QuantumMargin);
5708 mode_info.height=action_info.height << 1;
5709 mode_info.x=reply_info.x;
5710 mode_info.y=action_info.y-action_info.height+action_info.bevel_width;
5712 Initialize scroll information.
5714 XGetWidgetInfo((char *) NULL,&scroll_info);
5715 scroll_info.bevel_width--;
5716 scroll_info.width=height;
5717 scroll_info.height=(unsigned int)
5718 (reply_info.y-back_info.y-(QuantumMargin >> 1));
5719 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
5720 scroll_info.y=back_info.y-reply_info.bevel_width;
5721 scroll_info.raised=MagickFalse;
5722 scroll_info.trough=MagickTrue;
5723 north_info=scroll_info;
5724 north_info.raised=MagickTrue;
5725 north_info.width-=(north_info.bevel_width << 1);
5726 north_info.height=north_info.width-1;
5727 north_info.x+=north_info.bevel_width;
5728 north_info.y+=north_info.bevel_width;
5729 south_info=north_info;
5730 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
5733 slider_info=north_info;
5735 slider_info.width-=2;
5736 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
5737 slider_info.bevel_width+2;
5738 slider_info.height=scroll_info.height-((slider_info.min_y-
5739 scroll_info.y+1) << 1)+4;
5740 visible_fonts=scroll_info.height/(height+(height >> 3));
5741 if (fonts > (int) visible_fonts)
5742 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5743 slider_info.max_y=south_info.y-south_info.bevel_width-
5744 slider_info.bevel_width-2;
5745 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
5746 slider_info.y=slider_info.min_y;
5747 expose_info=scroll_info;
5748 expose_info.y=slider_info.y;
5750 Initialize list information.
5752 XGetWidgetInfo((char *) NULL,&list_info);
5753 list_info.raised=MagickFalse;
5754 list_info.bevel_width--;
5755 list_info.width=(unsigned int)
5756 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
5757 list_info.height=scroll_info.height;
5758 list_info.x=reply_info.x;
5759 list_info.y=scroll_info.y;
5760 if (windows->widget.mapped == MagickFalse)
5761 state|=JumpListState;
5763 Initialize text information.
5766 XGetWidgetInfo(text,&text_info);
5767 text_info.center=MagickFalse;
5768 text_info.width=reply_info.width;
5769 text_info.height=height;
5770 text_info.x=list_info.x-(QuantumMargin >> 1);
5771 text_info.y=QuantumMargin;
5773 Initialize selection information.
5775 XGetWidgetInfo((char *) NULL,&selection_info);
5776 selection_info.center=MagickFalse;
5777 selection_info.width=list_info.width;
5778 selection_info.height=(unsigned int) ((9*height) >> 3);
5779 selection_info.x=list_info.x;
5780 state&=(~UpdateConfigurationState);
5782 if (state & RedrawWidgetState)
5785 Redraw Font Browser window.
5788 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
5789 (void) XDrawString(display,windows->widget.id,
5790 windows->widget.annotate_context,x,y,FontPatternText,
5791 Extent(FontPatternText));
5792 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5793 XDrawWidgetText(display,&windows->widget,&text_info);
5794 XDrawBeveledButton(display,&windows->widget,&back_info);
5795 XDrawBeveledButton(display,&windows->widget,&reset_info);
5796 XDrawBeveledMatte(display,&windows->widget,&list_info);
5797 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5798 XDrawTriangleNorth(display,&windows->widget,&north_info);
5799 XDrawBeveledButton(display,&windows->widget,&slider_info);
5800 XDrawTriangleSouth(display,&windows->widget,&south_info);
5802 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
5803 (void) XDrawString(display,windows->widget.id,
5804 windows->widget.annotate_context,x,y,FontnameText,
5805 Extent(FontnameText));
5806 XDrawBeveledMatte(display,&windows->widget,&reply_info);
5807 XDrawMatteText(display,&windows->widget,&reply_info);
5808 XDrawBeveledButton(display,&windows->widget,&action_info);
5809 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5810 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5811 selection_info.id=(~0);
5812 state|=RedrawActionState;
5813 state|=RedrawListState;
5814 state&=(~RedrawWidgetState);
5816 if (state & UpdateListState)
5827 checklist=XListFonts(display,glob_pattern,32767,&number_fonts);
5828 if (checklist == (char **) NULL)
5830 if ((strchr(glob_pattern,'*') == (char *) NULL) &&
5831 (strchr(glob_pattern,'?') == (char *) NULL))
5834 Might be a scaleable font-- exit.
5836 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
5837 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5838 action_info.raised=MagickFalse;
5839 XDrawBeveledButton(display,&windows->widget,&action_info);
5842 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5843 (void) XBell(display,0);
5846 if (number_fonts == 1)
5849 Reply is a single font name-- exit.
5851 (void) CopyMagickString(reply,checklist[0],MaxTextExtent);
5852 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5853 (void) XFreeFontNames(checklist);
5854 action_info.raised=MagickFalse;
5855 XDrawBeveledButton(display,&windows->widget,&action_info);
5860 (void) XFreeFontNames(listhead);
5861 fontlist=(char **) RelinquishMagickMemory(fontlist);
5866 Sort font list in ascending order.
5869 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,
5871 if (fontlist == (char **) NULL)
5873 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5874 "UnableToViewFonts");
5877 for (i=0; i < fonts; i++)
5878 fontlist[i]=listhead[i];
5879 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5881 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
5882 if (fonts > (int) visible_fonts)
5883 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5884 slider_info.max_y=south_info.y-south_info.bevel_width-
5885 slider_info.bevel_width-2;
5887 slider_info.y=slider_info.min_y;
5888 expose_info.y=slider_info.y;
5889 selection_info.id=(~0);
5891 state|=RedrawListState;
5893 Redraw font name & reply.
5895 *reply_info.text='\0';
5896 reply_info.cursor=reply_info.text;
5897 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5898 XDrawWidgetText(display,&windows->widget,&text_info);
5899 XDrawMatteText(display,&windows->widget,&reply_info);
5900 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5901 XDrawTriangleNorth(display,&windows->widget,&north_info);
5902 XDrawBeveledButton(display,&windows->widget,&slider_info);
5903 XDrawTriangleSouth(display,&windows->widget,&south_info);
5904 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5905 state&=(~UpdateListState);
5907 if (state & JumpListState)
5910 Jump scroll to match user font.
5913 for (i=0; i < fonts; i++)
5914 if (LocaleCompare(fontlist[i],reply) >= 0)
5916 list_info.id=LocaleCompare(fontlist[i],reply) == 0 ? i : ~0;
5919 if ((i < slider_info.id) || (i >= (int) (slider_info.id+visible_fonts)))
5920 slider_info.id=i-(visible_fonts >> 1);
5921 selection_info.id=(~0);
5922 state|=RedrawListState;
5923 state&=(~JumpListState);
5925 if (state & RedrawListState)
5928 Determine slider id and position.
5930 if (slider_info.id >= (int) (fonts-visible_fonts))
5931 slider_info.id=fonts-visible_fonts;
5932 if ((slider_info.id < 0) || (fonts <= (int) visible_fonts))
5934 slider_info.y=slider_info.min_y;
5937 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/fonts;
5938 if (slider_info.id != selection_info.id)
5941 Redraw scroll bar and file names.
5943 selection_info.id=slider_info.id;
5944 selection_info.y=list_info.y+(height >> 3)+2;
5945 for (i=0; i < (int) visible_fonts; i++)
5947 selection_info.raised=(slider_info.id+i) != list_info.id ?
5948 MagickTrue : MagickFalse;
5949 selection_info.text=(char *) NULL;
5950 if ((slider_info.id+i) < fonts)
5951 selection_info.text=fontlist[slider_info.id+i];
5952 XDrawWidgetText(display,&windows->widget,&selection_info);
5953 selection_info.y+=(int) selection_info.height;
5958 if (slider_info.y > expose_info.y)
5960 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
5961 expose_info.y=slider_info.y-expose_info.height-
5962 slider_info.bevel_width-1;
5966 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
5967 expose_info.y=slider_info.y+slider_info.height+
5968 slider_info.bevel_width+1;
5970 XDrawTriangleNorth(display,&windows->widget,&north_info);
5971 XDrawMatte(display,&windows->widget,&expose_info);
5972 XDrawBeveledButton(display,&windows->widget,&slider_info);
5973 XDrawTriangleSouth(display,&windows->widget,&south_info);
5974 expose_info.y=slider_info.y;
5976 state&=(~RedrawListState);
5978 if (state & RedrawActionState)
5984 Display the selected font in a drawing area.
5986 save_info=windows->widget.font_info;
5987 font_info=XLoadQueryFont(display,reply_info.text);
5988 if (font_info != (XFontStruct *) NULL)
5990 windows->widget.font_info=font_info;
5991 (void) XSetFont(display,windows->widget.widget_context,
5994 XDrawBeveledButton(display,&windows->widget,&mode_info);
5995 windows->widget.font_info=save_info;
5996 if (font_info != (XFontStruct *) NULL)
5998 (void) XSetFont(display,windows->widget.widget_context,
5999 windows->widget.font_info->fid);
6000 (void) XFreeFont(display,font_info);
6002 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
6003 XDrawMatteText(display,&windows->widget,&reply_info);
6004 state&=(~RedrawActionState);
6007 Wait for next event.
6009 if (north_info.raised && south_info.raised)
6010 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
6014 Brief delay before advancing scroll bar.
6016 XDelay(display,delay);
6018 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
6019 if (north_info.raised == MagickFalse)
6020 if (slider_info.id > 0)
6026 state|=RedrawListState;
6028 if (south_info.raised == MagickFalse)
6029 if (slider_info.id < fonts)
6035 state|=RedrawListState;
6037 if (event.type != ButtonRelease)
6044 if (MatteIsActive(slider_info,event.xbutton))
6049 slider_info.active=MagickTrue;
6052 if (MatteIsActive(north_info,event.xbutton))
6053 if (slider_info.id > 0)
6058 north_info.raised=MagickFalse;
6060 state|=RedrawListState;
6063 if (MatteIsActive(south_info,event.xbutton))
6064 if (slider_info.id < fonts)
6069 south_info.raised=MagickFalse;
6071 state|=RedrawListState;
6074 if (MatteIsActive(scroll_info,event.xbutton))
6079 if (event.xbutton.y < slider_info.y)
6080 slider_info.id-=(visible_fonts-1);
6082 slider_info.id+=(visible_fonts-1);
6083 state|=RedrawListState;
6086 if (MatteIsActive(list_info,event.xbutton))
6092 User pressed list matte.
6094 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
6095 selection_info.height;
6096 if (id >= (int) fonts)
6098 (void) CopyMagickString(reply_info.text,fontlist[id],MaxTextExtent);
6099 reply_info.highlight=MagickFalse;
6100 reply_info.marker=reply_info.text;
6101 reply_info.cursor=reply_info.text+Extent(reply_info.text);
6102 XDrawMatteText(display,&windows->widget,&reply_info);
6103 state|=RedrawActionState;
6104 if (id == list_info.id)
6106 (void) CopyMagickString(glob_pattern,reply_info.text,
6108 state|=UpdateListState;
6110 selection_info.id=(~0);
6112 state|=RedrawListState;
6115 if (MatteIsActive(back_info,event.xbutton))
6118 User pressed Back button.
6120 back_info.raised=MagickFalse;
6121 XDrawBeveledButton(display,&windows->widget,&back_info);
6124 if (MatteIsActive(reset_info,event.xbutton))
6127 User pressed Reset button.
6129 reset_info.raised=MagickFalse;
6130 XDrawBeveledButton(display,&windows->widget,&reset_info);
6133 if (MatteIsActive(action_info,event.xbutton))
6136 User pressed action button.
6138 action_info.raised=MagickFalse;
6139 XDrawBeveledButton(display,&windows->widget,&action_info);
6142 if (MatteIsActive(cancel_info,event.xbutton))
6145 User pressed Cancel button.
6147 cancel_info.raised=MagickFalse;
6148 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6151 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
6153 if (event.xbutton.button != Button2)
6159 Move text cursor to position of button press.
6161 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
6162 for (i=1; i <= Extent(reply_info.marker); i++)
6163 if (XTextWidth(font_info,reply_info.marker,i) > x)
6165 reply_info.cursor=reply_info.marker+i-1;
6166 if (event.xbutton.time > (click_time+DoubleClick))
6167 reply_info.highlight=MagickFalse;
6171 Become the XA_PRIMARY selection owner.
6173 (void) CopyMagickString(primary_selection,reply_info.text,
6175 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
6176 event.xbutton.time);
6177 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
6178 windows->widget.id ? MagickTrue : MagickFalse;
6180 XDrawMatteText(display,&windows->widget,&reply_info);
6181 click_time=event.xbutton.time;
6185 Request primary selection.
6187 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
6188 windows->widget.id,event.xbutton.time);
6193 if (windows->widget.mapped == MagickFalse)
6195 if (north_info.raised == MagickFalse)
6198 User released up button.
6200 delay=SuspendTime << 2;
6201 north_info.raised=MagickTrue;
6202 XDrawTriangleNorth(display,&windows->widget,&north_info);
6204 if (south_info.raised == MagickFalse)
6207 User released down button.
6209 delay=SuspendTime << 2;
6210 south_info.raised=MagickTrue;
6211 XDrawTriangleSouth(display,&windows->widget,&south_info);
6213 if (slider_info.active)
6216 Stop tracking slider.
6218 slider_info.active=MagickFalse;
6221 if (back_info.raised == MagickFalse)
6223 if (event.xbutton.window == windows->widget.id)
6224 if (MatteIsActive(back_info,event.xbutton))
6226 (void) CopyMagickString(glob_pattern,back_pattern,
6228 state|=UpdateListState;
6230 back_info.raised=MagickTrue;
6231 XDrawBeveledButton(display,&windows->widget,&back_info);
6233 if (reset_info.raised == MagickFalse)
6235 if (event.xbutton.window == windows->widget.id)
6236 if (MatteIsActive(reset_info,event.xbutton))
6238 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6239 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
6240 state|=UpdateListState;
6242 reset_info.raised=MagickTrue;
6243 XDrawBeveledButton(display,&windows->widget,&reset_info);
6245 if (action_info.raised == MagickFalse)
6247 if (event.xbutton.window == windows->widget.id)
6249 if (MatteIsActive(action_info,event.xbutton))
6251 if (*reply_info.text == '\0')
6252 (void) XBell(display,0);
6257 action_info.raised=MagickTrue;
6258 XDrawBeveledButton(display,&windows->widget,&action_info);
6260 if (cancel_info.raised == MagickFalse)
6262 if (event.xbutton.window == windows->widget.id)
6263 if (MatteIsActive(cancel_info,event.xbutton))
6265 *reply_info.text='\0';
6268 cancel_info.raised=MagickTrue;
6269 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6276 If client window delete message, exit.
6278 if (event.xclient.message_type != windows->wm_protocols)
6280 if (*event.xclient.data.l == (int) windows->wm_take_focus)
6282 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
6283 (Time) event.xclient.data.l[1]);
6286 if (*event.xclient.data.l != (int) windows->wm_delete_window)
6288 if (event.xclient.window == windows->widget.id)
6290 *reply_info.text='\0';
6296 case ConfigureNotify:
6299 Update widget configuration.
6301 if (event.xconfigure.window != windows->widget.id)
6303 if ((event.xconfigure.width == (int) windows->widget.width) &&
6304 (event.xconfigure.height == (int) windows->widget.height))
6306 windows->widget.width=(unsigned int)
6307 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
6308 windows->widget.height=(unsigned int)
6309 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
6310 state|=UpdateConfigurationState;
6315 if (event.xcrossing.window != windows->widget.id)
6317 state&=(~InactiveWidgetState);
6322 if (event.xexpose.window != windows->widget.id)
6324 if (event.xexpose.count != 0)
6326 state|=RedrawWidgetState;
6332 command[MaxTextExtent];
6341 Respond to a user key press.
6343 if (event.xkey.window != windows->widget.id)
6345 length=XLookupString((XKeyEvent *) &event.xkey,command,
6346 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6347 *(command+length)='\0';
6348 if (AreaIsActive(scroll_info,event.xkey))
6353 switch ((int) key_symbol)
6376 slider_info.id-=visible_fonts;
6382 slider_info.id+=visible_fonts;
6388 slider_info.id=fonts;
6392 state|=RedrawListState;
6395 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
6398 Read new font or glob patterm.
6400 if (*reply_info.text == '\0')
6402 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6403 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
6404 state|=UpdateListState;
6407 if (key_symbol == XK_Control_L)
6409 state|=ControlState;
6412 if (state & ControlState)
6413 switch ((int) key_symbol)
6419 Erase the entire line of text.
6421 *reply_info.text='\0';
6422 reply_info.cursor=reply_info.text;
6423 reply_info.marker=reply_info.text;
6424 reply_info.highlight=MagickFalse;
6430 XEditText(display,&reply_info,key_symbol,command,state);
6431 XDrawMatteText(display,&windows->widget,&reply_info);
6432 state|=JumpListState;
6438 command[MaxTextExtent];
6444 Respond to a user key release.
6446 if (event.xkey.window != windows->widget.id)
6448 (void) XLookupString((XKeyEvent *) &event.xkey,command,
6449 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6450 if (key_symbol == XK_Control_L)
6451 state&=(~ControlState);
6456 if (event.xcrossing.window != windows->widget.id)
6458 state|=InactiveWidgetState;
6470 Discard pending button motion events.
6472 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
6473 if (slider_info.active)
6478 slider_info.y=event.xmotion.y-
6479 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
6480 if (slider_info.y < slider_info.min_y)
6481 slider_info.y=slider_info.min_y;
6482 if (slider_info.y > slider_info.max_y)
6483 slider_info.y=slider_info.max_y;
6485 if (slider_info.y != slider_info.min_y)
6486 slider_info.id=(fonts*(slider_info.y-slider_info.min_y+1))/
6487 (slider_info.max_y-slider_info.min_y+1);
6488 state|=RedrawListState;
6491 if (state & InactiveWidgetState)
6493 if (back_info.raised == MatteIsActive(back_info,event.xmotion))
6496 Back button status changed.
6498 back_info.raised=!back_info.raised;
6499 XDrawBeveledButton(display,&windows->widget,&back_info);
6502 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
6505 Reset button status changed.
6507 reset_info.raised=!reset_info.raised;
6508 XDrawBeveledButton(display,&windows->widget,&reset_info);
6511 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
6514 Action button status changed.
6516 action_info.raised=action_info.raised == MagickFalse ?
6517 MagickTrue : MagickFalse;
6518 XDrawBeveledButton(display,&windows->widget,&action_info);
6521 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
6524 Cancel button status changed.
6526 cancel_info.raised=cancel_info.raised == MagickFalse ?
6527 MagickTrue : MagickFalse;
6528 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6533 case SelectionClear:
6535 reply_info.highlight=MagickFalse;
6536 XDrawMatteText(display,&windows->widget,&reply_info);
6539 case SelectionNotify:
6555 Obtain response from primary selection.
6557 if (event.xselection.property == (Atom) None)
6559 status=XGetWindowProperty(display,event.xselection.requestor,
6560 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
6561 &format,&length,&after,&data);
6562 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
6565 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
6566 (void) XBell(display,0);
6570 Insert primary selection in reply text.
6572 *(data+length)='\0';
6573 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
6575 XDrawMatteText(display,&windows->widget,&reply_info);
6576 state|=JumpListState;
6577 state|=RedrawActionState;
6579 (void) XFree((void *) data);
6582 case SelectionRequest:
6587 XSelectionRequestEvent
6591 Set XA_PRIMARY selection.
6593 request=(&(event.xselectionrequest));
6594 (void) XChangeProperty(request->display,request->requestor,
6595 request->property,request->target,8,PropModeReplace,
6596 (unsigned char *) primary_selection,Extent(primary_selection));
6597 notify.type=SelectionNotify;
6598 notify.display=request->display;
6599 notify.requestor=request->requestor;
6600 notify.selection=request->selection;
6601 notify.target=request->target;
6602 notify.time=request->time;
6603 if (request->property == None)
6604 notify.property=request->target;
6606 notify.property=request->property;
6607 (void) XSendEvent(request->display,request->requestor,False,0,
6608 (XEvent *) ¬ify);
6613 } while ((state & ExitState) == 0);
6614 XSetCursorState(display,windows,MagickFalse);
6615 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
6616 XCheckRefreshWindows(display,windows);
6620 (void) XFreeFontNames(listhead);
6621 fontlist=(char **) RelinquishMagickMemory(fontlist);
6625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6629 % X I n f o W i d g e t %
6633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6635 % XInfoWidget() displays text in the Info widget. The purpose is to inform
6636 % the user that what activity is currently being performed (e.g. reading
6637 % an image, rotating an image, etc.).
6639 % The format of the XInfoWidget method is:
6641 % void XInfoWidget(Display *display,XWindows *windows,const char *activity)
6643 % A description of each parameter follows:
6645 % o display: Specifies a connection to an X server; returned from
6648 % o window: Specifies a pointer to a XWindows structure.
6650 % o activity: This character string reflects the current activity and is
6651 % displayed in the Info widget.
6654 MagickExport void XInfoWidget(Display *display,XWindows *windows,
6655 const char *activity)
6671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
6672 assert(display != (Display *) NULL);
6673 assert(windows != (XWindows *) NULL);
6674 assert(activity != (char *) NULL);
6675 font_info=windows->info.font_info;
6676 width=WidgetTextWidth(font_info,(char *) activity)+((3*QuantumMargin) >> 1)+4;
6677 height=(unsigned int) (((6*(font_info->ascent+font_info->descent)) >> 2)+4);
6678 if ((windows->info.width != width) || (windows->info.height != height))
6681 Size Info widget to accommodate the activity text.
6683 windows->info.width=width;
6684 windows->info.height=height;
6685 window_changes.width=(int) width;
6686 window_changes.height=(int) height;
6687 (void) XReconfigureWMWindow(display,windows->info.id,windows->info.screen,
6688 (unsigned int) (CWWidth | CWHeight),&window_changes);
6690 if (windows->info.mapped == MagickFalse)
6692 (void) XMapRaised(display,windows->info.id);
6693 windows->info.mapped=MagickTrue;
6696 Initialize Info matte information.
6698 height=(unsigned int) (font_info->ascent+font_info->descent);
6699 XGetWidgetInfo(activity,&monitor_info);
6700 monitor_info.bevel_width--;
6701 margin=monitor_info.bevel_width+((windows->info.height-height) >> 1)-2;
6702 monitor_info.center=MagickFalse;
6703 monitor_info.x=(int) margin;
6704 monitor_info.y=(int) margin;
6705 monitor_info.width=windows->info.width-(margin << 1);
6706 monitor_info.height=windows->info.height-(margin << 1)+1;
6710 monitor_info.raised=MagickFalse;
6711 XDrawBeveledMatte(display,&windows->info,&monitor_info);
6712 monitor_info.raised=MagickTrue;
6713 XDrawWidgetText(display,&windows->info,&monitor_info);
6717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6721 % X L i s t B r o w s e r W i d g e t %
6725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6727 % XListBrowserWidget() displays a List Browser widget with a query to the
6728 % user. The user keys a reply or select a reply from the list. Finally, the
6729 % user presses the Action or Cancel button to exit. The typed text is
6730 % returned as the reply function parameter.
6732 % The format of the XListBrowserWidget method is:
6734 % void XListBrowserWidget(Display *display,XWindows *windows,
6735 % XWindowInfo *window_info,const char **list,const char *action,
6736 % const char *query,char *reply)
6738 % A description of each parameter follows:
6740 % o display: Specifies a connection to an X server; returned from
6743 % o window: Specifies a pointer to a XWindows structure.
6745 % o list: Specifies a pointer to an array of strings. The user can
6746 % select from these strings as a possible reply value.
6748 % o action: Specifies a pointer to the action of this widget.
6750 % o query: Specifies a pointer to the query to present to the user.
6752 % o reply: the response from the user is returned in this parameter.
6755 MagickExport void XListBrowserWidget(Display *display,XWindows *windows,
6756 XWindowInfo *window_info,const char **list,const char *action,
6757 const char *query,char *reply)
6759 #define CancelButtonText "Cancel"
6762 primary_selection[MaxTextExtent];
6770 static MagickStatusType
6771 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
6813 Count the number of entries in the list.
6815 assert(display != (Display *) NULL);
6816 assert(windows != (XWindows *) NULL);
6817 assert(window_info != (XWindowInfo *) NULL);
6818 assert(list != (const char **) NULL);
6819 assert(action != (char *) NULL);
6820 assert(query != (char *) NULL);
6821 assert(reply != (char *) NULL);
6822 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
6823 XSetCursorState(display,windows,MagickTrue);
6824 XCheckRefreshWindows(display,windows);
6825 if (list == (const char **) NULL)
6827 XNoticeWidget(display,windows,"No text to browse:",(char *) NULL);
6830 for (entries=0; ; entries++)
6831 if (list[entries] == (char *) NULL)
6834 Determine Font Browser widget attributes.
6836 font_info=window_info->font_info;
6837 text_width=WidgetTextWidth(font_info,(char *) query);
6838 for (i=0; i < (int) entries; i++)
6839 if (WidgetTextWidth(font_info,(char *) list[i]) > text_width)
6840 text_width=WidgetTextWidth(font_info,(char *) list[i]);
6841 width=WidgetTextWidth(font_info,(char *) action);
6842 if (WidgetTextWidth(font_info,CancelButtonText) > width)
6843 width=WidgetTextWidth(font_info,CancelButtonText);
6844 width+=QuantumMargin;
6845 height=(unsigned int) (font_info->ascent+font_info->descent);
6847 Position List Browser widget.
6849 window_info->width=(unsigned int) MagickMin((int) text_width,(int)
6850 MaxTextWidth)+((9*QuantumMargin) >> 1);
6851 window_info->min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
6852 if (window_info->width < window_info->min_width)
6853 window_info->width=window_info->min_width;
6854 window_info->height=(unsigned int)
6855 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
6856 window_info->min_height=(unsigned int)
6857 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
6858 if (window_info->height < window_info->min_height)
6859 window_info->height=window_info->min_height;
6860 XConstrainWindowPosition(display,window_info);
6862 Map List Browser widget.
6864 (void) CopyMagickString(window_info->name,"Browse",MaxTextExtent);
6865 status=XStringListToTextProperty(&window_info->name,1,&window_name);
6866 if (status != False)
6868 XSetWMName(display,window_info->id,&window_name);
6869 XSetWMIconName(display,windows->widget.id,&window_name);
6870 (void) XFree((void *) window_name.value);
6872 window_changes.width=(int) window_info->width;
6873 window_changes.height=(int) window_info->height;
6874 window_changes.x=window_info->x;
6875 window_changes.y=window_info->y;
6876 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,mask,
6878 (void) XMapRaised(display,window_info->id);
6879 window_info->mapped=MagickFalse;
6881 Respond to X events.
6883 XGetWidgetInfo((char *) NULL,&slider_info);
6884 XGetWidgetInfo((char *) NULL,&north_info);
6885 XGetWidgetInfo((char *) NULL,&south_info);
6886 XGetWidgetInfo((char *) NULL,&expose_info);
6888 delay=SuspendTime << 2;
6889 state=UpdateConfigurationState;
6892 if (state & UpdateConfigurationState)
6898 Initialize button information.
6900 XGetWidgetInfo(CancelButtonText,&cancel_info);
6901 cancel_info.width=width;
6902 cancel_info.height=(unsigned int) ((3*height) >> 1);
6904 (window_info->width-cancel_info.width-QuantumMargin-2);
6906 (window_info->height-cancel_info.height-QuantumMargin);
6907 XGetWidgetInfo(action,&action_info);
6908 action_info.width=width;
6909 action_info.height=(unsigned int) ((3*height) >> 1);
6910 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
6911 (action_info.bevel_width << 1));
6912 action_info.y=cancel_info.y;
6914 Initialize reply information.
6916 XGetWidgetInfo(reply,&reply_info);
6917 reply_info.raised=MagickFalse;
6918 reply_info.bevel_width--;
6919 reply_info.width=window_info->width-((4*QuantumMargin) >> 1);
6920 reply_info.height=height << 1;
6921 reply_info.x=QuantumMargin;
6922 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
6924 Initialize scroll information.
6926 XGetWidgetInfo((char *) NULL,&scroll_info);
6927 scroll_info.bevel_width--;
6928 scroll_info.width=height;
6929 scroll_info.height=(unsigned int)
6930 (reply_info.y-((6*QuantumMargin) >> 1)-height);
6931 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
6932 scroll_info.y=((5*QuantumMargin) >> 1)+height-reply_info.bevel_width;
6933 scroll_info.raised=MagickFalse;
6934 scroll_info.trough=MagickTrue;
6935 north_info=scroll_info;
6936 north_info.raised=MagickTrue;
6937 north_info.width-=(north_info.bevel_width << 1);
6938 north_info.height=north_info.width-1;
6939 north_info.x+=north_info.bevel_width;
6940 north_info.y+=north_info.bevel_width;
6941 south_info=north_info;
6942 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
6945 slider_info=north_info;
6947 slider_info.width-=2;
6948 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
6949 slider_info.bevel_width+2;
6950 slider_info.height=scroll_info.height-((slider_info.min_y-
6951 scroll_info.y+1) << 1)+4;
6952 visible_entries=scroll_info.height/(height+(height >> 3));
6953 if (entries > visible_entries)
6954 slider_info.height=(visible_entries*slider_info.height)/entries;
6955 slider_info.max_y=south_info.y-south_info.bevel_width-
6956 slider_info.bevel_width-2;
6957 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
6958 slider_info.y=slider_info.min_y;
6959 expose_info=scroll_info;
6960 expose_info.y=slider_info.y;
6962 Initialize list information.
6964 XGetWidgetInfo((char *) NULL,&list_info);
6965 list_info.raised=MagickFalse;
6966 list_info.bevel_width--;
6967 list_info.width=(unsigned int)
6968 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
6969 list_info.height=scroll_info.height;
6970 list_info.x=reply_info.x;
6971 list_info.y=scroll_info.y;
6972 if (window_info->mapped == MagickFalse)
6973 for (i=0; i < (int) entries; i++)
6974 if (LocaleCompare(list[i],reply) == 0)
6977 slider_info.id=i-(visible_entries >> 1);
6978 if (slider_info.id < 0)
6982 Initialize text information.
6984 XGetWidgetInfo(query,&text_info);
6985 text_info.width=reply_info.width;
6986 text_info.height=height;
6987 text_info.x=list_info.x-(QuantumMargin >> 1);
6988 text_info.y=QuantumMargin;
6990 Initialize selection information.
6992 XGetWidgetInfo((char *) NULL,&selection_info);
6993 selection_info.center=MagickFalse;
6994 selection_info.width=list_info.width;
6995 selection_info.height=(unsigned int) ((9*height) >> 3);
6996 selection_info.x=list_info.x;
6997 state&=(~UpdateConfigurationState);
6999 if (state & RedrawWidgetState)
7002 Redraw List Browser window.
7004 XDrawWidgetText(display,window_info,&text_info);
7005 XDrawBeveledMatte(display,window_info,&list_info);
7006 XDrawBeveledMatte(display,window_info,&scroll_info);
7007 XDrawTriangleNorth(display,window_info,&north_info);
7008 XDrawBeveledButton(display,window_info,&slider_info);
7009 XDrawTriangleSouth(display,window_info,&south_info);
7010 XDrawBeveledMatte(display,window_info,&reply_info);
7011 XDrawMatteText(display,window_info,&reply_info);
7012 XDrawBeveledButton(display,window_info,&action_info);
7013 XDrawBeveledButton(display,window_info,&cancel_info);
7014 XHighlightWidget(display,window_info,BorderOffset,BorderOffset);
7015 selection_info.id=(~0);
7016 state|=RedrawActionState;
7017 state|=RedrawListState;
7018 state&=(~RedrawWidgetState);
7020 if (state & RedrawListState)
7023 Determine slider id and position.
7025 if (slider_info.id >= (int) (entries-visible_entries))
7026 slider_info.id=(int) (entries-visible_entries);
7027 if ((slider_info.id < 0) || (entries <= visible_entries))
7029 slider_info.y=slider_info.min_y;
7032 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/entries;
7033 if (slider_info.id != selection_info.id)
7036 Redraw scroll bar and file names.
7038 selection_info.id=slider_info.id;
7039 selection_info.y=list_info.y+(height >> 3)+2;
7040 for (i=0; i < (int) visible_entries; i++)
7042 selection_info.raised=(slider_info.id+i) != list_info.id ?
7043 MagickTrue : MagickFalse;
7044 selection_info.text=(char *) NULL;
7045 if ((slider_info.id+i) < (int) entries)
7046 selection_info.text=(char *) list[slider_info.id+i];
7047 XDrawWidgetText(display,window_info,&selection_info);
7048 selection_info.y+=(int) selection_info.height;
7053 if (slider_info.y > expose_info.y)
7055 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
7056 expose_info.y=slider_info.y-expose_info.height-
7057 slider_info.bevel_width-1;
7061 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
7062 expose_info.y=slider_info.y+slider_info.height+
7063 slider_info.bevel_width+1;
7065 XDrawTriangleNorth(display,window_info,&north_info);
7066 XDrawMatte(display,window_info,&expose_info);
7067 XDrawBeveledButton(display,window_info,&slider_info);
7068 XDrawTriangleSouth(display,window_info,&south_info);
7069 expose_info.y=slider_info.y;
7071 state&=(~RedrawListState);
7074 Wait for next event.
7076 if (north_info.raised && south_info.raised)
7077 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7081 Brief delay before advancing scroll bar.
7083 XDelay(display,delay);
7085 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
7086 if (north_info.raised == MagickFalse)
7087 if (slider_info.id > 0)
7093 state|=RedrawListState;
7095 if (south_info.raised == MagickFalse)
7096 if (slider_info.id < (int) entries)
7102 state|=RedrawListState;
7104 if (event.type != ButtonRelease)
7111 if (MatteIsActive(slider_info,event.xbutton))
7116 slider_info.active=MagickTrue;
7119 if (MatteIsActive(north_info,event.xbutton))
7120 if (slider_info.id > 0)
7125 north_info.raised=MagickFalse;
7127 state|=RedrawListState;
7130 if (MatteIsActive(south_info,event.xbutton))
7131 if (slider_info.id < (int) entries)
7136 south_info.raised=MagickFalse;
7138 state|=RedrawListState;
7141 if (MatteIsActive(scroll_info,event.xbutton))
7146 if (event.xbutton.y < slider_info.y)
7147 slider_info.id-=(visible_entries-1);
7149 slider_info.id+=(visible_entries-1);
7150 state|=RedrawListState;
7153 if (MatteIsActive(list_info,event.xbutton))
7159 User pressed list matte.
7161 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
7162 selection_info.height;
7163 if (id >= (int) entries)
7165 (void) CopyMagickString(reply_info.text,list[id],MaxTextExtent);
7166 reply_info.highlight=MagickFalse;
7167 reply_info.marker=reply_info.text;
7168 reply_info.cursor=reply_info.text+Extent(reply_info.text);
7169 XDrawMatteText(display,window_info,&reply_info);
7170 selection_info.id=(~0);
7171 if (id == list_info.id)
7173 action_info.raised=MagickFalse;
7174 XDrawBeveledButton(display,window_info,&action_info);
7178 state|=RedrawListState;
7181 if (MatteIsActive(action_info,event.xbutton))
7184 User pressed action button.
7186 action_info.raised=MagickFalse;
7187 XDrawBeveledButton(display,window_info,&action_info);
7190 if (MatteIsActive(cancel_info,event.xbutton))
7193 User pressed Cancel button.
7195 cancel_info.raised=MagickFalse;
7196 XDrawBeveledButton(display,window_info,&cancel_info);
7199 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7201 if (event.xbutton.button != Button2)
7207 Move text cursor to position of button press.
7209 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
7210 for (i=1; i <= Extent(reply_info.marker); i++)
7211 if (XTextWidth(font_info,reply_info.marker,i) > x)
7213 reply_info.cursor=reply_info.marker+i-1;
7214 if (event.xbutton.time > (click_time+DoubleClick))
7215 reply_info.highlight=MagickFalse;
7219 Become the XA_PRIMARY selection owner.
7221 (void) CopyMagickString(primary_selection,reply_info.text,
7223 (void) XSetSelectionOwner(display,XA_PRIMARY,window_info->id,
7224 event.xbutton.time);
7225 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
7226 window_info->id ? MagickTrue : MagickFalse;
7228 XDrawMatteText(display,window_info,&reply_info);
7229 click_time=event.xbutton.time;
7233 Request primary selection.
7235 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
7236 window_info->id,event.xbutton.time);
7241 if (window_info->mapped == MagickFalse)
7243 if (north_info.raised == MagickFalse)
7246 User released up button.
7248 delay=SuspendTime << 2;
7249 north_info.raised=MagickTrue;
7250 XDrawTriangleNorth(display,window_info,&north_info);
7252 if (south_info.raised == MagickFalse)
7255 User released down button.
7257 delay=SuspendTime << 2;
7258 south_info.raised=MagickTrue;
7259 XDrawTriangleSouth(display,window_info,&south_info);
7261 if (slider_info.active)
7264 Stop tracking slider.
7266 slider_info.active=MagickFalse;
7269 if (action_info.raised == MagickFalse)
7271 if (event.xbutton.window == window_info->id)
7273 if (MatteIsActive(action_info,event.xbutton))
7275 if (*reply_info.text == '\0')
7276 (void) XBell(display,0);
7281 action_info.raised=MagickTrue;
7282 XDrawBeveledButton(display,window_info,&action_info);
7284 if (cancel_info.raised == MagickFalse)
7286 if (event.xbutton.window == window_info->id)
7287 if (MatteIsActive(cancel_info,event.xbutton))
7289 *reply_info.text='\0';
7292 cancel_info.raised=MagickTrue;
7293 XDrawBeveledButton(display,window_info,&cancel_info);
7295 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7302 If client window delete message, exit.
7304 if (event.xclient.message_type != windows->wm_protocols)
7306 if (*event.xclient.data.l == (int) windows->wm_take_focus)
7308 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
7309 (Time) event.xclient.data.l[1]);
7312 if (*event.xclient.data.l != (int) windows->wm_delete_window)
7314 if (event.xclient.window == window_info->id)
7316 *reply_info.text='\0';
7322 case ConfigureNotify:
7325 Update widget configuration.
7327 if (event.xconfigure.window != window_info->id)
7329 if ((event.xconfigure.width == (int) window_info->width) &&
7330 (event.xconfigure.height == (int) window_info->height))
7332 window_info->width=(unsigned int)
7333 MagickMax(event.xconfigure.width,(int) window_info->min_width);
7334 window_info->height=(unsigned int)
7335 MagickMax(event.xconfigure.height,(int) window_info->min_height);
7336 state|=UpdateConfigurationState;
7341 if (event.xcrossing.window != window_info->id)
7343 state&=(~InactiveWidgetState);
7348 if (event.xexpose.window != window_info->id)
7350 if (event.xexpose.count != 0)
7352 state|=RedrawWidgetState;
7358 command[MaxTextExtent];
7367 Respond to a user key press.
7369 if (event.xkey.window != window_info->id)
7371 length=XLookupString((XKeyEvent *) &event.xkey,command,
7372 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7373 *(command+length)='\0';
7374 if (AreaIsActive(scroll_info,event.xkey))
7379 switch ((int) key_symbol)
7402 slider_info.id-=visible_entries;
7408 slider_info.id+=visible_entries;
7414 slider_info.id=(int) entries;
7418 state|=RedrawListState;
7421 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
7426 if (*reply_info.text == '\0')
7428 action_info.raised=MagickFalse;
7429 XDrawBeveledButton(display,window_info,&action_info);
7433 if (key_symbol == XK_Control_L)
7435 state|=ControlState;
7438 if (state & ControlState)
7439 switch ((int) key_symbol)
7445 Erase the entire line of text.
7447 *reply_info.text='\0';
7448 reply_info.cursor=reply_info.text;
7449 reply_info.marker=reply_info.text;
7450 reply_info.highlight=MagickFalse;
7456 XEditText(display,&reply_info,key_symbol,command,state);
7457 XDrawMatteText(display,window_info,&reply_info);
7463 command[MaxTextExtent];
7469 Respond to a user key release.
7471 if (event.xkey.window != window_info->id)
7473 (void) XLookupString((XKeyEvent *) &event.xkey,command,
7474 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7475 if (key_symbol == XK_Control_L)
7476 state&=(~ControlState);
7481 if (event.xcrossing.window != window_info->id)
7483 state|=InactiveWidgetState;
7495 Discard pending button motion events.
7497 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7498 if (slider_info.active)
7503 slider_info.y=event.xmotion.y-
7504 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
7505 if (slider_info.y < slider_info.min_y)
7506 slider_info.y=slider_info.min_y;
7507 if (slider_info.y > slider_info.max_y)
7508 slider_info.y=slider_info.max_y;
7510 if (slider_info.y != slider_info.min_y)
7511 slider_info.id=(int) ((entries*(slider_info.y-
7512 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
7513 state|=RedrawListState;
7516 if (state & InactiveWidgetState)
7518 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
7521 Action button status changed.
7523 action_info.raised=action_info.raised == MagickFalse ?
7524 MagickTrue : MagickFalse;
7525 XDrawBeveledButton(display,window_info,&action_info);
7528 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
7531 Cancel button status changed.
7533 cancel_info.raised=cancel_info.raised == MagickFalse ?
7534 MagickTrue : MagickFalse;
7535 XDrawBeveledButton(display,window_info,&cancel_info);
7540 case SelectionClear:
7542 reply_info.highlight=MagickFalse;
7543 XDrawMatteText(display,window_info,&reply_info);
7546 case SelectionNotify:
7562 Obtain response from primary selection.
7564 if (event.xselection.property == (Atom) None)
7566 status=XGetWindowProperty(display,
7567 event.xselection.requestor,event.xselection.property,0L,2047L,
7568 MagickTrue,XA_STRING,&type,&format,&length,&after,&data);
7569 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
7572 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
7573 (void) XBell(display,0);
7577 Insert primary selection in reply text.
7579 *(data+length)='\0';
7580 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
7582 XDrawMatteText(display,window_info,&reply_info);
7583 state|=RedrawActionState;
7585 (void) XFree((void *) data);
7588 case SelectionRequest:
7593 XSelectionRequestEvent
7596 if (reply_info.highlight == MagickFalse)
7599 Set primary selection.
7601 request=(&(event.xselectionrequest));
7602 (void) XChangeProperty(request->display,request->requestor,
7603 request->property,request->target,8,PropModeReplace,
7604 (unsigned char *) primary_selection,Extent(primary_selection));
7605 notify.type=SelectionNotify;
7606 notify.send_event=MagickTrue;
7607 notify.display=request->display;
7608 notify.requestor=request->requestor;
7609 notify.selection=request->selection;
7610 notify.target=request->target;
7611 notify.time=request->time;
7612 if (request->property == None)
7613 notify.property=request->target;
7615 notify.property=request->property;
7616 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
7617 (XEvent *) ¬ify);
7622 } while ((state & ExitState) == 0);
7623 XSetCursorState(display,windows,MagickFalse);
7624 (void) XWithdrawWindow(display,window_info->id,window_info->screen);
7625 XCheckRefreshWindows(display,windows);
7629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7633 % X M e n u W i d g e t %
7637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7639 % XMenuWidget() maps a menu and returns the command pointed to by the user
7640 % when the button is released.
7642 % The format of the XMenuWidget method is:
7644 % int XMenuWidget(Display *display,XWindows *windows,const char *title,
7645 % const char **selections,char *item)
7647 % A description of each parameter follows:
7649 % o selection_number: Specifies the number of the selection that the
7652 % o display: Specifies a connection to an X server; returned from
7655 % o window: Specifies a pointer to a XWindows structure.
7657 % o title: Specifies a character string that describes the menu selections.
7659 % o selections: Specifies a pointer to one or more strings that comprise
7660 % the choices in the menu.
7662 % o item: Specifies a character array. The item selected from the menu
7666 MagickExport int XMenuWidget(Display *display,XWindows *windows,
7667 const char *title,const char **selections,char *item)
7693 XSetWindowAttributes
7705 Determine Menu widget attributes.
7707 assert(display != (Display *) NULL);
7708 assert(windows != (XWindows *) NULL);
7709 assert(title != (char *) NULL);
7710 assert(selections != (const char **) NULL);
7711 assert(item != (char *) NULL);
7712 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
7713 font_info=windows->widget.font_info;
7714 windows->widget.width=submenu_info.active == 0 ?
7715 WidgetTextWidth(font_info,(char *) title) : 0;
7716 for (id=0; selections[id] != (char *) NULL; id++)
7718 width=WidgetTextWidth(font_info,(char *) selections[id]);
7719 if (width > windows->widget.width)
7720 windows->widget.width=width;
7722 number_selections=(unsigned int) id;
7723 XGetWidgetInfo((char *) NULL,&menu_info);
7724 title_height=(unsigned int) (submenu_info.active == 0 ?
7725 (3*(font_info->descent+font_info->ascent) >> 1)+5 : 2);
7726 width=WidgetTextWidth(font_info,(char *) title);
7727 height=(unsigned int) ((3*(font_info->ascent+font_info->descent)) >> 1);
7729 Position Menu widget.
7731 windows->widget.width+=QuantumMargin+(menu_info.bevel_width << 1);
7732 top_offset=title_height+menu_info.bevel_width-1;
7733 windows->widget.height=top_offset+number_selections*height+4;
7734 windows->widget.min_width=windows->widget.width;
7735 windows->widget.min_height=windows->widget.height;
7736 XQueryPosition(display,windows->widget.root,&x,&y);
7737 windows->widget.x=x-(QuantumMargin >> 1);
7738 if (submenu_info.active != 0)
7741 windows->command.x+windows->command.width-QuantumMargin;
7742 toggle_info.raised=MagickTrue;
7743 XDrawTriangleEast(display,&windows->command,&toggle_info);
7745 windows->widget.y=submenu_info.active == 0 ? y-(int)
7746 ((3*title_height) >> 2) : y;
7747 if (submenu_info.active != 0)
7748 windows->widget.y=windows->command.y+submenu_info.y;
7749 XConstrainWindowPosition(display,&windows->widget);
7753 window_attributes.override_redirect=MagickTrue;
7754 (void) XChangeWindowAttributes(display,windows->widget.id,
7755 (size_t) CWOverrideRedirect,&window_attributes);
7756 window_changes.width=(int) windows->widget.width;
7757 window_changes.height=(int) windows->widget.height;
7758 window_changes.x=windows->widget.x;
7759 window_changes.y=windows->widget.y;
7760 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
7761 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
7762 (void) XMapRaised(display,windows->widget.id);
7763 windows->widget.mapped=MagickFalse;
7765 Respond to X events.
7767 selection_info.height=height;
7768 cursor=XCreateFontCursor(display,XC_right_ptr);
7769 (void) XCheckDefineCursor(display,windows->image.id,cursor);
7770 (void) XCheckDefineCursor(display,windows->command.id,cursor);
7771 (void) XCheckDefineCursor(display,windows->widget.id,cursor);
7772 state=UpdateConfigurationState;
7775 if (state & UpdateConfigurationState)
7778 Initialize selection information.
7780 XGetWidgetInfo((char *) NULL,&menu_info);
7781 menu_info.bevel_width--;
7782 menu_info.width=windows->widget.width-((menu_info.bevel_width) << 1);
7783 menu_info.height=windows->widget.height-((menu_info.bevel_width) << 1);
7784 menu_info.x=(int) menu_info.bevel_width;
7785 menu_info.y=(int) menu_info.bevel_width;
7786 XGetWidgetInfo((char *) NULL,&selection_info);
7787 selection_info.center=MagickFalse;
7788 selection_info.width=menu_info.width;
7789 selection_info.height=height;
7790 selection_info.x=menu_info.x;
7791 highlight_info=selection_info;
7792 highlight_info.bevel_width--;
7793 highlight_info.width-=(highlight_info.bevel_width << 1);
7794 highlight_info.height-=(highlight_info.bevel_width << 1);
7795 highlight_info.x+=highlight_info.bevel_width;
7796 state&=(~UpdateConfigurationState);
7798 if (state & RedrawWidgetState)
7803 if (submenu_info.active == 0)
7805 y=(int) title_height;
7806 XSetBevelColor(display,&windows->widget,MagickFalse);
7807 (void) XDrawLine(display,windows->widget.id,
7808 windows->widget.widget_context,selection_info.x,y-1,
7809 (int) selection_info.width,y-1);
7810 XSetBevelColor(display,&windows->widget,MagickTrue);
7811 (void) XDrawLine(display,windows->widget.id,
7812 windows->widget.widget_context,selection_info.x,y,
7813 (int) selection_info.width,y);
7814 (void) XSetFillStyle(display,windows->widget.widget_context,
7818 Draw menu selections.
7820 selection_info.center=MagickTrue;
7821 selection_info.y=(int) menu_info.bevel_width;
7822 selection_info.text=(char *) title;
7823 if (submenu_info.active == 0)
7824 XDrawWidgetText(display,&windows->widget,&selection_info);
7825 selection_info.center=MagickFalse;
7826 selection_info.y=(int) top_offset;
7827 for (id=0; id < (int) number_selections; id++)
7829 selection_info.text=(char *) selections[id];
7830 XDrawWidgetText(display,&windows->widget,&selection_info);
7831 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7832 if (id == selection_info.id)
7833 XDrawBevel(display,&windows->widget,&highlight_info);
7834 selection_info.y+=(int) selection_info.height;
7836 XDrawBevel(display,&windows->widget,&menu_info);
7837 state&=(~RedrawWidgetState);
7839 if (number_selections > 2)
7844 y=(int) (top_offset+selection_info.height*(number_selections-1));
7845 XSetBevelColor(display,&windows->widget,MagickFalse);
7846 (void) XDrawLine(display,windows->widget.id,
7847 windows->widget.widget_context,selection_info.x,y-1,
7848 (int) selection_info.width,y-1);
7849 XSetBevelColor(display,&windows->widget,MagickTrue);
7850 (void) XDrawLine(display,windows->widget.id,
7851 windows->widget.widget_context,selection_info.x,y,
7852 (int) selection_info.width,y);
7853 (void) XSetFillStyle(display,windows->widget.widget_context,FillSolid);
7856 Wait for next event.
7858 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7863 if (event.xbutton.window != windows->widget.id)
7868 if (event.xbutton.window == windows->command.id)
7869 (void) XPutBackEvent(display,&event);
7870 selection_info.id=(~0);
7875 state&=(~InactiveWidgetState);
7876 id=(event.xbutton.y-top_offset)/(int) selection_info.height;
7877 selection_info.id=id;
7878 if ((id < 0) || (id >= (int) number_selections))
7881 Highlight this selection.
7883 selection_info.y=(int) (top_offset+id*selection_info.height);
7884 selection_info.text=(char *) selections[id];
7885 XDrawWidgetText(display,&windows->widget,&selection_info);
7886 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7887 XDrawBevel(display,&windows->widget,&highlight_info);
7892 if (windows->widget.mapped == MagickFalse)
7894 if (event.xbutton.window == windows->command.id)
7895 if ((state & InactiveWidgetState) == 0)
7900 XSetCursorState(display,windows,MagickFalse);
7905 case ConfigureNotify:
7908 Update widget configuration.
7910 if (event.xconfigure.window != windows->widget.id)
7912 if ((event.xconfigure.width == (int) windows->widget.width) &&
7913 (event.xconfigure.height == (int) windows->widget.height))
7915 windows->widget.width=(unsigned int)
7916 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
7917 windows->widget.height=(unsigned int)
7918 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
7919 state|=UpdateConfigurationState;
7924 if (event.xcrossing.window != windows->widget.id)
7926 if (event.xcrossing.state == 0)
7928 state&=(~InactiveWidgetState);
7929 id=((event.xcrossing.y-top_offset)/(int) selection_info.height);
7930 if ((selection_info.id >= 0) &&
7931 (selection_info.id < (int) number_selections))
7934 Unhighlight last selection.
7936 if (id == selection_info.id)
7938 selection_info.y=(int)
7939 (top_offset+selection_info.id*selection_info.height);
7940 selection_info.text=(char *) selections[selection_info.id];
7941 XDrawWidgetText(display,&windows->widget,&selection_info);
7943 if ((id < 0) || (id >= (int) number_selections))
7946 Highlight this selection.
7948 selection_info.id=id;
7949 selection_info.y=(int)
7950 (top_offset+selection_info.id*selection_info.height);
7951 selection_info.text=(char *) selections[selection_info.id];
7952 XDrawWidgetText(display,&windows->widget,&selection_info);
7953 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7954 XDrawBevel(display,&windows->widget,&highlight_info);
7959 if (event.xexpose.window != windows->widget.id)
7961 if (event.xexpose.count != 0)
7963 state|=RedrawWidgetState;
7968 if (event.xcrossing.window != windows->widget.id)
7970 state|=InactiveWidgetState;
7971 id=selection_info.id;
7972 if ((id < 0) || (id >= (int) number_selections))
7975 Unhighlight last selection.
7977 selection_info.y=(int) (top_offset+id*selection_info.height);
7978 selection_info.id=(~0);
7979 selection_info.text=(char *) selections[id];
7980 XDrawWidgetText(display,&windows->widget,&selection_info);
7986 Discard pending button motion events.
7988 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7989 if (submenu_info.active != 0)
7990 if (event.xmotion.window == windows->command.id)
7992 if ((state & InactiveWidgetState) == 0)
7994 if (MatteIsActive(submenu_info,event.xmotion) == MagickFalse)
7996 selection_info.id=(~0);
8003 if (WindowIsActive(windows->command,event.xmotion))
8005 selection_info.id=(~0);
8011 if (event.xmotion.window != windows->widget.id)
8013 if (state & InactiveWidgetState)
8015 id=(event.xmotion.y-top_offset)/(int) selection_info.height;
8016 if ((selection_info.id >= 0) &&
8017 (selection_info.id < (int) number_selections))
8020 Unhighlight last selection.
8022 if (id == selection_info.id)
8024 selection_info.y=(int)
8025 (top_offset+selection_info.id*selection_info.height);
8026 selection_info.text=(char *) selections[selection_info.id];
8027 XDrawWidgetText(display,&windows->widget,&selection_info);
8029 selection_info.id=id;
8030 if ((id < 0) || (id >= (int) number_selections))
8033 Highlight this selection.
8035 selection_info.y=(int) (top_offset+id*selection_info.height);
8036 selection_info.text=(char *) selections[id];
8037 XDrawWidgetText(display,&windows->widget,&selection_info);
8038 highlight_info.y=selection_info.y+highlight_info.bevel_width;
8039 XDrawBevel(display,&windows->widget,&highlight_info);
8045 } while ((state & ExitState) == 0);
8046 (void) XFreeCursor(display,cursor);
8047 window_attributes.override_redirect=MagickFalse;
8048 (void) XChangeWindowAttributes(display,windows->widget.id,
8049 (size_t) CWOverrideRedirect,&window_attributes);
8050 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8051 XCheckRefreshWindows(display,windows);
8052 if (submenu_info.active != 0)
8054 submenu_info.active=MagickFalse;
8055 toggle_info.raised=MagickFalse;
8056 XDrawTriangleEast(display,&windows->command,&toggle_info);
8058 if ((selection_info.id < 0) || (selection_info.id >= (int) number_selections))
8060 (void) CopyMagickString(item,selections[selection_info.id],MaxTextExtent);
8061 return(selection_info.id);
8065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8069 % X N o t i c e W i d g e t %
8073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8075 % XNoticeWidget() displays a Notice widget with a notice to the user. The
8076 % function returns when the user presses the "Dismiss" button.
8078 % The format of the XNoticeWidget method is:
8080 % void XNoticeWidget(Display *display,XWindows *windows,
8081 % const char *reason,const char *description)
8083 % A description of each parameter follows:
8085 % o display: Specifies a connection to an X server; returned from
8088 % o window: Specifies a pointer to a XWindows structure.
8090 % o reason: Specifies the message to display before terminating the
8093 % o description: Specifies any description to the message.
8096 MagickExport void XNoticeWidget(Display *display,XWindows *windows,
8097 const char *reason,const char *description)
8099 #define DismissButtonText "Dismiss"
8138 Determine Notice widget attributes.
8140 assert(display != (Display *) NULL);
8141 assert(windows != (XWindows *) NULL);
8142 assert(reason != (char *) NULL);
8143 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
8144 XDelay(display,SuspendTime << 3); /* avoid surpise with delay */
8145 XSetCursorState(display,windows,MagickTrue);
8146 XCheckRefreshWindows(display,windows);
8147 font_info=windows->widget.font_info;
8148 width=WidgetTextWidth(font_info,DismissButtonText);
8149 text=GetLocaleExceptionMessage(XServerError,reason);
8150 if (text != (char *) NULL)
8151 if (WidgetTextWidth(font_info,(char *) text) > width)
8152 width=WidgetTextWidth(font_info,(char *) text);
8153 if (description != (char *) NULL)
8155 text=GetLocaleExceptionMessage(XServerError,description);
8156 if (text != (char *) NULL)
8157 if (WidgetTextWidth(font_info,(char *) text) > width)
8158 width=WidgetTextWidth(font_info,(char *) text);
8160 height=(unsigned int) (font_info->ascent+font_info->descent);
8162 Position Notice widget.
8164 windows->widget.width=width+4*QuantumMargin;
8165 windows->widget.min_width=width+QuantumMargin;
8166 if (windows->widget.width < windows->widget.min_width)
8167 windows->widget.width=windows->widget.min_width;
8168 windows->widget.height=(unsigned int) (12*height);
8169 windows->widget.min_height=(unsigned int) (7*height);
8170 if (windows->widget.height < windows->widget.min_height)
8171 windows->widget.height=windows->widget.min_height;
8172 XConstrainWindowPosition(display,&windows->widget);
8176 (void) CopyMagickString(windows->widget.name,"Notice",MaxTextExtent);
8177 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8178 if (status != False)
8180 XSetWMName(display,windows->widget.id,&window_name);
8181 XSetWMIconName(display,windows->widget.id,&window_name);
8182 (void) XFree((void *) window_name.value);
8184 window_changes.width=(int) windows->widget.width;
8185 window_changes.height=(int) windows->widget.height;
8186 window_changes.x=windows->widget.x;
8187 window_changes.y=windows->widget.y;
8188 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8189 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8190 (void) XMapRaised(display,windows->widget.id);
8191 windows->widget.mapped=MagickFalse;
8192 (void) XBell(display,0);
8194 Respond to X events.
8196 timer=time((time_t *) NULL)+Timeout;
8197 state=UpdateConfigurationState;
8200 if (time((time_t *) NULL) > timer)
8202 if (state & UpdateConfigurationState)
8205 Initialize Dismiss button information.
8207 XGetWidgetInfo(DismissButtonText,&dismiss_info);
8208 dismiss_info.width=(unsigned int) QuantumMargin+
8209 WidgetTextWidth(font_info,DismissButtonText);
8210 dismiss_info.height=(unsigned int) ((3*height) >> 1);
8211 dismiss_info.x=(int)
8212 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
8213 dismiss_info.y=(int)
8214 (windows->widget.height-(dismiss_info.height << 1));
8215 state&=(~UpdateConfigurationState);
8217 if (state & RedrawWidgetState)
8220 Redraw Notice widget.
8222 width=WidgetTextWidth(font_info,(char *) reason);
8223 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8224 y=(int) ((windows->widget.height >> 1)-(height << 1));
8225 (void) XDrawString(display,windows->widget.id,
8226 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
8227 if (description != (char *) NULL)
8229 width=WidgetTextWidth(font_info,(char *) description);
8230 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8232 (void) XDrawString(display,windows->widget.id,
8233 windows->widget.annotate_context,x,y,(char *) description,
8234 Extent(description));
8236 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8237 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8238 state&=(~RedrawWidgetState);
8241 Wait for next event.
8243 if (XCheckIfEvent(display,&event,XScreenEvent,(char *) windows) == MagickFalse)
8246 Do not block if delay > 0.
8248 XDelay(display,SuspendTime << 2);
8255 if (MatteIsActive(dismiss_info,event.xbutton))
8258 User pressed Dismiss button.
8260 dismiss_info.raised=MagickFalse;
8261 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8268 if (windows->widget.mapped == MagickFalse)
8270 if (dismiss_info.raised == MagickFalse)
8272 if (event.xbutton.window == windows->widget.id)
8273 if (MatteIsActive(dismiss_info,event.xbutton))
8275 dismiss_info.raised=MagickTrue;
8276 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8283 If client window delete message, exit.
8285 if (event.xclient.message_type != windows->wm_protocols)
8287 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8289 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8290 (Time) event.xclient.data.l[1]);
8293 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8295 if (event.xclient.window == windows->widget.id)
8302 case ConfigureNotify:
8305 Update widget configuration.
8307 if (event.xconfigure.window != windows->widget.id)
8309 if ((event.xconfigure.width == (int) windows->widget.width) &&
8310 (event.xconfigure.height == (int) windows->widget.height))
8312 windows->widget.width=(unsigned int)
8313 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8314 windows->widget.height=(unsigned int)
8315 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8316 state|=UpdateConfigurationState;
8321 if (event.xcrossing.window != windows->widget.id)
8323 state&=(~InactiveWidgetState);
8328 if (event.xexpose.window != windows->widget.id)
8330 if (event.xexpose.count != 0)
8332 state|=RedrawWidgetState;
8338 command[MaxTextExtent];
8344 Respond to a user key press.
8346 if (event.xkey.window != windows->widget.id)
8348 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8349 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8350 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8352 dismiss_info.raised=MagickFalse;
8353 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8361 if (event.xcrossing.window != windows->widget.id)
8363 state|=InactiveWidgetState;
8369 Discard pending button motion events.
8371 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8372 if (state & InactiveWidgetState)
8374 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
8377 Dismiss button status changed.
8379 dismiss_info.raised=
8380 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8381 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8389 } while ((state & ExitState) == 0);
8390 XSetCursorState(display,windows,MagickFalse);
8391 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8392 XCheckRefreshWindows(display,windows);
8396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8400 % X P r e f e r e n c e s W i d g e t %
8404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8406 % XPreferencesWidget() displays a Preferences widget with program preferences.
8407 % If the user presses the Apply button, the preferences are stored in a
8408 % configuration file in the users' home directory.
8410 % The format of the XPreferencesWidget method is:
8412 % MagickBooleanType XPreferencesWidget(Display *display,
8413 % XResourceInfo *resource_info,XWindows *windows)
8415 % A description of each parameter follows:
8417 % o display: Specifies a connection to an X server; returned from
8420 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8422 % o window: Specifies a pointer to a XWindows structure.
8425 MagickExport MagickBooleanType XPreferencesWidget(Display *display,
8426 XResourceInfo *resource_info,XWindows *windows)
8428 #define ApplyButtonText "Apply"
8429 #define CacheButtonText "%lu mega-bytes of memory in the undo edit cache "
8430 #define CancelButtonText "Cancel"
8431 #define NumberPreferences 8
8436 "display image centered on a backdrop",
8437 "confirm on program exit",
8438 "confirm on image edits",
8439 "correct image for display gamma",
8440 "display warning messages",
8441 "apply Floyd/Steinberg error diffusion to image",
8442 "use a shared colormap for colormapped X visuals",
8443 "display images as an X server pixmap"
8447 cache[MaxTextExtent];
8480 preferences_info[NumberPreferences];
8486 Determine Preferences widget attributes.
8488 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8489 assert(display != (Display *) NULL);
8490 assert(resource_info != (XResourceInfo *) NULL);
8491 assert(windows != (XWindows *) NULL);
8492 XCheckRefreshWindows(display,windows);
8493 font_info=windows->widget.font_info;
8494 text_width=WidgetTextWidth(font_info,CacheButtonText);
8495 for (i=0; i < NumberPreferences; i++)
8496 if (WidgetTextWidth(font_info,(char *) Preferences[i]) > text_width)
8497 text_width=WidgetTextWidth(font_info,(char *) Preferences[i]);
8498 width=WidgetTextWidth(font_info,ApplyButtonText);
8499 if (WidgetTextWidth(font_info,CancelButtonText) > width)
8500 width=WidgetTextWidth(font_info,CancelButtonText);
8501 width+=(unsigned int) QuantumMargin;
8502 height=(unsigned int) (font_info->ascent+font_info->descent);
8504 Position Preferences widget.
8506 windows->widget.width=(unsigned int) (MagickMax((int) (width << 1),
8507 (int) text_width)+6*QuantumMargin);
8508 windows->widget.min_width=(width << 1)+QuantumMargin;
8509 if (windows->widget.width < windows->widget.min_width)
8510 windows->widget.width=windows->widget.min_width;
8511 windows->widget.height=(unsigned int)
8512 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8513 windows->widget.min_height=(unsigned int)
8514 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8515 if (windows->widget.height < windows->widget.min_height)
8516 windows->widget.height=windows->widget.min_height;
8517 XConstrainWindowPosition(display,&windows->widget);
8519 Map Preferences widget.
8521 (void) CopyMagickString(windows->widget.name,"Preferences",MaxTextExtent);
8522 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8523 if (status != False)
8525 XSetWMName(display,windows->widget.id,&window_name);
8526 XSetWMIconName(display,windows->widget.id,&window_name);
8527 (void) XFree((void *) window_name.value);
8529 window_changes.width=(int) windows->widget.width;
8530 window_changes.height=(int) windows->widget.height;
8531 window_changes.x=windows->widget.x;
8532 window_changes.y=windows->widget.y;
8533 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8534 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8535 (void) XMapRaised(display,windows->widget.id);
8536 windows->widget.mapped=MagickFalse;
8538 Respond to X events.
8540 state=UpdateConfigurationState;
8541 XSetCursorState(display,windows,MagickTrue);
8544 if (state & UpdateConfigurationState)
8547 Initialize button information.
8549 XGetWidgetInfo(CancelButtonText,&cancel_info);
8550 cancel_info.width=width;
8551 cancel_info.height=(unsigned int) (3*height) >> 1;
8552 cancel_info.x=(int) windows->widget.width-cancel_info.width-
8553 (QuantumMargin << 1);
8554 cancel_info.y=(int) windows->widget.height-
8555 cancel_info.height-QuantumMargin;
8556 XGetWidgetInfo(ApplyButtonText,&apply_info);
8557 apply_info.width=width;
8558 apply_info.height=(unsigned int) (3*height) >> 1;
8559 apply_info.x=QuantumMargin << 1;
8560 apply_info.y=cancel_info.y;
8561 y=(int) (height << 1);
8562 for (i=0; i < NumberPreferences; i++)
8564 XGetWidgetInfo(Preferences[i],&preferences_info[i]);
8565 preferences_info[i].bevel_width--;
8566 preferences_info[i].width=(unsigned int) QuantumMargin >> 1;
8567 preferences_info[i].height=(unsigned int) QuantumMargin >> 1;
8568 preferences_info[i].x=QuantumMargin << 1;
8569 preferences_info[i].y=y;
8570 y+=height+(QuantumMargin >> 1);
8572 preferences_info[0].raised=resource_info->backdrop ==
8573 MagickFalse ? MagickTrue : MagickFalse;
8574 preferences_info[1].raised=resource_info->confirm_exit ==
8575 MagickFalse ? MagickTrue : MagickFalse;
8576 preferences_info[2].raised=resource_info->confirm_edit ==
8577 MagickFalse ? MagickTrue : MagickFalse;
8578 preferences_info[3].raised=resource_info->gamma_correct ==
8579 MagickFalse ? MagickTrue : MagickFalse;
8580 preferences_info[4].raised=resource_info->display_warnings ==
8581 MagickFalse ? MagickTrue : MagickFalse;
8582 preferences_info[5].raised=resource_info->quantize_info->dither ==
8583 MagickFalse ? MagickTrue : MagickFalse;
8584 preferences_info[6].raised=resource_info->colormap !=
8585 SharedColormap ? MagickTrue : MagickFalse;
8586 preferences_info[7].raised=resource_info->use_pixmap ==
8587 MagickFalse ? MagickTrue : MagickFalse;
8588 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8589 (unsigned long) resource_info->undo_cache);
8590 XGetWidgetInfo(cache,&cache_info);
8591 cache_info.bevel_width--;
8592 cache_info.width=(unsigned int) QuantumMargin >> 1;
8593 cache_info.height=(unsigned int) QuantumMargin >> 1;
8594 cache_info.x=QuantumMargin << 1;
8596 state&=(~UpdateConfigurationState);
8598 if (state & RedrawWidgetState)
8601 Redraw Preferences widget.
8603 XDrawBeveledButton(display,&windows->widget,&apply_info);
8604 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8605 for (i=0; i < NumberPreferences; i++)
8606 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8607 XDrawTriangleEast(display,&windows->widget,&cache_info);
8608 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8609 state&=(~RedrawWidgetState);
8612 Wait for next event.
8614 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
8619 if (MatteIsActive(apply_info,event.xbutton))
8622 User pressed Apply button.
8624 apply_info.raised=MagickFalse;
8625 XDrawBeveledButton(display,&windows->widget,&apply_info);
8628 if (MatteIsActive(cancel_info,event.xbutton))
8631 User pressed Cancel button.
8633 cancel_info.raised=MagickFalse;
8634 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8637 for (i=0; i < NumberPreferences; i++)
8638 if (MatteIsActive(preferences_info[i],event.xbutton))
8641 User pressed a Preferences button.
8643 preferences_info[i].raised=preferences_info[i].raised ==
8644 MagickFalse ? MagickTrue : MagickFalse;
8645 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8648 if (MatteIsActive(cache_info,event.xbutton))
8651 User pressed Cache button.
8653 x=cache_info.x+cache_info.width+cache_info.bevel_width+
8654 (QuantumMargin >> 1);
8655 y=cache_info.y+((cache_info.height-height) >> 1);
8656 width=WidgetTextWidth(font_info,cache);
8657 (void) XClearArea(display,windows->widget.id,x,y,width,height,
8659 resource_info->undo_cache<<=1;
8660 if (resource_info->undo_cache > 256)
8661 resource_info->undo_cache=1;
8662 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8663 (unsigned long) resource_info->undo_cache);
8664 cache_info.raised=MagickFalse;
8665 XDrawTriangleEast(display,&windows->widget,&cache_info);
8672 if (windows->widget.mapped == MagickFalse)
8674 if (apply_info.raised == MagickFalse)
8676 if (event.xbutton.window == windows->widget.id)
8677 if (MatteIsActive(apply_info,event.xbutton))
8679 apply_info.raised=MagickTrue;
8680 XDrawBeveledButton(display,&windows->widget,&apply_info);
8681 apply_info.raised=MagickFalse;
8683 if (cancel_info.raised == MagickFalse)
8685 if (event.xbutton.window == windows->widget.id)
8686 if (MatteIsActive(cancel_info,event.xbutton))
8688 cancel_info.raised=MagickTrue;
8689 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8691 if (cache_info.raised == MagickFalse)
8693 cache_info.raised=MagickTrue;
8694 XDrawTriangleEast(display,&windows->widget,&cache_info);
8701 If client window delete message, exit.
8703 if (event.xclient.message_type != windows->wm_protocols)
8705 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8707 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8708 (Time) event.xclient.data.l[1]);
8711 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8713 if (event.xclient.window == windows->widget.id)
8720 case ConfigureNotify:
8723 Update widget configuration.
8725 if (event.xconfigure.window != windows->widget.id)
8727 if ((event.xconfigure.width == (int) windows->widget.width) &&
8728 (event.xconfigure.height == (int) windows->widget.height))
8730 windows->widget.width=(unsigned int)
8731 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8732 windows->widget.height=(unsigned int)
8733 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8734 state|=UpdateConfigurationState;
8739 if (event.xcrossing.window != windows->widget.id)
8741 state&=(~InactiveWidgetState);
8746 if (event.xexpose.window != windows->widget.id)
8748 if (event.xexpose.count != 0)
8750 state|=RedrawWidgetState;
8756 command[MaxTextExtent];
8762 Respond to a user key press.
8764 if (event.xkey.window != windows->widget.id)
8766 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8767 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8768 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8770 apply_info.raised=MagickFalse;
8771 XDrawBeveledButton(display,&windows->widget,&apply_info);
8779 if (event.xcrossing.window != windows->widget.id)
8781 state|=InactiveWidgetState;
8787 Discard pending button motion events.
8789 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8790 if (state & InactiveWidgetState)
8792 if (apply_info.raised == MatteIsActive(apply_info,event.xmotion))
8795 Apply button status changed.
8798 apply_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8799 XDrawBeveledButton(display,&windows->widget,&apply_info);
8802 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
8805 Cancel button status changed.
8808 cancel_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8809 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8817 } while ((state & ExitState) == 0);
8818 XSetCursorState(display,windows,MagickFalse);
8819 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8820 XCheckRefreshWindows(display,windows);
8821 if (apply_info.raised)
8822 return(MagickFalse);
8824 Save user preferences to the client configuration file.
8826 resource_info->backdrop=
8827 preferences_info[0].raised == MagickFalse ? MagickTrue : MagickFalse;
8828 resource_info->confirm_exit=
8829 preferences_info[1].raised == MagickFalse ? MagickTrue : MagickFalse;
8830 resource_info->confirm_edit=
8831 preferences_info[2].raised == MagickFalse ? MagickTrue : MagickFalse;
8832 resource_info->gamma_correct=
8833 preferences_info[3].raised == MagickFalse ? MagickTrue : MagickFalse;
8834 resource_info->display_warnings=
8835 preferences_info[4].raised == MagickFalse ? MagickTrue : MagickFalse;
8836 resource_info->quantize_info->dither=
8837 preferences_info[5].raised == MagickFalse ? MagickTrue : MagickFalse;
8838 resource_info->colormap=SharedColormap;
8839 if (preferences_info[6].raised)
8840 resource_info->colormap=PrivateColormap;
8841 resource_info->use_pixmap=
8842 preferences_info[7].raised == MagickFalse ? MagickTrue : MagickFalse;
8843 XUserPreferences(resource_info);
8848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8852 % X P r o g r e s s M o n i t o r W i d g e t %
8856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8858 % XProgressMonitorWidget() displays the progress a task is making in
8859 % completing a task. A span of zero toggles the active status. An inactive
8860 % state disables the progress monitor.
8862 % The format of the XProgressMonitorWidget method is:
8864 % void XProgressMonitorWidget(Display *display,XWindows *windows,
8865 % const char *task,const MagickOffsetType offset,
8866 % const MagickSizeType span)
8868 % A description of each parameter follows:
8870 % o display: Specifies a connection to an X server; returned from
8873 % o window: Specifies a pointer to a XWindows structure.
8875 % o task: Identifies the task in progress.
8877 % o offset: Specifies the offset position within the span which represents
8878 % how much progress has been made in completing a task.
8880 % o span: Specifies the span relative to completing a task.
8883 MagickExport void XProgressMonitorWidget(Display *display,XWindows *windows,
8884 const char *task,const MagickOffsetType offset,const MagickSizeType span)
8892 assert(display != (Display *) NULL);
8893 assert(windows != (XWindows *) NULL);
8894 assert(task != (const char *) NULL);
8895 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",task);
8899 Update image windows if there is a pending expose event.
8901 while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
8902 (void) XCommandWidget(display,windows,(const char **) NULL,&event);
8903 while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
8904 XRefreshWindow(display,&windows->image,&event);
8905 while (XCheckTypedWindowEvent(display,windows->info.id,Expose,&event))
8906 if (monitor_info.text != (char *) NULL)
8907 XInfoWidget(display,windows,monitor_info.text);
8909 Draw progress monitor bar to represent percent completion of a task.
8911 if ((windows->info.mapped == MagickFalse) || (task != monitor_info.text))
8912 XInfoWidget(display,windows,task);
8913 width=(unsigned int) (((offset+1)*(windows->info.width-
8914 (2*monitor_info.x)))/span);
8915 if (width < monitor_info.width)
8917 monitor_info.raised=MagickTrue;
8918 XDrawWidgetText(display,&windows->info,&monitor_info);
8919 monitor_info.raised=MagickFalse;
8921 monitor_info.width=width;
8922 XDrawWidgetText(display,&windows->info,&monitor_info);
8923 (void) XFlush(display);
8927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8931 % X T e x t V i e w W i d g e t %
8935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8937 % XTextViewWidget() displays text in a Text View widget.
8939 % The format of the XTextViewWidget method is:
8941 % void XTextViewWidget(Display *display,const XResourceInfo *resource_info,
8942 % XWindows *windows,const MagickBooleanType mono,const char *title,
8943 % const char **textlist)
8945 % A description of each parameter follows:
8947 % o display: Specifies a connection to an X server; returned from
8950 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8952 % o window: Specifies a pointer to a XWindows structure.
8954 % o mono: Use mono-spaced font when displaying text.
8956 % o title: This character string is displayed at the top of the widget
8959 % o textlist: This string list is displayed within the Text View widget.
8962 MagickExport void XTextViewWidget(Display *display,
8963 const XResourceInfo *resource_info,XWindows *windows,
8964 const MagickBooleanType mono,const char *title,const char **textlist)
8966 #define DismissButtonText "Dismiss"
8969 primary_selection[MaxTextExtent];
8974 static MagickStatusType
8975 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
9015 Convert text string to a text list.
9017 assert(display != (Display *) NULL);
9018 assert(resource_info != (XResourceInfo *) NULL);
9019 assert(windows != (XWindows *) NULL);
9020 assert(title != (const char *) NULL);
9021 assert(textlist != (const char **) NULL);
9022 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
9023 XSetCursorState(display,windows,MagickTrue);
9024 XCheckRefreshWindows(display,windows);
9025 if (textlist == (const char **) NULL)
9027 XNoticeWidget(display,windows,"No text to view:",(char *) NULL);
9031 Determine Text View widget attributes.
9033 font_info=windows->widget.font_info;
9034 text_info=(XFontStruct *) NULL;
9035 if (mono != MagickFalse)
9036 text_info=XBestFont(display,resource_info,MagickTrue);
9037 if (text_info == (XFontStruct *) NULL)
9038 text_info=windows->widget.font_info;
9040 for (i=0; textlist[i] != (char *) NULL; i++)
9041 if (WidgetTextWidth(text_info,(char *) textlist[i]) > text_width)
9042 text_width=(unsigned int) XTextWidth(text_info,(char *) textlist[i],
9043 MagickMin(Extent(textlist[i]),160));
9044 lines=(unsigned int) i;
9045 width=WidgetTextWidth(font_info,DismissButtonText);
9046 width+=QuantumMargin;
9047 height=(unsigned int) (text_info->ascent+text_info->descent);
9049 Position Text View widget.
9051 windows->widget.width=(unsigned int) (MagickMin((int) text_width,
9052 (int) MaxTextWidth)+5*QuantumMargin);
9053 windows->widget.min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
9054 if (windows->widget.width < windows->widget.min_width)
9055 windows->widget.width=windows->widget.min_width;
9056 windows->widget.height=(unsigned int) (MagickMin(MagickMax((int) lines,3),32)*
9057 height+((13*height) >> 1)+((9*QuantumMargin) >> 1));
9058 windows->widget.min_height=(unsigned int) (3*height+((13*height) >> 1)+((9*
9059 QuantumMargin) >> 1));
9060 if (windows->widget.height < windows->widget.min_height)
9061 windows->widget.height=windows->widget.min_height;
9062 XConstrainWindowPosition(display,&windows->widget);
9064 Map Text View widget.
9066 (void) CopyMagickString(windows->widget.name,title,MaxTextExtent);
9067 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
9068 if (status != False)
9070 XSetWMName(display,windows->widget.id,&window_name);
9071 XSetWMIconName(display,windows->widget.id,&window_name);
9072 (void) XFree((void *) window_name.value);
9074 window_changes.width=(int) windows->widget.width;
9075 window_changes.height=(int) windows->widget.height;
9076 window_changes.x=windows->widget.x;
9077 window_changes.y=windows->widget.y;
9078 (void) XReconfigureWMWindow(display,windows->widget.id,
9079 windows->widget.screen,(unsigned int) mask,&window_changes);
9080 (void) XMapRaised(display,windows->widget.id);
9081 windows->widget.mapped=MagickFalse;
9083 Respond to X events.
9085 XGetWidgetInfo((char *) NULL,&slider_info);
9086 XGetWidgetInfo((char *) NULL,&north_info);
9087 XGetWidgetInfo((char *) NULL,&south_info);
9088 XGetWidgetInfo((char *) NULL,&expose_info);
9090 delay=SuspendTime << 2;
9091 height=(unsigned int) (font_info->ascent+font_info->descent);
9092 state=UpdateConfigurationState;
9095 if (state & UpdateConfigurationState)
9101 Initialize button information.
9103 XGetWidgetInfo(DismissButtonText,&dismiss_info);
9104 dismiss_info.width=width;
9105 dismiss_info.height=(unsigned int) ((3*height) >> 1);
9106 dismiss_info.x=(int) windows->widget.width-dismiss_info.width-
9108 dismiss_info.y=(int) windows->widget.height-dismiss_info.height-
9111 Initialize scroll information.
9113 XGetWidgetInfo((char *) NULL,&scroll_info);
9114 scroll_info.bevel_width--;
9115 scroll_info.width=height;
9116 scroll_info.height=(unsigned int) (dismiss_info.y-((5*QuantumMargin) >>
9118 scroll_info.x=(int) windows->widget.width-QuantumMargin-
9120 scroll_info.y=(3*QuantumMargin) >> 1;
9121 scroll_info.raised=MagickFalse;
9122 scroll_info.trough=MagickTrue;
9123 north_info=scroll_info;
9124 north_info.raised=MagickTrue;
9125 north_info.width-=(north_info.bevel_width << 1);
9126 north_info.height=north_info.width-1;
9127 north_info.x+=north_info.bevel_width;
9128 north_info.y+=north_info.bevel_width;
9129 south_info=north_info;
9130 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
9133 slider_info=north_info;
9135 slider_info.width-=2;
9136 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
9137 slider_info.bevel_width+2;
9138 slider_info.height=scroll_info.height-((slider_info.min_y-
9139 scroll_info.y+1) << 1)+4;
9140 visible_lines=scroll_info.height/(text_info->ascent+text_info->descent+
9141 ((text_info->ascent+text_info->descent) >> 3));
9142 if (lines > visible_lines)
9143 slider_info.height=(unsigned int) (visible_lines*slider_info.height)/
9145 slider_info.max_y=south_info.y-south_info.bevel_width-
9146 slider_info.bevel_width-2;
9147 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
9148 slider_info.y=slider_info.min_y;
9149 expose_info=scroll_info;
9150 expose_info.y=slider_info.y;
9152 Initialize list information.
9154 XGetWidgetInfo((char *) NULL,&list_info);
9155 list_info.raised=MagickFalse;
9156 list_info.bevel_width--;
9157 list_info.width=(unsigned int) scroll_info.x-((3*QuantumMargin) >> 1);
9158 list_info.height=scroll_info.height;
9159 list_info.x=QuantumMargin;
9160 list_info.y=scroll_info.y;
9162 Initialize selection information.
9164 XGetWidgetInfo((char *) NULL,&selection_info);
9165 selection_info.center=MagickFalse;
9166 selection_info.width=list_info.width;
9167 selection_info.height=(unsigned int)
9168 (9*(text_info->ascent+text_info->descent)) >> 3;
9169 selection_info.x=list_info.x;
9170 state&=(~UpdateConfigurationState);
9172 if (state & RedrawWidgetState)
9175 Redraw Text View window.
9177 XDrawBeveledMatte(display,&windows->widget,&list_info);
9178 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
9179 XDrawTriangleNorth(display,&windows->widget,&north_info);
9180 XDrawBeveledButton(display,&windows->widget,&slider_info);
9181 XDrawTriangleSouth(display,&windows->widget,&south_info);
9182 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9183 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
9184 selection_info.id=(~0);
9185 state|=RedrawListState;
9186 state&=(~RedrawWidgetState);
9188 if (state & RedrawListState)
9191 Determine slider id and position.
9193 if (slider_info.id >= (int) (lines-visible_lines))
9194 slider_info.id=(int) lines-visible_lines;
9195 if ((slider_info.id < 0) || (lines <= visible_lines))
9197 slider_info.y=slider_info.min_y;
9200 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/lines;
9201 if (slider_info.id != selection_info.id)
9204 Redraw scroll bar and text.
9206 windows->widget.font_info=text_info;
9207 (void) XSetFont(display,windows->widget.annotate_context,
9209 (void) XSetFont(display,windows->widget.highlight_context,
9211 selection_info.id=slider_info.id;
9212 selection_info.y=list_info.y+(height >> 3)+2;
9213 for (i=0; i < (int) visible_lines; i++)
9215 selection_info.raised=
9216 (slider_info.id+i) != list_info.id ? MagickTrue : MagickFalse;
9217 selection_info.text=(char *) NULL;
9218 if ((slider_info.id+i) < (int) lines)
9219 selection_info.text=(char *) textlist[slider_info.id+i];
9220 XDrawWidgetText(display,&windows->widget,&selection_info);
9221 selection_info.y+=(int) selection_info.height;
9223 windows->widget.font_info=font_info;
9224 (void) XSetFont(display,windows->widget.annotate_context,
9226 (void) XSetFont(display,windows->widget.highlight_context,
9231 if (slider_info.y > expose_info.y)
9233 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
9234 expose_info.y=slider_info.y-expose_info.height-
9235 slider_info.bevel_width-1;
9239 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
9240 expose_info.y=slider_info.y+slider_info.height+
9241 slider_info.bevel_width+1;
9243 XDrawTriangleNorth(display,&windows->widget,&north_info);
9244 XDrawMatte(display,&windows->widget,&expose_info);
9245 XDrawBeveledButton(display,&windows->widget,&slider_info);
9246 XDrawTriangleSouth(display,&windows->widget,&south_info);
9247 expose_info.y=slider_info.y;
9249 state&=(~RedrawListState);
9252 Wait for next event.
9254 if (north_info.raised && south_info.raised)
9255 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
9259 Brief delay before advancing scroll bar.
9261 XDelay(display,delay);
9263 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
9264 if (north_info.raised == MagickFalse)
9265 if (slider_info.id > 0)
9271 state|=RedrawListState;
9273 if (south_info.raised == MagickFalse)
9274 if (slider_info.id < (int) lines)
9280 state|=RedrawListState;
9282 if (event.type != ButtonRelease)
9289 if (MatteIsActive(slider_info,event.xbutton))
9294 slider_info.active=MagickTrue;
9297 if (MatteIsActive(north_info,event.xbutton))
9298 if (slider_info.id > 0)
9303 north_info.raised=MagickFalse;
9305 state|=RedrawListState;
9308 if (MatteIsActive(south_info,event.xbutton))
9309 if (slider_info.id < (int) lines)
9314 south_info.raised=MagickFalse;
9316 state|=RedrawListState;
9319 if (MatteIsActive(scroll_info,event.xbutton))
9324 if (event.xbutton.y < slider_info.y)
9325 slider_info.id-=(visible_lines-1);
9327 slider_info.id+=(visible_lines-1);
9328 state|=RedrawListState;
9331 if (MatteIsActive(dismiss_info,event.xbutton))
9334 User pressed Dismiss button.
9336 dismiss_info.raised=MagickFalse;
9337 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9340 if (MatteIsActive(list_info,event.xbutton))
9349 User pressed list matte.
9351 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
9352 selection_info.height;
9353 if (id >= (int) lines)
9355 if (id != list_info.id)
9358 click_time=event.xbutton.time;
9362 if (event.xbutton.time >= (click_time+DoubleClick))
9364 click_time=event.xbutton.time;
9367 click_time=event.xbutton.time;
9369 Become the XA_PRIMARY selection owner.
9371 (void) CopyMagickString(primary_selection,textlist[list_info.id],
9373 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
9374 event.xbutton.time);
9375 if (XGetSelectionOwner(display,XA_PRIMARY) != windows->widget.id)
9377 selection_info.id=(~0);
9379 state|=RedrawListState;
9386 if (windows->widget.mapped == MagickFalse)
9388 if (north_info.raised == MagickFalse)
9391 User released up button.
9393 delay=SuspendTime << 2;
9394 north_info.raised=MagickTrue;
9395 XDrawTriangleNorth(display,&windows->widget,&north_info);
9397 if (south_info.raised == MagickFalse)
9400 User released down button.
9402 delay=SuspendTime << 2;
9403 south_info.raised=MagickTrue;
9404 XDrawTriangleSouth(display,&windows->widget,&south_info);
9406 if (slider_info.active)
9409 Stop tracking slider.
9411 slider_info.active=MagickFalse;
9414 if (dismiss_info.raised == MagickFalse)
9416 if (event.xbutton.window == windows->widget.id)
9417 if (MatteIsActive(dismiss_info,event.xbutton))
9419 dismiss_info.raised=MagickTrue;
9420 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9427 If client window delete message, exit.
9429 if (event.xclient.message_type != windows->wm_protocols)
9431 if (*event.xclient.data.l == (int) windows->wm_take_focus)
9433 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
9434 (Time) event.xclient.data.l[1]);
9437 if (*event.xclient.data.l != (int) windows->wm_delete_window)
9439 if (event.xclient.window == windows->widget.id)
9446 case ConfigureNotify:
9449 Update widget configuration.
9451 if (event.xconfigure.window != windows->widget.id)
9453 if ((event.xconfigure.width == (int) windows->widget.width) &&
9454 (event.xconfigure.height == (int) windows->widget.height))
9456 windows->widget.width=(unsigned int)
9457 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
9458 windows->widget.height=(unsigned int)
9459 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
9460 state|=UpdateConfigurationState;
9465 if (event.xcrossing.window != windows->widget.id)
9467 state&=(~InactiveWidgetState);
9472 if (event.xexpose.window != windows->widget.id)
9474 if (event.xexpose.count != 0)
9476 state|=RedrawWidgetState;
9482 command[MaxTextExtent];
9491 Respond to a user key press.
9493 if (event.xkey.window != windows->widget.id)
9495 length=XLookupString((XKeyEvent *) &event.xkey,command,
9496 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9497 *(command+length)='\0';
9498 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
9500 dismiss_info.raised=MagickFalse;
9501 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9505 if (AreaIsActive(scroll_info,event.xkey))
9510 switch ((int) key_symbol)
9533 slider_info.id-=visible_lines;
9539 slider_info.id+=visible_lines;
9545 slider_info.id=(int) lines;
9549 state|=RedrawListState;
9558 if (event.xcrossing.window != windows->widget.id)
9560 state|=InactiveWidgetState;
9572 Discard pending button motion events.
9574 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9575 if (slider_info.active)
9580 slider_info.y=event.xmotion.y-
9581 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
9582 if (slider_info.y < slider_info.min_y)
9583 slider_info.y=slider_info.min_y;
9584 if (slider_info.y > slider_info.max_y)
9585 slider_info.y=slider_info.max_y;
9587 if (slider_info.y != slider_info.min_y)
9588 slider_info.id=(int) (lines*(slider_info.y-slider_info.min_y+1))/
9589 (slider_info.max_y-slider_info.min_y+1);
9590 state|=RedrawListState;
9593 if (state & InactiveWidgetState)
9595 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
9598 Dismiss button status changed.
9600 dismiss_info.raised=
9601 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
9602 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9607 case SelectionClear:
9610 selection_info.id=(~0);
9611 state|=RedrawListState;
9614 case SelectionRequest:
9619 XSelectionRequestEvent
9622 if (list_info.id == (~0))
9625 Set primary selection.
9627 request=(&(event.xselectionrequest));
9628 (void) XChangeProperty(request->display,request->requestor,
9629 request->property,request->target,8,PropModeReplace,
9630 (unsigned char *) primary_selection,Extent(primary_selection));
9631 notify.type=SelectionNotify;
9632 notify.send_event=MagickTrue;
9633 notify.display=request->display;
9634 notify.requestor=request->requestor;
9635 notify.selection=request->selection;
9636 notify.target=request->target;
9637 notify.time=request->time;
9638 if (request->property == None)
9639 notify.property=request->target;
9641 notify.property=request->property;
9642 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
9643 (XEvent *) ¬ify);
9648 } while ((state & ExitState) == 0);
9649 if (text_info != windows->widget.font_info)
9650 (void) XFreeFont(display,text_info);
9651 XSetCursorState(display,windows,MagickFalse);
9652 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
9653 XCheckRefreshWindows(display,windows);