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/token-private.h"
55 #include "MagickCore/utility.h"
56 #include "MagickCore/utility-private.h"
57 #include "MagickCore/xwindow-private.h"
58 #include "MagickCore/widget.h"
59 #include "MagickCore/widget-private.h"
61 #if defined(MAGICKCORE_X11_DELEGATE)
66 #define AreaIsActive(matte_info,position) ( \
67 ((position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
68 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
69 ? MagickTrue : MagickFalse)
70 #define Extent(s) ((int) strlen(s))
71 #define MatteIsActive(matte_info,position) ( \
72 ((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \
73 (position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
74 (position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) && \
75 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
76 ? MagickTrue : MagickFalse)
77 #define MaxTextWidth ((unsigned int) (255*XTextWidth(font_info,"_",1)))
78 #define MinTextWidth (26*XTextWidth(font_info,"_",1))
79 #define QuantumMargin MagickMax(font_info->max_bounds.width,12)
80 #define WidgetTextWidth(font_info,text) \
81 ((unsigned int) XTextWidth(font_info,text,Extent(text)))
82 #define WindowIsActive(window_info,position) ( \
83 ((position.x >= 0) && (position.y >= 0) && \
84 (position.x < (int) window_info.width) && \
85 (position.y < (int) window_info.height)) ? MagickTrue : MagickFalse)
92 ControlState = 0x0001,
93 InactiveWidgetState = 0x0004,
94 JumpListState = 0x0008,
95 RedrawActionState = 0x0010,
96 RedrawListState = 0x0020,
97 RedrawWidgetState = 0x0040,
98 UpdateListState = 0x0100
102 Typedef declarations.
104 typedef struct _XWidgetInfo
134 Variable declarations.
139 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
140 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
144 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
145 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
147 *selection_info = (XWidgetInfo *) NULL,
150 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
151 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
155 Constant declarations.
165 XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *),
166 XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType),
167 XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType),
168 XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType);
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 % D e s t r o y X W i d g e t %
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 % DestroyXWidget() destroys resources associated with the X widget.
183 % The format of the DestroyXWidget method is:
185 % void DestroyXWidget()
187 % A description of each parameter follows:
190 MagickPrivate void DestroyXWidget(void)
192 if (selection_info != (XWidgetInfo *) NULL)
193 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 + X D r a w B e v e l %
205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 % XDrawBevel() "sets off" an area with a highlighted upper and left bevel and
208 % a shadowed lower and right bevel. The highlighted and shadowed bevels
209 % create a 3-D effect.
211 % The format of the XDrawBevel function is:
213 % XDrawBevel(display,window_info,bevel_info)
215 % A description of each parameter follows:
217 % o display: Specifies a pointer to the Display structure; returned from
220 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
222 % o bevel_info: Specifies a pointer to a XWidgetInfo structure. It
223 % contains the extents of the bevel.
226 static void XDrawBevel(Display *display,const XWindowInfo *window_info,
227 const XWidgetInfo *bevel_info)
242 Draw upper and left beveled border.
245 y1=bevel_info->y+bevel_info->height;
246 x2=bevel_info->x+bevel_info->width;
248 bevel_width=bevel_info->bevel_width;
255 points[3].x=x2+bevel_width;
256 points[3].y=y2-bevel_width;
257 points[4].x=x1-bevel_width;
258 points[4].y=y2-bevel_width;
259 points[5].x=x1-bevel_width;
260 points[5].y=y1+bevel_width;
261 XSetBevelColor(display,window_info,bevel_info->raised);
262 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
263 points,6,Complex,CoordModeOrigin);
265 Draw lower and right beveled border.
273 points[3].x=x2+bevel_width;
274 points[3].y=y2-bevel_width;
275 points[4].x=x2+bevel_width;
276 points[4].y=y1+bevel_width;
277 points[5].x=x1-bevel_width;
278 points[5].y=y1+bevel_width;
279 XSetBevelColor(display,window_info,!bevel_info->raised);
280 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
281 points,6,Complex,CoordModeOrigin);
282 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290 + X D r a w B e v e l e d B u t t o n %
294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 % XDrawBeveledButton() draws a button with a highlighted upper and left bevel
297 % and a shadowed lower and right bevel. The highlighted and shadowed bevels
298 % create a 3-D effect.
300 % The format of the XDrawBeveledButton function is:
302 % XDrawBeveledButton(display,window_info,button_info)
304 % A description of each parameter follows:
306 % o display: Specifies a pointer to the Display structure; returned from
309 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
311 % o button_info: Specifies a pointer to a XWidgetInfo structure. It
312 % contains the extents of the button.
316 static inline int MagickAbsoluteValue(const int x)
323 static inline int MagickMax(const int x,const int y)
330 static inline int MagickMin(const int x,const int y)
337 static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info,
338 const XWidgetInfo *button_info)
356 XDrawBevel(display,window_info,button_info);
357 XSetMatteColor(display,window_info,button_info->raised);
358 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
359 button_info->x,button_info->y,button_info->width,button_info->height);
360 x=button_info->x-button_info->bevel_width-1;
361 y=button_info->y-button_info->bevel_width-1;
362 (void) XSetForeground(display,window_info->widget_context,
363 window_info->pixel_info->trough_color.pixel);
364 if (button_info->raised || (window_info->depth == 1))
365 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
366 x,y,button_info->width+(button_info->bevel_width << 1)+1,
367 button_info->height+(button_info->bevel_width << 1)+1);
368 if (button_info->text == (char *) NULL)
373 crop_info.width=(unsigned short) button_info->width;
374 crop_info.height=(unsigned short) button_info->height;
375 crop_info.x=button_info->x;
376 crop_info.y=button_info->y;
380 font_info=window_info->font_info;
381 width=WidgetTextWidth(font_info,button_info->text);
382 x=button_info->x+(QuantumMargin >> 1);
383 if (button_info->center)
384 x=button_info->x+(button_info->width >> 1)-(width >> 1);
385 y=button_info->y+((button_info->height-
386 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
387 if ((int) button_info->width == (QuantumMargin >> 1))
390 Option button-- write label to right of button.
392 XSetTextColor(display,window_info,MagickTrue);
393 x=button_info->x+button_info->width+button_info->bevel_width+
394 (QuantumMargin >> 1);
395 (void) XDrawString(display,window_info->id,window_info->widget_context,
396 x,y,button_info->text,Extent(button_info->text));
399 (void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info,
401 XSetTextColor(display,window_info,button_info->raised);
402 (void) XDrawString(display,window_info->id,window_info->widget_context,x,y,
403 button_info->text,Extent(button_info->text));
404 (void) XSetClipMask(display,window_info->widget_context,None);
405 if (button_info->raised == MagickFalse)
406 XDelay(display,SuspendTime << 2);
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414 + X D r a w B e v e l e d M a t t e %
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 % XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and
421 % a highlighted lower and right bevel. The highlighted and shadowed bevels
422 % create a 3-D effect.
424 % The format of the XDrawBeveledMatte function is:
426 % XDrawBeveledMatte(display,window_info,matte_info)
428 % A description of each parameter follows:
430 % o display: Specifies a pointer to the Display structure; returned from
433 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
435 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
436 % contains the extents of the matte.
439 static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info,
440 const XWidgetInfo *matte_info)
445 XDrawBevel(display,window_info,matte_info);
446 XDrawMatte(display,window_info,matte_info);
450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 + X D r a w M a t t e %
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460 % XDrawMatte() fills a rectangular area with the matte color.
462 % The format of the XDrawMatte function is:
464 % XDrawMatte(display,window_info,matte_info)
466 % A description of each parameter follows:
468 % o display: Specifies a pointer to the Display structure; returned from
471 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
473 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
474 % contains the extents of the matte.
477 static void XDrawMatte(Display *display,const XWindowInfo *window_info,
478 const XWidgetInfo *matte_info)
483 if ((matte_info->trough == MagickFalse) || (window_info->depth == 1))
484 (void) XFillRectangle(display,window_info->id,
485 window_info->highlight_context,matte_info->x,matte_info->y,
486 matte_info->width,matte_info->height);
489 (void) XSetForeground(display,window_info->widget_context,
490 window_info->pixel_info->trough_color.pixel);
491 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
492 matte_info->x,matte_info->y,matte_info->width,matte_info->height);
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 + X D r a w M a t t e T e x t %
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 % XDrawMatteText() draws a matte with text. If the text exceeds the extents
508 % of the text, a portion of the text relative to the cursor is displayed.
510 % The format of the XDrawMatteText function is:
512 % XDrawMatteText(display,window_info,text_info)
514 % A description of each parameter follows:
516 % o display: Specifies a pointer to the Display structure; returned from
519 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
521 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
522 % contains the extents of the text.
525 static void XDrawMatteText(Display *display,const XWindowInfo *window_info,
526 XWidgetInfo *text_info)
552 XSetMatteColor(display,window_info,MagickFalse);
553 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
554 text_info->x,text_info->y,text_info->width,text_info->height);
555 if (text_info->text == (char *) NULL)
557 XSetTextColor(display,window_info,text_info->highlight);
558 font_info=window_info->font_info;
559 x=text_info->x+(QuantumMargin >> 2);
560 y=text_info->y+font_info->ascent+(text_info->height >> 2);
561 width=text_info->width-(QuantumMargin >> 1);
562 height=(unsigned int) (font_info->ascent+font_info->descent);
563 if (*text_info->text == '\0')
566 No text-- just draw cursor.
568 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
575 crop_info.width=(unsigned short) text_info->width;
576 crop_info.height=(unsigned short) text_info->height;
577 crop_info.x=text_info->x;
578 crop_info.y=text_info->y;
580 Determine beginning of the visible text.
582 if (text_info->cursor < text_info->marker)
583 text_info->marker=text_info->cursor;
586 text=text_info->marker;
587 if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) >
590 text=text_info->text;
591 for (i=0; i < Extent(text); i++)
593 n=XTextWidth(font_info,(char *) text+i,(int)
594 (text_info->cursor-text-i));
595 if (n <= (int) width)
598 text_info->marker=(char *) text+i;
602 Draw text and cursor.
604 if (text_info->highlight == MagickFalse)
606 (void) XSetClipRectangles(display,window_info->widget_context,0,0,
607 &crop_info,1,Unsorted);
608 (void) XDrawString(display,window_info->id,window_info->widget_context,
609 x,y,text_info->marker,Extent(text_info->marker));
610 (void) XSetClipMask(display,window_info->widget_context,None);
614 (void) XSetClipRectangles(display,window_info->annotate_context,0,0,
615 &crop_info,1,Unsorted);
616 width=WidgetTextWidth(font_info,text_info->marker);
617 (void) XFillRectangle(display,window_info->id,
618 window_info->annotate_context,x,y-font_info->ascent,width,height);
619 (void) XSetClipMask(display,window_info->annotate_context,None);
620 (void) XSetClipRectangles(display,window_info->highlight_context,0,0,
621 &crop_info,1,Unsorted);
622 (void) XDrawString(display,window_info->id,
623 window_info->highlight_context,x,y,text_info->marker,
624 Extent(text_info->marker));
625 (void) XSetClipMask(display,window_info->highlight_context,None);
627 x+=XTextWidth(font_info,text_info->marker,(int)
628 (text_info->cursor-text_info->marker));
629 (void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3,
634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638 + X D r a w T r i a n g l e E a s t %
642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 % XDrawTriangleEast() draws a triangle with a highlighted left bevel and a
645 % shadowed right and lower bevel. The highlighted and shadowed bevels create
648 % The format of the XDrawTriangleEast function is:
650 % XDrawTriangleEast(display,window_info,triangle_info)
652 % A description of each parameter follows:
654 % o display: Specifies a pointer to the Display structure; returned from
657 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
659 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
660 % contains the extents of the triangle.
663 static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info,
664 const XWidgetInfo *triangle_info)
688 x2=triangle_info->x+triangle_info->width;
689 y2=triangle_info->y+(triangle_info->height >> 1);
691 y3=triangle_info->y+triangle_info->height;
692 bevel_width=triangle_info->bevel_width;
699 XSetMatteColor(display,window_info,triangle_info->raised);
700 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
701 points,3,Complex,CoordModeOrigin);
709 points[2].x=x3-bevel_width;
710 points[2].y=y3+bevel_width;
711 points[3].x=x2+bevel_width;
713 XSetBevelColor(display,window_info,!triangle_info->raised);
714 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
715 points,4,Complex,CoordModeOrigin);
723 points[2].x=x1-bevel_width+1;
724 points[2].y=y1-bevel_width;
725 points[3].x=x3-bevel_width+1;
726 points[3].y=y3+bevel_width;
727 XSetBevelColor(display,window_info,triangle_info->raised);
728 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
729 points,4,Complex,CoordModeOrigin);
737 points[2].x=x2+bevel_width;
739 points[3].x=x1-bevel_width;
740 points[3].y=y1-bevel_width;
741 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
742 points,4,Complex,CoordModeOrigin);
743 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
744 if (triangle_info->text == (char *) NULL)
747 Write label to right of triangle.
749 font_info=window_info->font_info;
750 XSetTextColor(display,window_info,MagickTrue);
751 x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+
752 (QuantumMargin >> 1);
753 y1=triangle_info->y+((triangle_info->height-
754 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
755 (void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1,
756 triangle_info->text,Extent(triangle_info->text));
760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 + X D r a w T r i a n g l e N o r t h %
768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 % XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a
771 % shadowed right and lower bevel. The highlighted and shadowed bevels create
774 % The format of the XDrawTriangleNorth function is:
776 % XDrawTriangleNorth(display,window_info,triangle_info)
778 % A description of each parameter follows:
780 % o display: Specifies a pointer to the Display structure; returned from
783 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
785 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
786 % contains the extents of the triangle.
789 static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info,
790 const XWidgetInfo *triangle_info)
810 y1=triangle_info->y+triangle_info->height;
811 x2=triangle_info->x+(triangle_info->width >> 1);
813 x3=triangle_info->x+triangle_info->width;
814 y3=triangle_info->y+triangle_info->height;
815 bevel_width=triangle_info->bevel_width;
822 XSetMatteColor(display,window_info,triangle_info->raised);
823 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
824 points,3,Complex,CoordModeOrigin);
833 points[2].y=y2-bevel_width-2;
834 points[3].x=x1-bevel_width-1;
835 points[3].y=y1+bevel_width;
836 XSetBevelColor(display,window_info,triangle_info->raised);
837 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
838 points,4,Complex,CoordModeOrigin);
846 points[2].x=x3+bevel_width;
847 points[2].y=y3+bevel_width;
849 points[3].y=y2-bevel_width;
850 XSetBevelColor(display,window_info,!triangle_info->raised);
851 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
852 points,4,Complex,CoordModeOrigin);
860 points[2].x=x1-bevel_width;
861 points[2].y=y1+bevel_width;
862 points[3].x=x3+bevel_width;
863 points[3].y=y3+bevel_width;
864 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
865 points,4,Complex,CoordModeOrigin);
866 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874 + X D r a w T r i a n g l e S o u t h %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880 % XDrawTriangleSouth() draws a border with a highlighted left and right bevel
881 % and a shadowed lower bevel. The highlighted and shadowed bevels create a
884 % The format of the XDrawTriangleSouth function is:
886 % XDrawTriangleSouth(display,window_info,triangle_info)
888 % A description of each parameter follows:
890 % o display: Specifies a pointer to the Display structure; returned from
893 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
895 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
896 % contains the extents of the triangle.
899 static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info,
900 const XWidgetInfo *triangle_info)
921 x2=triangle_info->x+(triangle_info->width >> 1);
922 y2=triangle_info->y+triangle_info->height;
923 x3=triangle_info->x+triangle_info->width;
925 bevel_width=triangle_info->bevel_width;
932 XSetMatteColor(display,window_info,triangle_info->raised);
933 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
934 points,3,Complex,CoordModeOrigin);
942 points[2].x=x1-bevel_width;
943 points[2].y=y1-bevel_width;
944 points[3].x=x3+bevel_width;
945 points[3].y=y3-bevel_width;
946 XSetBevelColor(display,window_info,triangle_info->raised);
947 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
948 points,4,Complex,CoordModeOrigin);
955 points[1].y=y3-bevel_width;
956 points[2].x=x3+bevel_width;
957 points[2].y=y3-bevel_width;
959 points[3].y=y2+bevel_width;
960 XSetBevelColor(display,window_info,!triangle_info->raised);
961 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
962 points,4,Complex,CoordModeOrigin);
971 points[2].y=y2+bevel_width;
972 points[3].x=x1-bevel_width;
973 points[3].y=y1-bevel_width;
974 XSetBevelColor(display,window_info,triangle_info->raised);
975 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
976 points,4,Complex,CoordModeOrigin);
977 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985 + X D r a w W i d g e t T e x t %
989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 % XDrawWidgetText() first clears the widget and draws a text string justifed
992 % left (or center) in the x-direction and centered within the y-direction.
994 % The format of the XDrawWidgetText function is:
996 % XDrawWidgetText(display,window_info,text_info)
998 % A description of each parameter follows:
1000 % o display: Specifies a pointer to the Display structure; returned from
1003 % o window_info: Specifies a pointer to a XWindowText structure.
1005 % o text_info: Specifies a pointer to XWidgetInfo structure.
1008 static void XDrawWidgetText(Display *display,const XWindowInfo *window_info,
1009 XWidgetInfo *text_info)
1029 Clear the text area.
1031 widget_context=window_info->annotate_context;
1032 if (text_info->raised)
1033 (void) XClearArea(display,window_info->id,text_info->x,text_info->y,
1034 text_info->width,text_info->height,MagickFalse);
1037 (void) XFillRectangle(display,window_info->id,widget_context,text_info->x,
1038 text_info->y,text_info->width,text_info->height);
1039 widget_context=window_info->highlight_context;
1041 if (text_info->text == (char *) NULL)
1043 if (*text_info->text == '\0')
1046 Set cropping region.
1048 font_info=window_info->font_info;
1049 crop_info.width=(unsigned short) text_info->width;
1050 crop_info.height=(unsigned short) text_info->height;
1051 crop_info.x=text_info->x;
1052 crop_info.y=text_info->y;
1056 width=WidgetTextWidth(font_info,text_info->text);
1057 x=text_info->x+(QuantumMargin >> 1);
1058 if (text_info->center)
1059 x=text_info->x+(text_info->width >> 1)-(width >> 1);
1060 if (text_info->raised)
1061 if (width > (text_info->width-QuantumMargin))
1062 x+=(text_info->width-QuantumMargin-width);
1063 height=(unsigned int) (font_info->ascent+font_info->descent);
1064 y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent;
1065 (void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted);
1066 (void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text,
1067 Extent(text_info->text));
1068 (void) XSetClipMask(display,widget_context,None);
1069 if (x < text_info->x)
1070 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
1071 text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1);
1075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 + X E d i t T e x t %
1083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1085 % XEditText() edits a text string as indicated by the key symbol.
1087 % The format of the XEditText function is:
1089 % XEditText(display,text_info,key_symbol,text,state)
1091 % A description of each parameter follows:
1093 % o display: Specifies a connection to an X server; returned from
1096 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
1097 % contains the extents of the text.
1099 % o key_symbol: A X11 KeySym that indicates what editing function to
1100 % perform to the text.
1102 % o text: A character string to insert into the text.
1104 % o state: An size_t that indicates whether the key symbol is a
1105 % control character or not.
1108 static void XEditText(Display *display,XWidgetInfo *text_info,
1109 const KeySym key_symbol,char *text,const size_t state)
1111 switch ((int) key_symbol)
1116 if (text_info->highlight)
1119 Erase the entire line of text.
1121 *text_info->text='\0';
1122 text_info->cursor=text_info->text;
1123 text_info->marker=text_info->text;
1124 text_info->highlight=MagickFalse;
1127 Erase one character.
1129 if (text_info->cursor != text_info->text)
1131 text_info->cursor--;
1132 (void) CopyMagickString(text_info->cursor,text_info->cursor+1,
1134 text_info->highlight=MagickFalse;
1142 Move cursor one position left.
1144 if (text_info->cursor == text_info->text)
1146 text_info->cursor--;
1153 Move cursor one position right.
1155 if (text_info->cursor == (text_info->text+Extent(text_info->text)))
1157 text_info->cursor++;
1169 if (state & ControlState)
1173 if ((Extent(text_info->text)+1) >= (int) MaxTextExtent)
1174 (void) XBell(display,0);
1177 if (text_info->highlight)
1180 Erase the entire line of text.
1182 *text_info->text='\0';
1183 text_info->cursor=text_info->text;
1184 text_info->marker=text_info->text;
1185 text_info->highlight=MagickFalse;
1188 Insert a string into the text.
1190 q=text_info->text+Extent(text_info->text)+strlen(text);
1191 for (i=0; i <= Extent(text_info->cursor); i++)
1193 *q=(*(q-Extent(text)));
1197 for (i=0; i < Extent(text); i++)
1198 *text_info->cursor++=(*p++);
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210 + X G e t W i d g e t I n f o %
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216 % XGetWidgetInfo() initializes the XWidgetInfo structure.
1218 % The format of the XGetWidgetInfo function is:
1220 % XGetWidgetInfo(text,widget_info)
1222 % A description of each parameter follows:
1224 % o text: A string of characters associated with the widget.
1226 % o widget_info: Specifies a pointer to a X11 XWidgetInfo structure.
1229 static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info)
1232 Initialize widget info.
1234 widget_info->id=(~0);
1235 widget_info->bevel_width=3;
1236 widget_info->width=1;
1237 widget_info->height=1;
1240 widget_info->min_y=0;
1241 widget_info->max_y=0;
1242 widget_info->raised=MagickTrue;
1243 widget_info->active=MagickFalse;
1244 widget_info->center=MagickTrue;
1245 widget_info->trough=MagickFalse;
1246 widget_info->highlight=MagickFalse;
1247 widget_info->text=(char *) text;
1248 widget_info->cursor=(char *) text;
1249 if (text != (char *) NULL)
1250 widget_info->cursor+=Extent(text);
1251 widget_info->marker=(char *) text;
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259 + X H i g h l i g h t W i d g e t %
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265 % XHighlightWidget() draws a highlighted border around a window.
1267 % The format of the XHighlightWidget function is:
1269 % XHighlightWidget(display,window_info,x,y)
1271 % A description of each parameter follows:
1273 % o display: Specifies a pointer to the Display structure; returned from
1276 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1278 % o x: Specifies an integer representing the rectangle offset in the
1281 % o y: Specifies an integer representing the rectangle offset in the
1285 static void XHighlightWidget(Display *display,const XWindowInfo *window_info,
1286 const int x,const int y)
1289 Draw the widget highlighting rectangle.
1291 XSetBevelColor(display,window_info,MagickTrue);
1292 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y,
1293 window_info->width-(x << 1),window_info->height-(y << 1));
1294 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1295 x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1);
1296 XSetBevelColor(display,window_info,MagickFalse);
1297 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1298 x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1));
1299 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
1303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1307 + X S c r e e n E v e n t %
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1313 % XScreenEvent() returns MagickTrue if the any event on the X server queue is
1314 % associated with the widget window.
1316 % The format of the XScreenEvent function is:
1318 % int XScreenEvent(Display *display,XEvent *event,char *data)
1320 % A description of each parameter follows:
1322 % o display: Specifies a pointer to the Display structure; returned from
1325 % o event: Specifies a pointer to a X11 XEvent structure.
1327 % o data: Specifies a pointer to a XWindows structure.
1331 #if defined(__cplusplus) || defined(c_plusplus)
1335 static int XScreenEvent(Display *display,XEvent *event,char *data)
1340 windows=(XWindows *) data;
1341 if (event->xany.window == windows->popup.id)
1343 if (event->type == MapNotify)
1344 windows->popup.mapped=MagickTrue;
1345 if (event->type == UnmapNotify)
1346 windows->popup.mapped=MagickFalse;
1349 if (event->xany.window == windows->widget.id)
1351 if (event->type == MapNotify)
1352 windows->widget.mapped=MagickTrue;
1353 if (event->type == UnmapNotify)
1354 windows->widget.mapped=MagickFalse;
1357 switch (event->type)
1361 if ((event->xbutton.button == Button3) &&
1362 (event->xbutton.state & Mod1Mask))
1365 Convert Alt-Button3 to Button2.
1367 event->xbutton.button=Button2;
1368 event->xbutton.state&=(~Mod1Mask);
1374 if (event->xexpose.window == windows->image.id)
1376 XRefreshWindow(display,&windows->image,event);
1379 if (event->xexpose.window == windows->magnify.id)
1380 if (event->xexpose.count == 0)
1381 if (windows->magnify.mapped)
1383 XMakeMagnifyImage(display,windows);
1386 if (event->xexpose.window == windows->command.id)
1387 if (event->xexpose.count == 0)
1389 (void) XCommandWidget(display,windows,(const char **) NULL,event);
1397 Set input focus for backdrop window.
1399 if (event->xfocus.window == windows->image.id)
1400 (void) XSetInputFocus(display,windows->image.id,RevertToNone,
1408 case SelectionNotify:
1413 return(MagickFalse);
1416 #if defined(__cplusplus) || defined(c_plusplus)
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1425 + X S e t B e v e l C o l o r %
1429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1431 % XSetBevelColor() sets the graphic context for drawing a beveled border.
1433 % The format of the XSetBevelColor function is:
1435 % XSetBevelColor(display,window_info,raised)
1437 % A description of each parameter follows:
1439 % o display: Specifies a pointer to the Display structure; returned from
1442 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1444 % o raised: A value other than zero indicates the color show be a
1445 % "highlight" color, otherwise the "shadow" color is set.
1448 static void XSetBevelColor(Display *display,const XWindowInfo *window_info,
1449 const MagickStatusType raised)
1451 if (window_info->depth == 1)
1459 (void) XSetBackground(display,window_info->widget_context,
1460 XBlackPixel(display,window_info->screen));
1461 (void) XSetForeground(display,window_info->widget_context,
1462 XWhitePixel(display,window_info->screen));
1463 (void) XSetFillStyle(display,window_info->widget_context,
1464 FillOpaqueStippled);
1465 stipple=window_info->highlight_stipple;
1466 if (raised == MagickFalse)
1467 stipple=window_info->shadow_stipple;
1468 (void) XSetStipple(display,window_info->widget_context,stipple);
1472 (void) XSetForeground(display,window_info->widget_context,
1473 window_info->pixel_info->highlight_color.pixel);
1475 (void) XSetForeground(display,window_info->widget_context,
1476 window_info->pixel_info->shadow_color.pixel);
1480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1484 + X S e t M a t t e C o l o r %
1488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1490 % XSetMatteColor() sets the graphic context for drawing the matte.
1492 % The format of the XSetMatteColor function is:
1494 % XSetMatteColor(display,window_info,raised)
1496 % A description of each parameter follows:
1498 % o display: Specifies a pointer to the Display structure; returned from
1501 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1503 % o raised: A value other than zero indicates the matte is active.
1506 static void XSetMatteColor(Display *display,const XWindowInfo *window_info,
1507 const MagickStatusType raised)
1509 if (window_info->depth == 1)
1515 (void) XSetForeground(display,window_info->widget_context,
1516 XWhitePixel(display,window_info->screen));
1518 (void) XSetForeground(display,window_info->widget_context,
1519 XBlackPixel(display,window_info->screen));
1523 (void) XSetForeground(display,window_info->widget_context,
1524 window_info->pixel_info->matte_color.pixel);
1526 (void) XSetForeground(display,window_info->widget_context,
1527 window_info->pixel_info->depth_color.pixel);
1531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1535 + X S e t T e x t C o l o r %
1539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1541 % XSetTextColor() sets the graphic context for drawing text on a matte.
1543 % The format of the XSetTextColor function is:
1545 % XSetTextColor(display,window_info,raised)
1547 % A description of each parameter follows:
1549 % o display: Specifies a pointer to the Display structure; returned from
1552 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1554 % o raised: A value other than zero indicates the color show be a
1555 % "highlight" color, otherwise the "shadow" color is set.
1558 static void XSetTextColor(Display *display,const XWindowInfo *window_info,
1559 const MagickStatusType raised)
1565 if (window_info->depth == 1)
1571 (void) XSetForeground(display,window_info->widget_context,
1572 XBlackPixel(display,window_info->screen));
1574 (void) XSetForeground(display,window_info->widget_context,
1575 XWhitePixel(display,window_info->screen));
1578 foreground=(ssize_t) XPixelIntensity(
1579 &window_info->pixel_info->foreground_color);
1580 matte=(ssize_t) XPixelIntensity(&window_info->pixel_info->matte_color);
1581 if (MagickAbsoluteValue((int) (foreground-matte)) > (65535L >> 3))
1582 (void) XSetForeground(display,window_info->widget_context,
1583 window_info->pixel_info->foreground_color.pixel);
1585 (void) XSetForeground(display,window_info->widget_context,
1586 window_info->pixel_info->background_color.pixel);
1590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1594 % X C o l o r B r o w s e r W i d g e t %
1598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1600 % XColorBrowserWidget() displays a Color Browser widget with a color query
1601 % to the user. The user keys a reply and presses the Action or Cancel button
1602 % to exit. The typed text is returned as the reply function parameter.
1604 % The format of the XColorBrowserWidget method is:
1606 % void XColorBrowserWidget(Display *display,XWindows *windows,
1607 % const char *action,char *reply)
1609 % A description of each parameter follows:
1611 % o display: Specifies a connection to an X server; returned from
1614 % o window: Specifies a pointer to a XWindows structure.
1616 % o action: Specifies a pointer to the action of this widget.
1618 % o reply: the response from the user is returned in this parameter.
1621 MagickPrivate void XColorBrowserWidget(Display *display,XWindows *windows,
1622 const char *action,char *reply)
1624 #define CancelButtonText "Cancel"
1625 #define ColornameText "Name:"
1626 #define ColorPatternText "Pattern:"
1627 #define GrabButtonText "Grab"
1628 #define ResetButtonText "Reset"
1632 primary_selection[MaxTextExtent],
1633 reset_pattern[MaxTextExtent],
1634 text[MaxTextExtent];
1647 glob_pattern[MaxTextExtent] = "*";
1649 static MagickStatusType
1650 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
1698 Get color list and sort in ascending order.
1700 assert(display != (Display *) NULL);
1701 assert(windows != (XWindows *) NULL);
1702 assert(action != (char *) NULL);
1703 assert(reply != (char *) NULL);
1704 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
1705 XSetCursorState(display,windows,MagickTrue);
1706 XCheckRefreshWindows(display,windows);
1707 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
1708 exception=AcquireExceptionInfo();
1709 colorlist=GetColorList(glob_pattern,&colors,exception);
1710 if (colorlist == (char **) NULL)
1713 Pattern failed, obtain all the colors.
1715 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
1716 colorlist=GetColorList(glob_pattern,&colors,exception);
1717 if (colorlist == (char **) NULL)
1719 XNoticeWidget(display,windows,"Unable to obtain colors names:",
1721 (void) XDialogWidget(display,windows,action,"Enter color name:",
1727 Determine Color Browser widget attributes.
1729 font_info=windows->widget.font_info;
1731 for (i=0; i < (int) colors; i++)
1732 if (WidgetTextWidth(font_info,colorlist[i]) > text_width)
1733 text_width=WidgetTextWidth(font_info,colorlist[i]);
1734 width=WidgetTextWidth(font_info,(char *) action);
1735 if (WidgetTextWidth(font_info,CancelButtonText) > width)
1736 width=WidgetTextWidth(font_info,CancelButtonText);
1737 if (WidgetTextWidth(font_info,ResetButtonText) > width)
1738 width=WidgetTextWidth(font_info,ResetButtonText);
1739 if (WidgetTextWidth(font_info,GrabButtonText) > width)
1740 width=WidgetTextWidth(font_info,GrabButtonText);
1741 width+=QuantumMargin;
1742 if (WidgetTextWidth(font_info,ColorPatternText) > width)
1743 width=WidgetTextWidth(font_info,ColorPatternText);
1744 if (WidgetTextWidth(font_info,ColornameText) > width)
1745 width=WidgetTextWidth(font_info,ColornameText);
1746 height=(unsigned int) (font_info->ascent+font_info->descent);
1748 Position Color Browser widget.
1750 windows->widget.width=(unsigned int)
1751 (width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin);
1752 windows->widget.min_width=(unsigned int)
1753 (width+MinTextWidth+4*QuantumMargin);
1754 if (windows->widget.width < windows->widget.min_width)
1755 windows->widget.width=windows->widget.min_width;
1756 windows->widget.height=(unsigned int)
1757 ((81*height) >> 2)+((13*QuantumMargin) >> 1)+4;
1758 windows->widget.min_height=(unsigned int)
1759 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
1760 if (windows->widget.height < windows->widget.min_height)
1761 windows->widget.height=windows->widget.min_height;
1762 XConstrainWindowPosition(display,&windows->widget);
1764 Map Color Browser widget.
1766 (void) CopyMagickString(windows->widget.name,"Browse and Select a Color",
1768 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
1769 if (status != False)
1771 XSetWMName(display,windows->widget.id,&window_name);
1772 XSetWMIconName(display,windows->widget.id,&window_name);
1773 (void) XFree((void *) window_name.value);
1775 window_changes.width=(int) windows->widget.width;
1776 window_changes.height=(int) windows->widget.height;
1777 window_changes.x=windows->widget.x;
1778 window_changes.y=windows->widget.y;
1779 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
1780 mask,&window_changes);
1781 (void) XMapRaised(display,windows->widget.id);
1782 windows->widget.mapped=MagickFalse;
1784 Respond to X events.
1786 XGetWidgetInfo((char *) NULL,&slider_info);
1787 XGetWidgetInfo((char *) NULL,&north_info);
1788 XGetWidgetInfo((char *) NULL,&south_info);
1789 XGetWidgetInfo((char *) NULL,&expose_info);
1791 delay=SuspendTime << 2;
1792 state=UpdateConfigurationState;
1795 if (state & UpdateConfigurationState)
1801 Initialize button information.
1803 XGetWidgetInfo(CancelButtonText,&cancel_info);
1804 cancel_info.width=width;
1805 cancel_info.height=(unsigned int) ((3*height) >> 1);
1807 (windows->widget.width-cancel_info.width-QuantumMargin-2);
1809 (windows->widget.height-cancel_info.height-QuantumMargin);
1810 XGetWidgetInfo(action,&action_info);
1811 action_info.width=width;
1812 action_info.height=(unsigned int) ((3*height) >> 1);
1813 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
1814 (action_info.bevel_width << 1));
1815 action_info.y=cancel_info.y;
1816 XGetWidgetInfo(GrabButtonText,&grab_info);
1817 grab_info.width=width;
1818 grab_info.height=(unsigned int) ((3*height) >> 1);
1819 grab_info.x=QuantumMargin;
1820 grab_info.y=((5*QuantumMargin) >> 1)+height;
1821 XGetWidgetInfo(ResetButtonText,&reset_info);
1822 reset_info.width=width;
1823 reset_info.height=(unsigned int) ((3*height) >> 1);
1824 reset_info.x=QuantumMargin;
1825 reset_info.y=grab_info.y+grab_info.height+QuantumMargin;
1827 Initialize reply information.
1829 XGetWidgetInfo(reply,&reply_info);
1830 reply_info.raised=MagickFalse;
1831 reply_info.bevel_width--;
1832 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
1833 reply_info.height=height << 1;
1834 reply_info.x=(int) (width+(QuantumMargin << 1));
1835 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
1837 Initialize mode information.
1839 XGetWidgetInfo((char *) NULL,&mode_info);
1840 mode_info.active=MagickTrue;
1841 mode_info.bevel_width=0;
1842 mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1));
1843 mode_info.height=action_info.height;
1844 mode_info.x=QuantumMargin;
1845 mode_info.y=action_info.y;
1847 Initialize scroll information.
1849 XGetWidgetInfo((char *) NULL,&scroll_info);
1850 scroll_info.bevel_width--;
1851 scroll_info.width=height;
1852 scroll_info.height=(unsigned int) (reply_info.y-grab_info.y-
1853 (QuantumMargin >> 1));
1854 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
1855 scroll_info.y=grab_info.y-reply_info.bevel_width;
1856 scroll_info.raised=MagickFalse;
1857 scroll_info.trough=MagickTrue;
1858 north_info=scroll_info;
1859 north_info.raised=MagickTrue;
1860 north_info.width-=(north_info.bevel_width << 1);
1861 north_info.height=north_info.width-1;
1862 north_info.x+=north_info.bevel_width;
1863 north_info.y+=north_info.bevel_width;
1864 south_info=north_info;
1865 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
1868 slider_info=north_info;
1870 slider_info.width-=2;
1871 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
1872 slider_info.bevel_width+2;
1873 slider_info.height=scroll_info.height-((slider_info.min_y-
1874 scroll_info.y+1) << 1)+4;
1875 visible_colors=scroll_info.height/(height+(height >> 3));
1876 if (colors > visible_colors)
1877 slider_info.height=(unsigned int)
1878 ((visible_colors*slider_info.height)/colors);
1879 slider_info.max_y=south_info.y-south_info.bevel_width-
1880 slider_info.bevel_width-2;
1881 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
1882 slider_info.y=slider_info.min_y;
1883 expose_info=scroll_info;
1884 expose_info.y=slider_info.y;
1886 Initialize list information.
1888 XGetWidgetInfo((char *) NULL,&list_info);
1889 list_info.raised=MagickFalse;
1890 list_info.bevel_width--;
1891 list_info.width=(unsigned int)
1892 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
1893 list_info.height=scroll_info.height;
1894 list_info.x=reply_info.x;
1895 list_info.y=scroll_info.y;
1896 if (windows->widget.mapped == MagickFalse)
1897 state|=JumpListState;
1899 Initialize text information.
1902 XGetWidgetInfo(text,&text_info);
1903 text_info.center=MagickFalse;
1904 text_info.width=reply_info.width;
1905 text_info.height=height;
1906 text_info.x=list_info.x-(QuantumMargin >> 1);
1907 text_info.y=QuantumMargin;
1909 Initialize selection information.
1911 XGetWidgetInfo((char *) NULL,&selection_info);
1912 selection_info.center=MagickFalse;
1913 selection_info.width=list_info.width;
1914 selection_info.height=(unsigned int) ((9*height) >> 3);
1915 selection_info.x=list_info.x;
1916 state&=(~UpdateConfigurationState);
1918 if (state & RedrawWidgetState)
1921 Redraw Color Browser window.
1924 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
1925 (void) XDrawString(display,windows->widget.id,
1926 windows->widget.annotate_context,x,y,ColorPatternText,
1927 Extent(ColorPatternText));
1928 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
1929 XDrawWidgetText(display,&windows->widget,&text_info);
1930 XDrawBeveledButton(display,&windows->widget,&grab_info);
1931 XDrawBeveledButton(display,&windows->widget,&reset_info);
1932 XDrawBeveledMatte(display,&windows->widget,&list_info);
1933 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
1934 XDrawTriangleNorth(display,&windows->widget,&north_info);
1935 XDrawBeveledButton(display,&windows->widget,&slider_info);
1936 XDrawTriangleSouth(display,&windows->widget,&south_info);
1938 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
1939 (void) XDrawString(display,windows->widget.id,
1940 windows->widget.annotate_context,x,y,ColornameText,
1941 Extent(ColornameText));
1942 XDrawBeveledMatte(display,&windows->widget,&reply_info);
1943 XDrawMatteText(display,&windows->widget,&reply_info);
1944 XDrawBeveledButton(display,&windows->widget,&action_info);
1945 XDrawBeveledButton(display,&windows->widget,&cancel_info);
1946 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
1947 selection_info.id=(~0);
1948 state|=RedrawActionState;
1949 state|=RedrawListState;
1950 state&=(~RedrawWidgetState);
1952 if (state & UpdateListState)
1960 status=XParseColor(display,windows->widget.map_info->colormap,
1961 glob_pattern,&color);
1962 if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL))
1965 Reply is a single color name-- exit.
1967 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
1968 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1969 action_info.raised=MagickFalse;
1970 XDrawBeveledButton(display,&windows->widget,&action_info);
1976 checklist=GetColorList(glob_pattern,&number_colors,exception);
1977 if (number_colors == 0)
1979 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1980 (void) XBell(display,0);
1984 for (i=0; i < (int) colors; i++)
1985 colorlist[i]=DestroyString(colorlist[i]);
1986 if (colorlist != (char **) NULL)
1987 colorlist=(char **) RelinquishMagickMemory(colorlist);
1988 colorlist=checklist;
1989 colors=number_colors;
1992 Sort color list in ascending order.
1995 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
1996 if (colors > visible_colors)
1997 slider_info.height=(unsigned int)
1998 ((visible_colors*slider_info.height)/colors);
1999 slider_info.max_y=south_info.y-south_info.bevel_width-
2000 slider_info.bevel_width-2;
2002 slider_info.y=slider_info.min_y;
2003 expose_info.y=slider_info.y;
2004 selection_info.id=(~0);
2006 state|=RedrawListState;
2008 Redraw color name & reply.
2010 *reply_info.text='\0';
2011 reply_info.cursor=reply_info.text;
2012 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
2013 XDrawWidgetText(display,&windows->widget,&text_info);
2014 XDrawMatteText(display,&windows->widget,&reply_info);
2015 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
2016 XDrawTriangleNorth(display,&windows->widget,&north_info);
2017 XDrawBeveledButton(display,&windows->widget,&slider_info);
2018 XDrawTriangleSouth(display,&windows->widget,&south_info);
2019 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
2020 state&=(~UpdateListState);
2022 if (state & JumpListState)
2025 Jump scroll to match user color.
2028 for (i=0; i < (int) colors; i++)
2029 if (LocaleCompare(colorlist[i],reply) >= 0)
2031 list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0;
2034 if ((i < slider_info.id) ||
2035 (i >= (int) (slider_info.id+visible_colors)))
2036 slider_info.id=i-(visible_colors >> 1);
2037 selection_info.id=(~0);
2038 state|=RedrawListState;
2039 state&=(~JumpListState);
2041 if (state & RedrawListState)
2044 Determine slider id and position.
2046 if (slider_info.id >= (int) (colors-visible_colors))
2047 slider_info.id=(int) (colors-visible_colors);
2048 if ((slider_info.id < 0) || (colors <= visible_colors))
2050 slider_info.y=slider_info.min_y;
2052 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
2053 slider_info.min_y+1)/colors);
2054 if (slider_info.id != selection_info.id)
2057 Redraw scroll bar and file names.
2059 selection_info.id=slider_info.id;
2060 selection_info.y=list_info.y+(height >> 3)+2;
2061 for (i=0; i < (int) visible_colors; i++)
2063 selection_info.raised=(slider_info.id+i) != list_info.id ?
2064 MagickTrue : MagickFalse;
2065 selection_info.text=(char *) NULL;
2066 if ((slider_info.id+i) < (int) colors)
2067 selection_info.text=colorlist[slider_info.id+i];
2068 XDrawWidgetText(display,&windows->widget,&selection_info);
2069 selection_info.y+=(int) selection_info.height;
2074 if (slider_info.y > expose_info.y)
2076 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
2077 expose_info.y=slider_info.y-expose_info.height-
2078 slider_info.bevel_width-1;
2082 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
2083 expose_info.y=slider_info.y+slider_info.height+
2084 slider_info.bevel_width+1;
2086 XDrawTriangleNorth(display,&windows->widget,&north_info);
2087 XDrawMatte(display,&windows->widget,&expose_info);
2088 XDrawBeveledButton(display,&windows->widget,&slider_info);
2089 XDrawTriangleSouth(display,&windows->widget,&south_info);
2090 expose_info.y=slider_info.y;
2092 state&=(~RedrawListState);
2094 if (state & RedrawActionState)
2097 colorname[MaxTextExtent];
2100 Display the selected color in a drawing area.
2102 color=windows->widget.pixel_info->matte_color;
2103 (void) XParseColor(display,windows->widget.map_info->colormap,
2104 reply_info.text,&windows->widget.pixel_info->matte_color);
2105 XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL,
2106 (unsigned int) windows->widget.visual_info->colormap_size,
2107 &windows->widget.pixel_info->matte_color);
2108 mode_info.text=colorname;
2109 (void) FormatLocaleString(mode_info.text,MaxTextExtent,"#%02x%02x%02x",
2110 windows->widget.pixel_info->matte_color.red,
2111 windows->widget.pixel_info->matte_color.green,
2112 windows->widget.pixel_info->matte_color.blue);
2113 XDrawBeveledButton(display,&windows->widget,&mode_info);
2114 windows->widget.pixel_info->matte_color=color;
2115 state&=(~RedrawActionState);
2118 Wait for next event.
2120 if (north_info.raised && south_info.raised)
2121 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
2125 Brief delay before advancing scroll bar.
2127 XDelay(display,delay);
2129 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
2130 if (north_info.raised == MagickFalse)
2131 if (slider_info.id > 0)
2137 state|=RedrawListState;
2139 if (south_info.raised == MagickFalse)
2140 if (slider_info.id < (int) colors)
2146 state|=RedrawListState;
2148 if (event.type != ButtonRelease)
2155 if (MatteIsActive(slider_info,event.xbutton))
2160 slider_info.active=MagickTrue;
2163 if (MatteIsActive(north_info,event.xbutton))
2164 if (slider_info.id > 0)
2169 north_info.raised=MagickFalse;
2171 state|=RedrawListState;
2174 if (MatteIsActive(south_info,event.xbutton))
2175 if (slider_info.id < (int) colors)
2180 south_info.raised=MagickFalse;
2182 state|=RedrawListState;
2185 if (MatteIsActive(scroll_info,event.xbutton))
2190 if (event.xbutton.y < slider_info.y)
2191 slider_info.id-=(visible_colors-1);
2193 slider_info.id+=(visible_colors-1);
2194 state|=RedrawListState;
2197 if (MatteIsActive(list_info,event.xbutton))
2203 User pressed list matte.
2205 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
2206 selection_info.height;
2207 if (id >= (int) colors)
2209 (void) CopyMagickString(reply_info.text,colorlist[id],
2211 reply_info.highlight=MagickFalse;
2212 reply_info.marker=reply_info.text;
2213 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2214 XDrawMatteText(display,&windows->widget,&reply_info);
2215 state|=RedrawActionState;
2216 if (id == list_info.id)
2218 (void) CopyMagickString(glob_pattern,reply_info.text,
2220 state|=UpdateListState;
2222 selection_info.id=(~0);
2224 state|=RedrawListState;
2227 if (MatteIsActive(grab_info,event.xbutton))
2230 User pressed Grab button.
2232 grab_info.raised=MagickFalse;
2233 XDrawBeveledButton(display,&windows->widget,&grab_info);
2236 if (MatteIsActive(reset_info,event.xbutton))
2239 User pressed Reset button.
2241 reset_info.raised=MagickFalse;
2242 XDrawBeveledButton(display,&windows->widget,&reset_info);
2245 if (MatteIsActive(mode_info,event.xbutton))
2248 User pressed mode button.
2250 (void) CopyMagickString(reply_info.text,mode_info.text,
2252 (void) CopyMagickString(primary_selection,reply_info.text,
2254 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2255 event.xbutton.time);
2256 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2257 windows->widget.id ? MagickTrue : MagickFalse;
2258 reply_info.marker=reply_info.text;
2259 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2260 XDrawMatteText(display,&windows->widget,&reply_info);
2263 if (MatteIsActive(action_info,event.xbutton))
2266 User pressed action button.
2268 action_info.raised=MagickFalse;
2269 XDrawBeveledButton(display,&windows->widget,&action_info);
2272 if (MatteIsActive(cancel_info,event.xbutton))
2275 User pressed Cancel button.
2277 cancel_info.raised=MagickFalse;
2278 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2281 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2283 if (event.xbutton.button != Button2)
2289 Move text cursor to position of button press.
2291 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
2292 for (i=1; i <= Extent(reply_info.marker); i++)
2293 if (XTextWidth(font_info,reply_info.marker,i) > x)
2295 reply_info.cursor=reply_info.marker+i-1;
2296 if (event.xbutton.time > (click_time+DoubleClick))
2297 reply_info.highlight=MagickFalse;
2301 Become the XA_PRIMARY selection owner.
2303 (void) CopyMagickString(primary_selection,reply_info.text,
2305 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2306 event.xbutton.time);
2307 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2308 windows->widget.id ? MagickTrue : MagickFalse;
2310 XDrawMatteText(display,&windows->widget,&reply_info);
2311 click_time=event.xbutton.time;
2315 Request primary selection.
2317 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2318 windows->widget.id,event.xbutton.time);
2323 if (windows->widget.mapped == MagickFalse)
2325 if (north_info.raised == MagickFalse)
2328 User released up button.
2330 delay=SuspendTime << 2;
2331 north_info.raised=MagickTrue;
2332 XDrawTriangleNorth(display,&windows->widget,&north_info);
2334 if (south_info.raised == MagickFalse)
2337 User released down button.
2339 delay=SuspendTime << 2;
2340 south_info.raised=MagickTrue;
2341 XDrawTriangleSouth(display,&windows->widget,&south_info);
2343 if (slider_info.active)
2346 Stop tracking slider.
2348 slider_info.active=MagickFalse;
2351 if (grab_info.raised == MagickFalse)
2353 if (event.xbutton.window == windows->widget.id)
2354 if (MatteIsActive(grab_info,event.xbutton))
2357 Select a pen color from the X server.
2359 (void) XGetWindowColor(display,windows,reply_info.text);
2360 reply_info.marker=reply_info.text;
2361 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2362 XDrawMatteText(display,&windows->widget,&reply_info);
2363 state|=RedrawActionState;
2365 grab_info.raised=MagickTrue;
2366 XDrawBeveledButton(display,&windows->widget,&grab_info);
2368 if (reset_info.raised == MagickFalse)
2370 if (event.xbutton.window == windows->widget.id)
2371 if (MatteIsActive(reset_info,event.xbutton))
2373 (void) CopyMagickString(glob_pattern,reset_pattern,
2375 state|=UpdateListState;
2377 reset_info.raised=MagickTrue;
2378 XDrawBeveledButton(display,&windows->widget,&reset_info);
2380 if (action_info.raised == MagickFalse)
2382 if (event.xbutton.window == windows->widget.id)
2384 if (MatteIsActive(action_info,event.xbutton))
2386 if (*reply_info.text == '\0')
2387 (void) XBell(display,0);
2392 action_info.raised=MagickTrue;
2393 XDrawBeveledButton(display,&windows->widget,&action_info);
2395 if (cancel_info.raised == MagickFalse)
2397 if (event.xbutton.window == windows->widget.id)
2398 if (MatteIsActive(cancel_info,event.xbutton))
2400 *reply_info.text='\0';
2403 cancel_info.raised=MagickTrue;
2404 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2406 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2413 If client window delete message, exit.
2415 if (event.xclient.message_type != windows->wm_protocols)
2417 if (*event.xclient.data.l == (int) windows->wm_take_focus)
2419 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2420 (Time) event.xclient.data.l[1]);
2423 if (*event.xclient.data.l != (int) windows->wm_delete_window)
2425 if (event.xclient.window == windows->widget.id)
2427 *reply_info.text='\0';
2433 case ConfigureNotify:
2436 Update widget configuration.
2438 if (event.xconfigure.window != windows->widget.id)
2440 if ((event.xconfigure.width == (int) windows->widget.width) &&
2441 (event.xconfigure.height == (int) windows->widget.height))
2443 windows->widget.width=(unsigned int)
2444 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
2445 windows->widget.height=(unsigned int)
2446 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
2447 state|=UpdateConfigurationState;
2452 if (event.xcrossing.window != windows->widget.id)
2454 state&=(~InactiveWidgetState);
2459 if (event.xexpose.window != windows->widget.id)
2461 if (event.xexpose.count != 0)
2463 state|=RedrawWidgetState;
2469 command[MaxTextExtent];
2478 Respond to a user key press.
2480 if (event.xkey.window != windows->widget.id)
2482 length=XLookupString((XKeyEvent *) &event.xkey,command,
2483 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2484 *(command+length)='\0';
2485 if (AreaIsActive(scroll_info,event.xkey))
2490 switch ((int) key_symbol)
2513 slider_info.id-=visible_colors;
2519 slider_info.id+=visible_colors;
2525 slider_info.id=(int) colors;
2529 state|=RedrawListState;
2532 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
2535 Read new color or glob patterm.
2537 if (*reply_info.text == '\0')
2539 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
2540 state|=UpdateListState;
2543 if (key_symbol == XK_Control_L)
2545 state|=ControlState;
2548 if (state & ControlState)
2549 switch ((int) key_symbol)
2555 Erase the entire line of text.
2557 *reply_info.text='\0';
2558 reply_info.cursor=reply_info.text;
2559 reply_info.marker=reply_info.text;
2560 reply_info.highlight=MagickFalse;
2566 XEditText(display,&reply_info,key_symbol,command,state);
2567 XDrawMatteText(display,&windows->widget,&reply_info);
2568 state|=JumpListState;
2569 status=XParseColor(display,windows->widget.map_info->colormap,
2570 reply_info.text,&color);
2571 if (status != False)
2572 state|=RedrawActionState;
2578 command[MaxTextExtent];
2584 Respond to a user key release.
2586 if (event.xkey.window != windows->widget.id)
2588 (void) XLookupString((XKeyEvent *) &event.xkey,command,
2589 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2590 if (key_symbol == XK_Control_L)
2591 state&=(~ControlState);
2596 if (event.xcrossing.window != windows->widget.id)
2598 state|=InactiveWidgetState;
2610 Discard pending button motion events.
2612 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
2613 if (slider_info.active)
2618 slider_info.y=event.xmotion.y-
2619 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
2620 if (slider_info.y < slider_info.min_y)
2621 slider_info.y=slider_info.min_y;
2622 if (slider_info.y > slider_info.max_y)
2623 slider_info.y=slider_info.max_y;
2625 if (slider_info.y != slider_info.min_y)
2626 slider_info.id=(int) ((colors*(slider_info.y-
2627 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
2628 state|=RedrawListState;
2631 if (state & InactiveWidgetState)
2633 if (grab_info.raised == MatteIsActive(grab_info,event.xmotion))
2636 Grab button status changed.
2638 grab_info.raised=!grab_info.raised;
2639 XDrawBeveledButton(display,&windows->widget,&grab_info);
2642 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
2645 Reset button status changed.
2647 reset_info.raised=!reset_info.raised;
2648 XDrawBeveledButton(display,&windows->widget,&reset_info);
2651 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
2654 Action button status changed.
2656 action_info.raised=action_info.raised == MagickFalse ?
2657 MagickTrue : MagickFalse;
2658 XDrawBeveledButton(display,&windows->widget,&action_info);
2661 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
2664 Cancel button status changed.
2666 cancel_info.raised=cancel_info.raised == MagickFalse ?
2667 MagickTrue : MagickFalse;
2668 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2673 case SelectionClear:
2675 reply_info.highlight=MagickFalse;
2676 XDrawMatteText(display,&windows->widget,&reply_info);
2679 case SelectionNotify:
2695 Obtain response from primary selection.
2697 if (event.xselection.property == (Atom) None)
2699 status=XGetWindowProperty(display,event.xselection.requestor,
2700 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
2701 &format,&length,&after,&data);
2702 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2705 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
2706 (void) XBell(display,0);
2710 Insert primary selection in reply text.
2712 *(data+length)='\0';
2713 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
2715 XDrawMatteText(display,&windows->widget,&reply_info);
2716 state|=JumpListState;
2717 state|=RedrawActionState;
2719 (void) XFree((void *) data);
2722 case SelectionRequest:
2727 XSelectionRequestEvent
2730 if (reply_info.highlight == MagickFalse)
2733 Set primary selection.
2735 request=(&(event.xselectionrequest));
2736 (void) XChangeProperty(request->display,request->requestor,
2737 request->property,request->target,8,PropModeReplace,
2738 (unsigned char *) primary_selection,Extent(primary_selection));
2739 notify.type=SelectionNotify;
2740 notify.send_event=MagickTrue;
2741 notify.display=request->display;
2742 notify.requestor=request->requestor;
2743 notify.selection=request->selection;
2744 notify.target=request->target;
2745 notify.time=request->time;
2746 if (request->property == None)
2747 notify.property=request->target;
2749 notify.property=request->property;
2750 (void) XSendEvent(request->display,request->requestor,False,
2751 NoEventMask,(XEvent *) ¬ify);
2756 } while ((state & ExitState) == 0);
2757 XSetCursorState(display,windows,MagickFalse);
2758 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
2759 XCheckRefreshWindows(display,windows);
2763 for (i=0; i < (int) colors; i++)
2764 colorlist[i]=DestroyString(colorlist[i]);
2765 if (colorlist != (char **) NULL)
2766 colorlist=(char **) RelinquishMagickMemory(colorlist);
2767 exception=DestroyExceptionInfo(exception);
2768 if ((*reply == '\0') || (strchr(reply,'-') != (char *) NULL))
2770 status=XParseColor(display,windows->widget.map_info->colormap,reply,&color);
2771 if (status != False)
2773 XNoticeWidget(display,windows,"Color is unknown to X server:",reply);
2774 (void) CopyMagickString(reply,"gray",MaxTextExtent);
2778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2782 % X C o m m a n d W i d g e t %
2786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2788 % XCommandWidget() maps a menu and returns the command pointed to by the user
2789 % when the button is released.
2791 % The format of the XCommandWidget method is:
2793 % int XCommandWidget(Display *display,XWindows *windows,
2794 % const char **selections,XEvent *event)
2796 % A description of each parameter follows:
2798 % o selection_number: Specifies the number of the selection that the
2801 % o display: Specifies a connection to an X server; returned from
2804 % o window: Specifies a pointer to a XWindows structure.
2806 % o selections: Specifies a pointer to one or more strings that comprise
2807 % the choices in the menu.
2809 % o event: Specifies a pointer to a X11 XEvent structure.
2812 MagickPrivate int XCommandWidget(Display *display,XWindows *windows,
2813 const char **selections,XEvent *event)
2815 #define tile_width 112
2816 #define tile_height 70
2818 static const unsigned char
2821 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2822 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2823 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
2825 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2826 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
2827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2828 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2829 0x00, 0x00, 0x1e, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2830 0x00, 0x00, 0x00, 0x00, 0x1e, 0xbc, 0x9f, 0x03, 0x00, 0x3e, 0x00, 0xc0,
2831 0x1f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x0f, 0x80, 0x3f,
2832 0x00, 0xf0, 0x1f, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x1f,
2833 0xe0, 0x3f, 0x00, 0xfc, 0x1f, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc,
2834 0xff, 0x1f, 0xf0, 0x3f, 0x00, 0xfe, 0x1f, 0xf8, 0x0f, 0x00, 0x00, 0x00,
2835 0x1e, 0xfc, 0xfc, 0x3f, 0xf8, 0x3f, 0x00, 0xff, 0x1e, 0xfc, 0x0f, 0x00,
2836 0x00, 0x00, 0x1e, 0x7c, 0xfc, 0x3e, 0xf8, 0x3c, 0x80, 0x1f, 0x1e, 0x7c,
2837 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 0xc0, 0x0f,
2838 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c,
2839 0xc0, 0x07, 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c,
2840 0x7c, 0x7c, 0xc0, 0x0f, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78,
2841 0x78, 0x3c, 0xfc, 0x7c, 0x80, 0x7f, 0x1e, 0x7c, 0x00, 0x00, 0x00, 0x00,
2842 0x1e, 0xf8, 0x78, 0x7c, 0xf8, 0xff, 0x00, 0xff, 0x1f, 0xf8, 0xff, 0x00,
2843 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xfe, 0x1f, 0xf8,
2844 0xff, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xf8,
2845 0x1f, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xc0, 0xef,
2846 0x07, 0xe0, 0x1f, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0x70, 0x40, 0x78,
2847 0x00, 0xc7, 0x07, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00,
2848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
2849 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
2851 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
2852 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2853 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2854 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2855 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
2856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00,
2857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
2858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
2859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2860 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00,
2861 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
2862 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2863 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2864 0x60, 0x00, 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2865 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2866 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00,
2867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0x9f, 0x7f, 0x00,
2868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0xdf,
2869 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00,
2870 0xe0, 0xdf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0c,
2871 0x78, 0x30, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
2872 0x00, 0x0f, 0xf8, 0x70, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x1f, 0x00, 0xe0,
2873 0x0f, 0x1e, 0x80, 0x0f, 0xf8, 0x78, 0xf0, 0xfd, 0xf9, 0x00, 0xc0, 0x1f,
2874 0x00, 0xf8, 0x0f, 0x00, 0xe0, 0x1f, 0xf8, 0x7c, 0xf0, 0xfc, 0xf9, 0x00,
2875 0xf0, 0x1f, 0x00, 0xfe, 0x0f, 0x00, 0xf0, 0x07, 0xf8, 0x3e, 0xf8, 0xfc,
2876 0xf0, 0x01, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x1e, 0xf0, 0x03, 0xf8, 0x3f,
2877 0xf8, 0xf8, 0xf0, 0x01, 0xfc, 0x1f, 0x80, 0x7f, 0x0f, 0x1e, 0xf8, 0x00,
2878 0xf8, 0x1f, 0x78, 0x18, 0xf0, 0x01, 0x7c, 0x1e, 0xc0, 0x0f, 0x0f, 0x1e,
2879 0x7c, 0x00, 0xf0, 0x0f, 0x78, 0x00, 0xf0, 0x01, 0x3e, 0x1e, 0xe0, 0x07,
2880 0x0f, 0x1e, 0x7c, 0x00, 0xf0, 0x07, 0x7c, 0x00, 0xe0, 0x01, 0x3e, 0x1e,
2881 0xe0, 0x03, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x0f, 0x7c, 0x00, 0xe0, 0x03,
2882 0x3e, 0x3e, 0xe0, 0x07, 0x0f, 0x1e, 0x1e, 0x00, 0xf0, 0x1f, 0x3c, 0x00,
2883 0xe0, 0x03, 0x7e, 0x3e, 0xc0, 0x3f, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x1f,
2884 0x3e, 0x00, 0xe0, 0x03, 0xfc, 0x7f, 0x80, 0xff, 0x0f, 0x1e, 0xfc, 0x00,
2885 0xf0, 0x3e, 0x3e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xff, 0x0f, 0x1e,
2886 0xfc, 0x07, 0xf0, 0x7c, 0x1e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xfc,
2887 0x0f, 0x1e, 0xf8, 0x1f, 0xf0, 0xf8, 0x1e, 0x00, 0xc0, 0x03, 0xe0, 0xf7,
2888 0x03, 0xf0, 0x0f, 0x1e, 0xe0, 0x3f, 0xf0, 0x78, 0x1c, 0x00, 0x80, 0x03,
2889 0x80, 0xe3, 0x03, 0x00, 0x0f, 0x1e, 0xc0, 0x3f, 0xf0, 0x30, 0x00, 0x00,
2890 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x3e, 0x00, 0x00,
2891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x10,
2892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00,
2893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
2894 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2895 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2896 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2897 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
2899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
2900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
2901 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2902 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2925 assert(display != (Display *) NULL);
2926 assert(windows != (XWindows *) NULL);
2927 font_info=windows->command.font_info;
2928 height=(unsigned int) (font_info->ascent+font_info->descent);
2931 if (event == (XEvent *) NULL)
2943 Determine command window attributes.
2945 assert(selections != (const char **) NULL);
2946 windows->command.width=0;
2947 for (i=0; selections[i] != (char *) NULL; i++)
2949 width=WidgetTextWidth(font_info,(char *) selections[i]);
2950 if (width > windows->command.width)
2951 windows->command.width=width;
2953 number_selections=(unsigned int) i;
2954 windows->command.width+=3*QuantumMargin+10;
2955 if ((int) windows->command.width < (tile_width+QuantumMargin+10))
2956 windows->command.width=(unsigned int) (tile_width+QuantumMargin+10);
2957 windows->command.height=(unsigned int) (number_selections*
2958 (((3*height) >> 1)+10)+tile_height+20);
2959 windows->command.min_width=windows->command.width;
2960 windows->command.min_height=windows->command.height;
2961 XConstrainWindowPosition(display,&windows->command);
2962 if (windows->command.id != (Window) NULL)
2968 Reconfigure command window.
2970 status=XStringListToTextProperty(&windows->command.name,1,
2972 if (status != False)
2974 XSetWMName(display,windows->command.id,&window_name);
2975 XSetWMIconName(display,windows->command.id,&window_name);
2976 (void) XFree((void *) window_name.value);
2978 window_changes.width=(int) windows->command.width;
2979 window_changes.height=(int) windows->command.height;
2980 (void) XReconfigureWMWindow(display,windows->command.id,
2981 windows->command.screen,(unsigned int) (CWWidth | CWHeight),
2985 Allocate selection info memory.
2987 if (selection_info != (XWidgetInfo *) NULL)
2988 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
2989 selection_info=(XWidgetInfo *) AcquireQuantumMemory(number_selections,
2990 sizeof(*selection_info));
2991 if (selection_info == (XWidgetInfo *) NULL)
2993 ThrowXWindowFatalException(ResourceLimitError,
2994 "MemoryAllocationFailed","...");
2997 state|=UpdateConfigurationState | RedrawWidgetState;
3000 Wait for next event.
3002 if (event != (XEvent *) NULL)
3003 switch (event->type)
3007 for (i=0; i < (int) number_selections; i++)
3009 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3011 if (i >= (int) windows->command.data)
3013 selection_info[i].raised=MagickFalse;
3014 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3017 submenu_info=selection_info[i];
3018 submenu_info.active=MagickTrue;
3020 submenu_info.y+(submenu_info.height >> 1)-(toggle_info.height >> 1);
3022 (void) XCheckWindowEvent(display,windows->widget.id,LeaveWindowMask,
3030 for (i=0; i < (int) number_selections; i++)
3032 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3035 if (id >= (int) windows->command.data)
3037 selection_info[id].raised=MagickTrue;
3038 XDrawBeveledButton(display,&windows->command,&selection_info[id]);
3048 If client window delete message, withdraw command widget.
3050 if (event->xclient.message_type != windows->wm_protocols)
3052 if (*event->xclient.data.l != (int) windows->wm_delete_window)
3054 (void) XWithdrawWindow(display,windows->command.id,
3055 windows->command.screen);
3058 case ConfigureNotify:
3061 Update widget configuration.
3063 if (event->xconfigure.window != windows->command.id)
3065 if (event->xconfigure.send_event != 0)
3067 windows->command.x=event->xconfigure.x;
3068 windows->command.y=event->xconfigure.y;
3070 if ((event->xconfigure.width == (int) windows->command.width) &&
3071 (event->xconfigure.height == (int) windows->command.height))
3073 windows->command.width=(unsigned int)
3074 MagickMax(event->xconfigure.width,(int) windows->command.min_width);
3075 windows->command.height=(unsigned int)
3076 MagickMax(event->xconfigure.height,(int) windows->command.min_height);
3077 state|=UpdateConfigurationState;
3082 if (event->xexpose.window != windows->command.id)
3084 if (event->xexpose.count != 0)
3086 state|=RedrawWidgetState;
3092 Return the ID of the highlighted menu entry.
3096 for (i=0; i < (int) number_selections; i++)
3098 if (i >= (int) windows->command.data)
3100 if (selection_info[i].raised ==
3101 MatteIsActive(selection_info[i],event->xmotion))
3104 Button status changed.
3106 selection_info[i].raised=!selection_info[i].raised;
3107 XDrawBeveledButton(display,&windows->command,
3108 &selection_info[i]);
3112 if (MatteIsActive(selection_info[i],event->xmotion) == MagickFalse)
3114 submenu_info=selection_info[i];
3115 submenu_info.active=MagickTrue;
3116 toggle_info.raised=MagickTrue;
3117 toggle_info.y=submenu_info.y+(submenu_info.height >> 1)-
3118 (toggle_info.height >> 1);
3119 XDrawTriangleEast(display,&windows->command,&toggle_info);
3122 XDelay(display,SuspendTime);
3123 if (XCheckMaskEvent(display,ButtonMotionMask,event) == MagickFalse)
3125 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
3126 toggle_info.raised=MagickFalse;
3127 if (windows->command.data != 0)
3128 XDrawTriangleEast(display,&windows->command,&toggle_info);
3134 windows->command.mapped=MagickTrue;
3139 windows->command.mapped=MagickFalse;
3145 if (state & UpdateConfigurationState)
3148 Initialize button information.
3150 assert(selections != (const char **) NULL);
3152 for (i=0; i < (int) number_selections; i++)
3154 XGetWidgetInfo(selections[i],&selection_info[i]);
3155 selection_info[i].center=MagickFalse;
3156 selection_info[i].bevel_width--;
3157 selection_info[i].height=(unsigned int) ((3*height) >> 1);
3158 selection_info[i].x=(QuantumMargin >> 1)+4;
3159 selection_info[i].width=(unsigned int)
3160 (windows->command.width-(selection_info[i].x << 1));
3161 selection_info[i].y=y;
3162 y+=selection_info[i].height+(selection_info[i].bevel_width << 1)+6;
3164 XGetWidgetInfo((char *) NULL,&toggle_info);
3165 toggle_info.bevel_width--;
3166 toggle_info.width=(unsigned int)
3167 (((5*height) >> 3)-(toggle_info.bevel_width << 1));
3168 toggle_info.height=toggle_info.width;
3169 toggle_info.x=selection_info[0].x+selection_info[0].width-
3170 toggle_info.width-(QuantumMargin >> 1);
3171 if (windows->command.mapped)
3172 (void) XClearWindow(display,windows->command.id);
3174 if (state & RedrawWidgetState)
3180 Draw command buttons.
3182 tile_pixmap=XCreatePixmapFromBitmapData(display,windows->command.id,
3183 (char *) tile_bits,tile_width,tile_height,1L,0L,1);
3184 if (tile_pixmap != (Pixmap) NULL)
3186 (void) XCopyPlane(display,tile_pixmap,windows->command.id,
3187 windows->command.annotate_context,0,0,tile_width,tile_height,
3188 (int) ((windows->command.width-tile_width) >> 1),10,1L);
3189 (void) XFreePixmap(display,tile_pixmap);
3191 for (i=0; i < (int) number_selections; i++)
3193 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3194 if (i >= (int) windows->command.data)
3196 toggle_info.raised=i == id ? MagickTrue : MagickFalse;
3197 toggle_info.y=selection_info[i].y+
3198 (selection_info[i].height >> 1)-(toggle_info.height >> 1);
3199 XDrawTriangleEast(display,&windows->command,&toggle_info);
3201 XHighlightWidget(display,&windows->command,BorderOffset,BorderOffset);
3207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3211 % X C o n f i r m W i d g e t %
3215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3217 % XConfirmWidget() displays a Confirm widget with a notice to the user. The
3218 % function returns -1 if Dismiss is pressed, 0 for Cancel, and 1 for Yes.
3220 % The format of the XConfirmWidget method is:
3222 % int XConfirmWidget(Display *display,XWindows *windows,
3223 % const char *reason,const char *description)
3225 % A description of each parameter follows:
3227 % o display: Specifies a connection to an X server; returned from
3230 % o window: Specifies a pointer to a XWindows structure.
3232 % o reason: Specifies the message to display before terminating the
3235 % o description: Specifies any description to the message.
3238 MagickPrivate int XConfirmWidget(Display *display,XWindows *windows,
3239 const char *reason,const char *description)
3241 #define CancelButtonText "Cancel"
3242 #define DismissButtonText "Dismiss"
3243 #define YesButtonText "Yes"
3278 Determine Confirm widget attributes.
3280 assert(display != (Display *) NULL);
3281 assert(windows != (XWindows *) NULL);
3282 assert(reason != (char *) NULL);
3283 assert(description != (char *) NULL);
3284 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
3285 XCheckRefreshWindows(display,windows);
3286 font_info=windows->widget.font_info;
3287 width=WidgetTextWidth(font_info,CancelButtonText);
3288 if (WidgetTextWidth(font_info,DismissButtonText) > width)
3289 width=WidgetTextWidth(font_info,DismissButtonText);
3290 if (WidgetTextWidth(font_info,YesButtonText) > width)
3291 width=WidgetTextWidth(font_info,YesButtonText);
3293 if (description != (char *) NULL)
3294 if (WidgetTextWidth(font_info,(char *) description) > width)
3295 width=WidgetTextWidth(font_info,(char *) description);
3296 height=(unsigned int) (font_info->ascent+font_info->descent);
3298 Position Confirm widget.
3300 windows->widget.width=(unsigned int) (width+9*QuantumMargin);
3301 windows->widget.min_width=(unsigned int) (9*QuantumMargin+
3302 WidgetTextWidth(font_info,CancelButtonText)+
3303 WidgetTextWidth(font_info,DismissButtonText)+
3304 WidgetTextWidth(font_info,YesButtonText));
3305 if (windows->widget.width < windows->widget.min_width)
3306 windows->widget.width=windows->widget.min_width;
3307 windows->widget.height=(unsigned int) (12*height);
3308 windows->widget.min_height=(unsigned int) (7*height);
3309 if (windows->widget.height < windows->widget.min_height)
3310 windows->widget.height=windows->widget.min_height;
3311 XConstrainWindowPosition(display,&windows->widget);
3315 (void) CopyMagickString(windows->widget.name,"Confirm",MaxTextExtent);
3316 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3317 if (status != False)
3319 XSetWMName(display,windows->widget.id,&window_name);
3320 XSetWMIconName(display,windows->widget.id,&window_name);
3321 (void) XFree((void *) window_name.value);
3323 window_changes.width=(int) windows->widget.width;
3324 window_changes.height=(int) windows->widget.height;
3325 window_changes.x=windows->widget.x;
3326 window_changes.y=windows->widget.y;
3327 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3328 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3329 (void) XMapRaised(display,windows->widget.id);
3330 windows->widget.mapped=MagickFalse;
3332 Respond to X events.
3335 state=UpdateConfigurationState;
3336 XSetCursorState(display,windows,MagickTrue);
3339 if (state & UpdateConfigurationState)
3342 Initialize button information.
3344 XGetWidgetInfo(CancelButtonText,&cancel_info);
3345 cancel_info.width=(unsigned int) QuantumMargin+
3346 WidgetTextWidth(font_info,CancelButtonText);
3347 cancel_info.height=(unsigned int) ((3*height) >> 1);
3348 cancel_info.x=(int) (windows->widget.width-cancel_info.width-
3350 cancel_info.y=(int) (windows->widget.height-(cancel_info.height << 1));
3351 dismiss_info=cancel_info;
3352 dismiss_info.text=(char *) DismissButtonText;
3353 if (LocaleCompare(description,"Do you want to save it") == 0)
3354 dismiss_info.text=(char *) "Don't Save";
3355 dismiss_info.width=(unsigned int) QuantumMargin+
3356 WidgetTextWidth(font_info,dismiss_info.text);
3357 dismiss_info.x=(int)
3358 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
3359 yes_info=cancel_info;
3360 yes_info.text=(char *) YesButtonText;
3361 if (LocaleCompare(description,"Do you want to save it") == 0)
3362 yes_info.text=(char *) "Save";
3363 yes_info.width=(unsigned int) QuantumMargin+
3364 WidgetTextWidth(font_info,yes_info.text);
3365 if (yes_info.width < cancel_info.width)
3366 yes_info.width=cancel_info.width;
3367 yes_info.x=QuantumMargin;
3368 state&=(~UpdateConfigurationState);
3370 if (state & RedrawWidgetState)
3373 Redraw Confirm widget.
3375 width=WidgetTextWidth(font_info,(char *) reason);
3376 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3377 y=(int) ((windows->widget.height >> 1)-(height << 1));
3378 (void) XDrawString(display,windows->widget.id,
3379 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
3380 if (description != (char *) NULL)
3383 question[MaxTextExtent];
3385 (void) CopyMagickString(question,description,MaxTextExtent);
3386 (void) ConcatenateMagickString(question,"?",MaxTextExtent);
3387 width=WidgetTextWidth(font_info,question);
3388 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3390 (void) XDrawString(display,windows->widget.id,
3391 windows->widget.annotate_context,x,y,question,Extent(question));
3393 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3394 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3395 XDrawBeveledButton(display,&windows->widget,&yes_info);
3396 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3397 state&=(~RedrawWidgetState);
3400 Wait for next event.
3402 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3407 if (MatteIsActive(cancel_info,event.xbutton))
3410 User pressed No button.
3412 cancel_info.raised=MagickFalse;
3413 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3416 if (MatteIsActive(dismiss_info,event.xbutton))
3419 User pressed Dismiss button.
3421 dismiss_info.raised=MagickFalse;
3422 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3425 if (MatteIsActive(yes_info,event.xbutton))
3428 User pressed Yes button.
3430 yes_info.raised=MagickFalse;
3431 XDrawBeveledButton(display,&windows->widget,&yes_info);
3438 if (windows->widget.mapped == MagickFalse)
3440 if (cancel_info.raised == MagickFalse)
3442 if (event.xbutton.window == windows->widget.id)
3443 if (MatteIsActive(cancel_info,event.xbutton))
3448 cancel_info.raised=MagickTrue;
3449 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3451 if (dismiss_info.raised == MagickFalse)
3453 if (event.xbutton.window == windows->widget.id)
3454 if (MatteIsActive(dismiss_info,event.xbutton))
3459 dismiss_info.raised=MagickTrue;
3460 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3462 if (yes_info.raised == MagickFalse)
3464 if (event.xbutton.window == windows->widget.id)
3465 if (MatteIsActive(yes_info,event.xbutton))
3470 yes_info.raised=MagickTrue;
3471 XDrawBeveledButton(display,&windows->widget,&yes_info);
3478 If client window delete message, exit.
3480 if (event.xclient.message_type != windows->wm_protocols)
3482 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3484 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3485 (Time) event.xclient.data.l[1]);
3488 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3490 if (event.xclient.window == windows->widget.id)
3497 case ConfigureNotify:
3500 Update widget configuration.
3502 if (event.xconfigure.window != windows->widget.id)
3504 if ((event.xconfigure.width == (int) windows->widget.width) &&
3505 (event.xconfigure.height == (int) windows->widget.height))
3507 windows->widget.width=(unsigned int)
3508 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3509 windows->widget.height=(unsigned int)
3510 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3511 state|=UpdateConfigurationState;
3516 if (event.xcrossing.window != windows->widget.id)
3518 state&=(~InactiveWidgetState);
3523 if (event.xexpose.window != windows->widget.id)
3525 if (event.xexpose.count != 0)
3527 state|=RedrawWidgetState;
3533 command[MaxTextExtent];
3539 Respond to a user key press.
3541 if (event.xkey.window != windows->widget.id)
3543 (void) XLookupString((XKeyEvent *) &event.xkey,command,
3544 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3545 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
3547 yes_info.raised=MagickFalse;
3548 XDrawBeveledButton(display,&windows->widget,&yes_info);
3557 if (event.xcrossing.window != windows->widget.id)
3559 state|=InactiveWidgetState;
3565 Discard pending button motion events.
3567 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
3568 if (state & InactiveWidgetState)
3570 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
3573 Cancel button status changed.
3575 cancel_info.raised=cancel_info.raised == MagickFalse ?
3576 MagickTrue : MagickFalse;
3577 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3580 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
3583 Dismiss button status changed.
3585 dismiss_info.raised=cancel_info.raised == MagickFalse ?
3586 MagickTrue : MagickFalse;
3587 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3590 if (yes_info.raised == MatteIsActive(yes_info,event.xmotion))
3593 Yes button status changed.
3595 yes_info.raised=yes_info.raised == MagickFalse ?
3596 MagickTrue : MagickFalse;
3597 XDrawBeveledButton(display,&windows->widget,&yes_info);
3605 } while ((state & ExitState) == 0);
3606 XSetCursorState(display,windows,MagickFalse);
3607 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
3608 XCheckRefreshWindows(display,windows);
3613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3617 % X D i a l o g W i d g e t %
3621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3623 % XDialogWidget() displays a Dialog widget with a query to the user. The user
3624 % keys a reply and presses the Ok or Cancel button to exit. The typed text is
3625 % returned as the reply function parameter.
3627 % The format of the XDialogWidget method is:
3629 % int XDialogWidget(Display *display,XWindows *windows,const char *action,
3630 % const char *query,char *reply)
3632 % A description of each parameter follows:
3634 % o display: Specifies a connection to an X server; returned from
3637 % o window: Specifies a pointer to a XWindows structure.
3639 % o action: Specifies a pointer to the action of this widget.
3641 % o query: Specifies a pointer to the query to present to the user.
3643 % o reply: the response from the user is returned in this parameter.
3646 MagickPrivate int XDialogWidget(Display *display,XWindows *windows,
3647 const char *action,const char *query,char *reply)
3649 #define CancelButtonText "Cancel"
3652 primary_selection[MaxTextExtent];
3660 static MagickBooleanType
3661 raised = MagickFalse;
3694 Determine Dialog widget attributes.
3696 assert(display != (Display *) NULL);
3697 assert(windows != (XWindows *) NULL);
3698 assert(action != (char *) NULL);
3699 assert(query != (char *) NULL);
3700 assert(reply != (char *) NULL);
3701 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
3702 XCheckRefreshWindows(display,windows);
3703 font_info=windows->widget.font_info;
3704 width=WidgetTextWidth(font_info,(char *) action);
3705 if (WidgetTextWidth(font_info,CancelButtonText) > width)
3706 width=WidgetTextWidth(font_info,CancelButtonText);
3707 width+=(3*QuantumMargin) >> 1;
3708 height=(unsigned int) (font_info->ascent+font_info->descent);
3710 Position Dialog widget.
3712 windows->widget.width=(unsigned int) MagickMax((int) (2*width),(int)
3713 WidgetTextWidth(font_info,(char *) query));
3714 if (windows->widget.width < WidgetTextWidth(font_info,reply))
3715 windows->widget.width=WidgetTextWidth(font_info,reply);
3716 windows->widget.width+=6*QuantumMargin;
3717 windows->widget.min_width=(unsigned int)
3718 (width+28*XTextWidth(font_info,"#",1)+4*QuantumMargin);
3719 if (windows->widget.width < windows->widget.min_width)
3720 windows->widget.width=windows->widget.min_width;
3721 windows->widget.height=(unsigned int) (7*height+(QuantumMargin << 1));
3722 windows->widget.min_height=windows->widget.height;
3723 if (windows->widget.height < windows->widget.min_height)
3724 windows->widget.height=windows->widget.min_height;
3725 XConstrainWindowPosition(display,&windows->widget);
3729 (void) CopyMagickString(windows->widget.name,"Dialog",MaxTextExtent);
3730 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3731 if (status != False)
3733 XSetWMName(display,windows->widget.id,&window_name);
3734 XSetWMIconName(display,windows->widget.id,&window_name);
3735 (void) XFree((void *) window_name.value);
3737 window_changes.width=(int) windows->widget.width;
3738 window_changes.height=(int) windows->widget.height;
3739 window_changes.x=windows->widget.x;
3740 window_changes.y=windows->widget.y;
3741 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3742 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3743 (void) XMapRaised(display,windows->widget.id);
3744 windows->widget.mapped=MagickFalse;
3746 Respond to X events.
3748 anomaly=(LocaleCompare(action,"Background") == 0) ||
3749 (LocaleCompare(action,"New") == 0) ||
3750 (LocaleCompare(action,"Quantize") == 0) ||
3751 (LocaleCompare(action,"Resize") == 0) ||
3752 (LocaleCompare(action,"Save") == 0) ||
3753 (LocaleCompare(action,"Shade") == 0);
3754 state=UpdateConfigurationState;
3755 XSetCursorState(display,windows,MagickTrue);
3758 if (state & UpdateConfigurationState)
3761 Initialize button information.
3763 XGetWidgetInfo(CancelButtonText,&cancel_info);
3764 cancel_info.width=width;
3765 cancel_info.height=(unsigned int) ((3*height) >> 1);
3767 (windows->widget.width-cancel_info.width-((3*QuantumMargin) >> 1));
3769 (windows->widget.height-cancel_info.height-((3*QuantumMargin) >> 1));
3770 XGetWidgetInfo(action,&action_info);
3771 action_info.width=width;
3772 action_info.height=(unsigned int) ((3*height) >> 1);
3773 action_info.x=cancel_info.x-(cancel_info.width+QuantumMargin+
3774 (action_info.bevel_width << 1));
3775 action_info.y=cancel_info.y;
3777 Initialize reply information.
3779 XGetWidgetInfo(reply,&reply_info);
3780 reply_info.raised=MagickFalse;
3781 reply_info.bevel_width--;
3782 reply_info.width=windows->widget.width-(3*QuantumMargin);
3783 reply_info.height=height << 1;
3784 reply_info.x=(3*QuantumMargin) >> 1;
3785 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
3787 Initialize option information.
3789 XGetWidgetInfo("Dither",&special_info);
3790 special_info.raised=raised;
3791 special_info.bevel_width--;
3792 special_info.width=(unsigned int) QuantumMargin >> 1;
3793 special_info.height=(unsigned int) QuantumMargin >> 1;
3794 special_info.x=reply_info.x;
3795 special_info.y=action_info.y+action_info.height-special_info.height;
3796 if (LocaleCompare(action,"Background") == 0)
3797 special_info.text=(char *) "Backdrop";
3798 if (LocaleCompare(action,"New") == 0)
3799 special_info.text=(char *) "Gradation";
3800 if (LocaleCompare(action,"Resize") == 0)
3801 special_info.text=(char *) "Constrain ratio";
3802 if (LocaleCompare(action,"Save") == 0)
3803 special_info.text=(char *) "Non-progressive";
3804 if (LocaleCompare(action,"Shade") == 0)
3805 special_info.text=(char *) "Color shading";
3807 Initialize text information.
3809 XGetWidgetInfo(query,&text_info);
3810 text_info.width=reply_info.width;
3811 text_info.height=height;
3812 text_info.x=reply_info.x-(QuantumMargin >> 1);
3813 text_info.y=QuantumMargin;
3814 text_info.center=MagickFalse;
3815 state&=(~UpdateConfigurationState);
3817 if (state & RedrawWidgetState)
3820 Redraw Dialog widget.
3822 XDrawWidgetText(display,&windows->widget,&text_info);
3823 XDrawBeveledMatte(display,&windows->widget,&reply_info);
3824 XDrawMatteText(display,&windows->widget,&reply_info);
3826 XDrawBeveledButton(display,&windows->widget,&special_info);
3827 XDrawBeveledButton(display,&windows->widget,&action_info);
3828 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3829 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3830 state&=(~RedrawWidgetState);
3833 Wait for next event.
3835 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3841 if (MatteIsActive(special_info,event.xbutton))
3844 Option button status changed.
3846 special_info.raised=!special_info.raised;
3847 XDrawBeveledButton(display,&windows->widget,&special_info);
3850 if (MatteIsActive(action_info,event.xbutton))
3853 User pressed Action button.
3855 action_info.raised=MagickFalse;
3856 XDrawBeveledButton(display,&windows->widget,&action_info);
3859 if (MatteIsActive(cancel_info,event.xbutton))
3862 User pressed Cancel button.
3864 cancel_info.raised=MagickFalse;
3865 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3868 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
3870 if (event.xbutton.button != Button2)
3876 Move text cursor to position of button press.
3878 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
3879 for (i=1; i <= Extent(reply_info.marker); i++)
3880 if (XTextWidth(font_info,reply_info.marker,i) > x)
3882 reply_info.cursor=reply_info.marker+i-1;
3883 if (event.xbutton.time > (click_time+DoubleClick))
3884 reply_info.highlight=MagickFalse;
3888 Become the XA_PRIMARY selection owner.
3890 (void) CopyMagickString(primary_selection,reply_info.text,
3892 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
3893 event.xbutton.time);
3894 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
3895 windows->widget.id ? MagickTrue : MagickFalse;
3897 XDrawMatteText(display,&windows->widget,&reply_info);
3898 click_time=event.xbutton.time;
3902 Request primary selection.
3904 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
3905 windows->widget.id,event.xbutton.time);
3910 if (windows->widget.mapped == MagickFalse)
3912 if (action_info.raised == MagickFalse)
3914 if (event.xbutton.window == windows->widget.id)
3915 if (MatteIsActive(action_info,event.xbutton))
3917 action_info.raised=MagickTrue;
3918 XDrawBeveledButton(display,&windows->widget,&action_info);
3920 if (cancel_info.raised == MagickFalse)
3922 if (event.xbutton.window == windows->widget.id)
3923 if (MatteIsActive(cancel_info,event.xbutton))
3925 *reply_info.text='\0';
3928 cancel_info.raised=MagickTrue;
3929 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3936 If client window delete message, exit.
3938 if (event.xclient.message_type != windows->wm_protocols)
3940 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3942 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3943 (Time) event.xclient.data.l[1]);
3946 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3948 if (event.xclient.window == windows->widget.id)
3950 *reply_info.text='\0';
3956 case ConfigureNotify:
3959 Update widget configuration.
3961 if (event.xconfigure.window != windows->widget.id)
3963 if ((event.xconfigure.width == (int) windows->widget.width) &&
3964 (event.xconfigure.height == (int) windows->widget.height))
3966 windows->widget.width=(unsigned int)
3967 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3968 windows->widget.height=(unsigned int)
3969 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3970 state|=UpdateConfigurationState;
3975 if (event.xcrossing.window != windows->widget.id)
3977 state&=(~InactiveWidgetState);
3982 if (event.xexpose.window != windows->widget.id)
3984 if (event.xexpose.count != 0)
3986 state|=RedrawWidgetState;
3992 command[MaxTextExtent];
4001 Respond to a user key press.
4003 if (event.xkey.window != windows->widget.id)
4005 length=XLookupString((XKeyEvent *) &event.xkey,command,
4006 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4007 *(command+length)='\0';
4008 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
4010 action_info.raised=MagickFalse;
4011 XDrawBeveledButton(display,&windows->widget,&action_info);
4015 if (key_symbol == XK_Control_L)
4017 state|=ControlState;
4020 if (state & ControlState)
4021 switch ((int) key_symbol)
4027 Erase the entire line of text.
4029 *reply_info.text='\0';
4030 reply_info.cursor=reply_info.text;
4031 reply_info.marker=reply_info.text;
4032 reply_info.highlight=MagickFalse;
4038 XEditText(display,&reply_info,key_symbol,command,state);
4039 XDrawMatteText(display,&windows->widget,&reply_info);
4045 command[MaxTextExtent];
4051 Respond to a user key release.
4053 if (event.xkey.window != windows->widget.id)
4055 (void) XLookupString((XKeyEvent *) &event.xkey,command,
4056 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4057 if (key_symbol == XK_Control_L)
4058 state&=(~ControlState);
4063 if (event.xcrossing.window != windows->widget.id)
4065 state|=InactiveWidgetState;
4071 Discard pending button motion events.
4073 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
4074 if (state & InactiveWidgetState)
4076 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
4079 Action button status changed.
4081 action_info.raised=action_info.raised == MagickFalse ?
4082 MagickTrue : MagickFalse;
4083 XDrawBeveledButton(display,&windows->widget,&action_info);
4086 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
4089 Cancel button status changed.
4091 cancel_info.raised=cancel_info.raised == MagickFalse ?
4092 MagickTrue : MagickFalse;
4093 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4098 case SelectionClear:
4100 reply_info.highlight=MagickFalse;
4101 XDrawMatteText(display,&windows->widget,&reply_info);
4104 case SelectionNotify:
4120 Obtain response from primary selection.
4122 if (event.xselection.property == (Atom) None)
4124 status=XGetWindowProperty(display,event.xselection.requestor,
4125 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
4126 &format,&length,&after,&data);
4127 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
4130 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
4131 (void) XBell(display,0);
4135 Insert primary selection in reply text.
4137 *(data+length)='\0';
4138 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
4140 XDrawMatteText(display,&windows->widget,&reply_info);
4142 (void) XFree((void *) data);
4145 case SelectionRequest:
4150 XSelectionRequestEvent
4153 if (reply_info.highlight == MagickFalse)
4156 Set primary selection.
4158 request=(&(event.xselectionrequest));
4159 (void) XChangeProperty(request->display,request->requestor,
4160 request->property,request->target,8,PropModeReplace,
4161 (unsigned char *) primary_selection,Extent(primary_selection));
4162 notify.type=SelectionNotify;
4163 notify.display=request->display;
4164 notify.requestor=request->requestor;
4165 notify.selection=request->selection;
4166 notify.target=request->target;
4167 notify.time=request->time;
4168 if (request->property == None)
4169 notify.property=request->target;
4171 notify.property=request->property;
4172 (void) XSendEvent(request->display,request->requestor,False,0,
4173 (XEvent *) ¬ify);
4178 } while ((state & ExitState) == 0);
4179 XSetCursorState(display,windows,MagickFalse);
4180 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
4181 XCheckRefreshWindows(display,windows);
4183 if (special_info.raised)
4186 return(raised == MagickFalse);
4190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4194 % X F i l e B r o w s e r W i d g e t %
4198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4200 % XFileBrowserWidget() displays a File Browser widget with a file query to the
4201 % user. The user keys a reply and presses the Action or Cancel button to
4202 % exit. The typed text is returned as the reply function parameter.
4204 % The format of the XFileBrowserWidget method is:
4206 % void XFileBrowserWidget(Display *display,XWindows *windows,
4207 % const char *action,char *reply)
4209 % A description of each parameter follows:
4211 % o display: Specifies a connection to an X server; returned from
4214 % o window: Specifies a pointer to a XWindows structure.
4216 % o action: Specifies a pointer to the action of this widget.
4218 % o reply: the response from the user is returned in this parameter.
4221 MagickPrivate void XFileBrowserWidget(Display *display,XWindows *windows,
4222 const char *action,char *reply)
4224 #define CancelButtonText "Cancel"
4225 #define DirectoryText "Directory:"
4226 #define FilenameText "File name:"
4227 #define GrabButtonText "Grab"
4228 #define FormatButtonText "Format"
4229 #define HomeButtonText "Home"
4230 #define UpButtonText "Up"
4235 home_directory[MaxTextExtent],
4236 primary_selection[MaxTextExtent],
4237 text[MaxTextExtent],
4238 working_path[MaxTextExtent];
4248 glob_pattern[MaxTextExtent] = "*",
4249 format[MaxTextExtent] = "miff";
4251 static MagickStatusType
4252 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
4298 Read filelist from current directory.
4300 assert(display != (Display *) NULL);
4301 assert(windows != (XWindows *) NULL);
4302 assert(action != (char *) NULL);
4303 assert(reply != (char *) NULL);
4304 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
4305 XSetCursorState(display,windows,MagickTrue);
4306 XCheckRefreshWindows(display,windows);
4307 directory=getcwd(home_directory,MaxTextExtent);
4309 (void) CopyMagickString(working_path,home_directory,MaxTextExtent);
4310 filelist=ListFiles(working_path,glob_pattern,&files);
4311 if (filelist == (char **) NULL)
4314 Directory read failed.
4316 XNoticeWidget(display,windows,"Unable to read directory:",working_path);
4317 (void) XDialogWidget(display,windows,action,"Enter filename:",reply);
4321 Determine File Browser widget attributes.
4323 font_info=windows->widget.font_info;
4325 for (i=0; i < (ssize_t) files; i++)
4326 if (WidgetTextWidth(font_info,filelist[i]) > text_width)
4327 text_width=WidgetTextWidth(font_info,filelist[i]);
4328 width=WidgetTextWidth(font_info,(char *) action);
4329 if (WidgetTextWidth(font_info,GrabButtonText) > width)
4330 width=WidgetTextWidth(font_info,GrabButtonText);
4331 if (WidgetTextWidth(font_info,FormatButtonText) > width)
4332 width=WidgetTextWidth(font_info,FormatButtonText);
4333 if (WidgetTextWidth(font_info,CancelButtonText) > width)
4334 width=WidgetTextWidth(font_info,CancelButtonText);
4335 if (WidgetTextWidth(font_info,HomeButtonText) > width)
4336 width=WidgetTextWidth(font_info,HomeButtonText);
4337 if (WidgetTextWidth(font_info,UpButtonText) > width)
4338 width=WidgetTextWidth(font_info,UpButtonText);
4339 width+=QuantumMargin;
4340 if (WidgetTextWidth(font_info,DirectoryText) > width)
4341 width=WidgetTextWidth(font_info,DirectoryText);
4342 if (WidgetTextWidth(font_info,FilenameText) > width)
4343 width=WidgetTextWidth(font_info,FilenameText);
4344 height=(unsigned int) (font_info->ascent+font_info->descent);
4346 Position File Browser widget.
4348 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
4350 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
4351 if (windows->widget.width < windows->widget.min_width)
4352 windows->widget.width=windows->widget.min_width;
4353 windows->widget.height=(unsigned int)
4354 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
4355 windows->widget.min_height=(unsigned int)
4356 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
4357 if (windows->widget.height < windows->widget.min_height)
4358 windows->widget.height=windows->widget.min_height;
4359 XConstrainWindowPosition(display,&windows->widget);
4361 Map File Browser widget.
4363 (void) CopyMagickString(windows->widget.name,"Browse and Select a File",
4365 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
4366 if (status != False)
4368 XSetWMName(display,windows->widget.id,&window_name);
4369 XSetWMIconName(display,windows->widget.id,&window_name);
4370 (void) XFree((void *) window_name.value);
4372 window_changes.width=(int) windows->widget.width;
4373 window_changes.height=(int) windows->widget.height;
4374 window_changes.x=windows->widget.x;
4375 window_changes.y=windows->widget.y;
4376 (void) XReconfigureWMWindow(display,windows->widget.id,
4377 windows->widget.screen,mask,&window_changes);
4378 (void) XMapRaised(display,windows->widget.id);
4379 windows->widget.mapped=MagickFalse;
4381 Respond to X events.
4383 XGetWidgetInfo((char *) NULL,&slider_info);
4384 XGetWidgetInfo((char *) NULL,&north_info);
4385 XGetWidgetInfo((char *) NULL,&south_info);
4386 XGetWidgetInfo((char *) NULL,&expose_info);
4388 anomaly=(LocaleCompare(action,"Composite") == 0) ||
4389 (LocaleCompare(action,"Open") == 0) || (LocaleCompare(action,"Map") == 0);
4391 delay=SuspendTime << 2;
4392 state=UpdateConfigurationState;
4395 if (state & UpdateConfigurationState)
4401 Initialize button information.
4403 XGetWidgetInfo(CancelButtonText,&cancel_info);
4404 cancel_info.width=width;
4405 cancel_info.height=(unsigned int) ((3*height) >> 1);
4407 (windows->widget.width-cancel_info.width-QuantumMargin-2);
4409 (windows->widget.height-cancel_info.height-QuantumMargin);
4410 XGetWidgetInfo(action,&action_info);
4411 action_info.width=width;
4412 action_info.height=(unsigned int) ((3*height) >> 1);
4413 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
4414 (action_info.bevel_width << 1));
4415 action_info.y=cancel_info.y;
4416 XGetWidgetInfo(GrabButtonText,&special_info);
4417 special_info.width=width;
4418 special_info.height=(unsigned int) ((3*height) >> 1);
4419 special_info.x=action_info.x-(action_info.width+(QuantumMargin >> 1)+
4420 (special_info.bevel_width << 1));
4421 special_info.y=action_info.y;
4422 if (anomaly == MagickFalse)
4427 special_info.text=(char *) FormatButtonText;
4428 p=reply+Extent(reply)-1;
4429 while ((p > (reply+1)) && (*(p-1) != '.'))
4431 if ((p > (reply+1)) && (*(p-1) == '.'))
4432 (void) CopyMagickString(format,p,MaxTextExtent);
4434 XGetWidgetInfo(UpButtonText,&up_info);
4435 up_info.width=width;
4436 up_info.height=(unsigned int) ((3*height) >> 1);
4437 up_info.x=QuantumMargin;
4438 up_info.y=((5*QuantumMargin) >> 1)+height;
4439 XGetWidgetInfo(HomeButtonText,&home_info);
4440 home_info.width=width;
4441 home_info.height=(unsigned int) ((3*height) >> 1);
4442 home_info.x=QuantumMargin;
4443 home_info.y=up_info.y+up_info.height+QuantumMargin;
4445 Initialize reply information.
4447 XGetWidgetInfo(reply,&reply_info);
4448 reply_info.raised=MagickFalse;
4449 reply_info.bevel_width--;
4450 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
4451 reply_info.height=height << 1;
4452 reply_info.x=(int) (width+(QuantumMargin << 1));
4453 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
4455 Initialize scroll information.
4457 XGetWidgetInfo((char *) NULL,&scroll_info);
4458 scroll_info.bevel_width--;
4459 scroll_info.width=height;
4460 scroll_info.height=(unsigned int)
4461 (reply_info.y-up_info.y-(QuantumMargin >> 1));
4462 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
4463 scroll_info.y=up_info.y-reply_info.bevel_width;
4464 scroll_info.raised=MagickFalse;
4465 scroll_info.trough=MagickTrue;
4466 north_info=scroll_info;
4467 north_info.raised=MagickTrue;
4468 north_info.width-=(north_info.bevel_width << 1);
4469 north_info.height=north_info.width-1;
4470 north_info.x+=north_info.bevel_width;
4471 north_info.y+=north_info.bevel_width;
4472 south_info=north_info;
4473 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
4476 slider_info=north_info;
4478 slider_info.width-=2;
4479 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
4480 slider_info.bevel_width+2;
4481 slider_info.height=scroll_info.height-((slider_info.min_y-
4482 scroll_info.y+1) << 1)+4;
4483 visible_files=scroll_info.height/(height+(height >> 3));
4484 if (files > visible_files)
4485 slider_info.height=(unsigned int)
4486 ((visible_files*slider_info.height)/files);
4487 slider_info.max_y=south_info.y-south_info.bevel_width-
4488 slider_info.bevel_width-2;
4489 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
4490 slider_info.y=slider_info.min_y;
4491 expose_info=scroll_info;
4492 expose_info.y=slider_info.y;
4494 Initialize list information.
4496 XGetWidgetInfo((char *) NULL,&list_info);
4497 list_info.raised=MagickFalse;
4498 list_info.bevel_width--;
4499 list_info.width=(unsigned int)
4500 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
4501 list_info.height=scroll_info.height;
4502 list_info.x=reply_info.x;
4503 list_info.y=scroll_info.y;
4504 if (windows->widget.mapped == MagickFalse)
4505 state|=JumpListState;
4507 Initialize text information.
4510 XGetWidgetInfo(text,&text_info);
4511 text_info.center=MagickFalse;
4512 text_info.width=reply_info.width;
4513 text_info.height=height;
4514 text_info.x=list_info.x-(QuantumMargin >> 1);
4515 text_info.y=QuantumMargin;
4517 Initialize selection information.
4519 XGetWidgetInfo((char *) NULL,&selection_info);
4520 selection_info.center=MagickFalse;
4521 selection_info.width=list_info.width;
4522 selection_info.height=(unsigned int) ((9*height) >> 3);
4523 selection_info.x=list_info.x;
4524 state&=(~UpdateConfigurationState);
4526 if (state & RedrawWidgetState)
4529 Redraw File Browser window.
4532 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
4533 (void) XDrawString(display,windows->widget.id,
4534 windows->widget.annotate_context,x,y,DirectoryText,
4535 Extent(DirectoryText));
4536 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4537 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4539 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4541 XDrawWidgetText(display,&windows->widget,&text_info);
4542 XDrawBeveledButton(display,&windows->widget,&up_info);
4543 XDrawBeveledButton(display,&windows->widget,&home_info);
4544 XDrawBeveledMatte(display,&windows->widget,&list_info);
4545 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4546 XDrawTriangleNorth(display,&windows->widget,&north_info);
4547 XDrawBeveledButton(display,&windows->widget,&slider_info);
4548 XDrawTriangleSouth(display,&windows->widget,&south_info);
4550 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
4551 (void) XDrawString(display,windows->widget.id,
4552 windows->widget.annotate_context,x,y,FilenameText,
4553 Extent(FilenameText));
4554 XDrawBeveledMatte(display,&windows->widget,&reply_info);
4555 XDrawMatteText(display,&windows->widget,&reply_info);
4556 XDrawBeveledButton(display,&windows->widget,&special_info);
4557 XDrawBeveledButton(display,&windows->widget,&action_info);
4558 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4559 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4560 selection_info.id=(~0);
4561 state|=RedrawListState;
4562 state&=(~RedrawWidgetState);
4564 if (state & UpdateListState)
4575 checklist=ListFiles(working_path,glob_pattern,&number_files);
4576 if (checklist == (char **) NULL)
4579 Reply is a filename, exit.
4581 action_info.raised=MagickFalse;
4582 XDrawBeveledButton(display,&windows->widget,&action_info);
4585 for (i=0; i < (ssize_t) files; i++)
4586 filelist[i]=DestroyString(filelist[i]);
4587 if (filelist != (char **) NULL)
4588 filelist=(char **) RelinquishMagickMemory(filelist);
4595 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
4596 if (files > visible_files)
4597 slider_info.height=(unsigned int)
4598 ((visible_files*slider_info.height)/files);
4599 slider_info.max_y=south_info.y-south_info.bevel_width-
4600 slider_info.bevel_width-2;
4602 slider_info.y=slider_info.min_y;
4603 expose_info.y=slider_info.y;
4604 selection_info.id=(~0);
4606 state|=RedrawListState;
4608 Redraw directory name & reply.
4610 if (IsGlob(reply_info.text) == MagickFalse)
4612 *reply_info.text='\0';
4613 reply_info.cursor=reply_info.text;
4615 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4616 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4618 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4620 XDrawWidgetText(display,&windows->widget,&text_info);
4621 XDrawMatteText(display,&windows->widget,&reply_info);
4622 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4623 XDrawTriangleNorth(display,&windows->widget,&north_info);
4624 XDrawBeveledButton(display,&windows->widget,&slider_info);
4625 XDrawTriangleSouth(display,&windows->widget,&south_info);
4626 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4627 state&=(~UpdateListState);
4629 if (state & JumpListState)
4632 Jump scroll to match user filename.
4635 for (i=0; i < (ssize_t) files; i++)
4636 if (LocaleCompare(filelist[i],reply) >= 0)
4639 (LocaleCompare(filelist[i],reply) == 0 ? i : ~0);
4642 if ((i < (ssize_t) slider_info.id) ||
4643 (i >= (ssize_t) (slider_info.id+visible_files)))
4644 slider_info.id=(int) i-(visible_files >> 1);
4645 selection_info.id=(~0);
4646 state|=RedrawListState;
4647 state&=(~JumpListState);
4649 if (state & RedrawListState)
4652 Determine slider id and position.
4654 if (slider_info.id >= (int) (files-visible_files))
4655 slider_info.id=(int) (files-visible_files);
4656 if ((slider_info.id < 0) || (files <= visible_files))
4658 slider_info.y=slider_info.min_y;
4660 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
4661 slider_info.min_y+1)/files);
4662 if (slider_info.id != selection_info.id)
4665 Redraw scroll bar and file names.
4667 selection_info.id=slider_info.id;
4668 selection_info.y=list_info.y+(height >> 3)+2;
4669 for (i=0; i < (ssize_t) visible_files; i++)
4671 selection_info.raised=(int) (slider_info.id+i) != list_info.id ?
4672 MagickTrue : MagickFalse;
4673 selection_info.text=(char *) NULL;
4674 if ((slider_info.id+i) < (ssize_t) files)
4675 selection_info.text=filelist[slider_info.id+i];
4676 XDrawWidgetText(display,&windows->widget,&selection_info);
4677 selection_info.y+=(int) selection_info.height;
4682 if (slider_info.y > expose_info.y)
4684 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
4685 expose_info.y=slider_info.y-expose_info.height-
4686 slider_info.bevel_width-1;
4690 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
4691 expose_info.y=slider_info.y+slider_info.height+
4692 slider_info.bevel_width+1;
4694 XDrawTriangleNorth(display,&windows->widget,&north_info);
4695 XDrawMatte(display,&windows->widget,&expose_info);
4696 XDrawBeveledButton(display,&windows->widget,&slider_info);
4697 XDrawTriangleSouth(display,&windows->widget,&south_info);
4698 expose_info.y=slider_info.y;
4700 state&=(~RedrawListState);
4703 Wait for next event.
4705 if (north_info.raised && south_info.raised)
4706 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
4710 Brief delay before advancing scroll bar.
4712 XDelay(display,delay);
4714 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
4715 if (north_info.raised == MagickFalse)
4716 if (slider_info.id > 0)
4722 state|=RedrawListState;
4724 if (south_info.raised == MagickFalse)
4725 if (slider_info.id < (int) files)
4731 state|=RedrawListState;
4733 if (event.type != ButtonRelease)
4740 if (MatteIsActive(slider_info,event.xbutton))
4745 slider_info.active=MagickTrue;
4748 if (MatteIsActive(north_info,event.xbutton))
4749 if (slider_info.id > 0)
4754 north_info.raised=MagickFalse;
4756 state|=RedrawListState;
4759 if (MatteIsActive(south_info,event.xbutton))
4760 if (slider_info.id < (int) files)
4765 south_info.raised=MagickFalse;
4767 state|=RedrawListState;
4770 if (MatteIsActive(scroll_info,event.xbutton))
4775 if (event.xbutton.y < slider_info.y)
4776 slider_info.id-=(visible_files-1);
4778 slider_info.id+=(visible_files-1);
4779 state|=RedrawListState;
4782 if (MatteIsActive(list_info,event.xbutton))
4788 User pressed file matte.
4790 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
4791 selection_info.height;
4792 if (id >= (int) files)
4794 (void) CopyMagickString(reply_info.text,filelist[id],MaxTextExtent);
4795 reply_info.highlight=MagickFalse;
4796 reply_info.marker=reply_info.text;
4797 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4798 XDrawMatteText(display,&windows->widget,&reply_info);
4799 if (id == list_info.id)
4804 p=reply_info.text+strlen(reply_info.text)-1;
4805 if (*p == *DirectorySeparator)
4806 ChopPathComponents(reply_info.text,1);
4807 (void) ConcatenateMagickString(working_path,DirectorySeparator,
4809 (void) ConcatenateMagickString(working_path,reply_info.text,
4812 state|=UpdateListState;
4814 selection_info.id=(~0);
4816 state|=RedrawListState;
4819 if (MatteIsActive(up_info,event.xbutton))
4822 User pressed Up button.
4824 up_info.raised=MagickFalse;
4825 XDrawBeveledButton(display,&windows->widget,&up_info);
4828 if (MatteIsActive(home_info,event.xbutton))
4831 User pressed Home button.
4833 home_info.raised=MagickFalse;
4834 XDrawBeveledButton(display,&windows->widget,&home_info);
4837 if (MatteIsActive(special_info,event.xbutton))
4840 User pressed Special button.
4842 special_info.raised=MagickFalse;
4843 XDrawBeveledButton(display,&windows->widget,&special_info);
4846 if (MatteIsActive(action_info,event.xbutton))
4849 User pressed action button.
4851 action_info.raised=MagickFalse;
4852 XDrawBeveledButton(display,&windows->widget,&action_info);
4855 if (MatteIsActive(cancel_info,event.xbutton))
4858 User pressed Cancel button.
4860 cancel_info.raised=MagickFalse;
4861 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4864 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
4866 if (event.xbutton.button != Button2)
4872 Move text cursor to position of button press.
4874 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
4875 for (i=1; i <= (ssize_t) Extent(reply_info.marker); i++)
4876 if (XTextWidth(font_info,reply_info.marker,(int) i) > x)
4878 reply_info.cursor=reply_info.marker+i-1;
4879 if (event.xbutton.time > (click_time+DoubleClick))
4880 reply_info.highlight=MagickFalse;
4884 Become the XA_PRIMARY selection owner.
4886 (void) CopyMagickString(primary_selection,reply_info.text,
4888 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
4889 event.xbutton.time);
4890 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
4891 windows->widget.id ? MagickTrue : MagickFalse;
4893 XDrawMatteText(display,&windows->widget,&reply_info);
4894 click_time=event.xbutton.time;
4898 Request primary selection.
4900 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
4901 windows->widget.id,event.xbutton.time);
4906 if (windows->widget.mapped == MagickFalse)
4908 if (north_info.raised == MagickFalse)
4911 User released up button.
4913 delay=SuspendTime << 2;
4914 north_info.raised=MagickTrue;
4915 XDrawTriangleNorth(display,&windows->widget,&north_info);
4917 if (south_info.raised == MagickFalse)
4920 User released down button.
4922 delay=SuspendTime << 2;
4923 south_info.raised=MagickTrue;
4924 XDrawTriangleSouth(display,&windows->widget,&south_info);
4926 if (slider_info.active)
4929 Stop tracking slider.
4931 slider_info.active=MagickFalse;
4934 if (up_info.raised == MagickFalse)
4936 if (event.xbutton.window == windows->widget.id)
4937 if (MatteIsActive(up_info,event.xbutton))
4939 ChopPathComponents(working_path,1);
4940 if (*working_path == '\0')
4941 (void) CopyMagickString(working_path,DirectorySeparator,
4943 state|=UpdateListState;
4945 up_info.raised=MagickTrue;
4946 XDrawBeveledButton(display,&windows->widget,&up_info);
4948 if (home_info.raised == MagickFalse)
4950 if (event.xbutton.window == windows->widget.id)
4951 if (MatteIsActive(home_info,event.xbutton))
4953 (void) CopyMagickString(working_path,home_directory,
4955 state|=UpdateListState;
4957 home_info.raised=MagickTrue;
4958 XDrawBeveledButton(display,&windows->widget,&home_info);
4960 if (special_info.raised == MagickFalse)
4962 if (anomaly == MagickFalse)
4974 Let user select image format.
4976 exception=AcquireExceptionInfo();
4977 formats=GetMagickList("*",&number_formats,exception);
4978 exception=DestroyExceptionInfo(exception);
4979 (void) XCheckDefineCursor(display,windows->widget.id,
4980 windows->widget.busy_cursor);
4981 windows->popup.x=windows->widget.x+60;
4982 windows->popup.y=windows->widget.y+60;
4983 XListBrowserWidget(display,windows,&windows->popup,
4984 (const char **) formats,"Select","Select image format type:",
4986 XSetCursorState(display,windows,MagickTrue);
4987 (void) XCheckDefineCursor(display,windows->widget.id,
4988 windows->widget.cursor);
4989 LocaleLower(format);
4990 AppendImageFormat(format,reply_info.text);
4991 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4992 XDrawMatteText(display,&windows->widget,&reply_info);
4993 special_info.raised=MagickTrue;
4994 XDrawBeveledButton(display,&windows->widget,&special_info);
4995 for (i=0; i < (ssize_t) number_formats; i++)
4996 formats[i]=DestroyString(formats[i]);
4997 formats=(char **) RelinquishMagickMemory(formats);
5000 if (event.xbutton.window == windows->widget.id)
5001 if (MatteIsActive(special_info,event.xbutton))
5003 (void) CopyMagickString(working_path,"x:",MaxTextExtent);
5006 special_info.raised=MagickTrue;
5007 XDrawBeveledButton(display,&windows->widget,&special_info);
5009 if (action_info.raised == MagickFalse)
5011 if (event.xbutton.window == windows->widget.id)
5013 if (MatteIsActive(action_info,event.xbutton))
5015 if (*reply_info.text == '\0')
5016 (void) XBell(display,0);
5021 action_info.raised=MagickTrue;
5022 XDrawBeveledButton(display,&windows->widget,&action_info);
5024 if (cancel_info.raised == MagickFalse)
5026 if (event.xbutton.window == windows->widget.id)
5027 if (MatteIsActive(cancel_info,event.xbutton))
5029 *reply_info.text='\0';
5033 cancel_info.raised=MagickTrue;
5034 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5041 If client window delete message, exit.
5043 if (event.xclient.message_type != windows->wm_protocols)
5045 if (*event.xclient.data.l == (int) windows->wm_take_focus)
5047 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
5048 (Time) event.xclient.data.l[1]);
5051 if (*event.xclient.data.l != (int) windows->wm_delete_window)
5053 if (event.xclient.window == windows->widget.id)
5055 *reply_info.text='\0';
5061 case ConfigureNotify:
5064 Update widget configuration.
5066 if (event.xconfigure.window != windows->widget.id)
5068 if ((event.xconfigure.width == (int) windows->widget.width) &&
5069 (event.xconfigure.height == (int) windows->widget.height))
5071 windows->widget.width=(unsigned int)
5072 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
5073 windows->widget.height=(unsigned int)
5074 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
5075 state|=UpdateConfigurationState;
5080 if (event.xcrossing.window != windows->widget.id)
5082 state&=(~InactiveWidgetState);
5087 if (event.xexpose.window != windows->widget.id)
5089 if (event.xexpose.count != 0)
5091 state|=RedrawWidgetState;
5097 command[MaxTextExtent];
5106 Respond to a user key press.
5108 if (event.xkey.window != windows->widget.id)
5110 length=XLookupString((XKeyEvent *) &event.xkey,command,
5111 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5112 *(command+length)='\0';
5113 if (AreaIsActive(scroll_info,event.xkey))
5118 switch ((int) key_symbol)
5141 slider_info.id-=visible_files;
5147 slider_info.id+=visible_files;
5153 slider_info.id=(int) files;
5157 state|=RedrawListState;
5160 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
5163 Read new directory or glob patterm.
5165 if (*reply_info.text == '\0')
5167 if (IsGlob(reply_info.text))
5168 (void) CopyMagickString(glob_pattern,reply_info.text,
5172 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5174 (void) ConcatenateMagickString(working_path,reply_info.text,
5176 if (*working_path == '~')
5177 ExpandFilename(working_path);
5180 state|=UpdateListState;
5183 if (key_symbol == XK_Control_L)
5185 state|=ControlState;
5188 if (state & ControlState)
5189 switch ((int) key_symbol)
5195 Erase the entire line of text.
5197 *reply_info.text='\0';
5198 reply_info.cursor=reply_info.text;
5199 reply_info.marker=reply_info.text;
5200 reply_info.highlight=MagickFalse;
5206 XEditText(display,&reply_info,key_symbol,command,state);
5207 XDrawMatteText(display,&windows->widget,&reply_info);
5208 state|=JumpListState;
5214 command[MaxTextExtent];
5220 Respond to a user key release.
5222 if (event.xkey.window != windows->widget.id)
5224 (void) XLookupString((XKeyEvent *) &event.xkey,command,
5225 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5226 if (key_symbol == XK_Control_L)
5227 state&=(~ControlState);
5232 if (event.xcrossing.window != windows->widget.id)
5234 state|=InactiveWidgetState;
5246 Discard pending button motion events.
5248 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
5249 if (slider_info.active)
5254 slider_info.y=event.xmotion.y-
5255 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
5256 if (slider_info.y < slider_info.min_y)
5257 slider_info.y=slider_info.min_y;
5258 if (slider_info.y > slider_info.max_y)
5259 slider_info.y=slider_info.max_y;
5261 if (slider_info.y != slider_info.min_y)
5262 slider_info.id=(int) ((files*(slider_info.y-slider_info.min_y+1))/
5263 (slider_info.max_y-slider_info.min_y+1));
5264 state|=RedrawListState;
5267 if (state & InactiveWidgetState)
5269 if (up_info.raised == MatteIsActive(up_info,event.xmotion))
5272 Up button status changed.
5274 up_info.raised=!up_info.raised;
5275 XDrawBeveledButton(display,&windows->widget,&up_info);
5278 if (home_info.raised == MatteIsActive(home_info,event.xmotion))
5281 Home button status changed.
5283 home_info.raised=!home_info.raised;
5284 XDrawBeveledButton(display,&windows->widget,&home_info);
5287 if (special_info.raised == MatteIsActive(special_info,event.xmotion))
5290 Grab button status changed.
5292 special_info.raised=!special_info.raised;
5293 XDrawBeveledButton(display,&windows->widget,&special_info);
5296 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
5299 Action button status changed.
5301 action_info.raised=action_info.raised == MagickFalse ?
5302 MagickTrue : MagickFalse;
5303 XDrawBeveledButton(display,&windows->widget,&action_info);
5306 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
5309 Cancel button status changed.
5311 cancel_info.raised=cancel_info.raised == MagickFalse ?
5312 MagickTrue : MagickFalse;
5313 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5318 case SelectionClear:
5320 reply_info.highlight=MagickFalse;
5321 XDrawMatteText(display,&windows->widget,&reply_info);
5324 case SelectionNotify:
5340 Obtain response from primary selection.
5342 if (event.xselection.property == (Atom) None)
5344 status=XGetWindowProperty(display,event.xselection.requestor,
5345 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
5346 &format,&length,&after,&data);
5347 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
5350 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
5351 (void) XBell(display,0);
5355 Insert primary selection in reply text.
5357 *(data+length)='\0';
5358 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
5360 XDrawMatteText(display,&windows->widget,&reply_info);
5361 state|=JumpListState;
5362 state|=RedrawActionState;
5364 (void) XFree((void *) data);
5367 case SelectionRequest:
5372 XSelectionRequestEvent
5375 if (reply_info.highlight == MagickFalse)
5378 Set primary selection.
5380 request=(&(event.xselectionrequest));
5381 (void) XChangeProperty(request->display,request->requestor,
5382 request->property,request->target,8,PropModeReplace,
5383 (unsigned char *) primary_selection,Extent(primary_selection));
5384 notify.type=SelectionNotify;
5385 notify.display=request->display;
5386 notify.requestor=request->requestor;
5387 notify.selection=request->selection;
5388 notify.target=request->target;
5389 notify.time=request->time;
5390 if (request->property == None)
5391 notify.property=request->target;
5393 notify.property=request->property;
5394 (void) XSendEvent(request->display,request->requestor,False,0,
5395 (XEvent *) ¬ify);
5400 } while ((state & ExitState) == 0);
5401 XSetCursorState(display,windows,MagickFalse);
5402 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
5403 XCheckRefreshWindows(display,windows);
5407 for (i=0; i < (ssize_t) files; i++)
5408 filelist[i]=DestroyString(filelist[i]);
5409 if (filelist != (char **) NULL)
5410 filelist=(char **) RelinquishMagickMemory(filelist);
5413 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5415 (void) ConcatenateMagickString(working_path,reply,MaxTextExtent);
5417 (void) CopyMagickString(reply,working_path,MaxTextExtent);
5419 ExpandFilename(reply);
5423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5427 % X F o n t B r o w s e r W i d g e t %
5431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5433 % XFontBrowserWidget() displays a Font Browser widget with a font query to the
5434 % user. The user keys a reply and presses the Action or Cancel button to
5435 % exit. The typed text is returned as the reply function parameter.
5437 % The format of the XFontBrowserWidget method is:
5439 % void XFontBrowserWidget(Display *display,XWindows *windows,
5440 % const char *action,char *reply)
5442 % A description of each parameter follows:
5444 % o display: Specifies a connection to an X server; returned from
5447 % o window: Specifies a pointer to a XWindows structure.
5449 % o action: Specifies a pointer to the action of this widget.
5451 % o reply: the response from the user is returned in this parameter.
5456 #if defined(__cplusplus) || defined(c_plusplus)
5460 static int FontCompare(const void *x,const void *y)
5466 p=(char *) *((char **) x);
5467 q=(char *) *((char **) y);
5468 while ((*p != '\0') && (*q != '\0') && (*p == *q))
5476 #if defined(__cplusplus) || defined(c_plusplus)
5480 MagickPrivate void XFontBrowserWidget(Display *display,XWindows *windows,
5481 const char *action,char *reply)
5483 #define BackButtonText "Back"
5484 #define CancelButtonText "Cancel"
5485 #define FontnameText "Name:"
5486 #define FontPatternText "Pattern:"
5487 #define ResetButtonText "Reset"
5490 back_pattern[MaxTextExtent],
5493 primary_selection[MaxTextExtent],
5494 reset_pattern[MaxTextExtent],
5495 text[MaxTextExtent];
5506 glob_pattern[MaxTextExtent] = "*";
5508 static MagickStatusType
5509 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
5553 Get font list and sort in ascending order.
5555 assert(display != (Display *) NULL);
5556 assert(windows != (XWindows *) NULL);
5557 assert(action != (char *) NULL);
5558 assert(reply != (char *) NULL);
5559 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
5560 XSetCursorState(display,windows,MagickTrue);
5561 XCheckRefreshWindows(display,windows);
5562 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
5563 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
5564 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5568 Pattern failed, obtain all the fonts.
5570 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5572 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
5573 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5574 if (fontlist == (char **) NULL)
5576 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5582 Sort font list in ascending order.
5585 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,sizeof(*fontlist));
5586 if (fontlist == (char **) NULL)
5588 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5589 "UnableToViewFonts");
5592 for (i=0; i < fonts; i++)
5593 fontlist[i]=listhead[i];
5594 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5596 Determine Font Browser widget attributes.
5598 font_info=windows->widget.font_info;
5600 for (i=0; i < fonts; i++)
5601 if (WidgetTextWidth(font_info,fontlist[i]) > text_width)
5602 text_width=WidgetTextWidth(font_info,fontlist[i]);
5603 width=WidgetTextWidth(font_info,(char *) action);
5604 if (WidgetTextWidth(font_info,CancelButtonText) > width)
5605 width=WidgetTextWidth(font_info,CancelButtonText);
5606 if (WidgetTextWidth(font_info,ResetButtonText) > width)
5607 width=WidgetTextWidth(font_info,ResetButtonText);
5608 if (WidgetTextWidth(font_info,BackButtonText) > width)
5609 width=WidgetTextWidth(font_info,BackButtonText);
5610 width+=QuantumMargin;
5611 if (WidgetTextWidth(font_info,FontPatternText) > width)
5612 width=WidgetTextWidth(font_info,FontPatternText);
5613 if (WidgetTextWidth(font_info,FontnameText) > width)
5614 width=WidgetTextWidth(font_info,FontnameText);
5615 height=(unsigned int) (font_info->ascent+font_info->descent);
5617 Position Font Browser widget.
5619 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
5621 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
5622 if (windows->widget.width < windows->widget.min_width)
5623 windows->widget.width=windows->widget.min_width;
5624 windows->widget.height=(unsigned int)
5625 (((85*height) >> 2)+((13*QuantumMargin) >> 1)+4);
5626 windows->widget.min_height=(unsigned int)
5627 (((27*height) >> 1)+((13*QuantumMargin) >> 1)+4);
5628 if (windows->widget.height < windows->widget.min_height)
5629 windows->widget.height=windows->widget.min_height;
5630 XConstrainWindowPosition(display,&windows->widget);
5632 Map Font Browser widget.
5634 (void) CopyMagickString(windows->widget.name,"Browse and Select a Font",
5636 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
5637 if (status != False)
5639 XSetWMName(display,windows->widget.id,&window_name);
5640 XSetWMIconName(display,windows->widget.id,&window_name);
5641 (void) XFree((void *) window_name.value);
5643 window_changes.width=(int) windows->widget.width;
5644 window_changes.height=(int) windows->widget.height;
5645 window_changes.x=windows->widget.x;
5646 window_changes.y=windows->widget.y;
5647 (void) XReconfigureWMWindow(display,windows->widget.id,
5648 windows->widget.screen,mask,&window_changes);
5649 (void) XMapRaised(display,windows->widget.id);
5650 windows->widget.mapped=MagickFalse;
5652 Respond to X events.
5654 XGetWidgetInfo((char *) NULL,&slider_info);
5655 XGetWidgetInfo((char *) NULL,&north_info);
5656 XGetWidgetInfo((char *) NULL,&south_info);
5657 XGetWidgetInfo((char *) NULL,&expose_info);
5659 delay=SuspendTime << 2;
5660 state=UpdateConfigurationState;
5663 if (state & UpdateConfigurationState)
5669 Initialize button information.
5671 XGetWidgetInfo(CancelButtonText,&cancel_info);
5672 cancel_info.width=width;
5673 cancel_info.height=(unsigned int) ((3*height) >> 1);
5675 (windows->widget.width-cancel_info.width-QuantumMargin-2);
5677 (windows->widget.height-cancel_info.height-QuantumMargin);
5678 XGetWidgetInfo(action,&action_info);
5679 action_info.width=width;
5680 action_info.height=(unsigned int) ((3*height) >> 1);
5681 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
5682 (action_info.bevel_width << 1));
5683 action_info.y=cancel_info.y;
5684 XGetWidgetInfo(BackButtonText,&back_info);
5685 back_info.width=width;
5686 back_info.height=(unsigned int) ((3*height) >> 1);
5687 back_info.x=QuantumMargin;
5688 back_info.y=((5*QuantumMargin) >> 1)+height;
5689 XGetWidgetInfo(ResetButtonText,&reset_info);
5690 reset_info.width=width;
5691 reset_info.height=(unsigned int) ((3*height) >> 1);
5692 reset_info.x=QuantumMargin;
5693 reset_info.y=back_info.y+back_info.height+QuantumMargin;
5695 Initialize reply information.
5697 XGetWidgetInfo(reply,&reply_info);
5698 reply_info.raised=MagickFalse;
5699 reply_info.bevel_width--;
5700 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
5701 reply_info.height=height << 1;
5702 reply_info.x=(int) (width+(QuantumMargin << 1));
5703 reply_info.y=action_info.y-(action_info.height << 1)-QuantumMargin;
5705 Initialize mode information.
5707 XGetWidgetInfo(reply,&mode_info);
5708 mode_info.bevel_width=0;
5709 mode_info.width=(unsigned int)
5710 (action_info.x-reply_info.x-QuantumMargin);
5711 mode_info.height=action_info.height << 1;
5712 mode_info.x=reply_info.x;
5713 mode_info.y=action_info.y-action_info.height+action_info.bevel_width;
5715 Initialize scroll information.
5717 XGetWidgetInfo((char *) NULL,&scroll_info);
5718 scroll_info.bevel_width--;
5719 scroll_info.width=height;
5720 scroll_info.height=(unsigned int)
5721 (reply_info.y-back_info.y-(QuantumMargin >> 1));
5722 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
5723 scroll_info.y=back_info.y-reply_info.bevel_width;
5724 scroll_info.raised=MagickFalse;
5725 scroll_info.trough=MagickTrue;
5726 north_info=scroll_info;
5727 north_info.raised=MagickTrue;
5728 north_info.width-=(north_info.bevel_width << 1);
5729 north_info.height=north_info.width-1;
5730 north_info.x+=north_info.bevel_width;
5731 north_info.y+=north_info.bevel_width;
5732 south_info=north_info;
5733 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
5736 slider_info=north_info;
5738 slider_info.width-=2;
5739 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
5740 slider_info.bevel_width+2;
5741 slider_info.height=scroll_info.height-((slider_info.min_y-
5742 scroll_info.y+1) << 1)+4;
5743 visible_fonts=scroll_info.height/(height+(height >> 3));
5744 if (fonts > (int) visible_fonts)
5745 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5746 slider_info.max_y=south_info.y-south_info.bevel_width-
5747 slider_info.bevel_width-2;
5748 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
5749 slider_info.y=slider_info.min_y;
5750 expose_info=scroll_info;
5751 expose_info.y=slider_info.y;
5753 Initialize list information.
5755 XGetWidgetInfo((char *) NULL,&list_info);
5756 list_info.raised=MagickFalse;
5757 list_info.bevel_width--;
5758 list_info.width=(unsigned int)
5759 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
5760 list_info.height=scroll_info.height;
5761 list_info.x=reply_info.x;
5762 list_info.y=scroll_info.y;
5763 if (windows->widget.mapped == MagickFalse)
5764 state|=JumpListState;
5766 Initialize text information.
5769 XGetWidgetInfo(text,&text_info);
5770 text_info.center=MagickFalse;
5771 text_info.width=reply_info.width;
5772 text_info.height=height;
5773 text_info.x=list_info.x-(QuantumMargin >> 1);
5774 text_info.y=QuantumMargin;
5776 Initialize selection information.
5778 XGetWidgetInfo((char *) NULL,&selection_info);
5779 selection_info.center=MagickFalse;
5780 selection_info.width=list_info.width;
5781 selection_info.height=(unsigned int) ((9*height) >> 3);
5782 selection_info.x=list_info.x;
5783 state&=(~UpdateConfigurationState);
5785 if (state & RedrawWidgetState)
5788 Redraw Font Browser window.
5791 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
5792 (void) XDrawString(display,windows->widget.id,
5793 windows->widget.annotate_context,x,y,FontPatternText,
5794 Extent(FontPatternText));
5795 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5796 XDrawWidgetText(display,&windows->widget,&text_info);
5797 XDrawBeveledButton(display,&windows->widget,&back_info);
5798 XDrawBeveledButton(display,&windows->widget,&reset_info);
5799 XDrawBeveledMatte(display,&windows->widget,&list_info);
5800 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5801 XDrawTriangleNorth(display,&windows->widget,&north_info);
5802 XDrawBeveledButton(display,&windows->widget,&slider_info);
5803 XDrawTriangleSouth(display,&windows->widget,&south_info);
5805 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
5806 (void) XDrawString(display,windows->widget.id,
5807 windows->widget.annotate_context,x,y,FontnameText,
5808 Extent(FontnameText));
5809 XDrawBeveledMatte(display,&windows->widget,&reply_info);
5810 XDrawMatteText(display,&windows->widget,&reply_info);
5811 XDrawBeveledButton(display,&windows->widget,&action_info);
5812 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5813 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5814 selection_info.id=(~0);
5815 state|=RedrawActionState;
5816 state|=RedrawListState;
5817 state&=(~RedrawWidgetState);
5819 if (state & UpdateListState)
5830 checklist=XListFonts(display,glob_pattern,32767,&number_fonts);
5831 if (checklist == (char **) NULL)
5833 if ((strchr(glob_pattern,'*') == (char *) NULL) &&
5834 (strchr(glob_pattern,'?') == (char *) NULL))
5837 Might be a scaleable font-- exit.
5839 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
5840 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5841 action_info.raised=MagickFalse;
5842 XDrawBeveledButton(display,&windows->widget,&action_info);
5845 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5846 (void) XBell(display,0);
5849 if (number_fonts == 1)
5852 Reply is a single font name-- exit.
5854 (void) CopyMagickString(reply,checklist[0],MaxTextExtent);
5855 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5856 (void) XFreeFontNames(checklist);
5857 action_info.raised=MagickFalse;
5858 XDrawBeveledButton(display,&windows->widget,&action_info);
5863 (void) XFreeFontNames(listhead);
5864 fontlist=(char **) RelinquishMagickMemory(fontlist);
5869 Sort font list in ascending order.
5872 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,
5874 if (fontlist == (char **) NULL)
5876 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5877 "UnableToViewFonts");
5880 for (i=0; i < fonts; i++)
5881 fontlist[i]=listhead[i];
5882 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5884 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
5885 if (fonts > (int) visible_fonts)
5886 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5887 slider_info.max_y=south_info.y-south_info.bevel_width-
5888 slider_info.bevel_width-2;
5890 slider_info.y=slider_info.min_y;
5891 expose_info.y=slider_info.y;
5892 selection_info.id=(~0);
5894 state|=RedrawListState;
5896 Redraw font name & reply.
5898 *reply_info.text='\0';
5899 reply_info.cursor=reply_info.text;
5900 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5901 XDrawWidgetText(display,&windows->widget,&text_info);
5902 XDrawMatteText(display,&windows->widget,&reply_info);
5903 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5904 XDrawTriangleNorth(display,&windows->widget,&north_info);
5905 XDrawBeveledButton(display,&windows->widget,&slider_info);
5906 XDrawTriangleSouth(display,&windows->widget,&south_info);
5907 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5908 state&=(~UpdateListState);
5910 if (state & JumpListState)
5913 Jump scroll to match user font.
5916 for (i=0; i < fonts; i++)
5917 if (LocaleCompare(fontlist[i],reply) >= 0)
5919 list_info.id=LocaleCompare(fontlist[i],reply) == 0 ? i : ~0;
5922 if ((i < slider_info.id) || (i >= (int) (slider_info.id+visible_fonts)))
5923 slider_info.id=i-(visible_fonts >> 1);
5924 selection_info.id=(~0);
5925 state|=RedrawListState;
5926 state&=(~JumpListState);
5928 if (state & RedrawListState)
5931 Determine slider id and position.
5933 if (slider_info.id >= (int) (fonts-visible_fonts))
5934 slider_info.id=fonts-visible_fonts;
5935 if ((slider_info.id < 0) || (fonts <= (int) visible_fonts))
5937 slider_info.y=slider_info.min_y;
5940 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/fonts;
5941 if (slider_info.id != selection_info.id)
5944 Redraw scroll bar and file names.
5946 selection_info.id=slider_info.id;
5947 selection_info.y=list_info.y+(height >> 3)+2;
5948 for (i=0; i < (int) visible_fonts; i++)
5950 selection_info.raised=(slider_info.id+i) != list_info.id ?
5951 MagickTrue : MagickFalse;
5952 selection_info.text=(char *) NULL;
5953 if ((slider_info.id+i) < fonts)
5954 selection_info.text=fontlist[slider_info.id+i];
5955 XDrawWidgetText(display,&windows->widget,&selection_info);
5956 selection_info.y+=(int) selection_info.height;
5961 if (slider_info.y > expose_info.y)
5963 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
5964 expose_info.y=slider_info.y-expose_info.height-
5965 slider_info.bevel_width-1;
5969 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
5970 expose_info.y=slider_info.y+slider_info.height+
5971 slider_info.bevel_width+1;
5973 XDrawTriangleNorth(display,&windows->widget,&north_info);
5974 XDrawMatte(display,&windows->widget,&expose_info);
5975 XDrawBeveledButton(display,&windows->widget,&slider_info);
5976 XDrawTriangleSouth(display,&windows->widget,&south_info);
5977 expose_info.y=slider_info.y;
5979 state&=(~RedrawListState);
5981 if (state & RedrawActionState)
5987 Display the selected font in a drawing area.
5989 save_info=windows->widget.font_info;
5990 font_info=XLoadQueryFont(display,reply_info.text);
5991 if (font_info != (XFontStruct *) NULL)
5993 windows->widget.font_info=font_info;
5994 (void) XSetFont(display,windows->widget.widget_context,
5997 XDrawBeveledButton(display,&windows->widget,&mode_info);
5998 windows->widget.font_info=save_info;
5999 if (font_info != (XFontStruct *) NULL)
6001 (void) XSetFont(display,windows->widget.widget_context,
6002 windows->widget.font_info->fid);
6003 (void) XFreeFont(display,font_info);
6005 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
6006 XDrawMatteText(display,&windows->widget,&reply_info);
6007 state&=(~RedrawActionState);
6010 Wait for next event.
6012 if (north_info.raised && south_info.raised)
6013 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
6017 Brief delay before advancing scroll bar.
6019 XDelay(display,delay);
6021 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
6022 if (north_info.raised == MagickFalse)
6023 if (slider_info.id > 0)
6029 state|=RedrawListState;
6031 if (south_info.raised == MagickFalse)
6032 if (slider_info.id < fonts)
6038 state|=RedrawListState;
6040 if (event.type != ButtonRelease)
6047 if (MatteIsActive(slider_info,event.xbutton))
6052 slider_info.active=MagickTrue;
6055 if (MatteIsActive(north_info,event.xbutton))
6056 if (slider_info.id > 0)
6061 north_info.raised=MagickFalse;
6063 state|=RedrawListState;
6066 if (MatteIsActive(south_info,event.xbutton))
6067 if (slider_info.id < fonts)
6072 south_info.raised=MagickFalse;
6074 state|=RedrawListState;
6077 if (MatteIsActive(scroll_info,event.xbutton))
6082 if (event.xbutton.y < slider_info.y)
6083 slider_info.id-=(visible_fonts-1);
6085 slider_info.id+=(visible_fonts-1);
6086 state|=RedrawListState;
6089 if (MatteIsActive(list_info,event.xbutton))
6095 User pressed list matte.
6097 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
6098 selection_info.height;
6099 if (id >= (int) fonts)
6101 (void) CopyMagickString(reply_info.text,fontlist[id],MaxTextExtent);
6102 reply_info.highlight=MagickFalse;
6103 reply_info.marker=reply_info.text;
6104 reply_info.cursor=reply_info.text+Extent(reply_info.text);
6105 XDrawMatteText(display,&windows->widget,&reply_info);
6106 state|=RedrawActionState;
6107 if (id == list_info.id)
6109 (void) CopyMagickString(glob_pattern,reply_info.text,
6111 state|=UpdateListState;
6113 selection_info.id=(~0);
6115 state|=RedrawListState;
6118 if (MatteIsActive(back_info,event.xbutton))
6121 User pressed Back button.
6123 back_info.raised=MagickFalse;
6124 XDrawBeveledButton(display,&windows->widget,&back_info);
6127 if (MatteIsActive(reset_info,event.xbutton))
6130 User pressed Reset button.
6132 reset_info.raised=MagickFalse;
6133 XDrawBeveledButton(display,&windows->widget,&reset_info);
6136 if (MatteIsActive(action_info,event.xbutton))
6139 User pressed action button.
6141 action_info.raised=MagickFalse;
6142 XDrawBeveledButton(display,&windows->widget,&action_info);
6145 if (MatteIsActive(cancel_info,event.xbutton))
6148 User pressed Cancel button.
6150 cancel_info.raised=MagickFalse;
6151 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6154 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
6156 if (event.xbutton.button != Button2)
6162 Move text cursor to position of button press.
6164 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
6165 for (i=1; i <= Extent(reply_info.marker); i++)
6166 if (XTextWidth(font_info,reply_info.marker,i) > x)
6168 reply_info.cursor=reply_info.marker+i-1;
6169 if (event.xbutton.time > (click_time+DoubleClick))
6170 reply_info.highlight=MagickFalse;
6174 Become the XA_PRIMARY selection owner.
6176 (void) CopyMagickString(primary_selection,reply_info.text,
6178 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
6179 event.xbutton.time);
6180 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
6181 windows->widget.id ? MagickTrue : MagickFalse;
6183 XDrawMatteText(display,&windows->widget,&reply_info);
6184 click_time=event.xbutton.time;
6188 Request primary selection.
6190 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
6191 windows->widget.id,event.xbutton.time);
6196 if (windows->widget.mapped == MagickFalse)
6198 if (north_info.raised == MagickFalse)
6201 User released up button.
6203 delay=SuspendTime << 2;
6204 north_info.raised=MagickTrue;
6205 XDrawTriangleNorth(display,&windows->widget,&north_info);
6207 if (south_info.raised == MagickFalse)
6210 User released down button.
6212 delay=SuspendTime << 2;
6213 south_info.raised=MagickTrue;
6214 XDrawTriangleSouth(display,&windows->widget,&south_info);
6216 if (slider_info.active)
6219 Stop tracking slider.
6221 slider_info.active=MagickFalse;
6224 if (back_info.raised == MagickFalse)
6226 if (event.xbutton.window == windows->widget.id)
6227 if (MatteIsActive(back_info,event.xbutton))
6229 (void) CopyMagickString(glob_pattern,back_pattern,
6231 state|=UpdateListState;
6233 back_info.raised=MagickTrue;
6234 XDrawBeveledButton(display,&windows->widget,&back_info);
6236 if (reset_info.raised == MagickFalse)
6238 if (event.xbutton.window == windows->widget.id)
6239 if (MatteIsActive(reset_info,event.xbutton))
6241 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6242 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
6243 state|=UpdateListState;
6245 reset_info.raised=MagickTrue;
6246 XDrawBeveledButton(display,&windows->widget,&reset_info);
6248 if (action_info.raised == MagickFalse)
6250 if (event.xbutton.window == windows->widget.id)
6252 if (MatteIsActive(action_info,event.xbutton))
6254 if (*reply_info.text == '\0')
6255 (void) XBell(display,0);
6260 action_info.raised=MagickTrue;
6261 XDrawBeveledButton(display,&windows->widget,&action_info);
6263 if (cancel_info.raised == MagickFalse)
6265 if (event.xbutton.window == windows->widget.id)
6266 if (MatteIsActive(cancel_info,event.xbutton))
6268 *reply_info.text='\0';
6271 cancel_info.raised=MagickTrue;
6272 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6279 If client window delete message, exit.
6281 if (event.xclient.message_type != windows->wm_protocols)
6283 if (*event.xclient.data.l == (int) windows->wm_take_focus)
6285 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
6286 (Time) event.xclient.data.l[1]);
6289 if (*event.xclient.data.l != (int) windows->wm_delete_window)
6291 if (event.xclient.window == windows->widget.id)
6293 *reply_info.text='\0';
6299 case ConfigureNotify:
6302 Update widget configuration.
6304 if (event.xconfigure.window != windows->widget.id)
6306 if ((event.xconfigure.width == (int) windows->widget.width) &&
6307 (event.xconfigure.height == (int) windows->widget.height))
6309 windows->widget.width=(unsigned int)
6310 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
6311 windows->widget.height=(unsigned int)
6312 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
6313 state|=UpdateConfigurationState;
6318 if (event.xcrossing.window != windows->widget.id)
6320 state&=(~InactiveWidgetState);
6325 if (event.xexpose.window != windows->widget.id)
6327 if (event.xexpose.count != 0)
6329 state|=RedrawWidgetState;
6335 command[MaxTextExtent];
6344 Respond to a user key press.
6346 if (event.xkey.window != windows->widget.id)
6348 length=XLookupString((XKeyEvent *) &event.xkey,command,
6349 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6350 *(command+length)='\0';
6351 if (AreaIsActive(scroll_info,event.xkey))
6356 switch ((int) key_symbol)
6379 slider_info.id-=visible_fonts;
6385 slider_info.id+=visible_fonts;
6391 slider_info.id=fonts;
6395 state|=RedrawListState;
6398 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
6401 Read new font or glob patterm.
6403 if (*reply_info.text == '\0')
6405 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6406 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
6407 state|=UpdateListState;
6410 if (key_symbol == XK_Control_L)
6412 state|=ControlState;
6415 if (state & ControlState)
6416 switch ((int) key_symbol)
6422 Erase the entire line of text.
6424 *reply_info.text='\0';
6425 reply_info.cursor=reply_info.text;
6426 reply_info.marker=reply_info.text;
6427 reply_info.highlight=MagickFalse;
6433 XEditText(display,&reply_info,key_symbol,command,state);
6434 XDrawMatteText(display,&windows->widget,&reply_info);
6435 state|=JumpListState;
6441 command[MaxTextExtent];
6447 Respond to a user key release.
6449 if (event.xkey.window != windows->widget.id)
6451 (void) XLookupString((XKeyEvent *) &event.xkey,command,
6452 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6453 if (key_symbol == XK_Control_L)
6454 state&=(~ControlState);
6459 if (event.xcrossing.window != windows->widget.id)
6461 state|=InactiveWidgetState;
6473 Discard pending button motion events.
6475 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
6476 if (slider_info.active)
6481 slider_info.y=event.xmotion.y-
6482 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
6483 if (slider_info.y < slider_info.min_y)
6484 slider_info.y=slider_info.min_y;
6485 if (slider_info.y > slider_info.max_y)
6486 slider_info.y=slider_info.max_y;
6488 if (slider_info.y != slider_info.min_y)
6489 slider_info.id=(fonts*(slider_info.y-slider_info.min_y+1))/
6490 (slider_info.max_y-slider_info.min_y+1);
6491 state|=RedrawListState;
6494 if (state & InactiveWidgetState)
6496 if (back_info.raised == MatteIsActive(back_info,event.xmotion))
6499 Back button status changed.
6501 back_info.raised=!back_info.raised;
6502 XDrawBeveledButton(display,&windows->widget,&back_info);
6505 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
6508 Reset button status changed.
6510 reset_info.raised=!reset_info.raised;
6511 XDrawBeveledButton(display,&windows->widget,&reset_info);
6514 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
6517 Action button status changed.
6519 action_info.raised=action_info.raised == MagickFalse ?
6520 MagickTrue : MagickFalse;
6521 XDrawBeveledButton(display,&windows->widget,&action_info);
6524 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
6527 Cancel button status changed.
6529 cancel_info.raised=cancel_info.raised == MagickFalse ?
6530 MagickTrue : MagickFalse;
6531 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6536 case SelectionClear:
6538 reply_info.highlight=MagickFalse;
6539 XDrawMatteText(display,&windows->widget,&reply_info);
6542 case SelectionNotify:
6558 Obtain response from primary selection.
6560 if (event.xselection.property == (Atom) None)
6562 status=XGetWindowProperty(display,event.xselection.requestor,
6563 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
6564 &format,&length,&after,&data);
6565 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
6568 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
6569 (void) XBell(display,0);
6573 Insert primary selection in reply text.
6575 *(data+length)='\0';
6576 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
6578 XDrawMatteText(display,&windows->widget,&reply_info);
6579 state|=JumpListState;
6580 state|=RedrawActionState;
6582 (void) XFree((void *) data);
6585 case SelectionRequest:
6590 XSelectionRequestEvent
6594 Set XA_PRIMARY selection.
6596 request=(&(event.xselectionrequest));
6597 (void) XChangeProperty(request->display,request->requestor,
6598 request->property,request->target,8,PropModeReplace,
6599 (unsigned char *) primary_selection,Extent(primary_selection));
6600 notify.type=SelectionNotify;
6601 notify.display=request->display;
6602 notify.requestor=request->requestor;
6603 notify.selection=request->selection;
6604 notify.target=request->target;
6605 notify.time=request->time;
6606 if (request->property == None)
6607 notify.property=request->target;
6609 notify.property=request->property;
6610 (void) XSendEvent(request->display,request->requestor,False,0,
6611 (XEvent *) ¬ify);
6616 } while ((state & ExitState) == 0);
6617 XSetCursorState(display,windows,MagickFalse);
6618 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
6619 XCheckRefreshWindows(display,windows);
6623 (void) XFreeFontNames(listhead);
6624 fontlist=(char **) RelinquishMagickMemory(fontlist);
6628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6632 % X I n f o W i d g e t %
6636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6638 % XInfoWidget() displays text in the Info widget. The purpose is to inform
6639 % the user that what activity is currently being performed (e.g. reading
6640 % an image, rotating an image, etc.).
6642 % The format of the XInfoWidget method is:
6644 % void XInfoWidget(Display *display,XWindows *windows,const char *activity)
6646 % A description of each parameter follows:
6648 % o display: Specifies a connection to an X server; returned from
6651 % o window: Specifies a pointer to a XWindows structure.
6653 % o activity: This character string reflects the current activity and is
6654 % displayed in the Info widget.
6657 MagickPrivate void XInfoWidget(Display *display,XWindows *windows,
6658 const char *activity)
6674 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
6675 assert(display != (Display *) NULL);
6676 assert(windows != (XWindows *) NULL);
6677 assert(activity != (char *) NULL);
6678 font_info=windows->info.font_info;
6679 width=WidgetTextWidth(font_info,(char *) activity)+((3*QuantumMargin) >> 1)+4;
6680 height=(unsigned int) (((6*(font_info->ascent+font_info->descent)) >> 2)+4);
6681 if ((windows->info.width != width) || (windows->info.height != height))
6684 Size Info widget to accommodate the activity text.
6686 windows->info.width=width;
6687 windows->info.height=height;
6688 window_changes.width=(int) width;
6689 window_changes.height=(int) height;
6690 (void) XReconfigureWMWindow(display,windows->info.id,windows->info.screen,
6691 (unsigned int) (CWWidth | CWHeight),&window_changes);
6693 if (windows->info.mapped == MagickFalse)
6695 (void) XMapRaised(display,windows->info.id);
6696 windows->info.mapped=MagickTrue;
6699 Initialize Info matte information.
6701 height=(unsigned int) (font_info->ascent+font_info->descent);
6702 XGetWidgetInfo(activity,&monitor_info);
6703 monitor_info.bevel_width--;
6704 margin=monitor_info.bevel_width+((windows->info.height-height) >> 1)-2;
6705 monitor_info.center=MagickFalse;
6706 monitor_info.x=(int) margin;
6707 monitor_info.y=(int) margin;
6708 monitor_info.width=windows->info.width-(margin << 1);
6709 monitor_info.height=windows->info.height-(margin << 1)+1;
6713 monitor_info.raised=MagickFalse;
6714 XDrawBeveledMatte(display,&windows->info,&monitor_info);
6715 monitor_info.raised=MagickTrue;
6716 XDrawWidgetText(display,&windows->info,&monitor_info);
6720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6724 % X L i s t B r o w s e r W i d g e t %
6728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6730 % XListBrowserWidget() displays a List Browser widget with a query to the
6731 % user. The user keys a reply or select a reply from the list. Finally, the
6732 % user presses the Action or Cancel button to exit. The typed text is
6733 % returned as the reply function parameter.
6735 % The format of the XListBrowserWidget method is:
6737 % void XListBrowserWidget(Display *display,XWindows *windows,
6738 % XWindowInfo *window_info,const char **list,const char *action,
6739 % const char *query,char *reply)
6741 % A description of each parameter follows:
6743 % o display: Specifies a connection to an X server; returned from
6746 % o window: Specifies a pointer to a XWindows structure.
6748 % o list: Specifies a pointer to an array of strings. The user can
6749 % select from these strings as a possible reply value.
6751 % o action: Specifies a pointer to the action of this widget.
6753 % o query: Specifies a pointer to the query to present to the user.
6755 % o reply: the response from the user is returned in this parameter.
6758 MagickPrivate void XListBrowserWidget(Display *display,XWindows *windows,
6759 XWindowInfo *window_info,const char **list,const char *action,
6760 const char *query,char *reply)
6762 #define CancelButtonText "Cancel"
6765 primary_selection[MaxTextExtent];
6773 static MagickStatusType
6774 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
6816 Count the number of entries in the list.
6818 assert(display != (Display *) NULL);
6819 assert(windows != (XWindows *) NULL);
6820 assert(window_info != (XWindowInfo *) NULL);
6821 assert(list != (const char **) NULL);
6822 assert(action != (char *) NULL);
6823 assert(query != (char *) NULL);
6824 assert(reply != (char *) NULL);
6825 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
6826 XSetCursorState(display,windows,MagickTrue);
6827 XCheckRefreshWindows(display,windows);
6828 if (list == (const char **) NULL)
6830 XNoticeWidget(display,windows,"No text to browse:",(char *) NULL);
6833 for (entries=0; ; entries++)
6834 if (list[entries] == (char *) NULL)
6837 Determine Font Browser widget attributes.
6839 font_info=window_info->font_info;
6840 text_width=WidgetTextWidth(font_info,(char *) query);
6841 for (i=0; i < (int) entries; i++)
6842 if (WidgetTextWidth(font_info,(char *) list[i]) > text_width)
6843 text_width=WidgetTextWidth(font_info,(char *) list[i]);
6844 width=WidgetTextWidth(font_info,(char *) action);
6845 if (WidgetTextWidth(font_info,CancelButtonText) > width)
6846 width=WidgetTextWidth(font_info,CancelButtonText);
6847 width+=QuantumMargin;
6848 height=(unsigned int) (font_info->ascent+font_info->descent);
6850 Position List Browser widget.
6852 window_info->width=(unsigned int) MagickMin((int) text_width,(int)
6853 MaxTextWidth)+((9*QuantumMargin) >> 1);
6854 window_info->min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
6855 if (window_info->width < window_info->min_width)
6856 window_info->width=window_info->min_width;
6857 window_info->height=(unsigned int)
6858 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
6859 window_info->min_height=(unsigned int)
6860 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
6861 if (window_info->height < window_info->min_height)
6862 window_info->height=window_info->min_height;
6863 XConstrainWindowPosition(display,window_info);
6865 Map List Browser widget.
6867 (void) CopyMagickString(window_info->name,"Browse",MaxTextExtent);
6868 status=XStringListToTextProperty(&window_info->name,1,&window_name);
6869 if (status != False)
6871 XSetWMName(display,window_info->id,&window_name);
6872 XSetWMIconName(display,windows->widget.id,&window_name);
6873 (void) XFree((void *) window_name.value);
6875 window_changes.width=(int) window_info->width;
6876 window_changes.height=(int) window_info->height;
6877 window_changes.x=window_info->x;
6878 window_changes.y=window_info->y;
6879 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,mask,
6881 (void) XMapRaised(display,window_info->id);
6882 window_info->mapped=MagickFalse;
6884 Respond to X events.
6886 XGetWidgetInfo((char *) NULL,&slider_info);
6887 XGetWidgetInfo((char *) NULL,&north_info);
6888 XGetWidgetInfo((char *) NULL,&south_info);
6889 XGetWidgetInfo((char *) NULL,&expose_info);
6891 delay=SuspendTime << 2;
6892 state=UpdateConfigurationState;
6895 if (state & UpdateConfigurationState)
6901 Initialize button information.
6903 XGetWidgetInfo(CancelButtonText,&cancel_info);
6904 cancel_info.width=width;
6905 cancel_info.height=(unsigned int) ((3*height) >> 1);
6907 (window_info->width-cancel_info.width-QuantumMargin-2);
6909 (window_info->height-cancel_info.height-QuantumMargin);
6910 XGetWidgetInfo(action,&action_info);
6911 action_info.width=width;
6912 action_info.height=(unsigned int) ((3*height) >> 1);
6913 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
6914 (action_info.bevel_width << 1));
6915 action_info.y=cancel_info.y;
6917 Initialize reply information.
6919 XGetWidgetInfo(reply,&reply_info);
6920 reply_info.raised=MagickFalse;
6921 reply_info.bevel_width--;
6922 reply_info.width=window_info->width-((4*QuantumMargin) >> 1);
6923 reply_info.height=height << 1;
6924 reply_info.x=QuantumMargin;
6925 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
6927 Initialize scroll information.
6929 XGetWidgetInfo((char *) NULL,&scroll_info);
6930 scroll_info.bevel_width--;
6931 scroll_info.width=height;
6932 scroll_info.height=(unsigned int)
6933 (reply_info.y-((6*QuantumMargin) >> 1)-height);
6934 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
6935 scroll_info.y=((5*QuantumMargin) >> 1)+height-reply_info.bevel_width;
6936 scroll_info.raised=MagickFalse;
6937 scroll_info.trough=MagickTrue;
6938 north_info=scroll_info;
6939 north_info.raised=MagickTrue;
6940 north_info.width-=(north_info.bevel_width << 1);
6941 north_info.height=north_info.width-1;
6942 north_info.x+=north_info.bevel_width;
6943 north_info.y+=north_info.bevel_width;
6944 south_info=north_info;
6945 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
6948 slider_info=north_info;
6950 slider_info.width-=2;
6951 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
6952 slider_info.bevel_width+2;
6953 slider_info.height=scroll_info.height-((slider_info.min_y-
6954 scroll_info.y+1) << 1)+4;
6955 visible_entries=scroll_info.height/(height+(height >> 3));
6956 if (entries > visible_entries)
6957 slider_info.height=(visible_entries*slider_info.height)/entries;
6958 slider_info.max_y=south_info.y-south_info.bevel_width-
6959 slider_info.bevel_width-2;
6960 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
6961 slider_info.y=slider_info.min_y;
6962 expose_info=scroll_info;
6963 expose_info.y=slider_info.y;
6965 Initialize list information.
6967 XGetWidgetInfo((char *) NULL,&list_info);
6968 list_info.raised=MagickFalse;
6969 list_info.bevel_width--;
6970 list_info.width=(unsigned int)
6971 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
6972 list_info.height=scroll_info.height;
6973 list_info.x=reply_info.x;
6974 list_info.y=scroll_info.y;
6975 if (window_info->mapped == MagickFalse)
6976 for (i=0; i < (int) entries; i++)
6977 if (LocaleCompare(list[i],reply) == 0)
6980 slider_info.id=i-(visible_entries >> 1);
6981 if (slider_info.id < 0)
6985 Initialize text information.
6987 XGetWidgetInfo(query,&text_info);
6988 text_info.width=reply_info.width;
6989 text_info.height=height;
6990 text_info.x=list_info.x-(QuantumMargin >> 1);
6991 text_info.y=QuantumMargin;
6993 Initialize selection information.
6995 XGetWidgetInfo((char *) NULL,&selection_info);
6996 selection_info.center=MagickFalse;
6997 selection_info.width=list_info.width;
6998 selection_info.height=(unsigned int) ((9*height) >> 3);
6999 selection_info.x=list_info.x;
7000 state&=(~UpdateConfigurationState);
7002 if (state & RedrawWidgetState)
7005 Redraw List Browser window.
7007 XDrawWidgetText(display,window_info,&text_info);
7008 XDrawBeveledMatte(display,window_info,&list_info);
7009 XDrawBeveledMatte(display,window_info,&scroll_info);
7010 XDrawTriangleNorth(display,window_info,&north_info);
7011 XDrawBeveledButton(display,window_info,&slider_info);
7012 XDrawTriangleSouth(display,window_info,&south_info);
7013 XDrawBeveledMatte(display,window_info,&reply_info);
7014 XDrawMatteText(display,window_info,&reply_info);
7015 XDrawBeveledButton(display,window_info,&action_info);
7016 XDrawBeveledButton(display,window_info,&cancel_info);
7017 XHighlightWidget(display,window_info,BorderOffset,BorderOffset);
7018 selection_info.id=(~0);
7019 state|=RedrawActionState;
7020 state|=RedrawListState;
7021 state&=(~RedrawWidgetState);
7023 if (state & RedrawListState)
7026 Determine slider id and position.
7028 if (slider_info.id >= (int) (entries-visible_entries))
7029 slider_info.id=(int) (entries-visible_entries);
7030 if ((slider_info.id < 0) || (entries <= visible_entries))
7032 slider_info.y=slider_info.min_y;
7035 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/entries;
7036 if (slider_info.id != selection_info.id)
7039 Redraw scroll bar and file names.
7041 selection_info.id=slider_info.id;
7042 selection_info.y=list_info.y+(height >> 3)+2;
7043 for (i=0; i < (int) visible_entries; i++)
7045 selection_info.raised=(slider_info.id+i) != list_info.id ?
7046 MagickTrue : MagickFalse;
7047 selection_info.text=(char *) NULL;
7048 if ((slider_info.id+i) < (int) entries)
7049 selection_info.text=(char *) list[slider_info.id+i];
7050 XDrawWidgetText(display,window_info,&selection_info);
7051 selection_info.y+=(int) selection_info.height;
7056 if (slider_info.y > expose_info.y)
7058 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
7059 expose_info.y=slider_info.y-expose_info.height-
7060 slider_info.bevel_width-1;
7064 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
7065 expose_info.y=slider_info.y+slider_info.height+
7066 slider_info.bevel_width+1;
7068 XDrawTriangleNorth(display,window_info,&north_info);
7069 XDrawMatte(display,window_info,&expose_info);
7070 XDrawBeveledButton(display,window_info,&slider_info);
7071 XDrawTriangleSouth(display,window_info,&south_info);
7072 expose_info.y=slider_info.y;
7074 state&=(~RedrawListState);
7077 Wait for next event.
7079 if (north_info.raised && south_info.raised)
7080 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7084 Brief delay before advancing scroll bar.
7086 XDelay(display,delay);
7088 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
7089 if (north_info.raised == MagickFalse)
7090 if (slider_info.id > 0)
7096 state|=RedrawListState;
7098 if (south_info.raised == MagickFalse)
7099 if (slider_info.id < (int) entries)
7105 state|=RedrawListState;
7107 if (event.type != ButtonRelease)
7114 if (MatteIsActive(slider_info,event.xbutton))
7119 slider_info.active=MagickTrue;
7122 if (MatteIsActive(north_info,event.xbutton))
7123 if (slider_info.id > 0)
7128 north_info.raised=MagickFalse;
7130 state|=RedrawListState;
7133 if (MatteIsActive(south_info,event.xbutton))
7134 if (slider_info.id < (int) entries)
7139 south_info.raised=MagickFalse;
7141 state|=RedrawListState;
7144 if (MatteIsActive(scroll_info,event.xbutton))
7149 if (event.xbutton.y < slider_info.y)
7150 slider_info.id-=(visible_entries-1);
7152 slider_info.id+=(visible_entries-1);
7153 state|=RedrawListState;
7156 if (MatteIsActive(list_info,event.xbutton))
7162 User pressed list matte.
7164 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
7165 selection_info.height;
7166 if (id >= (int) entries)
7168 (void) CopyMagickString(reply_info.text,list[id],MaxTextExtent);
7169 reply_info.highlight=MagickFalse;
7170 reply_info.marker=reply_info.text;
7171 reply_info.cursor=reply_info.text+Extent(reply_info.text);
7172 XDrawMatteText(display,window_info,&reply_info);
7173 selection_info.id=(~0);
7174 if (id == list_info.id)
7176 action_info.raised=MagickFalse;
7177 XDrawBeveledButton(display,window_info,&action_info);
7181 state|=RedrawListState;
7184 if (MatteIsActive(action_info,event.xbutton))
7187 User pressed action button.
7189 action_info.raised=MagickFalse;
7190 XDrawBeveledButton(display,window_info,&action_info);
7193 if (MatteIsActive(cancel_info,event.xbutton))
7196 User pressed Cancel button.
7198 cancel_info.raised=MagickFalse;
7199 XDrawBeveledButton(display,window_info,&cancel_info);
7202 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7204 if (event.xbutton.button != Button2)
7210 Move text cursor to position of button press.
7212 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
7213 for (i=1; i <= Extent(reply_info.marker); i++)
7214 if (XTextWidth(font_info,reply_info.marker,i) > x)
7216 reply_info.cursor=reply_info.marker+i-1;
7217 if (event.xbutton.time > (click_time+DoubleClick))
7218 reply_info.highlight=MagickFalse;
7222 Become the XA_PRIMARY selection owner.
7224 (void) CopyMagickString(primary_selection,reply_info.text,
7226 (void) XSetSelectionOwner(display,XA_PRIMARY,window_info->id,
7227 event.xbutton.time);
7228 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
7229 window_info->id ? MagickTrue : MagickFalse;
7231 XDrawMatteText(display,window_info,&reply_info);
7232 click_time=event.xbutton.time;
7236 Request primary selection.
7238 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
7239 window_info->id,event.xbutton.time);
7244 if (window_info->mapped == MagickFalse)
7246 if (north_info.raised == MagickFalse)
7249 User released up button.
7251 delay=SuspendTime << 2;
7252 north_info.raised=MagickTrue;
7253 XDrawTriangleNorth(display,window_info,&north_info);
7255 if (south_info.raised == MagickFalse)
7258 User released down button.
7260 delay=SuspendTime << 2;
7261 south_info.raised=MagickTrue;
7262 XDrawTriangleSouth(display,window_info,&south_info);
7264 if (slider_info.active)
7267 Stop tracking slider.
7269 slider_info.active=MagickFalse;
7272 if (action_info.raised == MagickFalse)
7274 if (event.xbutton.window == window_info->id)
7276 if (MatteIsActive(action_info,event.xbutton))
7278 if (*reply_info.text == '\0')
7279 (void) XBell(display,0);
7284 action_info.raised=MagickTrue;
7285 XDrawBeveledButton(display,window_info,&action_info);
7287 if (cancel_info.raised == MagickFalse)
7289 if (event.xbutton.window == window_info->id)
7290 if (MatteIsActive(cancel_info,event.xbutton))
7292 *reply_info.text='\0';
7295 cancel_info.raised=MagickTrue;
7296 XDrawBeveledButton(display,window_info,&cancel_info);
7298 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7305 If client window delete message, exit.
7307 if (event.xclient.message_type != windows->wm_protocols)
7309 if (*event.xclient.data.l == (int) windows->wm_take_focus)
7311 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
7312 (Time) event.xclient.data.l[1]);
7315 if (*event.xclient.data.l != (int) windows->wm_delete_window)
7317 if (event.xclient.window == window_info->id)
7319 *reply_info.text='\0';
7325 case ConfigureNotify:
7328 Update widget configuration.
7330 if (event.xconfigure.window != window_info->id)
7332 if ((event.xconfigure.width == (int) window_info->width) &&
7333 (event.xconfigure.height == (int) window_info->height))
7335 window_info->width=(unsigned int)
7336 MagickMax(event.xconfigure.width,(int) window_info->min_width);
7337 window_info->height=(unsigned int)
7338 MagickMax(event.xconfigure.height,(int) window_info->min_height);
7339 state|=UpdateConfigurationState;
7344 if (event.xcrossing.window != window_info->id)
7346 state&=(~InactiveWidgetState);
7351 if (event.xexpose.window != window_info->id)
7353 if (event.xexpose.count != 0)
7355 state|=RedrawWidgetState;
7361 command[MaxTextExtent];
7370 Respond to a user key press.
7372 if (event.xkey.window != window_info->id)
7374 length=XLookupString((XKeyEvent *) &event.xkey,command,
7375 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7376 *(command+length)='\0';
7377 if (AreaIsActive(scroll_info,event.xkey))
7382 switch ((int) key_symbol)
7405 slider_info.id-=visible_entries;
7411 slider_info.id+=visible_entries;
7417 slider_info.id=(int) entries;
7421 state|=RedrawListState;
7424 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
7429 if (*reply_info.text == '\0')
7431 action_info.raised=MagickFalse;
7432 XDrawBeveledButton(display,window_info,&action_info);
7436 if (key_symbol == XK_Control_L)
7438 state|=ControlState;
7441 if (state & ControlState)
7442 switch ((int) key_symbol)
7448 Erase the entire line of text.
7450 *reply_info.text='\0';
7451 reply_info.cursor=reply_info.text;
7452 reply_info.marker=reply_info.text;
7453 reply_info.highlight=MagickFalse;
7459 XEditText(display,&reply_info,key_symbol,command,state);
7460 XDrawMatteText(display,window_info,&reply_info);
7466 command[MaxTextExtent];
7472 Respond to a user key release.
7474 if (event.xkey.window != window_info->id)
7476 (void) XLookupString((XKeyEvent *) &event.xkey,command,
7477 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7478 if (key_symbol == XK_Control_L)
7479 state&=(~ControlState);
7484 if (event.xcrossing.window != window_info->id)
7486 state|=InactiveWidgetState;
7498 Discard pending button motion events.
7500 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7501 if (slider_info.active)
7506 slider_info.y=event.xmotion.y-
7507 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
7508 if (slider_info.y < slider_info.min_y)
7509 slider_info.y=slider_info.min_y;
7510 if (slider_info.y > slider_info.max_y)
7511 slider_info.y=slider_info.max_y;
7513 if (slider_info.y != slider_info.min_y)
7514 slider_info.id=(int) ((entries*(slider_info.y-
7515 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
7516 state|=RedrawListState;
7519 if (state & InactiveWidgetState)
7521 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
7524 Action button status changed.
7526 action_info.raised=action_info.raised == MagickFalse ?
7527 MagickTrue : MagickFalse;
7528 XDrawBeveledButton(display,window_info,&action_info);
7531 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
7534 Cancel button status changed.
7536 cancel_info.raised=cancel_info.raised == MagickFalse ?
7537 MagickTrue : MagickFalse;
7538 XDrawBeveledButton(display,window_info,&cancel_info);
7543 case SelectionClear:
7545 reply_info.highlight=MagickFalse;
7546 XDrawMatteText(display,window_info,&reply_info);
7549 case SelectionNotify:
7565 Obtain response from primary selection.
7567 if (event.xselection.property == (Atom) None)
7569 status=XGetWindowProperty(display,
7570 event.xselection.requestor,event.xselection.property,0L,2047L,
7571 MagickTrue,XA_STRING,&type,&format,&length,&after,&data);
7572 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
7575 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
7576 (void) XBell(display,0);
7580 Insert primary selection in reply text.
7582 *(data+length)='\0';
7583 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
7585 XDrawMatteText(display,window_info,&reply_info);
7586 state|=RedrawActionState;
7588 (void) XFree((void *) data);
7591 case SelectionRequest:
7596 XSelectionRequestEvent
7599 if (reply_info.highlight == MagickFalse)
7602 Set primary selection.
7604 request=(&(event.xselectionrequest));
7605 (void) XChangeProperty(request->display,request->requestor,
7606 request->property,request->target,8,PropModeReplace,
7607 (unsigned char *) primary_selection,Extent(primary_selection));
7608 notify.type=SelectionNotify;
7609 notify.send_event=MagickTrue;
7610 notify.display=request->display;
7611 notify.requestor=request->requestor;
7612 notify.selection=request->selection;
7613 notify.target=request->target;
7614 notify.time=request->time;
7615 if (request->property == None)
7616 notify.property=request->target;
7618 notify.property=request->property;
7619 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
7620 (XEvent *) ¬ify);
7625 } while ((state & ExitState) == 0);
7626 XSetCursorState(display,windows,MagickFalse);
7627 (void) XWithdrawWindow(display,window_info->id,window_info->screen);
7628 XCheckRefreshWindows(display,windows);
7632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7636 % X M e n u W i d g e t %
7640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7642 % XMenuWidget() maps a menu and returns the command pointed to by the user
7643 % when the button is released.
7645 % The format of the XMenuWidget method is:
7647 % int XMenuWidget(Display *display,XWindows *windows,const char *title,
7648 % const char **selections,char *item)
7650 % A description of each parameter follows:
7652 % o selection_number: Specifies the number of the selection that the
7655 % o display: Specifies a connection to an X server; returned from
7658 % o window: Specifies a pointer to a XWindows structure.
7660 % o title: Specifies a character string that describes the menu selections.
7662 % o selections: Specifies a pointer to one or more strings that comprise
7663 % the choices in the menu.
7665 % o item: Specifies a character array. The item selected from the menu
7669 MagickPrivate int XMenuWidget(Display *display,XWindows *windows,
7670 const char *title,const char **selections,char *item)
7696 XSetWindowAttributes
7708 Determine Menu widget attributes.
7710 assert(display != (Display *) NULL);
7711 assert(windows != (XWindows *) NULL);
7712 assert(title != (char *) NULL);
7713 assert(selections != (const char **) NULL);
7714 assert(item != (char *) NULL);
7715 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
7716 font_info=windows->widget.font_info;
7717 windows->widget.width=submenu_info.active == 0 ?
7718 WidgetTextWidth(font_info,(char *) title) : 0;
7719 for (id=0; selections[id] != (char *) NULL; id++)
7721 width=WidgetTextWidth(font_info,(char *) selections[id]);
7722 if (width > windows->widget.width)
7723 windows->widget.width=width;
7725 number_selections=(unsigned int) id;
7726 XGetWidgetInfo((char *) NULL,&menu_info);
7727 title_height=(unsigned int) (submenu_info.active == 0 ?
7728 (3*(font_info->descent+font_info->ascent) >> 1)+5 : 2);
7729 width=WidgetTextWidth(font_info,(char *) title);
7730 height=(unsigned int) ((3*(font_info->ascent+font_info->descent)) >> 1);
7732 Position Menu widget.
7734 windows->widget.width+=QuantumMargin+(menu_info.bevel_width << 1);
7735 top_offset=title_height+menu_info.bevel_width-1;
7736 windows->widget.height=top_offset+number_selections*height+4;
7737 windows->widget.min_width=windows->widget.width;
7738 windows->widget.min_height=windows->widget.height;
7739 XQueryPosition(display,windows->widget.root,&x,&y);
7740 windows->widget.x=x-(QuantumMargin >> 1);
7741 if (submenu_info.active != 0)
7744 windows->command.x+windows->command.width-QuantumMargin;
7745 toggle_info.raised=MagickTrue;
7746 XDrawTriangleEast(display,&windows->command,&toggle_info);
7748 windows->widget.y=submenu_info.active == 0 ? y-(int)
7749 ((3*title_height) >> 2) : y;
7750 if (submenu_info.active != 0)
7751 windows->widget.y=windows->command.y+submenu_info.y;
7752 XConstrainWindowPosition(display,&windows->widget);
7756 window_attributes.override_redirect=MagickTrue;
7757 (void) XChangeWindowAttributes(display,windows->widget.id,
7758 (size_t) CWOverrideRedirect,&window_attributes);
7759 window_changes.width=(int) windows->widget.width;
7760 window_changes.height=(int) windows->widget.height;
7761 window_changes.x=windows->widget.x;
7762 window_changes.y=windows->widget.y;
7763 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
7764 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
7765 (void) XMapRaised(display,windows->widget.id);
7766 windows->widget.mapped=MagickFalse;
7768 Respond to X events.
7770 selection_info.height=height;
7771 cursor=XCreateFontCursor(display,XC_right_ptr);
7772 (void) XCheckDefineCursor(display,windows->image.id,cursor);
7773 (void) XCheckDefineCursor(display,windows->command.id,cursor);
7774 (void) XCheckDefineCursor(display,windows->widget.id,cursor);
7775 state=UpdateConfigurationState;
7778 if (state & UpdateConfigurationState)
7781 Initialize selection information.
7783 XGetWidgetInfo((char *) NULL,&menu_info);
7784 menu_info.bevel_width--;
7785 menu_info.width=windows->widget.width-((menu_info.bevel_width) << 1);
7786 menu_info.height=windows->widget.height-((menu_info.bevel_width) << 1);
7787 menu_info.x=(int) menu_info.bevel_width;
7788 menu_info.y=(int) menu_info.bevel_width;
7789 XGetWidgetInfo((char *) NULL,&selection_info);
7790 selection_info.center=MagickFalse;
7791 selection_info.width=menu_info.width;
7792 selection_info.height=height;
7793 selection_info.x=menu_info.x;
7794 highlight_info=selection_info;
7795 highlight_info.bevel_width--;
7796 highlight_info.width-=(highlight_info.bevel_width << 1);
7797 highlight_info.height-=(highlight_info.bevel_width << 1);
7798 highlight_info.x+=highlight_info.bevel_width;
7799 state&=(~UpdateConfigurationState);
7801 if (state & RedrawWidgetState)
7806 if (submenu_info.active == 0)
7808 y=(int) title_height;
7809 XSetBevelColor(display,&windows->widget,MagickFalse);
7810 (void) XDrawLine(display,windows->widget.id,
7811 windows->widget.widget_context,selection_info.x,y-1,
7812 (int) selection_info.width,y-1);
7813 XSetBevelColor(display,&windows->widget,MagickTrue);
7814 (void) XDrawLine(display,windows->widget.id,
7815 windows->widget.widget_context,selection_info.x,y,
7816 (int) selection_info.width,y);
7817 (void) XSetFillStyle(display,windows->widget.widget_context,
7821 Draw menu selections.
7823 selection_info.center=MagickTrue;
7824 selection_info.y=(int) menu_info.bevel_width;
7825 selection_info.text=(char *) title;
7826 if (submenu_info.active == 0)
7827 XDrawWidgetText(display,&windows->widget,&selection_info);
7828 selection_info.center=MagickFalse;
7829 selection_info.y=(int) top_offset;
7830 for (id=0; id < (int) number_selections; id++)
7832 selection_info.text=(char *) selections[id];
7833 XDrawWidgetText(display,&windows->widget,&selection_info);
7834 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7835 if (id == selection_info.id)
7836 XDrawBevel(display,&windows->widget,&highlight_info);
7837 selection_info.y+=(int) selection_info.height;
7839 XDrawBevel(display,&windows->widget,&menu_info);
7840 state&=(~RedrawWidgetState);
7842 if (number_selections > 2)
7847 y=(int) (top_offset+selection_info.height*(number_selections-1));
7848 XSetBevelColor(display,&windows->widget,MagickFalse);
7849 (void) XDrawLine(display,windows->widget.id,
7850 windows->widget.widget_context,selection_info.x,y-1,
7851 (int) selection_info.width,y-1);
7852 XSetBevelColor(display,&windows->widget,MagickTrue);
7853 (void) XDrawLine(display,windows->widget.id,
7854 windows->widget.widget_context,selection_info.x,y,
7855 (int) selection_info.width,y);
7856 (void) XSetFillStyle(display,windows->widget.widget_context,FillSolid);
7859 Wait for next event.
7861 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7866 if (event.xbutton.window != windows->widget.id)
7871 if (event.xbutton.window == windows->command.id)
7872 (void) XPutBackEvent(display,&event);
7873 selection_info.id=(~0);
7878 state&=(~InactiveWidgetState);
7879 id=(event.xbutton.y-top_offset)/(int) selection_info.height;
7880 selection_info.id=id;
7881 if ((id < 0) || (id >= (int) number_selections))
7884 Highlight this selection.
7886 selection_info.y=(int) (top_offset+id*selection_info.height);
7887 selection_info.text=(char *) selections[id];
7888 XDrawWidgetText(display,&windows->widget,&selection_info);
7889 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7890 XDrawBevel(display,&windows->widget,&highlight_info);
7895 if (windows->widget.mapped == MagickFalse)
7897 if (event.xbutton.window == windows->command.id)
7898 if ((state & InactiveWidgetState) == 0)
7903 XSetCursorState(display,windows,MagickFalse);
7908 case ConfigureNotify:
7911 Update widget configuration.
7913 if (event.xconfigure.window != windows->widget.id)
7915 if ((event.xconfigure.width == (int) windows->widget.width) &&
7916 (event.xconfigure.height == (int) windows->widget.height))
7918 windows->widget.width=(unsigned int)
7919 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
7920 windows->widget.height=(unsigned int)
7921 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
7922 state|=UpdateConfigurationState;
7927 if (event.xcrossing.window != windows->widget.id)
7929 if (event.xcrossing.state == 0)
7931 state&=(~InactiveWidgetState);
7932 id=((event.xcrossing.y-top_offset)/(int) selection_info.height);
7933 if ((selection_info.id >= 0) &&
7934 (selection_info.id < (int) number_selections))
7937 Unhighlight last selection.
7939 if (id == selection_info.id)
7941 selection_info.y=(int)
7942 (top_offset+selection_info.id*selection_info.height);
7943 selection_info.text=(char *) selections[selection_info.id];
7944 XDrawWidgetText(display,&windows->widget,&selection_info);
7946 if ((id < 0) || (id >= (int) number_selections))
7949 Highlight this selection.
7951 selection_info.id=id;
7952 selection_info.y=(int)
7953 (top_offset+selection_info.id*selection_info.height);
7954 selection_info.text=(char *) selections[selection_info.id];
7955 XDrawWidgetText(display,&windows->widget,&selection_info);
7956 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7957 XDrawBevel(display,&windows->widget,&highlight_info);
7962 if (event.xexpose.window != windows->widget.id)
7964 if (event.xexpose.count != 0)
7966 state|=RedrawWidgetState;
7971 if (event.xcrossing.window != windows->widget.id)
7973 state|=InactiveWidgetState;
7974 id=selection_info.id;
7975 if ((id < 0) || (id >= (int) number_selections))
7978 Unhighlight last selection.
7980 selection_info.y=(int) (top_offset+id*selection_info.height);
7981 selection_info.id=(~0);
7982 selection_info.text=(char *) selections[id];
7983 XDrawWidgetText(display,&windows->widget,&selection_info);
7989 Discard pending button motion events.
7991 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7992 if (submenu_info.active != 0)
7993 if (event.xmotion.window == windows->command.id)
7995 if ((state & InactiveWidgetState) == 0)
7997 if (MatteIsActive(submenu_info,event.xmotion) == MagickFalse)
7999 selection_info.id=(~0);
8006 if (WindowIsActive(windows->command,event.xmotion))
8008 selection_info.id=(~0);
8014 if (event.xmotion.window != windows->widget.id)
8016 if (state & InactiveWidgetState)
8018 id=(event.xmotion.y-top_offset)/(int) selection_info.height;
8019 if ((selection_info.id >= 0) &&
8020 (selection_info.id < (int) number_selections))
8023 Unhighlight last selection.
8025 if (id == selection_info.id)
8027 selection_info.y=(int)
8028 (top_offset+selection_info.id*selection_info.height);
8029 selection_info.text=(char *) selections[selection_info.id];
8030 XDrawWidgetText(display,&windows->widget,&selection_info);
8032 selection_info.id=id;
8033 if ((id < 0) || (id >= (int) number_selections))
8036 Highlight this selection.
8038 selection_info.y=(int) (top_offset+id*selection_info.height);
8039 selection_info.text=(char *) selections[id];
8040 XDrawWidgetText(display,&windows->widget,&selection_info);
8041 highlight_info.y=selection_info.y+highlight_info.bevel_width;
8042 XDrawBevel(display,&windows->widget,&highlight_info);
8048 } while ((state & ExitState) == 0);
8049 (void) XFreeCursor(display,cursor);
8050 window_attributes.override_redirect=MagickFalse;
8051 (void) XChangeWindowAttributes(display,windows->widget.id,
8052 (size_t) CWOverrideRedirect,&window_attributes);
8053 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8054 XCheckRefreshWindows(display,windows);
8055 if (submenu_info.active != 0)
8057 submenu_info.active=MagickFalse;
8058 toggle_info.raised=MagickFalse;
8059 XDrawTriangleEast(display,&windows->command,&toggle_info);
8061 if ((selection_info.id < 0) || (selection_info.id >= (int) number_selections))
8063 (void) CopyMagickString(item,selections[selection_info.id],MaxTextExtent);
8064 return(selection_info.id);
8068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8072 % X N o t i c e W i d g e t %
8076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8078 % XNoticeWidget() displays a Notice widget with a notice to the user. The
8079 % function returns when the user presses the "Dismiss" button.
8081 % The format of the XNoticeWidget method is:
8083 % void XNoticeWidget(Display *display,XWindows *windows,
8084 % const char *reason,const char *description)
8086 % A description of each parameter follows:
8088 % o display: Specifies a connection to an X server; returned from
8091 % o window: Specifies a pointer to a XWindows structure.
8093 % o reason: Specifies the message to display before terminating the
8096 % o description: Specifies any description to the message.
8099 MagickPrivate void XNoticeWidget(Display *display,XWindows *windows,
8100 const char *reason,const char *description)
8102 #define DismissButtonText "Dismiss"
8141 Determine Notice widget attributes.
8143 assert(display != (Display *) NULL);
8144 assert(windows != (XWindows *) NULL);
8145 assert(reason != (char *) NULL);
8146 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
8147 XDelay(display,SuspendTime << 3); /* avoid surpise with delay */
8148 XSetCursorState(display,windows,MagickTrue);
8149 XCheckRefreshWindows(display,windows);
8150 font_info=windows->widget.font_info;
8151 width=WidgetTextWidth(font_info,DismissButtonText);
8152 text=GetLocaleExceptionMessage(XServerError,reason);
8153 if (text != (char *) NULL)
8154 if (WidgetTextWidth(font_info,(char *) text) > width)
8155 width=WidgetTextWidth(font_info,(char *) text);
8156 if (description != (char *) NULL)
8158 text=GetLocaleExceptionMessage(XServerError,description);
8159 if (text != (char *) NULL)
8160 if (WidgetTextWidth(font_info,(char *) text) > width)
8161 width=WidgetTextWidth(font_info,(char *) text);
8163 height=(unsigned int) (font_info->ascent+font_info->descent);
8165 Position Notice widget.
8167 windows->widget.width=width+4*QuantumMargin;
8168 windows->widget.min_width=width+QuantumMargin;
8169 if (windows->widget.width < windows->widget.min_width)
8170 windows->widget.width=windows->widget.min_width;
8171 windows->widget.height=(unsigned int) (12*height);
8172 windows->widget.min_height=(unsigned int) (7*height);
8173 if (windows->widget.height < windows->widget.min_height)
8174 windows->widget.height=windows->widget.min_height;
8175 XConstrainWindowPosition(display,&windows->widget);
8179 (void) CopyMagickString(windows->widget.name,"Notice",MaxTextExtent);
8180 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8181 if (status != False)
8183 XSetWMName(display,windows->widget.id,&window_name);
8184 XSetWMIconName(display,windows->widget.id,&window_name);
8185 (void) XFree((void *) window_name.value);
8187 window_changes.width=(int) windows->widget.width;
8188 window_changes.height=(int) windows->widget.height;
8189 window_changes.x=windows->widget.x;
8190 window_changes.y=windows->widget.y;
8191 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8192 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8193 (void) XMapRaised(display,windows->widget.id);
8194 windows->widget.mapped=MagickFalse;
8195 (void) XBell(display,0);
8197 Respond to X events.
8199 timer=time((time_t *) NULL)+Timeout;
8200 state=UpdateConfigurationState;
8203 if (time((time_t *) NULL) > timer)
8205 if (state & UpdateConfigurationState)
8208 Initialize Dismiss button information.
8210 XGetWidgetInfo(DismissButtonText,&dismiss_info);
8211 dismiss_info.width=(unsigned int) QuantumMargin+
8212 WidgetTextWidth(font_info,DismissButtonText);
8213 dismiss_info.height=(unsigned int) ((3*height) >> 1);
8214 dismiss_info.x=(int)
8215 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
8216 dismiss_info.y=(int)
8217 (windows->widget.height-(dismiss_info.height << 1));
8218 state&=(~UpdateConfigurationState);
8220 if (state & RedrawWidgetState)
8223 Redraw Notice widget.
8225 width=WidgetTextWidth(font_info,(char *) reason);
8226 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8227 y=(int) ((windows->widget.height >> 1)-(height << 1));
8228 (void) XDrawString(display,windows->widget.id,
8229 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
8230 if (description != (char *) NULL)
8232 width=WidgetTextWidth(font_info,(char *) description);
8233 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8235 (void) XDrawString(display,windows->widget.id,
8236 windows->widget.annotate_context,x,y,(char *) description,
8237 Extent(description));
8239 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8240 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8241 state&=(~RedrawWidgetState);
8244 Wait for next event.
8246 if (XCheckIfEvent(display,&event,XScreenEvent,(char *) windows) == MagickFalse)
8249 Do not block if delay > 0.
8251 XDelay(display,SuspendTime << 2);
8258 if (MatteIsActive(dismiss_info,event.xbutton))
8261 User pressed Dismiss button.
8263 dismiss_info.raised=MagickFalse;
8264 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8271 if (windows->widget.mapped == MagickFalse)
8273 if (dismiss_info.raised == MagickFalse)
8275 if (event.xbutton.window == windows->widget.id)
8276 if (MatteIsActive(dismiss_info,event.xbutton))
8278 dismiss_info.raised=MagickTrue;
8279 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8286 If client window delete message, exit.
8288 if (event.xclient.message_type != windows->wm_protocols)
8290 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8292 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8293 (Time) event.xclient.data.l[1]);
8296 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8298 if (event.xclient.window == windows->widget.id)
8305 case ConfigureNotify:
8308 Update widget configuration.
8310 if (event.xconfigure.window != windows->widget.id)
8312 if ((event.xconfigure.width == (int) windows->widget.width) &&
8313 (event.xconfigure.height == (int) windows->widget.height))
8315 windows->widget.width=(unsigned int)
8316 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8317 windows->widget.height=(unsigned int)
8318 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8319 state|=UpdateConfigurationState;
8324 if (event.xcrossing.window != windows->widget.id)
8326 state&=(~InactiveWidgetState);
8331 if (event.xexpose.window != windows->widget.id)
8333 if (event.xexpose.count != 0)
8335 state|=RedrawWidgetState;
8341 command[MaxTextExtent];
8347 Respond to a user key press.
8349 if (event.xkey.window != windows->widget.id)
8351 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8352 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8353 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8355 dismiss_info.raised=MagickFalse;
8356 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8364 if (event.xcrossing.window != windows->widget.id)
8366 state|=InactiveWidgetState;
8372 Discard pending button motion events.
8374 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8375 if (state & InactiveWidgetState)
8377 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
8380 Dismiss button status changed.
8382 dismiss_info.raised=
8383 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8384 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8392 } while ((state & ExitState) == 0);
8393 XSetCursorState(display,windows,MagickFalse);
8394 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8395 XCheckRefreshWindows(display,windows);
8399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8403 % X P r e f e r e n c e s W i d g e t %
8407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8409 % XPreferencesWidget() displays a Preferences widget with program preferences.
8410 % If the user presses the Apply button, the preferences are stored in a
8411 % configuration file in the users' home directory.
8413 % The format of the XPreferencesWidget method is:
8415 % MagickBooleanType XPreferencesWidget(Display *display,
8416 % XResourceInfo *resource_info,XWindows *windows)
8418 % A description of each parameter follows:
8420 % o display: Specifies a connection to an X server; returned from
8423 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8425 % o window: Specifies a pointer to a XWindows structure.
8428 MagickPrivate MagickBooleanType XPreferencesWidget(Display *display,
8429 XResourceInfo *resource_info,XWindows *windows)
8431 #define ApplyButtonText "Apply"
8432 #define CacheButtonText "%lu mega-bytes of memory in the undo edit cache "
8433 #define CancelButtonText "Cancel"
8434 #define NumberPreferences 8
8439 "display image centered on a backdrop",
8440 "confirm on program exit",
8441 "confirm on image edits",
8442 "correct image for display gamma",
8443 "display warning messages",
8444 "apply Floyd/Steinberg error diffusion to image",
8445 "use a shared colormap for colormapped X visuals",
8446 "display images as an X server pixmap"
8450 cache[MaxTextExtent];
8483 preferences_info[NumberPreferences];
8489 Determine Preferences widget attributes.
8491 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8492 assert(display != (Display *) NULL);
8493 assert(resource_info != (XResourceInfo *) NULL);
8494 assert(windows != (XWindows *) NULL);
8495 XCheckRefreshWindows(display,windows);
8496 font_info=windows->widget.font_info;
8497 text_width=WidgetTextWidth(font_info,CacheButtonText);
8498 for (i=0; i < NumberPreferences; i++)
8499 if (WidgetTextWidth(font_info,(char *) Preferences[i]) > text_width)
8500 text_width=WidgetTextWidth(font_info,(char *) Preferences[i]);
8501 width=WidgetTextWidth(font_info,ApplyButtonText);
8502 if (WidgetTextWidth(font_info,CancelButtonText) > width)
8503 width=WidgetTextWidth(font_info,CancelButtonText);
8504 width+=(unsigned int) QuantumMargin;
8505 height=(unsigned int) (font_info->ascent+font_info->descent);
8507 Position Preferences widget.
8509 windows->widget.width=(unsigned int) (MagickMax((int) (width << 1),
8510 (int) text_width)+6*QuantumMargin);
8511 windows->widget.min_width=(width << 1)+QuantumMargin;
8512 if (windows->widget.width < windows->widget.min_width)
8513 windows->widget.width=windows->widget.min_width;
8514 windows->widget.height=(unsigned int)
8515 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8516 windows->widget.min_height=(unsigned int)
8517 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8518 if (windows->widget.height < windows->widget.min_height)
8519 windows->widget.height=windows->widget.min_height;
8520 XConstrainWindowPosition(display,&windows->widget);
8522 Map Preferences widget.
8524 (void) CopyMagickString(windows->widget.name,"Preferences",MaxTextExtent);
8525 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8526 if (status != False)
8528 XSetWMName(display,windows->widget.id,&window_name);
8529 XSetWMIconName(display,windows->widget.id,&window_name);
8530 (void) XFree((void *) window_name.value);
8532 window_changes.width=(int) windows->widget.width;
8533 window_changes.height=(int) windows->widget.height;
8534 window_changes.x=windows->widget.x;
8535 window_changes.y=windows->widget.y;
8536 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8537 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8538 (void) XMapRaised(display,windows->widget.id);
8539 windows->widget.mapped=MagickFalse;
8541 Respond to X events.
8543 state=UpdateConfigurationState;
8544 XSetCursorState(display,windows,MagickTrue);
8547 if (state & UpdateConfigurationState)
8550 Initialize button information.
8552 XGetWidgetInfo(CancelButtonText,&cancel_info);
8553 cancel_info.width=width;
8554 cancel_info.height=(unsigned int) (3*height) >> 1;
8555 cancel_info.x=(int) windows->widget.width-cancel_info.width-
8556 (QuantumMargin << 1);
8557 cancel_info.y=(int) windows->widget.height-
8558 cancel_info.height-QuantumMargin;
8559 XGetWidgetInfo(ApplyButtonText,&apply_info);
8560 apply_info.width=width;
8561 apply_info.height=(unsigned int) (3*height) >> 1;
8562 apply_info.x=QuantumMargin << 1;
8563 apply_info.y=cancel_info.y;
8564 y=(int) (height << 1);
8565 for (i=0; i < NumberPreferences; i++)
8567 XGetWidgetInfo(Preferences[i],&preferences_info[i]);
8568 preferences_info[i].bevel_width--;
8569 preferences_info[i].width=(unsigned int) QuantumMargin >> 1;
8570 preferences_info[i].height=(unsigned int) QuantumMargin >> 1;
8571 preferences_info[i].x=QuantumMargin << 1;
8572 preferences_info[i].y=y;
8573 y+=height+(QuantumMargin >> 1);
8575 preferences_info[0].raised=resource_info->backdrop ==
8576 MagickFalse ? MagickTrue : MagickFalse;
8577 preferences_info[1].raised=resource_info->confirm_exit ==
8578 MagickFalse ? MagickTrue : MagickFalse;
8579 preferences_info[2].raised=resource_info->confirm_edit ==
8580 MagickFalse ? MagickTrue : MagickFalse;
8581 preferences_info[3].raised=resource_info->gamma_correct ==
8582 MagickFalse ? MagickTrue : MagickFalse;
8583 preferences_info[4].raised=resource_info->display_warnings ==
8584 MagickFalse ? MagickTrue : MagickFalse;
8585 preferences_info[5].raised=resource_info->quantize_info->dither ==
8586 MagickFalse ? MagickTrue : MagickFalse;
8587 preferences_info[6].raised=resource_info->colormap !=
8588 SharedColormap ? MagickTrue : MagickFalse;
8589 preferences_info[7].raised=resource_info->use_pixmap ==
8590 MagickFalse ? MagickTrue : MagickFalse;
8591 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8592 (unsigned long) resource_info->undo_cache);
8593 XGetWidgetInfo(cache,&cache_info);
8594 cache_info.bevel_width--;
8595 cache_info.width=(unsigned int) QuantumMargin >> 1;
8596 cache_info.height=(unsigned int) QuantumMargin >> 1;
8597 cache_info.x=QuantumMargin << 1;
8599 state&=(~UpdateConfigurationState);
8601 if (state & RedrawWidgetState)
8604 Redraw Preferences widget.
8606 XDrawBeveledButton(display,&windows->widget,&apply_info);
8607 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8608 for (i=0; i < NumberPreferences; i++)
8609 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8610 XDrawTriangleEast(display,&windows->widget,&cache_info);
8611 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8612 state&=(~RedrawWidgetState);
8615 Wait for next event.
8617 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
8622 if (MatteIsActive(apply_info,event.xbutton))
8625 User pressed Apply button.
8627 apply_info.raised=MagickFalse;
8628 XDrawBeveledButton(display,&windows->widget,&apply_info);
8631 if (MatteIsActive(cancel_info,event.xbutton))
8634 User pressed Cancel button.
8636 cancel_info.raised=MagickFalse;
8637 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8640 for (i=0; i < NumberPreferences; i++)
8641 if (MatteIsActive(preferences_info[i],event.xbutton))
8644 User pressed a Preferences button.
8646 preferences_info[i].raised=preferences_info[i].raised ==
8647 MagickFalse ? MagickTrue : MagickFalse;
8648 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8651 if (MatteIsActive(cache_info,event.xbutton))
8654 User pressed Cache button.
8656 x=cache_info.x+cache_info.width+cache_info.bevel_width+
8657 (QuantumMargin >> 1);
8658 y=cache_info.y+((cache_info.height-height) >> 1);
8659 width=WidgetTextWidth(font_info,cache);
8660 (void) XClearArea(display,windows->widget.id,x,y,width,height,
8662 resource_info->undo_cache<<=1;
8663 if (resource_info->undo_cache > 256)
8664 resource_info->undo_cache=1;
8665 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8666 (unsigned long) resource_info->undo_cache);
8667 cache_info.raised=MagickFalse;
8668 XDrawTriangleEast(display,&windows->widget,&cache_info);
8675 if (windows->widget.mapped == MagickFalse)
8677 if (apply_info.raised == MagickFalse)
8679 if (event.xbutton.window == windows->widget.id)
8680 if (MatteIsActive(apply_info,event.xbutton))
8682 apply_info.raised=MagickTrue;
8683 XDrawBeveledButton(display,&windows->widget,&apply_info);
8684 apply_info.raised=MagickFalse;
8686 if (cancel_info.raised == MagickFalse)
8688 if (event.xbutton.window == windows->widget.id)
8689 if (MatteIsActive(cancel_info,event.xbutton))
8691 cancel_info.raised=MagickTrue;
8692 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8694 if (cache_info.raised == MagickFalse)
8696 cache_info.raised=MagickTrue;
8697 XDrawTriangleEast(display,&windows->widget,&cache_info);
8704 If client window delete message, exit.
8706 if (event.xclient.message_type != windows->wm_protocols)
8708 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8710 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8711 (Time) event.xclient.data.l[1]);
8714 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8716 if (event.xclient.window == windows->widget.id)
8723 case ConfigureNotify:
8726 Update widget configuration.
8728 if (event.xconfigure.window != windows->widget.id)
8730 if ((event.xconfigure.width == (int) windows->widget.width) &&
8731 (event.xconfigure.height == (int) windows->widget.height))
8733 windows->widget.width=(unsigned int)
8734 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8735 windows->widget.height=(unsigned int)
8736 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8737 state|=UpdateConfigurationState;
8742 if (event.xcrossing.window != windows->widget.id)
8744 state&=(~InactiveWidgetState);
8749 if (event.xexpose.window != windows->widget.id)
8751 if (event.xexpose.count != 0)
8753 state|=RedrawWidgetState;
8759 command[MaxTextExtent];
8765 Respond to a user key press.
8767 if (event.xkey.window != windows->widget.id)
8769 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8770 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8771 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8773 apply_info.raised=MagickFalse;
8774 XDrawBeveledButton(display,&windows->widget,&apply_info);
8782 if (event.xcrossing.window != windows->widget.id)
8784 state|=InactiveWidgetState;
8790 Discard pending button motion events.
8792 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8793 if (state & InactiveWidgetState)
8795 if (apply_info.raised == MatteIsActive(apply_info,event.xmotion))
8798 Apply button status changed.
8801 apply_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8802 XDrawBeveledButton(display,&windows->widget,&apply_info);
8805 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
8808 Cancel button status changed.
8811 cancel_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8812 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8820 } while ((state & ExitState) == 0);
8821 XSetCursorState(display,windows,MagickFalse);
8822 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8823 XCheckRefreshWindows(display,windows);
8824 if (apply_info.raised)
8825 return(MagickFalse);
8827 Save user preferences to the client configuration file.
8829 resource_info->backdrop=
8830 preferences_info[0].raised == MagickFalse ? MagickTrue : MagickFalse;
8831 resource_info->confirm_exit=
8832 preferences_info[1].raised == MagickFalse ? MagickTrue : MagickFalse;
8833 resource_info->confirm_edit=
8834 preferences_info[2].raised == MagickFalse ? MagickTrue : MagickFalse;
8835 resource_info->gamma_correct=
8836 preferences_info[3].raised == MagickFalse ? MagickTrue : MagickFalse;
8837 resource_info->display_warnings=
8838 preferences_info[4].raised == MagickFalse ? MagickTrue : MagickFalse;
8839 resource_info->quantize_info->dither=
8840 preferences_info[5].raised == MagickFalse ? MagickTrue : MagickFalse;
8841 resource_info->colormap=SharedColormap;
8842 if (preferences_info[6].raised)
8843 resource_info->colormap=PrivateColormap;
8844 resource_info->use_pixmap=
8845 preferences_info[7].raised == MagickFalse ? MagickTrue : MagickFalse;
8846 XUserPreferences(resource_info);
8851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8855 % X P r o g r e s s M o n i t o r W i d g e t %
8859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8861 % XProgressMonitorWidget() displays the progress a task is making in
8862 % completing a task. A span of zero toggles the active status. An inactive
8863 % state disables the progress monitor.
8865 % The format of the XProgressMonitorWidget method is:
8867 % void XProgressMonitorWidget(Display *display,XWindows *windows,
8868 % const char *task,const MagickOffsetType offset,
8869 % const MagickSizeType span)
8871 % A description of each parameter follows:
8873 % o display: Specifies a connection to an X server; returned from
8876 % o window: Specifies a pointer to a XWindows structure.
8878 % o task: Identifies the task in progress.
8880 % o offset: Specifies the offset position within the span which represents
8881 % how much progress has been made in completing a task.
8883 % o span: Specifies the span relative to completing a task.
8886 MagickPrivate void XProgressMonitorWidget(Display *display,XWindows *windows,
8887 const char *task,const MagickOffsetType offset,const MagickSizeType span)
8895 assert(display != (Display *) NULL);
8896 assert(windows != (XWindows *) NULL);
8897 assert(task != (const char *) NULL);
8898 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",task);
8902 Update image windows if there is a pending expose event.
8904 while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
8905 (void) XCommandWidget(display,windows,(const char **) NULL,&event);
8906 while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
8907 XRefreshWindow(display,&windows->image,&event);
8908 while (XCheckTypedWindowEvent(display,windows->info.id,Expose,&event))
8909 if (monitor_info.text != (char *) NULL)
8910 XInfoWidget(display,windows,monitor_info.text);
8912 Draw progress monitor bar to represent percent completion of a task.
8914 if ((windows->info.mapped == MagickFalse) || (task != monitor_info.text))
8915 XInfoWidget(display,windows,task);
8916 width=(unsigned int) (((offset+1)*(windows->info.width-
8917 (2*monitor_info.x)))/span);
8918 if (width < monitor_info.width)
8920 monitor_info.raised=MagickTrue;
8921 XDrawWidgetText(display,&windows->info,&monitor_info);
8922 monitor_info.raised=MagickFalse;
8924 monitor_info.width=width;
8925 XDrawWidgetText(display,&windows->info,&monitor_info);
8926 (void) XFlush(display);
8930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8934 % X T e x t V i e w W i d g e t %
8938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8940 % XTextViewWidget() displays text in a Text View widget.
8942 % The format of the XTextViewWidget method is:
8944 % void XTextViewWidget(Display *display,const XResourceInfo *resource_info,
8945 % XWindows *windows,const MagickBooleanType mono,const char *title,
8946 % const char **textlist)
8948 % A description of each parameter follows:
8950 % o display: Specifies a connection to an X server; returned from
8953 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8955 % o window: Specifies a pointer to a XWindows structure.
8957 % o mono: Use mono-spaced font when displaying text.
8959 % o title: This character string is displayed at the top of the widget
8962 % o textlist: This string list is displayed within the Text View widget.
8965 MagickPrivate void XTextViewWidget(Display *display,
8966 const XResourceInfo *resource_info,XWindows *windows,
8967 const MagickBooleanType mono,const char *title,const char **textlist)
8969 #define DismissButtonText "Dismiss"
8972 primary_selection[MaxTextExtent];
8977 static MagickStatusType
8978 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
9018 Convert text string to a text list.
9020 assert(display != (Display *) NULL);
9021 assert(resource_info != (XResourceInfo *) NULL);
9022 assert(windows != (XWindows *) NULL);
9023 assert(title != (const char *) NULL);
9024 assert(textlist != (const char **) NULL);
9025 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
9026 XSetCursorState(display,windows,MagickTrue);
9027 XCheckRefreshWindows(display,windows);
9028 if (textlist == (const char **) NULL)
9030 XNoticeWidget(display,windows,"No text to view:",(char *) NULL);
9034 Determine Text View widget attributes.
9036 font_info=windows->widget.font_info;
9037 text_info=(XFontStruct *) NULL;
9038 if (mono != MagickFalse)
9039 text_info=XBestFont(display,resource_info,MagickTrue);
9040 if (text_info == (XFontStruct *) NULL)
9041 text_info=windows->widget.font_info;
9043 for (i=0; textlist[i] != (char *) NULL; i++)
9044 if (WidgetTextWidth(text_info,(char *) textlist[i]) > text_width)
9045 text_width=(unsigned int) XTextWidth(text_info,(char *) textlist[i],
9046 MagickMin(Extent(textlist[i]),160));
9047 lines=(unsigned int) i;
9048 width=WidgetTextWidth(font_info,DismissButtonText);
9049 width+=QuantumMargin;
9050 height=(unsigned int) (text_info->ascent+text_info->descent);
9052 Position Text View widget.
9054 windows->widget.width=(unsigned int) (MagickMin((int) text_width,
9055 (int) MaxTextWidth)+5*QuantumMargin);
9056 windows->widget.min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
9057 if (windows->widget.width < windows->widget.min_width)
9058 windows->widget.width=windows->widget.min_width;
9059 windows->widget.height=(unsigned int) (MagickMin(MagickMax((int) lines,3),32)*
9060 height+((13*height) >> 1)+((9*QuantumMargin) >> 1));
9061 windows->widget.min_height=(unsigned int) (3*height+((13*height) >> 1)+((9*
9062 QuantumMargin) >> 1));
9063 if (windows->widget.height < windows->widget.min_height)
9064 windows->widget.height=windows->widget.min_height;
9065 XConstrainWindowPosition(display,&windows->widget);
9067 Map Text View widget.
9069 (void) CopyMagickString(windows->widget.name,title,MaxTextExtent);
9070 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
9071 if (status != False)
9073 XSetWMName(display,windows->widget.id,&window_name);
9074 XSetWMIconName(display,windows->widget.id,&window_name);
9075 (void) XFree((void *) window_name.value);
9077 window_changes.width=(int) windows->widget.width;
9078 window_changes.height=(int) windows->widget.height;
9079 window_changes.x=windows->widget.x;
9080 window_changes.y=windows->widget.y;
9081 (void) XReconfigureWMWindow(display,windows->widget.id,
9082 windows->widget.screen,(unsigned int) mask,&window_changes);
9083 (void) XMapRaised(display,windows->widget.id);
9084 windows->widget.mapped=MagickFalse;
9086 Respond to X events.
9088 XGetWidgetInfo((char *) NULL,&slider_info);
9089 XGetWidgetInfo((char *) NULL,&north_info);
9090 XGetWidgetInfo((char *) NULL,&south_info);
9091 XGetWidgetInfo((char *) NULL,&expose_info);
9093 delay=SuspendTime << 2;
9094 height=(unsigned int) (font_info->ascent+font_info->descent);
9095 state=UpdateConfigurationState;
9098 if (state & UpdateConfigurationState)
9104 Initialize button information.
9106 XGetWidgetInfo(DismissButtonText,&dismiss_info);
9107 dismiss_info.width=width;
9108 dismiss_info.height=(unsigned int) ((3*height) >> 1);
9109 dismiss_info.x=(int) windows->widget.width-dismiss_info.width-
9111 dismiss_info.y=(int) windows->widget.height-dismiss_info.height-
9114 Initialize scroll information.
9116 XGetWidgetInfo((char *) NULL,&scroll_info);
9117 scroll_info.bevel_width--;
9118 scroll_info.width=height;
9119 scroll_info.height=(unsigned int) (dismiss_info.y-((5*QuantumMargin) >>
9121 scroll_info.x=(int) windows->widget.width-QuantumMargin-
9123 scroll_info.y=(3*QuantumMargin) >> 1;
9124 scroll_info.raised=MagickFalse;
9125 scroll_info.trough=MagickTrue;
9126 north_info=scroll_info;
9127 north_info.raised=MagickTrue;
9128 north_info.width-=(north_info.bevel_width << 1);
9129 north_info.height=north_info.width-1;
9130 north_info.x+=north_info.bevel_width;
9131 north_info.y+=north_info.bevel_width;
9132 south_info=north_info;
9133 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
9136 slider_info=north_info;
9138 slider_info.width-=2;
9139 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
9140 slider_info.bevel_width+2;
9141 slider_info.height=scroll_info.height-((slider_info.min_y-
9142 scroll_info.y+1) << 1)+4;
9143 visible_lines=scroll_info.height/(text_info->ascent+text_info->descent+
9144 ((text_info->ascent+text_info->descent) >> 3));
9145 if (lines > visible_lines)
9146 slider_info.height=(unsigned int) (visible_lines*slider_info.height)/
9148 slider_info.max_y=south_info.y-south_info.bevel_width-
9149 slider_info.bevel_width-2;
9150 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
9151 slider_info.y=slider_info.min_y;
9152 expose_info=scroll_info;
9153 expose_info.y=slider_info.y;
9155 Initialize list information.
9157 XGetWidgetInfo((char *) NULL,&list_info);
9158 list_info.raised=MagickFalse;
9159 list_info.bevel_width--;
9160 list_info.width=(unsigned int) scroll_info.x-((3*QuantumMargin) >> 1);
9161 list_info.height=scroll_info.height;
9162 list_info.x=QuantumMargin;
9163 list_info.y=scroll_info.y;
9165 Initialize selection information.
9167 XGetWidgetInfo((char *) NULL,&selection_info);
9168 selection_info.center=MagickFalse;
9169 selection_info.width=list_info.width;
9170 selection_info.height=(unsigned int)
9171 (9*(text_info->ascent+text_info->descent)) >> 3;
9172 selection_info.x=list_info.x;
9173 state&=(~UpdateConfigurationState);
9175 if (state & RedrawWidgetState)
9178 Redraw Text View window.
9180 XDrawBeveledMatte(display,&windows->widget,&list_info);
9181 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
9182 XDrawTriangleNorth(display,&windows->widget,&north_info);
9183 XDrawBeveledButton(display,&windows->widget,&slider_info);
9184 XDrawTriangleSouth(display,&windows->widget,&south_info);
9185 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9186 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
9187 selection_info.id=(~0);
9188 state|=RedrawListState;
9189 state&=(~RedrawWidgetState);
9191 if (state & RedrawListState)
9194 Determine slider id and position.
9196 if (slider_info.id >= (int) (lines-visible_lines))
9197 slider_info.id=(int) lines-visible_lines;
9198 if ((slider_info.id < 0) || (lines <= visible_lines))
9200 slider_info.y=slider_info.min_y;
9203 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/lines;
9204 if (slider_info.id != selection_info.id)
9207 Redraw scroll bar and text.
9209 windows->widget.font_info=text_info;
9210 (void) XSetFont(display,windows->widget.annotate_context,
9212 (void) XSetFont(display,windows->widget.highlight_context,
9214 selection_info.id=slider_info.id;
9215 selection_info.y=list_info.y+(height >> 3)+2;
9216 for (i=0; i < (int) visible_lines; i++)
9218 selection_info.raised=
9219 (slider_info.id+i) != list_info.id ? MagickTrue : MagickFalse;
9220 selection_info.text=(char *) NULL;
9221 if ((slider_info.id+i) < (int) lines)
9222 selection_info.text=(char *) textlist[slider_info.id+i];
9223 XDrawWidgetText(display,&windows->widget,&selection_info);
9224 selection_info.y+=(int) selection_info.height;
9226 windows->widget.font_info=font_info;
9227 (void) XSetFont(display,windows->widget.annotate_context,
9229 (void) XSetFont(display,windows->widget.highlight_context,
9234 if (slider_info.y > expose_info.y)
9236 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
9237 expose_info.y=slider_info.y-expose_info.height-
9238 slider_info.bevel_width-1;
9242 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
9243 expose_info.y=slider_info.y+slider_info.height+
9244 slider_info.bevel_width+1;
9246 XDrawTriangleNorth(display,&windows->widget,&north_info);
9247 XDrawMatte(display,&windows->widget,&expose_info);
9248 XDrawBeveledButton(display,&windows->widget,&slider_info);
9249 XDrawTriangleSouth(display,&windows->widget,&south_info);
9250 expose_info.y=slider_info.y;
9252 state&=(~RedrawListState);
9255 Wait for next event.
9257 if (north_info.raised && south_info.raised)
9258 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
9262 Brief delay before advancing scroll bar.
9264 XDelay(display,delay);
9266 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
9267 if (north_info.raised == MagickFalse)
9268 if (slider_info.id > 0)
9274 state|=RedrawListState;
9276 if (south_info.raised == MagickFalse)
9277 if (slider_info.id < (int) lines)
9283 state|=RedrawListState;
9285 if (event.type != ButtonRelease)
9292 if (MatteIsActive(slider_info,event.xbutton))
9297 slider_info.active=MagickTrue;
9300 if (MatteIsActive(north_info,event.xbutton))
9301 if (slider_info.id > 0)
9306 north_info.raised=MagickFalse;
9308 state|=RedrawListState;
9311 if (MatteIsActive(south_info,event.xbutton))
9312 if (slider_info.id < (int) lines)
9317 south_info.raised=MagickFalse;
9319 state|=RedrawListState;
9322 if (MatteIsActive(scroll_info,event.xbutton))
9327 if (event.xbutton.y < slider_info.y)
9328 slider_info.id-=(visible_lines-1);
9330 slider_info.id+=(visible_lines-1);
9331 state|=RedrawListState;
9334 if (MatteIsActive(dismiss_info,event.xbutton))
9337 User pressed Dismiss button.
9339 dismiss_info.raised=MagickFalse;
9340 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9343 if (MatteIsActive(list_info,event.xbutton))
9352 User pressed list matte.
9354 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
9355 selection_info.height;
9356 if (id >= (int) lines)
9358 if (id != list_info.id)
9361 click_time=event.xbutton.time;
9365 if (event.xbutton.time >= (click_time+DoubleClick))
9367 click_time=event.xbutton.time;
9370 click_time=event.xbutton.time;
9372 Become the XA_PRIMARY selection owner.
9374 (void) CopyMagickString(primary_selection,textlist[list_info.id],
9376 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
9377 event.xbutton.time);
9378 if (XGetSelectionOwner(display,XA_PRIMARY) != windows->widget.id)
9380 selection_info.id=(~0);
9382 state|=RedrawListState;
9389 if (windows->widget.mapped == MagickFalse)
9391 if (north_info.raised == MagickFalse)
9394 User released up button.
9396 delay=SuspendTime << 2;
9397 north_info.raised=MagickTrue;
9398 XDrawTriangleNorth(display,&windows->widget,&north_info);
9400 if (south_info.raised == MagickFalse)
9403 User released down button.
9405 delay=SuspendTime << 2;
9406 south_info.raised=MagickTrue;
9407 XDrawTriangleSouth(display,&windows->widget,&south_info);
9409 if (slider_info.active)
9412 Stop tracking slider.
9414 slider_info.active=MagickFalse;
9417 if (dismiss_info.raised == MagickFalse)
9419 if (event.xbutton.window == windows->widget.id)
9420 if (MatteIsActive(dismiss_info,event.xbutton))
9422 dismiss_info.raised=MagickTrue;
9423 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9430 If client window delete message, exit.
9432 if (event.xclient.message_type != windows->wm_protocols)
9434 if (*event.xclient.data.l == (int) windows->wm_take_focus)
9436 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
9437 (Time) event.xclient.data.l[1]);
9440 if (*event.xclient.data.l != (int) windows->wm_delete_window)
9442 if (event.xclient.window == windows->widget.id)
9449 case ConfigureNotify:
9452 Update widget configuration.
9454 if (event.xconfigure.window != windows->widget.id)
9456 if ((event.xconfigure.width == (int) windows->widget.width) &&
9457 (event.xconfigure.height == (int) windows->widget.height))
9459 windows->widget.width=(unsigned int)
9460 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
9461 windows->widget.height=(unsigned int)
9462 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
9463 state|=UpdateConfigurationState;
9468 if (event.xcrossing.window != windows->widget.id)
9470 state&=(~InactiveWidgetState);
9475 if (event.xexpose.window != windows->widget.id)
9477 if (event.xexpose.count != 0)
9479 state|=RedrawWidgetState;
9485 command[MaxTextExtent];
9494 Respond to a user key press.
9496 if (event.xkey.window != windows->widget.id)
9498 length=XLookupString((XKeyEvent *) &event.xkey,command,
9499 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9500 *(command+length)='\0';
9501 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
9503 dismiss_info.raised=MagickFalse;
9504 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9508 if (AreaIsActive(scroll_info,event.xkey))
9513 switch ((int) key_symbol)
9536 slider_info.id-=visible_lines;
9542 slider_info.id+=visible_lines;
9548 slider_info.id=(int) lines;
9552 state|=RedrawListState;
9561 if (event.xcrossing.window != windows->widget.id)
9563 state|=InactiveWidgetState;
9575 Discard pending button motion events.
9577 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9578 if (slider_info.active)
9583 slider_info.y=event.xmotion.y-
9584 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
9585 if (slider_info.y < slider_info.min_y)
9586 slider_info.y=slider_info.min_y;
9587 if (slider_info.y > slider_info.max_y)
9588 slider_info.y=slider_info.max_y;
9590 if (slider_info.y != slider_info.min_y)
9591 slider_info.id=(int) (lines*(slider_info.y-slider_info.min_y+1))/
9592 (slider_info.max_y-slider_info.min_y+1);
9593 state|=RedrawListState;
9596 if (state & InactiveWidgetState)
9598 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
9601 Dismiss button status changed.
9603 dismiss_info.raised=
9604 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
9605 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9610 case SelectionClear:
9613 selection_info.id=(~0);
9614 state|=RedrawListState;
9617 case SelectionRequest:
9622 XSelectionRequestEvent
9625 if (list_info.id == (~0))
9628 Set primary selection.
9630 request=(&(event.xselectionrequest));
9631 (void) XChangeProperty(request->display,request->requestor,
9632 request->property,request->target,8,PropModeReplace,
9633 (unsigned char *) primary_selection,Extent(primary_selection));
9634 notify.type=SelectionNotify;
9635 notify.send_event=MagickTrue;
9636 notify.display=request->display;
9637 notify.requestor=request->requestor;
9638 notify.selection=request->selection;
9639 notify.target=request->target;
9640 notify.time=request->time;
9641 if (request->property == None)
9642 notify.property=request->target;
9644 notify.property=request->property;
9645 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
9646 (XEvent *) ¬ify);
9651 } while ((state & ExitState) == 0);
9652 if (text_info != windows->widget.font_info)
9653 (void) XFreeFont(display,text_info);
9654 XSetCursorState(display,windows,MagickFalse);
9655 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
9656 XCheckRefreshWindows(display,windows);