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-2014 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
27 % http://www.imagemagick.org/script/license.php %
29 % Unless required by applicable law or agreed to in writing, software %
30 % distributed under the License is distributed on an "AS IS" BASIS, %
31 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
32 % See the License for the specific language governing permissions and %
33 % limitations under the License. %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/color.h"
45 #include "MagickCore/color-private.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/magick.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/PreRvIcccm.h"
52 #include "MagickCore/string_.h"
53 #include "MagickCore/token.h"
54 #include "MagickCore/token-private.h"
55 #include "MagickCore/utility.h"
56 #include "MagickCore/utility-private.h"
57 #include "MagickCore/xwindow-private.h"
58 #include "MagickCore/widget.h"
59 #include "MagickCore/widget-private.h"
61 #if defined(MAGICKCORE_X11_DELEGATE)
66 #define AreaIsActive(matte_info,position) ( \
67 ((position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
68 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
69 ? MagickTrue : MagickFalse)
70 #define Extent(s) ((int) strlen(s))
71 #define MatteIsActive(matte_info,position) ( \
72 ((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \
73 (position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
74 (position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) && \
75 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
76 ? MagickTrue : MagickFalse)
77 #define MaxTextWidth ((unsigned int) (255*XTextWidth(font_info,"_",1)))
78 #define MinTextWidth (26*XTextWidth(font_info,"_",1))
79 #define QuantumMargin MagickMax(font_info->max_bounds.width,12)
80 #define WidgetTextWidth(font_info,text) \
81 ((unsigned int) XTextWidth(font_info,text,Extent(text)))
82 #define WindowIsActive(window_info,position) ( \
83 ((position.x >= 0) && (position.y >= 0) && \
84 (position.x < (int) window_info.width) && \
85 (position.y < (int) window_info.height)) ? MagickTrue : MagickFalse)
92 ControlState = 0x0001,
93 InactiveWidgetState = 0x0004,
94 JumpListState = 0x0008,
95 RedrawActionState = 0x0010,
96 RedrawListState = 0x0020,
97 RedrawWidgetState = 0x0040,
98 UpdateListState = 0x0100
102 Typedef declarations.
104 typedef struct _XWidgetInfo
134 Variable declarations.
139 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
140 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
144 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
145 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
147 *selection_info = (XWidgetInfo *) NULL,
150 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
151 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
155 Constant declarations.
165 XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *),
166 XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType),
167 XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType),
168 XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType);
171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 % D e s t r o y X W i d g e t %
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 % DestroyXWidget() destroys resources associated with the X widget.
183 % The format of the DestroyXWidget method is:
185 % void DestroyXWidget()
187 % A description of each parameter follows:
190 MagickPrivate void DestroyXWidget(void)
192 if (selection_info != (XWidgetInfo *) NULL)
193 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 + X D r a w B e v e l %
205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 % XDrawBevel() "sets off" an area with a highlighted upper and left bevel and
208 % a shadowed lower and right bevel. The highlighted and shadowed bevels
209 % create a 3-D effect.
211 % The format of the XDrawBevel function is:
213 % XDrawBevel(display,window_info,bevel_info)
215 % A description of each parameter follows:
217 % o display: Specifies a pointer to the Display structure; returned from
220 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
222 % o bevel_info: Specifies a pointer to a XWidgetInfo structure. It
223 % contains the extents of the bevel.
226 static void XDrawBevel(Display *display,const XWindowInfo *window_info,
227 const XWidgetInfo *bevel_info)
242 Draw upper and left beveled border.
245 y1=bevel_info->y+bevel_info->height;
246 x2=bevel_info->x+bevel_info->width;
248 bevel_width=bevel_info->bevel_width;
255 points[3].x=x2+bevel_width;
256 points[3].y=y2-bevel_width;
257 points[4].x=x1-bevel_width;
258 points[4].y=y2-bevel_width;
259 points[5].x=x1-bevel_width;
260 points[5].y=y1+bevel_width;
261 XSetBevelColor(display,window_info,bevel_info->raised);
262 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
263 points,6,Complex,CoordModeOrigin);
265 Draw lower and right beveled border.
273 points[3].x=x2+bevel_width;
274 points[3].y=y2-bevel_width;
275 points[4].x=x2+bevel_width;
276 points[4].y=y1+bevel_width;
277 points[5].x=x1-bevel_width;
278 points[5].y=y1+bevel_width;
279 XSetBevelColor(display,window_info,!bevel_info->raised);
280 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
281 points,6,Complex,CoordModeOrigin);
282 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290 + X D r a w B e v e l e d B u t t o n %
294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 % XDrawBeveledButton() draws a button with a highlighted upper and left bevel
297 % and a shadowed lower and right bevel. The highlighted and shadowed bevels
298 % create a 3-D effect.
300 % The format of the XDrawBeveledButton function is:
302 % XDrawBeveledButton(display,window_info,button_info)
304 % A description of each parameter follows:
306 % o display: Specifies a pointer to the Display structure; returned from
309 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
311 % o button_info: Specifies a pointer to a XWidgetInfo structure. It
312 % contains the extents of the button.
316 static inline int MagickAbsoluteValue(const int x)
323 static inline int MagickMax(const int x,const int y)
330 static inline int MagickMin(const int x,const int y)
337 static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info,
338 const XWidgetInfo *button_info)
356 XDrawBevel(display,window_info,button_info);
357 XSetMatteColor(display,window_info,button_info->raised);
358 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
359 button_info->x,button_info->y,button_info->width,button_info->height);
360 x=button_info->x-button_info->bevel_width-1;
361 y=button_info->y-button_info->bevel_width-1;
362 (void) XSetForeground(display,window_info->widget_context,
363 window_info->pixel_info->trough_color.pixel);
364 if (button_info->raised || (window_info->depth == 1))
365 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
366 x,y,button_info->width+(button_info->bevel_width << 1)+1,
367 button_info->height+(button_info->bevel_width << 1)+1);
368 if (button_info->text == (char *) NULL)
373 crop_info.width=(unsigned short) button_info->width;
374 crop_info.height=(unsigned short) button_info->height;
375 crop_info.x=button_info->x;
376 crop_info.y=button_info->y;
380 font_info=window_info->font_info;
381 width=WidgetTextWidth(font_info,button_info->text);
382 x=button_info->x+(QuantumMargin >> 1);
383 if (button_info->center)
384 x=button_info->x+(button_info->width >> 1)-(width >> 1);
385 y=button_info->y+((button_info->height-
386 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
387 if ((int) button_info->width == (QuantumMargin >> 1))
390 Option button-- write label to right of button.
392 XSetTextColor(display,window_info,MagickTrue);
393 x=button_info->x+button_info->width+button_info->bevel_width+
394 (QuantumMargin >> 1);
395 (void) XDrawString(display,window_info->id,window_info->widget_context,
396 x,y,button_info->text,Extent(button_info->text));
399 (void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info,
401 XSetTextColor(display,window_info,button_info->raised);
402 (void) XDrawString(display,window_info->id,window_info->widget_context,x,y,
403 button_info->text,Extent(button_info->text));
404 (void) XSetClipMask(display,window_info->widget_context,None);
405 if (button_info->raised == MagickFalse)
406 XDelay(display,SuspendTime << 2);
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414 + X D r a w B e v e l e d M a t t e %
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 % XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and
421 % a highlighted lower and right bevel. The highlighted and shadowed bevels
422 % create a 3-D effect.
424 % The format of the XDrawBeveledMatte function is:
426 % XDrawBeveledMatte(display,window_info,matte_info)
428 % A description of each parameter follows:
430 % o display: Specifies a pointer to the Display structure; returned from
433 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
435 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
436 % contains the extents of the matte.
439 static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info,
440 const XWidgetInfo *matte_info)
445 XDrawBevel(display,window_info,matte_info);
446 XDrawMatte(display,window_info,matte_info);
450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 + X D r a w M a t t e %
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460 % XDrawMatte() fills a rectangular area with the matte color.
462 % The format of the XDrawMatte function is:
464 % XDrawMatte(display,window_info,matte_info)
466 % A description of each parameter follows:
468 % o display: Specifies a pointer to the Display structure; returned from
471 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
473 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It
474 % contains the extents of the matte.
477 static void XDrawMatte(Display *display,const XWindowInfo *window_info,
478 const XWidgetInfo *matte_info)
483 if ((matte_info->trough == MagickFalse) || (window_info->depth == 1))
484 (void) XFillRectangle(display,window_info->id,
485 window_info->highlight_context,matte_info->x,matte_info->y,
486 matte_info->width,matte_info->height);
489 (void) XSetForeground(display,window_info->widget_context,
490 window_info->pixel_info->trough_color.pixel);
491 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
492 matte_info->x,matte_info->y,matte_info->width,matte_info->height);
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 + X D r a w M a t t e T e x t %
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 % XDrawMatteText() draws a matte with text. If the text exceeds the extents
508 % of the text, a portion of the text relative to the cursor is displayed.
510 % The format of the XDrawMatteText function is:
512 % XDrawMatteText(display,window_info,text_info)
514 % A description of each parameter follows:
516 % o display: Specifies a pointer to the Display structure; returned from
519 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
521 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
522 % contains the extents of the text.
525 static void XDrawMatteText(Display *display,const XWindowInfo *window_info,
526 XWidgetInfo *text_info)
552 XSetMatteColor(display,window_info,MagickFalse);
553 (void) XFillRectangle(display,window_info->id,window_info->widget_context,
554 text_info->x,text_info->y,text_info->width,text_info->height);
555 if (text_info->text == (char *) NULL)
557 XSetTextColor(display,window_info,text_info->highlight);
558 font_info=window_info->font_info;
559 x=text_info->x+(QuantumMargin >> 2);
560 y=text_info->y+font_info->ascent+(text_info->height >> 2);
561 width=text_info->width-(QuantumMargin >> 1);
562 height=(unsigned int) (font_info->ascent+font_info->descent);
563 if (*text_info->text == '\0')
566 No text-- just draw cursor.
568 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
575 crop_info.width=(unsigned short) text_info->width;
576 crop_info.height=(unsigned short) text_info->height;
577 crop_info.x=text_info->x;
578 crop_info.y=text_info->y;
580 Determine beginning of the visible text.
582 if (text_info->cursor < text_info->marker)
583 text_info->marker=text_info->cursor;
586 text=text_info->marker;
587 if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) >
590 text=text_info->text;
591 for (i=0; i < Extent(text); i++)
593 n=XTextWidth(font_info,(char *) text+i,(int)
594 (text_info->cursor-text-i));
595 if (n <= (int) width)
598 text_info->marker=(char *) text+i;
602 Draw text and cursor.
604 if (text_info->highlight == MagickFalse)
606 (void) XSetClipRectangles(display,window_info->widget_context,0,0,
607 &crop_info,1,Unsorted);
608 (void) XDrawString(display,window_info->id,window_info->widget_context,
609 x,y,text_info->marker,Extent(text_info->marker));
610 (void) XSetClipMask(display,window_info->widget_context,None);
614 (void) XSetClipRectangles(display,window_info->annotate_context,0,0,
615 &crop_info,1,Unsorted);
616 width=WidgetTextWidth(font_info,text_info->marker);
617 (void) XFillRectangle(display,window_info->id,
618 window_info->annotate_context,x,y-font_info->ascent,width,height);
619 (void) XSetClipMask(display,window_info->annotate_context,None);
620 (void) XSetClipRectangles(display,window_info->highlight_context,0,0,
621 &crop_info,1,Unsorted);
622 (void) XDrawString(display,window_info->id,
623 window_info->highlight_context,x,y,text_info->marker,
624 Extent(text_info->marker));
625 (void) XSetClipMask(display,window_info->highlight_context,None);
627 x+=XTextWidth(font_info,text_info->marker,(int)
628 (text_info->cursor-text_info->marker));
629 (void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3,
634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638 + X D r a w T r i a n g l e E a s t %
642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 % XDrawTriangleEast() draws a triangle with a highlighted left bevel and a
645 % shadowed right and lower bevel. The highlighted and shadowed bevels create
648 % The format of the XDrawTriangleEast function is:
650 % XDrawTriangleEast(display,window_info,triangle_info)
652 % A description of each parameter follows:
654 % o display: Specifies a pointer to the Display structure; returned from
657 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
659 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
660 % contains the extents of the triangle.
663 static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info,
664 const XWidgetInfo *triangle_info)
688 x2=triangle_info->x+triangle_info->width;
689 y2=triangle_info->y+(triangle_info->height >> 1);
691 y3=triangle_info->y+triangle_info->height;
692 bevel_width=triangle_info->bevel_width;
699 XSetMatteColor(display,window_info,triangle_info->raised);
700 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
701 points,3,Complex,CoordModeOrigin);
709 points[2].x=x3-bevel_width;
710 points[2].y=y3+bevel_width;
711 points[3].x=x2+bevel_width;
713 XSetBevelColor(display,window_info,!triangle_info->raised);
714 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
715 points,4,Complex,CoordModeOrigin);
723 points[2].x=x1-bevel_width+1;
724 points[2].y=y1-bevel_width;
725 points[3].x=x3-bevel_width+1;
726 points[3].y=y3+bevel_width;
727 XSetBevelColor(display,window_info,triangle_info->raised);
728 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
729 points,4,Complex,CoordModeOrigin);
737 points[2].x=x2+bevel_width;
739 points[3].x=x1-bevel_width;
740 points[3].y=y1-bevel_width;
741 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
742 points,4,Complex,CoordModeOrigin);
743 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
744 if (triangle_info->text == (char *) NULL)
747 Write label to right of triangle.
749 font_info=window_info->font_info;
750 XSetTextColor(display,window_info,MagickTrue);
751 x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+
752 (QuantumMargin >> 1);
753 y1=triangle_info->y+((triangle_info->height-
754 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
755 (void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1,
756 triangle_info->text,Extent(triangle_info->text));
760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 + X D r a w T r i a n g l e N o r t h %
768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 % XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a
771 % shadowed right and lower bevel. The highlighted and shadowed bevels create
774 % The format of the XDrawTriangleNorth function is:
776 % XDrawTriangleNorth(display,window_info,triangle_info)
778 % A description of each parameter follows:
780 % o display: Specifies a pointer to the Display structure; returned from
783 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
785 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
786 % contains the extents of the triangle.
789 static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info,
790 const XWidgetInfo *triangle_info)
810 y1=triangle_info->y+triangle_info->height;
811 x2=triangle_info->x+(triangle_info->width >> 1);
813 x3=triangle_info->x+triangle_info->width;
814 y3=triangle_info->y+triangle_info->height;
815 bevel_width=triangle_info->bevel_width;
822 XSetMatteColor(display,window_info,triangle_info->raised);
823 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
824 points,3,Complex,CoordModeOrigin);
833 points[2].y=y2-bevel_width-2;
834 points[3].x=x1-bevel_width-1;
835 points[3].y=y1+bevel_width;
836 XSetBevelColor(display,window_info,triangle_info->raised);
837 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
838 points,4,Complex,CoordModeOrigin);
846 points[2].x=x3+bevel_width;
847 points[2].y=y3+bevel_width;
849 points[3].y=y2-bevel_width;
850 XSetBevelColor(display,window_info,!triangle_info->raised);
851 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
852 points,4,Complex,CoordModeOrigin);
860 points[2].x=x1-bevel_width;
861 points[2].y=y1+bevel_width;
862 points[3].x=x3+bevel_width;
863 points[3].y=y3+bevel_width;
864 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
865 points,4,Complex,CoordModeOrigin);
866 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874 + X D r a w T r i a n g l e S o u t h %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880 % XDrawTriangleSouth() draws a border with a highlighted left and right bevel
881 % and a shadowed lower bevel. The highlighted and shadowed bevels create a
884 % The format of the XDrawTriangleSouth function is:
886 % XDrawTriangleSouth(display,window_info,triangle_info)
888 % A description of each parameter follows:
890 % o display: Specifies a pointer to the Display structure; returned from
893 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
895 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
896 % contains the extents of the triangle.
899 static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info,
900 const XWidgetInfo *triangle_info)
921 x2=triangle_info->x+(triangle_info->width >> 1);
922 y2=triangle_info->y+triangle_info->height;
923 x3=triangle_info->x+triangle_info->width;
925 bevel_width=triangle_info->bevel_width;
932 XSetMatteColor(display,window_info,triangle_info->raised);
933 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
934 points,3,Complex,CoordModeOrigin);
942 points[2].x=x1-bevel_width;
943 points[2].y=y1-bevel_width;
944 points[3].x=x3+bevel_width;
945 points[3].y=y3-bevel_width;
946 XSetBevelColor(display,window_info,triangle_info->raised);
947 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
948 points,4,Complex,CoordModeOrigin);
955 points[1].y=y3-bevel_width;
956 points[2].x=x3+bevel_width;
957 points[2].y=y3-bevel_width;
959 points[3].y=y2+bevel_width;
960 XSetBevelColor(display,window_info,!triangle_info->raised);
961 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
962 points,4,Complex,CoordModeOrigin);
971 points[2].y=y2+bevel_width;
972 points[3].x=x1-bevel_width;
973 points[3].y=y1-bevel_width;
974 XSetBevelColor(display,window_info,triangle_info->raised);
975 (void) XFillPolygon(display,window_info->id,window_info->widget_context,
976 points,4,Complex,CoordModeOrigin);
977 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985 + X D r a w W i d g e t T e x t %
989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 % XDrawWidgetText() first clears the widget and draws a text string justifed
992 % left (or center) in the x-direction and centered within the y-direction.
994 % The format of the XDrawWidgetText function is:
996 % XDrawWidgetText(display,window_info,text_info)
998 % A description of each parameter follows:
1000 % o display: Specifies a pointer to the Display structure; returned from
1003 % o window_info: Specifies a pointer to a XWindowText structure.
1005 % o text_info: Specifies a pointer to XWidgetInfo structure.
1008 static void XDrawWidgetText(Display *display,const XWindowInfo *window_info,
1009 XWidgetInfo *text_info)
1029 Clear the text area.
1031 widget_context=window_info->annotate_context;
1032 if (text_info->raised)
1033 (void) XClearArea(display,window_info->id,text_info->x,text_info->y,
1034 text_info->width,text_info->height,MagickFalse);
1037 (void) XFillRectangle(display,window_info->id,widget_context,text_info->x,
1038 text_info->y,text_info->width,text_info->height);
1039 widget_context=window_info->highlight_context;
1041 if (text_info->text == (char *) NULL)
1043 if (*text_info->text == '\0')
1046 Set cropping region.
1048 font_info=window_info->font_info;
1049 crop_info.width=(unsigned short) text_info->width;
1050 crop_info.height=(unsigned short) text_info->height;
1051 crop_info.x=text_info->x;
1052 crop_info.y=text_info->y;
1056 width=WidgetTextWidth(font_info,text_info->text);
1057 x=text_info->x+(QuantumMargin >> 1);
1058 if (text_info->center)
1059 x=text_info->x+(text_info->width >> 1)-(width >> 1);
1060 if (text_info->raised)
1061 if (width > (text_info->width-QuantumMargin))
1062 x+=(text_info->width-QuantumMargin-width);
1063 height=(unsigned int) (font_info->ascent+font_info->descent);
1064 y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent;
1065 (void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted);
1066 (void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text,
1067 Extent(text_info->text));
1068 (void) XSetClipMask(display,widget_context,None);
1069 if (x < text_info->x)
1070 (void) XDrawLine(display,window_info->id,window_info->annotate_context,
1071 text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1);
1075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 + X E d i t T e x t %
1083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1085 % XEditText() edits a text string as indicated by the key symbol.
1087 % The format of the XEditText function is:
1089 % XEditText(display,text_info,key_symbol,text,state)
1091 % A description of each parameter follows:
1093 % o display: Specifies a connection to an X server; returned from
1096 % o text_info: Specifies a pointer to a XWidgetInfo structure. It
1097 % contains the extents of the text.
1099 % o key_symbol: A X11 KeySym that indicates what editing function to
1100 % perform to the text.
1102 % o text: A character string to insert into the text.
1104 % o state: An size_t that indicates whether the key symbol is a
1105 % control character or not.
1108 static void XEditText(Display *display,XWidgetInfo *text_info,
1109 const KeySym key_symbol,char *text,const size_t state)
1111 switch ((int) key_symbol)
1116 if (text_info->highlight)
1119 Erase the entire line of text.
1121 *text_info->text='\0';
1122 text_info->cursor=text_info->text;
1123 text_info->marker=text_info->text;
1124 text_info->highlight=MagickFalse;
1127 Erase one character.
1129 if (text_info->cursor != text_info->text)
1131 text_info->cursor--;
1132 (void) CopyMagickString(text_info->cursor,text_info->cursor+1,
1134 text_info->highlight=MagickFalse;
1142 Move cursor one position left.
1144 if (text_info->cursor == text_info->text)
1146 text_info->cursor--;
1153 Move cursor one position right.
1155 if (text_info->cursor == (text_info->text+Extent(text_info->text)))
1157 text_info->cursor++;
1169 if (state & ControlState)
1173 if ((Extent(text_info->text)+1) >= (int) MaxTextExtent)
1174 (void) XBell(display,0);
1177 if (text_info->highlight)
1180 Erase the entire line of text.
1182 *text_info->text='\0';
1183 text_info->cursor=text_info->text;
1184 text_info->marker=text_info->text;
1185 text_info->highlight=MagickFalse;
1188 Insert a string into the text.
1190 q=text_info->text+Extent(text_info->text)+strlen(text);
1191 for (i=0; i <= Extent(text_info->cursor); i++)
1193 *q=(*(q-Extent(text)));
1197 for (i=0; i < Extent(text); i++)
1198 *text_info->cursor++=(*p++);
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210 + X G e t W i d g e t I n f o %
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216 % XGetWidgetInfo() initializes the XWidgetInfo structure.
1218 % The format of the XGetWidgetInfo function is:
1220 % XGetWidgetInfo(text,widget_info)
1222 % A description of each parameter follows:
1224 % o text: A string of characters associated with the widget.
1226 % o widget_info: Specifies a pointer to a X11 XWidgetInfo structure.
1229 static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info)
1232 Initialize widget info.
1234 widget_info->id=(~0);
1235 widget_info->bevel_width=3;
1236 widget_info->width=1;
1237 widget_info->height=1;
1240 widget_info->min_y=0;
1241 widget_info->max_y=0;
1242 widget_info->raised=MagickTrue;
1243 widget_info->active=MagickFalse;
1244 widget_info->center=MagickTrue;
1245 widget_info->trough=MagickFalse;
1246 widget_info->highlight=MagickFalse;
1247 widget_info->text=(char *) text;
1248 widget_info->cursor=(char *) text;
1249 if (text != (char *) NULL)
1250 widget_info->cursor+=Extent(text);
1251 widget_info->marker=(char *) text;
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259 + X H i g h l i g h t W i d g e t %
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265 % XHighlightWidget() draws a highlighted border around a window.
1267 % The format of the XHighlightWidget function is:
1269 % XHighlightWidget(display,window_info,x,y)
1271 % A description of each parameter follows:
1273 % o display: Specifies a pointer to the Display structure; returned from
1276 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1278 % o x: Specifies an integer representing the rectangle offset in the
1281 % o y: Specifies an integer representing the rectangle offset in the
1285 static void XHighlightWidget(Display *display,const XWindowInfo *window_info,
1286 const int x,const int y)
1289 Draw the widget highlighting rectangle.
1291 XSetBevelColor(display,window_info,MagickTrue);
1292 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y,
1293 window_info->width-(x << 1),window_info->height-(y << 1));
1294 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1295 x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1);
1296 XSetBevelColor(display,window_info,MagickFalse);
1297 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
1298 x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1));
1299 (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
1303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1307 + X S c r e e n E v e n t %
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1313 % XScreenEvent() returns MagickTrue if the any event on the X server queue is
1314 % associated with the widget window.
1316 % The format of the XScreenEvent function is:
1318 % int XScreenEvent(Display *display,XEvent *event,char *data)
1320 % A description of each parameter follows:
1322 % o display: Specifies a pointer to the Display structure; returned from
1325 % o event: Specifies a pointer to a X11 XEvent structure.
1327 % o data: Specifies a pointer to a XWindows structure.
1331 #if defined(__cplusplus) || defined(c_plusplus)
1335 static int XScreenEvent(Display *display,XEvent *event,char *data)
1340 windows=(XWindows *) data;
1341 if (event->xany.window == windows->popup.id)
1343 if (event->type == MapNotify)
1344 windows->popup.mapped=MagickTrue;
1345 if (event->type == UnmapNotify)
1346 windows->popup.mapped=MagickFalse;
1349 if (event->xany.window == windows->widget.id)
1351 if (event->type == MapNotify)
1352 windows->widget.mapped=MagickTrue;
1353 if (event->type == UnmapNotify)
1354 windows->widget.mapped=MagickFalse;
1357 switch (event->type)
1361 if ((event->xbutton.button == Button3) &&
1362 (event->xbutton.state & Mod1Mask))
1365 Convert Alt-Button3 to Button2.
1367 event->xbutton.button=Button2;
1368 event->xbutton.state&=(~Mod1Mask);
1374 if (event->xexpose.window == windows->image.id)
1376 XRefreshWindow(display,&windows->image,event);
1379 if (event->xexpose.window == windows->magnify.id)
1380 if (event->xexpose.count == 0)
1381 if (windows->magnify.mapped)
1386 exception=AcquireExceptionInfo();
1387 XMakeMagnifyImage(display,windows,exception);
1388 exception=DestroyExceptionInfo(exception);
1391 if (event->xexpose.window == windows->command.id)
1392 if (event->xexpose.count == 0)
1394 (void) XCommandWidget(display,windows,(const char **) NULL,event);
1402 Set input focus for backdrop window.
1404 if (event->xfocus.window == windows->image.id)
1405 (void) XSetInputFocus(display,windows->image.id,RevertToNone,
1413 case SelectionNotify:
1418 return(MagickFalse);
1421 #if defined(__cplusplus) || defined(c_plusplus)
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 + X S e t B e v e l C o l o r %
1434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436 % XSetBevelColor() sets the graphic context for drawing a beveled border.
1438 % The format of the XSetBevelColor function is:
1440 % XSetBevelColor(display,window_info,raised)
1442 % A description of each parameter follows:
1444 % o display: Specifies a pointer to the Display structure; returned from
1447 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1449 % o raised: A value other than zero indicates the color show be a
1450 % "highlight" color, otherwise the "shadow" color is set.
1453 static void XSetBevelColor(Display *display,const XWindowInfo *window_info,
1454 const MagickStatusType raised)
1456 if (window_info->depth == 1)
1464 (void) XSetBackground(display,window_info->widget_context,
1465 XBlackPixel(display,window_info->screen));
1466 (void) XSetForeground(display,window_info->widget_context,
1467 XWhitePixel(display,window_info->screen));
1468 (void) XSetFillStyle(display,window_info->widget_context,
1469 FillOpaqueStippled);
1470 stipple=window_info->highlight_stipple;
1471 if (raised == MagickFalse)
1472 stipple=window_info->shadow_stipple;
1473 (void) XSetStipple(display,window_info->widget_context,stipple);
1477 (void) XSetForeground(display,window_info->widget_context,
1478 window_info->pixel_info->highlight_color.pixel);
1480 (void) XSetForeground(display,window_info->widget_context,
1481 window_info->pixel_info->shadow_color.pixel);
1485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489 + X S e t M a t t e C o l o r %
1493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1495 % XSetMatteColor() sets the graphic context for drawing the matte.
1497 % The format of the XSetMatteColor function is:
1499 % XSetMatteColor(display,window_info,raised)
1501 % A description of each parameter follows:
1503 % o display: Specifies a pointer to the Display structure; returned from
1506 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1508 % o raised: A value other than zero indicates the matte is active.
1511 static void XSetMatteColor(Display *display,const XWindowInfo *window_info,
1512 const MagickStatusType raised)
1514 if (window_info->depth == 1)
1520 (void) XSetForeground(display,window_info->widget_context,
1521 XWhitePixel(display,window_info->screen));
1523 (void) XSetForeground(display,window_info->widget_context,
1524 XBlackPixel(display,window_info->screen));
1528 (void) XSetForeground(display,window_info->widget_context,
1529 window_info->pixel_info->matte_color.pixel);
1531 (void) XSetForeground(display,window_info->widget_context,
1532 window_info->pixel_info->depth_color.pixel);
1536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1540 + X S e t T e x t C o l o r %
1544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1546 % XSetTextColor() sets the graphic context for drawing text on a matte.
1548 % The format of the XSetTextColor function is:
1550 % XSetTextColor(display,window_info,raised)
1552 % A description of each parameter follows:
1554 % o display: Specifies a pointer to the Display structure; returned from
1557 % o window_info: Specifies a pointer to a X11 XWindowInfo structure.
1559 % o raised: A value other than zero indicates the color show be a
1560 % "highlight" color, otherwise the "shadow" color is set.
1563 static void XSetTextColor(Display *display,const XWindowInfo *window_info,
1564 const MagickStatusType raised)
1570 if (window_info->depth == 1)
1576 (void) XSetForeground(display,window_info->widget_context,
1577 XBlackPixel(display,window_info->screen));
1579 (void) XSetForeground(display,window_info->widget_context,
1580 XWhitePixel(display,window_info->screen));
1583 foreground=(ssize_t) XPixelIntensity(
1584 &window_info->pixel_info->foreground_color);
1585 matte=(ssize_t) XPixelIntensity(&window_info->pixel_info->matte_color);
1586 if (MagickAbsoluteValue((int) (foreground-matte)) > (65535L >> 3))
1587 (void) XSetForeground(display,window_info->widget_context,
1588 window_info->pixel_info->foreground_color.pixel);
1590 (void) XSetForeground(display,window_info->widget_context,
1591 window_info->pixel_info->background_color.pixel);
1595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1599 % X C o l o r B r o w s e r W i d g e t %
1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605 % XColorBrowserWidget() displays a Color Browser widget with a color query
1606 % to the user. The user keys a reply and presses the Action or Cancel button
1607 % to exit. The typed text is returned as the reply function parameter.
1609 % The format of the XColorBrowserWidget method is:
1611 % void XColorBrowserWidget(Display *display,XWindows *windows,
1612 % const char *action,char *reply)
1614 % A description of each parameter follows:
1616 % o display: Specifies a connection to an X server; returned from
1619 % o window: Specifies a pointer to a XWindows structure.
1621 % o action: Specifies a pointer to the action of this widget.
1623 % o reply: the response from the user is returned in this parameter.
1626 MagickPrivate void XColorBrowserWidget(Display *display,XWindows *windows,
1627 const char *action,char *reply)
1629 #define CancelButtonText "Cancel"
1630 #define ColornameText "Name:"
1631 #define ColorPatternText "Pattern:"
1632 #define GrabButtonText "Grab"
1633 #define ResetButtonText "Reset"
1637 primary_selection[MaxTextExtent],
1638 reset_pattern[MaxTextExtent],
1639 text[MaxTextExtent];
1652 glob_pattern[MaxTextExtent] = "*";
1654 static MagickStatusType
1655 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
1703 Get color list and sort in ascending order.
1705 assert(display != (Display *) NULL);
1706 assert(windows != (XWindows *) NULL);
1707 assert(action != (char *) NULL);
1708 assert(reply != (char *) NULL);
1709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
1710 XSetCursorState(display,windows,MagickTrue);
1711 XCheckRefreshWindows(display,windows);
1712 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
1713 exception=AcquireExceptionInfo();
1714 colorlist=GetColorList(glob_pattern,&colors,exception);
1715 if (colorlist == (char **) NULL)
1718 Pattern failed, obtain all the colors.
1720 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
1721 colorlist=GetColorList(glob_pattern,&colors,exception);
1722 if (colorlist == (char **) NULL)
1724 XNoticeWidget(display,windows,"Unable to obtain colors names:",
1726 (void) XDialogWidget(display,windows,action,"Enter color name:",
1732 Determine Color Browser widget attributes.
1734 font_info=windows->widget.font_info;
1736 for (i=0; i < (int) colors; i++)
1737 if (WidgetTextWidth(font_info,colorlist[i]) > text_width)
1738 text_width=WidgetTextWidth(font_info,colorlist[i]);
1739 width=WidgetTextWidth(font_info,(char *) action);
1740 if (WidgetTextWidth(font_info,CancelButtonText) > width)
1741 width=WidgetTextWidth(font_info,CancelButtonText);
1742 if (WidgetTextWidth(font_info,ResetButtonText) > width)
1743 width=WidgetTextWidth(font_info,ResetButtonText);
1744 if (WidgetTextWidth(font_info,GrabButtonText) > width)
1745 width=WidgetTextWidth(font_info,GrabButtonText);
1746 width+=QuantumMargin;
1747 if (WidgetTextWidth(font_info,ColorPatternText) > width)
1748 width=WidgetTextWidth(font_info,ColorPatternText);
1749 if (WidgetTextWidth(font_info,ColornameText) > width)
1750 width=WidgetTextWidth(font_info,ColornameText);
1751 height=(unsigned int) (font_info->ascent+font_info->descent);
1753 Position Color Browser widget.
1755 windows->widget.width=(unsigned int)
1756 (width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin);
1757 windows->widget.min_width=(unsigned int)
1758 (width+MinTextWidth+4*QuantumMargin);
1759 if (windows->widget.width < windows->widget.min_width)
1760 windows->widget.width=windows->widget.min_width;
1761 windows->widget.height=(unsigned int)
1762 ((81*height) >> 2)+((13*QuantumMargin) >> 1)+4;
1763 windows->widget.min_height=(unsigned int)
1764 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
1765 if (windows->widget.height < windows->widget.min_height)
1766 windows->widget.height=windows->widget.min_height;
1767 XConstrainWindowPosition(display,&windows->widget);
1769 Map Color Browser widget.
1771 (void) CopyMagickString(windows->widget.name,"Browse and Select a Color",
1773 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
1774 if (status != False)
1776 XSetWMName(display,windows->widget.id,&window_name);
1777 XSetWMIconName(display,windows->widget.id,&window_name);
1778 (void) XFree((void *) window_name.value);
1780 window_changes.width=(int) windows->widget.width;
1781 window_changes.height=(int) windows->widget.height;
1782 window_changes.x=windows->widget.x;
1783 window_changes.y=windows->widget.y;
1784 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
1785 mask,&window_changes);
1786 (void) XMapRaised(display,windows->widget.id);
1787 windows->widget.mapped=MagickFalse;
1789 Respond to X events.
1791 XGetWidgetInfo((char *) NULL,&mode_info);
1792 XGetWidgetInfo((char *) NULL,&slider_info);
1793 XGetWidgetInfo((char *) NULL,&north_info);
1794 XGetWidgetInfo((char *) NULL,&south_info);
1795 XGetWidgetInfo((char *) NULL,&expose_info);
1796 XGetWidgetInfo((char *) NULL,&selection_info);
1798 delay=SuspendTime << 2;
1799 state=UpdateConfigurationState;
1802 if (state & UpdateConfigurationState)
1808 Initialize button information.
1810 XGetWidgetInfo(CancelButtonText,&cancel_info);
1811 cancel_info.width=width;
1812 cancel_info.height=(unsigned int) ((3*height) >> 1);
1814 (windows->widget.width-cancel_info.width-QuantumMargin-2);
1816 (windows->widget.height-cancel_info.height-QuantumMargin);
1817 XGetWidgetInfo(action,&action_info);
1818 action_info.width=width;
1819 action_info.height=(unsigned int) ((3*height) >> 1);
1820 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
1821 (action_info.bevel_width << 1));
1822 action_info.y=cancel_info.y;
1823 XGetWidgetInfo(GrabButtonText,&grab_info);
1824 grab_info.width=width;
1825 grab_info.height=(unsigned int) ((3*height) >> 1);
1826 grab_info.x=QuantumMargin;
1827 grab_info.y=((5*QuantumMargin) >> 1)+height;
1828 XGetWidgetInfo(ResetButtonText,&reset_info);
1829 reset_info.width=width;
1830 reset_info.height=(unsigned int) ((3*height) >> 1);
1831 reset_info.x=QuantumMargin;
1832 reset_info.y=grab_info.y+grab_info.height+QuantumMargin;
1834 Initialize reply information.
1836 XGetWidgetInfo(reply,&reply_info);
1837 reply_info.raised=MagickFalse;
1838 reply_info.bevel_width--;
1839 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
1840 reply_info.height=height << 1;
1841 reply_info.x=(int) (width+(QuantumMargin << 1));
1842 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
1844 Initialize mode information.
1846 XGetWidgetInfo((char *) NULL,&mode_info);
1847 mode_info.active=MagickTrue;
1848 mode_info.bevel_width=0;
1849 mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1));
1850 mode_info.height=action_info.height;
1851 mode_info.x=QuantumMargin;
1852 mode_info.y=action_info.y;
1854 Initialize scroll information.
1856 XGetWidgetInfo((char *) NULL,&scroll_info);
1857 scroll_info.bevel_width--;
1858 scroll_info.width=height;
1859 scroll_info.height=(unsigned int) (reply_info.y-grab_info.y-
1860 (QuantumMargin >> 1));
1861 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
1862 scroll_info.y=grab_info.y-reply_info.bevel_width;
1863 scroll_info.raised=MagickFalse;
1864 scroll_info.trough=MagickTrue;
1865 north_info=scroll_info;
1866 north_info.raised=MagickTrue;
1867 north_info.width-=(north_info.bevel_width << 1);
1868 north_info.height=north_info.width-1;
1869 north_info.x+=north_info.bevel_width;
1870 north_info.y+=north_info.bevel_width;
1871 south_info=north_info;
1872 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
1875 slider_info=north_info;
1877 slider_info.width-=2;
1878 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
1879 slider_info.bevel_width+2;
1880 slider_info.height=scroll_info.height-((slider_info.min_y-
1881 scroll_info.y+1) << 1)+4;
1882 visible_colors=scroll_info.height/(height+(height >> 3));
1883 if (colors > visible_colors)
1884 slider_info.height=(unsigned int)
1885 ((visible_colors*slider_info.height)/colors);
1886 slider_info.max_y=south_info.y-south_info.bevel_width-
1887 slider_info.bevel_width-2;
1888 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
1889 slider_info.y=slider_info.min_y;
1890 expose_info=scroll_info;
1891 expose_info.y=slider_info.y;
1893 Initialize list information.
1895 XGetWidgetInfo((char *) NULL,&list_info);
1896 list_info.raised=MagickFalse;
1897 list_info.bevel_width--;
1898 list_info.width=(unsigned int)
1899 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
1900 list_info.height=scroll_info.height;
1901 list_info.x=reply_info.x;
1902 list_info.y=scroll_info.y;
1903 if (windows->widget.mapped == MagickFalse)
1904 state|=JumpListState;
1906 Initialize text information.
1909 XGetWidgetInfo(text,&text_info);
1910 text_info.center=MagickFalse;
1911 text_info.width=reply_info.width;
1912 text_info.height=height;
1913 text_info.x=list_info.x-(QuantumMargin >> 1);
1914 text_info.y=QuantumMargin;
1916 Initialize selection information.
1918 XGetWidgetInfo((char *) NULL,&selection_info);
1919 selection_info.center=MagickFalse;
1920 selection_info.width=list_info.width;
1921 selection_info.height=(unsigned int) ((9*height) >> 3);
1922 selection_info.x=list_info.x;
1923 state&=(~UpdateConfigurationState);
1925 if (state & RedrawWidgetState)
1928 Redraw Color Browser window.
1931 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
1932 (void) XDrawString(display,windows->widget.id,
1933 windows->widget.annotate_context,x,y,ColorPatternText,
1934 Extent(ColorPatternText));
1935 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
1936 XDrawWidgetText(display,&windows->widget,&text_info);
1937 XDrawBeveledButton(display,&windows->widget,&grab_info);
1938 XDrawBeveledButton(display,&windows->widget,&reset_info);
1939 XDrawBeveledMatte(display,&windows->widget,&list_info);
1940 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
1941 XDrawTriangleNorth(display,&windows->widget,&north_info);
1942 XDrawBeveledButton(display,&windows->widget,&slider_info);
1943 XDrawTriangleSouth(display,&windows->widget,&south_info);
1945 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
1946 (void) XDrawString(display,windows->widget.id,
1947 windows->widget.annotate_context,x,y,ColornameText,
1948 Extent(ColornameText));
1949 XDrawBeveledMatte(display,&windows->widget,&reply_info);
1950 XDrawMatteText(display,&windows->widget,&reply_info);
1951 XDrawBeveledButton(display,&windows->widget,&action_info);
1952 XDrawBeveledButton(display,&windows->widget,&cancel_info);
1953 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
1954 selection_info.id=(~0);
1955 state|=RedrawActionState;
1956 state|=RedrawListState;
1957 state&=(~RedrawWidgetState);
1959 if (state & UpdateListState)
1967 status=XParseColor(display,windows->widget.map_info->colormap,
1968 glob_pattern,&color);
1969 if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL))
1972 Reply is a single color name-- exit.
1974 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
1975 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1976 action_info.raised=MagickFalse;
1977 XDrawBeveledButton(display,&windows->widget,&action_info);
1983 checklist=GetColorList(glob_pattern,&number_colors,exception);
1984 if (number_colors == 0)
1986 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
1987 (void) XBell(display,0);
1991 for (i=0; i < (int) colors; i++)
1992 colorlist[i]=DestroyString(colorlist[i]);
1993 if (colorlist != (char **) NULL)
1994 colorlist=(char **) RelinquishMagickMemory(colorlist);
1995 colorlist=checklist;
1996 colors=number_colors;
1999 Sort color list in ascending order.
2002 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
2003 if (colors > visible_colors)
2004 slider_info.height=(unsigned int)
2005 ((visible_colors*slider_info.height)/colors);
2006 slider_info.max_y=south_info.y-south_info.bevel_width-
2007 slider_info.bevel_width-2;
2009 slider_info.y=slider_info.min_y;
2010 expose_info.y=slider_info.y;
2011 selection_info.id=(~0);
2013 state|=RedrawListState;
2015 Redraw color name & reply.
2017 *reply_info.text='\0';
2018 reply_info.cursor=reply_info.text;
2019 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
2020 XDrawWidgetText(display,&windows->widget,&text_info);
2021 XDrawMatteText(display,&windows->widget,&reply_info);
2022 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
2023 XDrawTriangleNorth(display,&windows->widget,&north_info);
2024 XDrawBeveledButton(display,&windows->widget,&slider_info);
2025 XDrawTriangleSouth(display,&windows->widget,&south_info);
2026 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
2027 state&=(~UpdateListState);
2029 if (state & JumpListState)
2032 Jump scroll to match user color.
2035 for (i=0; i < (int) colors; i++)
2036 if (LocaleCompare(colorlist[i],reply) >= 0)
2038 list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0;
2041 if ((i < slider_info.id) ||
2042 (i >= (int) (slider_info.id+visible_colors)))
2043 slider_info.id=i-(visible_colors >> 1);
2044 selection_info.id=(~0);
2045 state|=RedrawListState;
2046 state&=(~JumpListState);
2048 if (state & RedrawListState)
2051 Determine slider id and position.
2053 if (slider_info.id >= (int) (colors-visible_colors))
2054 slider_info.id=(int) (colors-visible_colors);
2055 if ((slider_info.id < 0) || (colors <= visible_colors))
2057 slider_info.y=slider_info.min_y;
2059 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
2060 slider_info.min_y+1)/colors);
2061 if (slider_info.id != selection_info.id)
2064 Redraw scroll bar and file names.
2066 selection_info.id=slider_info.id;
2067 selection_info.y=list_info.y+(height >> 3)+2;
2068 for (i=0; i < (int) visible_colors; i++)
2070 selection_info.raised=(slider_info.id+i) != list_info.id ?
2071 MagickTrue : MagickFalse;
2072 selection_info.text=(char *) NULL;
2073 if ((slider_info.id+i) < (int) colors)
2074 selection_info.text=colorlist[slider_info.id+i];
2075 XDrawWidgetText(display,&windows->widget,&selection_info);
2076 selection_info.y+=(int) selection_info.height;
2081 if (slider_info.y > expose_info.y)
2083 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
2084 expose_info.y=slider_info.y-expose_info.height-
2085 slider_info.bevel_width-1;
2089 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
2090 expose_info.y=slider_info.y+slider_info.height+
2091 slider_info.bevel_width+1;
2093 XDrawTriangleNorth(display,&windows->widget,&north_info);
2094 XDrawMatte(display,&windows->widget,&expose_info);
2095 XDrawBeveledButton(display,&windows->widget,&slider_info);
2096 XDrawTriangleSouth(display,&windows->widget,&south_info);
2097 expose_info.y=slider_info.y;
2099 state&=(~RedrawListState);
2101 if (state & RedrawActionState)
2104 colorname[MaxTextExtent];
2107 Display the selected color in a drawing area.
2109 color=windows->widget.pixel_info->matte_color;
2110 (void) XParseColor(display,windows->widget.map_info->colormap,
2111 reply_info.text,&windows->widget.pixel_info->matte_color);
2112 XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL,
2113 (unsigned int) windows->widget.visual_info->colormap_size,
2114 &windows->widget.pixel_info->matte_color);
2115 mode_info.text=colorname;
2116 (void) FormatLocaleString(mode_info.text,MaxTextExtent,"#%02x%02x%02x",
2117 windows->widget.pixel_info->matte_color.red,
2118 windows->widget.pixel_info->matte_color.green,
2119 windows->widget.pixel_info->matte_color.blue);
2120 XDrawBeveledButton(display,&windows->widget,&mode_info);
2121 windows->widget.pixel_info->matte_color=color;
2122 state&=(~RedrawActionState);
2125 Wait for next event.
2127 if (north_info.raised && south_info.raised)
2128 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
2132 Brief delay before advancing scroll bar.
2134 XDelay(display,delay);
2136 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
2137 if (north_info.raised == MagickFalse)
2138 if (slider_info.id > 0)
2144 state|=RedrawListState;
2146 if (south_info.raised == MagickFalse)
2147 if (slider_info.id < (int) colors)
2153 state|=RedrawListState;
2155 if (event.type != ButtonRelease)
2162 if (MatteIsActive(slider_info,event.xbutton))
2167 slider_info.active=MagickTrue;
2170 if (MatteIsActive(north_info,event.xbutton))
2171 if (slider_info.id > 0)
2176 north_info.raised=MagickFalse;
2178 state|=RedrawListState;
2181 if (MatteIsActive(south_info,event.xbutton))
2182 if (slider_info.id < (int) colors)
2187 south_info.raised=MagickFalse;
2189 state|=RedrawListState;
2192 if (MatteIsActive(scroll_info,event.xbutton))
2197 if (event.xbutton.y < slider_info.y)
2198 slider_info.id-=(visible_colors-1);
2200 slider_info.id+=(visible_colors-1);
2201 state|=RedrawListState;
2204 if (MatteIsActive(list_info,event.xbutton))
2210 User pressed list matte.
2212 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
2213 selection_info.height;
2214 if (id >= (int) colors)
2216 (void) CopyMagickString(reply_info.text,colorlist[id],
2218 reply_info.highlight=MagickFalse;
2219 reply_info.marker=reply_info.text;
2220 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2221 XDrawMatteText(display,&windows->widget,&reply_info);
2222 state|=RedrawActionState;
2223 if (id == list_info.id)
2225 (void) CopyMagickString(glob_pattern,reply_info.text,
2227 state|=UpdateListState;
2229 selection_info.id=(~0);
2231 state|=RedrawListState;
2234 if (MatteIsActive(grab_info,event.xbutton))
2237 User pressed Grab button.
2239 grab_info.raised=MagickFalse;
2240 XDrawBeveledButton(display,&windows->widget,&grab_info);
2243 if (MatteIsActive(reset_info,event.xbutton))
2246 User pressed Reset button.
2248 reset_info.raised=MagickFalse;
2249 XDrawBeveledButton(display,&windows->widget,&reset_info);
2252 if (MatteIsActive(mode_info,event.xbutton))
2255 User pressed mode button.
2257 if (mode_info.text != (char *) NULL)
2258 (void) CopyMagickString(reply_info.text,mode_info.text,
2260 (void) CopyMagickString(primary_selection,reply_info.text,
2262 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2263 event.xbutton.time);
2264 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2265 windows->widget.id ? MagickTrue : MagickFalse;
2266 reply_info.marker=reply_info.text;
2267 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2268 XDrawMatteText(display,&windows->widget,&reply_info);
2271 if (MatteIsActive(action_info,event.xbutton))
2274 User pressed action button.
2276 action_info.raised=MagickFalse;
2277 XDrawBeveledButton(display,&windows->widget,&action_info);
2280 if (MatteIsActive(cancel_info,event.xbutton))
2283 User pressed Cancel button.
2285 cancel_info.raised=MagickFalse;
2286 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2289 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2291 if (event.xbutton.button != Button2)
2297 Move text cursor to position of button press.
2299 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
2300 for (i=1; i <= Extent(reply_info.marker); i++)
2301 if (XTextWidth(font_info,reply_info.marker,i) > x)
2303 reply_info.cursor=reply_info.marker+i-1;
2304 if (event.xbutton.time > (click_time+DoubleClick))
2305 reply_info.highlight=MagickFalse;
2309 Become the XA_PRIMARY selection owner.
2311 (void) CopyMagickString(primary_selection,reply_info.text,
2313 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
2314 event.xbutton.time);
2315 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
2316 windows->widget.id ? MagickTrue : MagickFalse;
2318 XDrawMatteText(display,&windows->widget,&reply_info);
2319 click_time=event.xbutton.time;
2323 Request primary selection.
2325 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2326 windows->widget.id,event.xbutton.time);
2331 if (windows->widget.mapped == MagickFalse)
2333 if (north_info.raised == MagickFalse)
2336 User released up button.
2338 delay=SuspendTime << 2;
2339 north_info.raised=MagickTrue;
2340 XDrawTriangleNorth(display,&windows->widget,&north_info);
2342 if (south_info.raised == MagickFalse)
2345 User released down button.
2347 delay=SuspendTime << 2;
2348 south_info.raised=MagickTrue;
2349 XDrawTriangleSouth(display,&windows->widget,&south_info);
2351 if (slider_info.active)
2354 Stop tracking slider.
2356 slider_info.active=MagickFalse;
2359 if (grab_info.raised == MagickFalse)
2361 if (event.xbutton.window == windows->widget.id)
2362 if (MatteIsActive(grab_info,event.xbutton))
2365 Select a fill color from the X server.
2367 (void) XGetWindowColor(display,windows,reply_info.text,
2369 reply_info.marker=reply_info.text;
2370 reply_info.cursor=reply_info.text+Extent(reply_info.text);
2371 XDrawMatteText(display,&windows->widget,&reply_info);
2372 state|=RedrawActionState;
2374 grab_info.raised=MagickTrue;
2375 XDrawBeveledButton(display,&windows->widget,&grab_info);
2377 if (reset_info.raised == MagickFalse)
2379 if (event.xbutton.window == windows->widget.id)
2380 if (MatteIsActive(reset_info,event.xbutton))
2382 (void) CopyMagickString(glob_pattern,reset_pattern,
2384 state|=UpdateListState;
2386 reset_info.raised=MagickTrue;
2387 XDrawBeveledButton(display,&windows->widget,&reset_info);
2389 if (action_info.raised == MagickFalse)
2391 if (event.xbutton.window == windows->widget.id)
2393 if (MatteIsActive(action_info,event.xbutton))
2395 if (*reply_info.text == '\0')
2396 (void) XBell(display,0);
2401 action_info.raised=MagickTrue;
2402 XDrawBeveledButton(display,&windows->widget,&action_info);
2404 if (cancel_info.raised == MagickFalse)
2406 if (event.xbutton.window == windows->widget.id)
2407 if (MatteIsActive(cancel_info,event.xbutton))
2409 *reply_info.text='\0';
2412 cancel_info.raised=MagickTrue;
2413 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2415 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
2422 If client window delete message, exit.
2424 if (event.xclient.message_type != windows->wm_protocols)
2426 if (*event.xclient.data.l == (int) windows->wm_take_focus)
2428 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2429 (Time) event.xclient.data.l[1]);
2432 if (*event.xclient.data.l != (int) windows->wm_delete_window)
2434 if (event.xclient.window == windows->widget.id)
2436 *reply_info.text='\0';
2442 case ConfigureNotify:
2445 Update widget configuration.
2447 if (event.xconfigure.window != windows->widget.id)
2449 if ((event.xconfigure.width == (int) windows->widget.width) &&
2450 (event.xconfigure.height == (int) windows->widget.height))
2452 windows->widget.width=(unsigned int)
2453 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
2454 windows->widget.height=(unsigned int)
2455 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
2456 state|=UpdateConfigurationState;
2461 if (event.xcrossing.window != windows->widget.id)
2463 state&=(~InactiveWidgetState);
2468 if (event.xexpose.window != windows->widget.id)
2470 if (event.xexpose.count != 0)
2472 state|=RedrawWidgetState;
2478 command[MaxTextExtent];
2487 Respond to a user key press.
2489 if (event.xkey.window != windows->widget.id)
2491 length=XLookupString((XKeyEvent *) &event.xkey,command,
2492 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2493 *(command+length)='\0';
2494 if (AreaIsActive(scroll_info,event.xkey))
2499 switch ((int) key_symbol)
2522 slider_info.id-=visible_colors;
2528 slider_info.id+=visible_colors;
2534 slider_info.id=(int) colors;
2538 state|=RedrawListState;
2541 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
2544 Read new color or glob patterm.
2546 if (*reply_info.text == '\0')
2548 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
2549 state|=UpdateListState;
2552 if (key_symbol == XK_Control_L)
2554 state|=ControlState;
2557 if (state & ControlState)
2558 switch ((int) key_symbol)
2564 Erase the entire line of text.
2566 *reply_info.text='\0';
2567 reply_info.cursor=reply_info.text;
2568 reply_info.marker=reply_info.text;
2569 reply_info.highlight=MagickFalse;
2575 XEditText(display,&reply_info,key_symbol,command,state);
2576 XDrawMatteText(display,&windows->widget,&reply_info);
2577 state|=JumpListState;
2578 status=XParseColor(display,windows->widget.map_info->colormap,
2579 reply_info.text,&color);
2580 if (status != False)
2581 state|=RedrawActionState;
2587 command[MaxTextExtent];
2593 Respond to a user key release.
2595 if (event.xkey.window != windows->widget.id)
2597 (void) XLookupString((XKeyEvent *) &event.xkey,command,
2598 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2599 if (key_symbol == XK_Control_L)
2600 state&=(~ControlState);
2605 if (event.xcrossing.window != windows->widget.id)
2607 state|=InactiveWidgetState;
2619 Discard pending button motion events.
2621 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
2622 if (slider_info.active)
2627 slider_info.y=event.xmotion.y-
2628 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
2629 if (slider_info.y < slider_info.min_y)
2630 slider_info.y=slider_info.min_y;
2631 if (slider_info.y > slider_info.max_y)
2632 slider_info.y=slider_info.max_y;
2634 if (slider_info.y != slider_info.min_y)
2635 slider_info.id=(int) ((colors*(slider_info.y-
2636 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
2637 state|=RedrawListState;
2640 if (state & InactiveWidgetState)
2642 if (grab_info.raised == MatteIsActive(grab_info,event.xmotion))
2645 Grab button status changed.
2647 grab_info.raised=!grab_info.raised;
2648 XDrawBeveledButton(display,&windows->widget,&grab_info);
2651 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
2654 Reset button status changed.
2656 reset_info.raised=!reset_info.raised;
2657 XDrawBeveledButton(display,&windows->widget,&reset_info);
2660 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
2663 Action button status changed.
2665 action_info.raised=action_info.raised == MagickFalse ?
2666 MagickTrue : MagickFalse;
2667 XDrawBeveledButton(display,&windows->widget,&action_info);
2670 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
2673 Cancel button status changed.
2675 cancel_info.raised=cancel_info.raised == MagickFalse ?
2676 MagickTrue : MagickFalse;
2677 XDrawBeveledButton(display,&windows->widget,&cancel_info);
2682 case SelectionClear:
2684 reply_info.highlight=MagickFalse;
2685 XDrawMatteText(display,&windows->widget,&reply_info);
2688 case SelectionNotify:
2704 Obtain response from primary selection.
2706 if (event.xselection.property == (Atom) None)
2708 status=XGetWindowProperty(display,event.xselection.requestor,
2709 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
2710 &format,&length,&after,&data);
2711 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2714 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
2715 (void) XBell(display,0);
2719 Insert primary selection in reply text.
2721 *(data+length)='\0';
2722 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
2724 XDrawMatteText(display,&windows->widget,&reply_info);
2725 state|=JumpListState;
2726 state|=RedrawActionState;
2728 (void) XFree((void *) data);
2731 case SelectionRequest:
2736 XSelectionRequestEvent
2739 if (reply_info.highlight == MagickFalse)
2742 Set primary selection.
2744 request=(&(event.xselectionrequest));
2745 (void) XChangeProperty(request->display,request->requestor,
2746 request->property,request->target,8,PropModeReplace,
2747 (unsigned char *) primary_selection,Extent(primary_selection));
2748 notify.type=SelectionNotify;
2749 notify.send_event=MagickTrue;
2750 notify.display=request->display;
2751 notify.requestor=request->requestor;
2752 notify.selection=request->selection;
2753 notify.target=request->target;
2754 notify.time=request->time;
2755 if (request->property == None)
2756 notify.property=request->target;
2758 notify.property=request->property;
2759 (void) XSendEvent(request->display,request->requestor,False,
2760 NoEventMask,(XEvent *) ¬ify);
2765 } while ((state & ExitState) == 0);
2766 XSetCursorState(display,windows,MagickFalse);
2767 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
2768 XCheckRefreshWindows(display,windows);
2772 for (i=0; i < (int) colors; i++)
2773 colorlist[i]=DestroyString(colorlist[i]);
2774 if (colorlist != (char **) NULL)
2775 colorlist=(char **) RelinquishMagickMemory(colorlist);
2776 exception=DestroyExceptionInfo(exception);
2777 if ((*reply == '\0') || (strchr(reply,'-') != (char *) NULL))
2779 status=XParseColor(display,windows->widget.map_info->colormap,reply,&color);
2780 if (status != False)
2782 XNoticeWidget(display,windows,"Color is unknown to X server:",reply);
2783 (void) CopyMagickString(reply,"gray",MaxTextExtent);
2787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2791 % X C o m m a n d W i d g e t %
2795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2797 % XCommandWidget() maps a menu and returns the command pointed to by the user
2798 % when the button is released.
2800 % The format of the XCommandWidget method is:
2802 % int XCommandWidget(Display *display,XWindows *windows,
2803 % const char **selections,XEvent *event)
2805 % A description of each parameter follows:
2807 % o selection_number: Specifies the number of the selection that the
2810 % o display: Specifies a connection to an X server; returned from
2813 % o window: Specifies a pointer to a XWindows structure.
2815 % o selections: Specifies a pointer to one or more strings that comprise
2816 % the choices in the menu.
2818 % o event: Specifies a pointer to a X11 XEvent structure.
2821 MagickPrivate int XCommandWidget(Display *display,XWindows *windows,
2822 const char **selections,XEvent *event)
2824 #define tile_width 112
2825 #define tile_height 70
2827 static const unsigned char
2830 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2831 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2832 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
2834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
2836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2837 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2838 0x00, 0x00, 0x1e, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2839 0x00, 0x00, 0x00, 0x00, 0x1e, 0xbc, 0x9f, 0x03, 0x00, 0x3e, 0x00, 0xc0,
2840 0x1f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x0f, 0x80, 0x3f,
2841 0x00, 0xf0, 0x1f, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x1f,
2842 0xe0, 0x3f, 0x00, 0xfc, 0x1f, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc,
2843 0xff, 0x1f, 0xf0, 0x3f, 0x00, 0xfe, 0x1f, 0xf8, 0x0f, 0x00, 0x00, 0x00,
2844 0x1e, 0xfc, 0xfc, 0x3f, 0xf8, 0x3f, 0x00, 0xff, 0x1e, 0xfc, 0x0f, 0x00,
2845 0x00, 0x00, 0x1e, 0x7c, 0xfc, 0x3e, 0xf8, 0x3c, 0x80, 0x1f, 0x1e, 0x7c,
2846 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 0xc0, 0x0f,
2847 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c,
2848 0xc0, 0x07, 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c,
2849 0x7c, 0x7c, 0xc0, 0x0f, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78,
2850 0x78, 0x3c, 0xfc, 0x7c, 0x80, 0x7f, 0x1e, 0x7c, 0x00, 0x00, 0x00, 0x00,
2851 0x1e, 0xf8, 0x78, 0x7c, 0xf8, 0xff, 0x00, 0xff, 0x1f, 0xf8, 0xff, 0x00,
2852 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xfe, 0x1f, 0xf8,
2853 0xff, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xf8,
2854 0x1f, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xc0, 0xef,
2855 0x07, 0xe0, 0x1f, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0x70, 0x40, 0x78,
2856 0x00, 0xc7, 0x07, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00,
2857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
2858 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
2859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
2860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
2861 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2862 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2863 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2864 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
2865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00,
2866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
2867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
2868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2869 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00,
2870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
2871 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2872 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2873 0x60, 0x00, 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2874 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2875 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00,
2876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0x9f, 0x7f, 0x00,
2877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0xdf,
2878 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00,
2879 0xe0, 0xdf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0c,
2880 0x78, 0x30, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
2881 0x00, 0x0f, 0xf8, 0x70, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x1f, 0x00, 0xe0,
2882 0x0f, 0x1e, 0x80, 0x0f, 0xf8, 0x78, 0xf0, 0xfd, 0xf9, 0x00, 0xc0, 0x1f,
2883 0x00, 0xf8, 0x0f, 0x00, 0xe0, 0x1f, 0xf8, 0x7c, 0xf0, 0xfc, 0xf9, 0x00,
2884 0xf0, 0x1f, 0x00, 0xfe, 0x0f, 0x00, 0xf0, 0x07, 0xf8, 0x3e, 0xf8, 0xfc,
2885 0xf0, 0x01, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x1e, 0xf0, 0x03, 0xf8, 0x3f,
2886 0xf8, 0xf8, 0xf0, 0x01, 0xfc, 0x1f, 0x80, 0x7f, 0x0f, 0x1e, 0xf8, 0x00,
2887 0xf8, 0x1f, 0x78, 0x18, 0xf0, 0x01, 0x7c, 0x1e, 0xc0, 0x0f, 0x0f, 0x1e,
2888 0x7c, 0x00, 0xf0, 0x0f, 0x78, 0x00, 0xf0, 0x01, 0x3e, 0x1e, 0xe0, 0x07,
2889 0x0f, 0x1e, 0x7c, 0x00, 0xf0, 0x07, 0x7c, 0x00, 0xe0, 0x01, 0x3e, 0x1e,
2890 0xe0, 0x03, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x0f, 0x7c, 0x00, 0xe0, 0x03,
2891 0x3e, 0x3e, 0xe0, 0x07, 0x0f, 0x1e, 0x1e, 0x00, 0xf0, 0x1f, 0x3c, 0x00,
2892 0xe0, 0x03, 0x7e, 0x3e, 0xc0, 0x3f, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x1f,
2893 0x3e, 0x00, 0xe0, 0x03, 0xfc, 0x7f, 0x80, 0xff, 0x0f, 0x1e, 0xfc, 0x00,
2894 0xf0, 0x3e, 0x3e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xff, 0x0f, 0x1e,
2895 0xfc, 0x07, 0xf0, 0x7c, 0x1e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xfc,
2896 0x0f, 0x1e, 0xf8, 0x1f, 0xf0, 0xf8, 0x1e, 0x00, 0xc0, 0x03, 0xe0, 0xf7,
2897 0x03, 0xf0, 0x0f, 0x1e, 0xe0, 0x3f, 0xf0, 0x78, 0x1c, 0x00, 0x80, 0x03,
2898 0x80, 0xe3, 0x03, 0x00, 0x0f, 0x1e, 0xc0, 0x3f, 0xf0, 0x30, 0x00, 0x00,
2899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x3e, 0x00, 0x00,
2900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x10,
2901 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00,
2902 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
2903 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2904 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2905 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2906 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
2908 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
2909 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
2910 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2911 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2933 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2934 assert(display != (Display *) NULL);
2935 assert(windows != (XWindows *) NULL);
2936 font_info=windows->command.font_info;
2937 height=(unsigned int) (font_info->ascent+font_info->descent);
2940 if (event == (XEvent *) NULL)
2952 Determine command window attributes.
2954 assert(selections != (const char **) NULL);
2955 windows->command.width=0;
2956 for (i=0; selections[i] != (char *) NULL; i++)
2958 width=WidgetTextWidth(font_info,(char *) selections[i]);
2959 if (width > windows->command.width)
2960 windows->command.width=width;
2962 number_selections=(unsigned int) i;
2963 windows->command.width+=3*QuantumMargin+10;
2964 if ((int) windows->command.width < (tile_width+QuantumMargin+10))
2965 windows->command.width=(unsigned int) (tile_width+QuantumMargin+10);
2966 windows->command.height=(unsigned int) (number_selections*
2967 (((3*height) >> 1)+10)+tile_height+20);
2968 windows->command.min_width=windows->command.width;
2969 windows->command.min_height=windows->command.height;
2970 XConstrainWindowPosition(display,&windows->command);
2971 if (windows->command.id != (Window) NULL)
2977 Reconfigure command window.
2979 status=XStringListToTextProperty(&windows->command.name,1,
2981 if (status != False)
2983 XSetWMName(display,windows->command.id,&window_name);
2984 XSetWMIconName(display,windows->command.id,&window_name);
2985 (void) XFree((void *) window_name.value);
2987 window_changes.width=(int) windows->command.width;
2988 window_changes.height=(int) windows->command.height;
2989 (void) XReconfigureWMWindow(display,windows->command.id,
2990 windows->command.screen,(unsigned int) (CWWidth | CWHeight),
2994 Allocate selection info memory.
2996 if (selection_info != (XWidgetInfo *) NULL)
2997 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
2998 selection_info=(XWidgetInfo *) AcquireQuantumMemory(number_selections,
2999 sizeof(*selection_info));
3000 if (selection_info == (XWidgetInfo *) NULL)
3002 ThrowXWindowFatalException(ResourceLimitFatalError,
3003 "MemoryAllocationFailed","...");
3006 state|=UpdateConfigurationState | RedrawWidgetState;
3009 Wait for next event.
3011 if (event != (XEvent *) NULL)
3012 switch (event->type)
3016 for (i=0; i < (int) number_selections; i++)
3018 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3020 if (i >= (int) windows->command.data)
3022 selection_info[i].raised=MagickFalse;
3023 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3026 submenu_info=selection_info[i];
3027 submenu_info.active=MagickTrue;
3029 submenu_info.y+(submenu_info.height >> 1)-(toggle_info.height >> 1);
3031 (void) XCheckWindowEvent(display,windows->widget.id,LeaveWindowMask,
3039 for (i=0; i < (int) number_selections; i++)
3041 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
3044 if (id >= (int) windows->command.data)
3046 selection_info[id].raised=MagickTrue;
3047 XDrawBeveledButton(display,&windows->command,&selection_info[id]);
3057 If client window delete message, withdraw command widget.
3059 if (event->xclient.message_type != windows->wm_protocols)
3061 if (*event->xclient.data.l != (int) windows->wm_delete_window)
3063 (void) XWithdrawWindow(display,windows->command.id,
3064 windows->command.screen);
3067 case ConfigureNotify:
3070 Update widget configuration.
3072 if (event->xconfigure.window != windows->command.id)
3074 if (event->xconfigure.send_event != 0)
3076 windows->command.x=event->xconfigure.x;
3077 windows->command.y=event->xconfigure.y;
3079 if ((event->xconfigure.width == (int) windows->command.width) &&
3080 (event->xconfigure.height == (int) windows->command.height))
3082 windows->command.width=(unsigned int)
3083 MagickMax(event->xconfigure.width,(int) windows->command.min_width);
3084 windows->command.height=(unsigned int)
3085 MagickMax(event->xconfigure.height,(int) windows->command.min_height);
3086 state|=UpdateConfigurationState;
3091 if (event->xexpose.window != windows->command.id)
3093 if (event->xexpose.count != 0)
3095 state|=RedrawWidgetState;
3101 Return the ID of the highlighted menu entry.
3105 for (i=0; i < (int) number_selections; i++)
3107 if (i >= (int) windows->command.data)
3109 if (selection_info[i].raised ==
3110 MatteIsActive(selection_info[i],event->xmotion))
3113 Button status changed.
3115 selection_info[i].raised=!selection_info[i].raised;
3116 XDrawBeveledButton(display,&windows->command,
3117 &selection_info[i]);
3121 if (MatteIsActive(selection_info[i],event->xmotion) == MagickFalse)
3123 submenu_info=selection_info[i];
3124 submenu_info.active=MagickTrue;
3125 toggle_info.raised=MagickTrue;
3126 toggle_info.y=submenu_info.y+(submenu_info.height >> 1)-
3127 (toggle_info.height >> 1);
3128 XDrawTriangleEast(display,&windows->command,&toggle_info);
3131 XDelay(display,SuspendTime);
3132 if (XCheckMaskEvent(display,ButtonMotionMask,event) == MagickFalse)
3134 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
3135 toggle_info.raised=MagickFalse;
3136 if (windows->command.data != 0)
3137 XDrawTriangleEast(display,&windows->command,&toggle_info);
3143 windows->command.mapped=MagickTrue;
3148 windows->command.mapped=MagickFalse;
3154 if (state & UpdateConfigurationState)
3157 Initialize button information.
3159 assert(selections != (const char **) NULL);
3161 for (i=0; i < (int) number_selections; i++)
3163 XGetWidgetInfo(selections[i],&selection_info[i]);
3164 selection_info[i].center=MagickFalse;
3165 selection_info[i].bevel_width--;
3166 selection_info[i].height=(unsigned int) ((3*height) >> 1);
3167 selection_info[i].x=(QuantumMargin >> 1)+4;
3168 selection_info[i].width=(unsigned int)
3169 (windows->command.width-(selection_info[i].x << 1));
3170 selection_info[i].y=y;
3171 y+=selection_info[i].height+(selection_info[i].bevel_width << 1)+6;
3173 XGetWidgetInfo((char *) NULL,&toggle_info);
3174 toggle_info.bevel_width--;
3175 toggle_info.width=(unsigned int)
3176 (((5*height) >> 3)-(toggle_info.bevel_width << 1));
3177 toggle_info.height=toggle_info.width;
3178 toggle_info.x=selection_info[0].x+selection_info[0].width-
3179 toggle_info.width-(QuantumMargin >> 1);
3180 if (windows->command.mapped)
3181 (void) XClearWindow(display,windows->command.id);
3183 if (state & RedrawWidgetState)
3189 Draw command buttons.
3191 tile_pixmap=XCreatePixmapFromBitmapData(display,windows->command.id,
3192 (char *) tile_bits,tile_width,tile_height,1L,0L,1);
3193 if (tile_pixmap != (Pixmap) NULL)
3195 (void) XCopyPlane(display,tile_pixmap,windows->command.id,
3196 windows->command.annotate_context,0,0,tile_width,tile_height,
3197 (int) ((windows->command.width-tile_width) >> 1),10,1L);
3198 (void) XFreePixmap(display,tile_pixmap);
3200 for (i=0; i < (int) number_selections; i++)
3202 XDrawBeveledButton(display,&windows->command,&selection_info[i]);
3203 if (i >= (int) windows->command.data)
3205 toggle_info.raised=i == id ? MagickTrue : MagickFalse;
3206 toggle_info.y=selection_info[i].y+
3207 (selection_info[i].height >> 1)-(toggle_info.height >> 1);
3208 XDrawTriangleEast(display,&windows->command,&toggle_info);
3210 XHighlightWidget(display,&windows->command,BorderOffset,BorderOffset);
3216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3220 % X C o n f i r m W i d g e t %
3224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3226 % XConfirmWidget() displays a Confirm widget with a notice to the user. The
3227 % function returns -1 if Dismiss is pressed, 0 for Cancel, and 1 for Yes.
3229 % The format of the XConfirmWidget method is:
3231 % int XConfirmWidget(Display *display,XWindows *windows,
3232 % const char *reason,const char *description)
3234 % A description of each parameter follows:
3236 % o display: Specifies a connection to an X server; returned from
3239 % o window: Specifies a pointer to a XWindows structure.
3241 % o reason: Specifies the message to display before terminating the
3244 % o description: Specifies any description to the message.
3247 MagickPrivate int XConfirmWidget(Display *display,XWindows *windows,
3248 const char *reason,const char *description)
3250 #define CancelButtonText "Cancel"
3251 #define DismissButtonText "Dismiss"
3252 #define YesButtonText "Yes"
3287 Determine Confirm widget attributes.
3289 assert(display != (Display *) NULL);
3290 assert(windows != (XWindows *) NULL);
3291 assert(reason != (char *) NULL);
3292 assert(description != (char *) NULL);
3293 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
3294 XCheckRefreshWindows(display,windows);
3295 font_info=windows->widget.font_info;
3296 width=WidgetTextWidth(font_info,CancelButtonText);
3297 if (WidgetTextWidth(font_info,DismissButtonText) > width)
3298 width=WidgetTextWidth(font_info,DismissButtonText);
3299 if (WidgetTextWidth(font_info,YesButtonText) > width)
3300 width=WidgetTextWidth(font_info,YesButtonText);
3302 if (description != (char *) NULL)
3303 if (WidgetTextWidth(font_info,(char *) description) > width)
3304 width=WidgetTextWidth(font_info,(char *) description);
3305 height=(unsigned int) (font_info->ascent+font_info->descent);
3307 Position Confirm widget.
3309 windows->widget.width=(unsigned int) (width+9*QuantumMargin);
3310 windows->widget.min_width=(unsigned int) (9*QuantumMargin+
3311 WidgetTextWidth(font_info,CancelButtonText)+
3312 WidgetTextWidth(font_info,DismissButtonText)+
3313 WidgetTextWidth(font_info,YesButtonText));
3314 if (windows->widget.width < windows->widget.min_width)
3315 windows->widget.width=windows->widget.min_width;
3316 windows->widget.height=(unsigned int) (12*height);
3317 windows->widget.min_height=(unsigned int) (7*height);
3318 if (windows->widget.height < windows->widget.min_height)
3319 windows->widget.height=windows->widget.min_height;
3320 XConstrainWindowPosition(display,&windows->widget);
3324 (void) CopyMagickString(windows->widget.name,"Confirm",MaxTextExtent);
3325 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3326 if (status != False)
3328 XSetWMName(display,windows->widget.id,&window_name);
3329 XSetWMIconName(display,windows->widget.id,&window_name);
3330 (void) XFree((void *) window_name.value);
3332 window_changes.width=(int) windows->widget.width;
3333 window_changes.height=(int) windows->widget.height;
3334 window_changes.x=windows->widget.x;
3335 window_changes.y=windows->widget.y;
3336 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3337 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3338 (void) XMapRaised(display,windows->widget.id);
3339 windows->widget.mapped=MagickFalse;
3341 Respond to X events.
3344 state=UpdateConfigurationState;
3345 XSetCursorState(display,windows,MagickTrue);
3348 if (state & UpdateConfigurationState)
3351 Initialize button information.
3353 XGetWidgetInfo(CancelButtonText,&cancel_info);
3354 cancel_info.width=(unsigned int) QuantumMargin+
3355 WidgetTextWidth(font_info,CancelButtonText);
3356 cancel_info.height=(unsigned int) ((3*height) >> 1);
3357 cancel_info.x=(int) (windows->widget.width-cancel_info.width-
3359 cancel_info.y=(int) (windows->widget.height-(cancel_info.height << 1));
3360 dismiss_info=cancel_info;
3361 dismiss_info.text=(char *) DismissButtonText;
3362 if (LocaleCompare(description,"Do you want to save it") == 0)
3363 dismiss_info.text=(char *) "Don't Save";
3364 dismiss_info.width=(unsigned int) QuantumMargin+
3365 WidgetTextWidth(font_info,dismiss_info.text);
3366 dismiss_info.x=(int)
3367 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
3368 yes_info=cancel_info;
3369 yes_info.text=(char *) YesButtonText;
3370 if (LocaleCompare(description,"Do you want to save it") == 0)
3371 yes_info.text=(char *) "Save";
3372 yes_info.width=(unsigned int) QuantumMargin+
3373 WidgetTextWidth(font_info,yes_info.text);
3374 if (yes_info.width < cancel_info.width)
3375 yes_info.width=cancel_info.width;
3376 yes_info.x=QuantumMargin;
3377 state&=(~UpdateConfigurationState);
3379 if (state & RedrawWidgetState)
3382 Redraw Confirm widget.
3384 width=WidgetTextWidth(font_info,(char *) reason);
3385 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3386 y=(int) ((windows->widget.height >> 1)-(height << 1));
3387 (void) XDrawString(display,windows->widget.id,
3388 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
3389 if (description != (char *) NULL)
3392 question[MaxTextExtent];
3394 (void) CopyMagickString(question,description,MaxTextExtent);
3395 (void) ConcatenateMagickString(question,"?",MaxTextExtent);
3396 width=WidgetTextWidth(font_info,question);
3397 x=(int) ((windows->widget.width >> 1)-(width >> 1));
3399 (void) XDrawString(display,windows->widget.id,
3400 windows->widget.annotate_context,x,y,question,Extent(question));
3402 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3403 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3404 XDrawBeveledButton(display,&windows->widget,&yes_info);
3405 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3406 state&=(~RedrawWidgetState);
3409 Wait for next event.
3411 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3416 if (MatteIsActive(cancel_info,event.xbutton))
3419 User pressed No button.
3421 cancel_info.raised=MagickFalse;
3422 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3425 if (MatteIsActive(dismiss_info,event.xbutton))
3428 User pressed Dismiss button.
3430 dismiss_info.raised=MagickFalse;
3431 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3434 if (MatteIsActive(yes_info,event.xbutton))
3437 User pressed Yes button.
3439 yes_info.raised=MagickFalse;
3440 XDrawBeveledButton(display,&windows->widget,&yes_info);
3447 if (windows->widget.mapped == MagickFalse)
3449 if (cancel_info.raised == MagickFalse)
3451 if (event.xbutton.window == windows->widget.id)
3452 if (MatteIsActive(cancel_info,event.xbutton))
3457 cancel_info.raised=MagickTrue;
3458 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3460 if (dismiss_info.raised == MagickFalse)
3462 if (event.xbutton.window == windows->widget.id)
3463 if (MatteIsActive(dismiss_info,event.xbutton))
3468 dismiss_info.raised=MagickTrue;
3469 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3471 if (yes_info.raised == MagickFalse)
3473 if (event.xbutton.window == windows->widget.id)
3474 if (MatteIsActive(yes_info,event.xbutton))
3479 yes_info.raised=MagickTrue;
3480 XDrawBeveledButton(display,&windows->widget,&yes_info);
3487 If client window delete message, exit.
3489 if (event.xclient.message_type != windows->wm_protocols)
3491 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3493 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3494 (Time) event.xclient.data.l[1]);
3497 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3499 if (event.xclient.window == windows->widget.id)
3506 case ConfigureNotify:
3509 Update widget configuration.
3511 if (event.xconfigure.window != windows->widget.id)
3513 if ((event.xconfigure.width == (int) windows->widget.width) &&
3514 (event.xconfigure.height == (int) windows->widget.height))
3516 windows->widget.width=(unsigned int)
3517 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3518 windows->widget.height=(unsigned int)
3519 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3520 state|=UpdateConfigurationState;
3525 if (event.xcrossing.window != windows->widget.id)
3527 state&=(~InactiveWidgetState);
3532 if (event.xexpose.window != windows->widget.id)
3534 if (event.xexpose.count != 0)
3536 state|=RedrawWidgetState;
3542 command[MaxTextExtent];
3548 Respond to a user key press.
3550 if (event.xkey.window != windows->widget.id)
3552 (void) XLookupString((XKeyEvent *) &event.xkey,command,
3553 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3554 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
3556 yes_info.raised=MagickFalse;
3557 XDrawBeveledButton(display,&windows->widget,&yes_info);
3566 if (event.xcrossing.window != windows->widget.id)
3568 state|=InactiveWidgetState;
3574 Discard pending button motion events.
3576 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
3577 if (state & InactiveWidgetState)
3579 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
3582 Cancel button status changed.
3584 cancel_info.raised=cancel_info.raised == MagickFalse ?
3585 MagickTrue : MagickFalse;
3586 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3589 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
3592 Dismiss button status changed.
3594 dismiss_info.raised=dismiss_info.raised == MagickFalse ?
3595 MagickTrue : MagickFalse;
3596 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
3599 if (yes_info.raised == MatteIsActive(yes_info,event.xmotion))
3602 Yes button status changed.
3604 yes_info.raised=yes_info.raised == MagickFalse ?
3605 MagickTrue : MagickFalse;
3606 XDrawBeveledButton(display,&windows->widget,&yes_info);
3614 } while ((state & ExitState) == 0);
3615 XSetCursorState(display,windows,MagickFalse);
3616 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
3617 XCheckRefreshWindows(display,windows);
3622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3626 % X D i a l o g W i d g e t %
3630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3632 % XDialogWidget() displays a Dialog widget with a query to the user. The user
3633 % keys a reply and presses the Ok or Cancel button to exit. The typed text is
3634 % returned as the reply function parameter.
3636 % The format of the XDialogWidget method is:
3638 % int XDialogWidget(Display *display,XWindows *windows,const char *action,
3639 % const char *query,char *reply)
3641 % A description of each parameter follows:
3643 % o display: Specifies a connection to an X server; returned from
3646 % o window: Specifies a pointer to a XWindows structure.
3648 % o action: Specifies a pointer to the action of this widget.
3650 % o query: Specifies a pointer to the query to present to the user.
3652 % o reply: the response from the user is returned in this parameter.
3655 MagickPrivate int XDialogWidget(Display *display,XWindows *windows,
3656 const char *action,const char *query,char *reply)
3658 #define CancelButtonText "Cancel"
3661 primary_selection[MaxTextExtent];
3669 static MagickBooleanType
3670 raised = MagickFalse;
3703 Determine Dialog widget attributes.
3705 assert(display != (Display *) NULL);
3706 assert(windows != (XWindows *) NULL);
3707 assert(action != (char *) NULL);
3708 assert(query != (char *) NULL);
3709 assert(reply != (char *) NULL);
3710 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
3711 XCheckRefreshWindows(display,windows);
3712 font_info=windows->widget.font_info;
3713 width=WidgetTextWidth(font_info,(char *) action);
3714 if (WidgetTextWidth(font_info,CancelButtonText) > width)
3715 width=WidgetTextWidth(font_info,CancelButtonText);
3716 width+=(3*QuantumMargin) >> 1;
3717 height=(unsigned int) (font_info->ascent+font_info->descent);
3719 Position Dialog widget.
3721 windows->widget.width=(unsigned int) MagickMax((int) (2*width),(int)
3722 WidgetTextWidth(font_info,(char *) query));
3723 if (windows->widget.width < WidgetTextWidth(font_info,reply))
3724 windows->widget.width=WidgetTextWidth(font_info,reply);
3725 windows->widget.width+=6*QuantumMargin;
3726 windows->widget.min_width=(unsigned int)
3727 (width+28*XTextWidth(font_info,"#",1)+4*QuantumMargin);
3728 if (windows->widget.width < windows->widget.min_width)
3729 windows->widget.width=windows->widget.min_width;
3730 windows->widget.height=(unsigned int) (7*height+(QuantumMargin << 1));
3731 windows->widget.min_height=windows->widget.height;
3732 if (windows->widget.height < windows->widget.min_height)
3733 windows->widget.height=windows->widget.min_height;
3734 XConstrainWindowPosition(display,&windows->widget);
3738 (void) CopyMagickString(windows->widget.name,"Dialog",MaxTextExtent);
3739 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
3740 if (status != False)
3742 XSetWMName(display,windows->widget.id,&window_name);
3743 XSetWMIconName(display,windows->widget.id,&window_name);
3744 (void) XFree((void *) window_name.value);
3746 window_changes.width=(int) windows->widget.width;
3747 window_changes.height=(int) windows->widget.height;
3748 window_changes.x=windows->widget.x;
3749 window_changes.y=windows->widget.y;
3750 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
3751 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
3752 (void) XMapRaised(display,windows->widget.id);
3753 windows->widget.mapped=MagickFalse;
3755 Respond to X events.
3757 anomaly=(LocaleCompare(action,"Background") == 0) ||
3758 (LocaleCompare(action,"New") == 0) ||
3759 (LocaleCompare(action,"Quantize") == 0) ||
3760 (LocaleCompare(action,"Resize") == 0) ||
3761 (LocaleCompare(action,"Save") == 0) ||
3762 (LocaleCompare(action,"Shade") == 0);
3763 state=UpdateConfigurationState;
3764 XSetCursorState(display,windows,MagickTrue);
3767 if (state & UpdateConfigurationState)
3770 Initialize button information.
3772 XGetWidgetInfo(CancelButtonText,&cancel_info);
3773 cancel_info.width=width;
3774 cancel_info.height=(unsigned int) ((3*height) >> 1);
3776 (windows->widget.width-cancel_info.width-((3*QuantumMargin) >> 1));
3778 (windows->widget.height-cancel_info.height-((3*QuantumMargin) >> 1));
3779 XGetWidgetInfo(action,&action_info);
3780 action_info.width=width;
3781 action_info.height=(unsigned int) ((3*height) >> 1);
3782 action_info.x=cancel_info.x-(cancel_info.width+QuantumMargin+
3783 (action_info.bevel_width << 1));
3784 action_info.y=cancel_info.y;
3786 Initialize reply information.
3788 XGetWidgetInfo(reply,&reply_info);
3789 reply_info.raised=MagickFalse;
3790 reply_info.bevel_width--;
3791 reply_info.width=windows->widget.width-(3*QuantumMargin);
3792 reply_info.height=height << 1;
3793 reply_info.x=(3*QuantumMargin) >> 1;
3794 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
3796 Initialize option information.
3798 XGetWidgetInfo("Dither",&special_info);
3799 special_info.raised=raised;
3800 special_info.bevel_width--;
3801 special_info.width=(unsigned int) QuantumMargin >> 1;
3802 special_info.height=(unsigned int) QuantumMargin >> 1;
3803 special_info.x=reply_info.x;
3804 special_info.y=action_info.y+action_info.height-special_info.height;
3805 if (LocaleCompare(action,"Background") == 0)
3806 special_info.text=(char *) "Backdrop";
3807 if (LocaleCompare(action,"New") == 0)
3808 special_info.text=(char *) "Gradation";
3809 if (LocaleCompare(action,"Resize") == 0)
3810 special_info.text=(char *) "Constrain ratio";
3811 if (LocaleCompare(action,"Save") == 0)
3812 special_info.text=(char *) "Non-progressive";
3813 if (LocaleCompare(action,"Shade") == 0)
3814 special_info.text=(char *) "Color shading";
3816 Initialize text information.
3818 XGetWidgetInfo(query,&text_info);
3819 text_info.width=reply_info.width;
3820 text_info.height=height;
3821 text_info.x=reply_info.x-(QuantumMargin >> 1);
3822 text_info.y=QuantumMargin;
3823 text_info.center=MagickFalse;
3824 state&=(~UpdateConfigurationState);
3826 if (state & RedrawWidgetState)
3829 Redraw Dialog widget.
3831 XDrawWidgetText(display,&windows->widget,&text_info);
3832 XDrawBeveledMatte(display,&windows->widget,&reply_info);
3833 XDrawMatteText(display,&windows->widget,&reply_info);
3835 XDrawBeveledButton(display,&windows->widget,&special_info);
3836 XDrawBeveledButton(display,&windows->widget,&action_info);
3837 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3838 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
3839 state&=(~RedrawWidgetState);
3842 Wait for next event.
3844 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
3850 if (MatteIsActive(special_info,event.xbutton))
3853 Option button status changed.
3855 special_info.raised=!special_info.raised;
3856 XDrawBeveledButton(display,&windows->widget,&special_info);
3859 if (MatteIsActive(action_info,event.xbutton))
3862 User pressed Action button.
3864 action_info.raised=MagickFalse;
3865 XDrawBeveledButton(display,&windows->widget,&action_info);
3868 if (MatteIsActive(cancel_info,event.xbutton))
3871 User pressed Cancel button.
3873 cancel_info.raised=MagickFalse;
3874 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3877 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
3879 if (event.xbutton.button != Button2)
3885 Move text cursor to position of button press.
3887 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
3888 for (i=1; i <= Extent(reply_info.marker); i++)
3889 if (XTextWidth(font_info,reply_info.marker,i) > x)
3891 reply_info.cursor=reply_info.marker+i-1;
3892 if (event.xbutton.time > (click_time+DoubleClick))
3893 reply_info.highlight=MagickFalse;
3897 Become the XA_PRIMARY selection owner.
3899 (void) CopyMagickString(primary_selection,reply_info.text,
3901 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
3902 event.xbutton.time);
3903 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
3904 windows->widget.id ? MagickTrue : MagickFalse;
3906 XDrawMatteText(display,&windows->widget,&reply_info);
3907 click_time=event.xbutton.time;
3911 Request primary selection.
3913 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
3914 windows->widget.id,event.xbutton.time);
3919 if (windows->widget.mapped == MagickFalse)
3921 if (action_info.raised == MagickFalse)
3923 if (event.xbutton.window == windows->widget.id)
3924 if (MatteIsActive(action_info,event.xbutton))
3926 action_info.raised=MagickTrue;
3927 XDrawBeveledButton(display,&windows->widget,&action_info);
3929 if (cancel_info.raised == MagickFalse)
3931 if (event.xbutton.window == windows->widget.id)
3932 if (MatteIsActive(cancel_info,event.xbutton))
3934 *reply_info.text='\0';
3937 cancel_info.raised=MagickTrue;
3938 XDrawBeveledButton(display,&windows->widget,&cancel_info);
3945 If client window delete message, exit.
3947 if (event.xclient.message_type != windows->wm_protocols)
3949 if (*event.xclient.data.l == (int) windows->wm_take_focus)
3951 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
3952 (Time) event.xclient.data.l[1]);
3955 if (*event.xclient.data.l != (int) windows->wm_delete_window)
3957 if (event.xclient.window == windows->widget.id)
3959 *reply_info.text='\0';
3965 case ConfigureNotify:
3968 Update widget configuration.
3970 if (event.xconfigure.window != windows->widget.id)
3972 if ((event.xconfigure.width == (int) windows->widget.width) &&
3973 (event.xconfigure.height == (int) windows->widget.height))
3975 windows->widget.width=(unsigned int)
3976 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
3977 windows->widget.height=(unsigned int)
3978 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
3979 state|=UpdateConfigurationState;
3984 if (event.xcrossing.window != windows->widget.id)
3986 state&=(~InactiveWidgetState);
3991 if (event.xexpose.window != windows->widget.id)
3993 if (event.xexpose.count != 0)
3995 state|=RedrawWidgetState;
4001 command[MaxTextExtent];
4010 Respond to a user key press.
4012 if (event.xkey.window != windows->widget.id)
4014 length=XLookupString((XKeyEvent *) &event.xkey,command,
4015 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4016 *(command+length)='\0';
4017 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
4019 action_info.raised=MagickFalse;
4020 XDrawBeveledButton(display,&windows->widget,&action_info);
4024 if (key_symbol == XK_Control_L)
4026 state|=ControlState;
4029 if (state & ControlState)
4030 switch ((int) key_symbol)
4036 Erase the entire line of text.
4038 *reply_info.text='\0';
4039 reply_info.cursor=reply_info.text;
4040 reply_info.marker=reply_info.text;
4041 reply_info.highlight=MagickFalse;
4047 XEditText(display,&reply_info,key_symbol,command,state);
4048 XDrawMatteText(display,&windows->widget,&reply_info);
4054 command[MaxTextExtent];
4060 Respond to a user key release.
4062 if (event.xkey.window != windows->widget.id)
4064 (void) XLookupString((XKeyEvent *) &event.xkey,command,
4065 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4066 if (key_symbol == XK_Control_L)
4067 state&=(~ControlState);
4072 if (event.xcrossing.window != windows->widget.id)
4074 state|=InactiveWidgetState;
4080 Discard pending button motion events.
4082 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
4083 if (state & InactiveWidgetState)
4085 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
4088 Action button status changed.
4090 action_info.raised=action_info.raised == MagickFalse ?
4091 MagickTrue : MagickFalse;
4092 XDrawBeveledButton(display,&windows->widget,&action_info);
4095 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
4098 Cancel button status changed.
4100 cancel_info.raised=cancel_info.raised == MagickFalse ?
4101 MagickTrue : MagickFalse;
4102 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4107 case SelectionClear:
4109 reply_info.highlight=MagickFalse;
4110 XDrawMatteText(display,&windows->widget,&reply_info);
4113 case SelectionNotify:
4129 Obtain response from primary selection.
4131 if (event.xselection.property == (Atom) None)
4133 status=XGetWindowProperty(display,event.xselection.requestor,
4134 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
4135 &format,&length,&after,&data);
4136 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
4139 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
4140 (void) XBell(display,0);
4144 Insert primary selection in reply text.
4146 *(data+length)='\0';
4147 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
4149 XDrawMatteText(display,&windows->widget,&reply_info);
4151 (void) XFree((void *) data);
4154 case SelectionRequest:
4159 XSelectionRequestEvent
4162 if (reply_info.highlight == MagickFalse)
4165 Set primary selection.
4167 request=(&(event.xselectionrequest));
4168 (void) XChangeProperty(request->display,request->requestor,
4169 request->property,request->target,8,PropModeReplace,
4170 (unsigned char *) primary_selection,Extent(primary_selection));
4171 notify.type=SelectionNotify;
4172 notify.display=request->display;
4173 notify.requestor=request->requestor;
4174 notify.selection=request->selection;
4175 notify.target=request->target;
4176 notify.time=request->time;
4177 if (request->property == None)
4178 notify.property=request->target;
4180 notify.property=request->property;
4181 (void) XSendEvent(request->display,request->requestor,False,0,
4182 (XEvent *) ¬ify);
4187 } while ((state & ExitState) == 0);
4188 XSetCursorState(display,windows,MagickFalse);
4189 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
4190 XCheckRefreshWindows(display,windows);
4192 if (special_info.raised)
4195 return(raised == MagickFalse);
4199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4203 % X F i l e B r o w s e r W i d g e t %
4207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4209 % XFileBrowserWidget() displays a File Browser widget with a file query to the
4210 % user. The user keys a reply and presses the Action or Cancel button to
4211 % exit. The typed text is returned as the reply function parameter.
4213 % The format of the XFileBrowserWidget method is:
4215 % void XFileBrowserWidget(Display *display,XWindows *windows,
4216 % const char *action,char *reply)
4218 % A description of each parameter follows:
4220 % o display: Specifies a connection to an X server; returned from
4223 % o window: Specifies a pointer to a XWindows structure.
4225 % o action: Specifies a pointer to the action of this widget.
4227 % o reply: the response from the user is returned in this parameter.
4230 MagickPrivate void XFileBrowserWidget(Display *display,XWindows *windows,
4231 const char *action,char *reply)
4233 #define CancelButtonText "Cancel"
4234 #define DirectoryText "Directory:"
4235 #define FilenameText "File name:"
4236 #define GrabButtonText "Grab"
4237 #define FormatButtonText "Format"
4238 #define HomeButtonText "Home"
4239 #define UpButtonText "Up"
4244 home_directory[MaxTextExtent],
4245 primary_selection[MaxTextExtent],
4246 text[MaxTextExtent],
4247 working_path[MaxTextExtent];
4257 glob_pattern[MaxTextExtent] = "*",
4258 format[MaxTextExtent] = "miff";
4260 static MagickStatusType
4261 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
4307 Read filelist from current directory.
4309 assert(display != (Display *) NULL);
4310 assert(windows != (XWindows *) NULL);
4311 assert(action != (char *) NULL);
4312 assert(reply != (char *) NULL);
4313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
4314 XSetCursorState(display,windows,MagickTrue);
4315 XCheckRefreshWindows(display,windows);
4316 directory=getcwd(home_directory,MaxTextExtent);
4318 (void) CopyMagickString(working_path,home_directory,MaxTextExtent);
4319 filelist=ListFiles(working_path,glob_pattern,&files);
4320 if (filelist == (char **) NULL)
4323 Directory read failed.
4325 XNoticeWidget(display,windows,"Unable to read directory:",working_path);
4326 (void) XDialogWidget(display,windows,action,"Enter filename:",reply);
4330 Determine File Browser widget attributes.
4332 font_info=windows->widget.font_info;
4334 for (i=0; i < (ssize_t) files; i++)
4335 if (WidgetTextWidth(font_info,filelist[i]) > text_width)
4336 text_width=WidgetTextWidth(font_info,filelist[i]);
4337 width=WidgetTextWidth(font_info,(char *) action);
4338 if (WidgetTextWidth(font_info,GrabButtonText) > width)
4339 width=WidgetTextWidth(font_info,GrabButtonText);
4340 if (WidgetTextWidth(font_info,FormatButtonText) > width)
4341 width=WidgetTextWidth(font_info,FormatButtonText);
4342 if (WidgetTextWidth(font_info,CancelButtonText) > width)
4343 width=WidgetTextWidth(font_info,CancelButtonText);
4344 if (WidgetTextWidth(font_info,HomeButtonText) > width)
4345 width=WidgetTextWidth(font_info,HomeButtonText);
4346 if (WidgetTextWidth(font_info,UpButtonText) > width)
4347 width=WidgetTextWidth(font_info,UpButtonText);
4348 width+=QuantumMargin;
4349 if (WidgetTextWidth(font_info,DirectoryText) > width)
4350 width=WidgetTextWidth(font_info,DirectoryText);
4351 if (WidgetTextWidth(font_info,FilenameText) > width)
4352 width=WidgetTextWidth(font_info,FilenameText);
4353 height=(unsigned int) (font_info->ascent+font_info->descent);
4355 Position File Browser widget.
4357 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
4359 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
4360 if (windows->widget.width < windows->widget.min_width)
4361 windows->widget.width=windows->widget.min_width;
4362 windows->widget.height=(unsigned int)
4363 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
4364 windows->widget.min_height=(unsigned int)
4365 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
4366 if (windows->widget.height < windows->widget.min_height)
4367 windows->widget.height=windows->widget.min_height;
4368 XConstrainWindowPosition(display,&windows->widget);
4370 Map File Browser widget.
4372 (void) CopyMagickString(windows->widget.name,"Browse and Select a File",
4374 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
4375 if (status != False)
4377 XSetWMName(display,windows->widget.id,&window_name);
4378 XSetWMIconName(display,windows->widget.id,&window_name);
4379 (void) XFree((void *) window_name.value);
4381 window_changes.width=(int) windows->widget.width;
4382 window_changes.height=(int) windows->widget.height;
4383 window_changes.x=windows->widget.x;
4384 window_changes.y=windows->widget.y;
4385 (void) XReconfigureWMWindow(display,windows->widget.id,
4386 windows->widget.screen,mask,&window_changes);
4387 (void) XMapRaised(display,windows->widget.id);
4388 windows->widget.mapped=MagickFalse;
4390 Respond to X events.
4392 XGetWidgetInfo((char *) NULL,&slider_info);
4393 XGetWidgetInfo((char *) NULL,&north_info);
4394 XGetWidgetInfo((char *) NULL,&south_info);
4395 XGetWidgetInfo((char *) NULL,&expose_info);
4397 anomaly=(LocaleCompare(action,"Composite") == 0) ||
4398 (LocaleCompare(action,"Open") == 0) || (LocaleCompare(action,"Map") == 0);
4400 delay=SuspendTime << 2;
4401 state=UpdateConfigurationState;
4404 if (state & UpdateConfigurationState)
4410 Initialize button information.
4412 XGetWidgetInfo(CancelButtonText,&cancel_info);
4413 cancel_info.width=width;
4414 cancel_info.height=(unsigned int) ((3*height) >> 1);
4416 (windows->widget.width-cancel_info.width-QuantumMargin-2);
4418 (windows->widget.height-cancel_info.height-QuantumMargin);
4419 XGetWidgetInfo(action,&action_info);
4420 action_info.width=width;
4421 action_info.height=(unsigned int) ((3*height) >> 1);
4422 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
4423 (action_info.bevel_width << 1));
4424 action_info.y=cancel_info.y;
4425 XGetWidgetInfo(GrabButtonText,&special_info);
4426 special_info.width=width;
4427 special_info.height=(unsigned int) ((3*height) >> 1);
4428 special_info.x=action_info.x-(action_info.width+(QuantumMargin >> 1)+
4429 (special_info.bevel_width << 1));
4430 special_info.y=action_info.y;
4431 if (anomaly == MagickFalse)
4436 special_info.text=(char *) FormatButtonText;
4437 p=reply+Extent(reply)-1;
4438 while ((p > (reply+1)) && (*(p-1) != '.'))
4440 if ((p > (reply+1)) && (*(p-1) == '.'))
4441 (void) CopyMagickString(format,p,MaxTextExtent);
4443 XGetWidgetInfo(UpButtonText,&up_info);
4444 up_info.width=width;
4445 up_info.height=(unsigned int) ((3*height) >> 1);
4446 up_info.x=QuantumMargin;
4447 up_info.y=((5*QuantumMargin) >> 1)+height;
4448 XGetWidgetInfo(HomeButtonText,&home_info);
4449 home_info.width=width;
4450 home_info.height=(unsigned int) ((3*height) >> 1);
4451 home_info.x=QuantumMargin;
4452 home_info.y=up_info.y+up_info.height+QuantumMargin;
4454 Initialize reply information.
4456 XGetWidgetInfo(reply,&reply_info);
4457 reply_info.raised=MagickFalse;
4458 reply_info.bevel_width--;
4459 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
4460 reply_info.height=height << 1;
4461 reply_info.x=(int) (width+(QuantumMargin << 1));
4462 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
4464 Initialize scroll information.
4466 XGetWidgetInfo((char *) NULL,&scroll_info);
4467 scroll_info.bevel_width--;
4468 scroll_info.width=height;
4469 scroll_info.height=(unsigned int)
4470 (reply_info.y-up_info.y-(QuantumMargin >> 1));
4471 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
4472 scroll_info.y=up_info.y-reply_info.bevel_width;
4473 scroll_info.raised=MagickFalse;
4474 scroll_info.trough=MagickTrue;
4475 north_info=scroll_info;
4476 north_info.raised=MagickTrue;
4477 north_info.width-=(north_info.bevel_width << 1);
4478 north_info.height=north_info.width-1;
4479 north_info.x+=north_info.bevel_width;
4480 north_info.y+=north_info.bevel_width;
4481 south_info=north_info;
4482 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
4485 slider_info=north_info;
4487 slider_info.width-=2;
4488 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
4489 slider_info.bevel_width+2;
4490 slider_info.height=scroll_info.height-((slider_info.min_y-
4491 scroll_info.y+1) << 1)+4;
4492 visible_files=scroll_info.height/(height+(height >> 3));
4493 if (files > visible_files)
4494 slider_info.height=(unsigned int)
4495 ((visible_files*slider_info.height)/files);
4496 slider_info.max_y=south_info.y-south_info.bevel_width-
4497 slider_info.bevel_width-2;
4498 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
4499 slider_info.y=slider_info.min_y;
4500 expose_info=scroll_info;
4501 expose_info.y=slider_info.y;
4503 Initialize list information.
4505 XGetWidgetInfo((char *) NULL,&list_info);
4506 list_info.raised=MagickFalse;
4507 list_info.bevel_width--;
4508 list_info.width=(unsigned int)
4509 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
4510 list_info.height=scroll_info.height;
4511 list_info.x=reply_info.x;
4512 list_info.y=scroll_info.y;
4513 if (windows->widget.mapped == MagickFalse)
4514 state|=JumpListState;
4516 Initialize text information.
4519 XGetWidgetInfo(text,&text_info);
4520 text_info.center=MagickFalse;
4521 text_info.width=reply_info.width;
4522 text_info.height=height;
4523 text_info.x=list_info.x-(QuantumMargin >> 1);
4524 text_info.y=QuantumMargin;
4526 Initialize selection information.
4528 XGetWidgetInfo((char *) NULL,&selection_info);
4529 selection_info.center=MagickFalse;
4530 selection_info.width=list_info.width;
4531 selection_info.height=(unsigned int) ((9*height) >> 3);
4532 selection_info.x=list_info.x;
4533 state&=(~UpdateConfigurationState);
4535 if (state & RedrawWidgetState)
4538 Redraw File Browser window.
4541 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
4542 (void) XDrawString(display,windows->widget.id,
4543 windows->widget.annotate_context,x,y,DirectoryText,
4544 Extent(DirectoryText));
4545 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4546 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4548 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4550 XDrawWidgetText(display,&windows->widget,&text_info);
4551 XDrawBeveledButton(display,&windows->widget,&up_info);
4552 XDrawBeveledButton(display,&windows->widget,&home_info);
4553 XDrawBeveledMatte(display,&windows->widget,&list_info);
4554 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4555 XDrawTriangleNorth(display,&windows->widget,&north_info);
4556 XDrawBeveledButton(display,&windows->widget,&slider_info);
4557 XDrawTriangleSouth(display,&windows->widget,&south_info);
4559 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
4560 (void) XDrawString(display,windows->widget.id,
4561 windows->widget.annotate_context,x,y,FilenameText,
4562 Extent(FilenameText));
4563 XDrawBeveledMatte(display,&windows->widget,&reply_info);
4564 XDrawMatteText(display,&windows->widget,&reply_info);
4565 XDrawBeveledButton(display,&windows->widget,&special_info);
4566 XDrawBeveledButton(display,&windows->widget,&action_info);
4567 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4568 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4569 selection_info.id=(~0);
4570 state|=RedrawListState;
4571 state&=(~RedrawWidgetState);
4573 if (state & UpdateListState)
4584 checklist=ListFiles(working_path,glob_pattern,&number_files);
4585 if (checklist == (char **) NULL)
4588 Reply is a filename, exit.
4590 action_info.raised=MagickFalse;
4591 XDrawBeveledButton(display,&windows->widget,&action_info);
4594 for (i=0; i < (ssize_t) files; i++)
4595 filelist[i]=DestroyString(filelist[i]);
4596 if (filelist != (char **) NULL)
4597 filelist=(char **) RelinquishMagickMemory(filelist);
4604 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
4605 if (files > visible_files)
4606 slider_info.height=(unsigned int)
4607 ((visible_files*slider_info.height)/files);
4608 slider_info.max_y=south_info.y-south_info.bevel_width-
4609 slider_info.bevel_width-2;
4611 slider_info.y=slider_info.min_y;
4612 expose_info.y=slider_info.y;
4613 selection_info.id=(~0);
4615 state|=RedrawListState;
4617 Redraw directory name & reply.
4619 if (IsGlob(reply_info.text) == MagickFalse)
4621 *reply_info.text='\0';
4622 reply_info.cursor=reply_info.text;
4624 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent);
4625 (void) ConcatenateMagickString(text_info.text,DirectorySeparator,
4627 (void) ConcatenateMagickString(text_info.text,glob_pattern,
4629 XDrawWidgetText(display,&windows->widget,&text_info);
4630 XDrawMatteText(display,&windows->widget,&reply_info);
4631 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
4632 XDrawTriangleNorth(display,&windows->widget,&north_info);
4633 XDrawBeveledButton(display,&windows->widget,&slider_info);
4634 XDrawTriangleSouth(display,&windows->widget,&south_info);
4635 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
4636 state&=(~UpdateListState);
4638 if (state & JumpListState)
4641 Jump scroll to match user filename.
4644 for (i=0; i < (ssize_t) files; i++)
4645 if (LocaleCompare(filelist[i],reply) >= 0)
4648 (LocaleCompare(filelist[i],reply) == 0 ? i : ~0);
4651 if ((i < (ssize_t) slider_info.id) ||
4652 (i >= (ssize_t) (slider_info.id+visible_files)))
4653 slider_info.id=(int) i-(visible_files >> 1);
4654 selection_info.id=(~0);
4655 state|=RedrawListState;
4656 state&=(~JumpListState);
4658 if (state & RedrawListState)
4661 Determine slider id and position.
4663 if (slider_info.id >= (int) (files-visible_files))
4664 slider_info.id=(int) (files-visible_files);
4665 if ((slider_info.id < 0) || (files <= visible_files))
4667 slider_info.y=slider_info.min_y;
4669 slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
4670 slider_info.min_y+1)/files);
4671 if (slider_info.id != selection_info.id)
4674 Redraw scroll bar and file names.
4676 selection_info.id=slider_info.id;
4677 selection_info.y=list_info.y+(height >> 3)+2;
4678 for (i=0; i < (ssize_t) visible_files; i++)
4680 selection_info.raised=(int) (slider_info.id+i) != list_info.id ?
4681 MagickTrue : MagickFalse;
4682 selection_info.text=(char *) NULL;
4683 if ((slider_info.id+i) < (ssize_t) files)
4684 selection_info.text=filelist[slider_info.id+i];
4685 XDrawWidgetText(display,&windows->widget,&selection_info);
4686 selection_info.y+=(int) selection_info.height;
4691 if (slider_info.y > expose_info.y)
4693 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
4694 expose_info.y=slider_info.y-expose_info.height-
4695 slider_info.bevel_width-1;
4699 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
4700 expose_info.y=slider_info.y+slider_info.height+
4701 slider_info.bevel_width+1;
4703 XDrawTriangleNorth(display,&windows->widget,&north_info);
4704 XDrawMatte(display,&windows->widget,&expose_info);
4705 XDrawBeveledButton(display,&windows->widget,&slider_info);
4706 XDrawTriangleSouth(display,&windows->widget,&south_info);
4707 expose_info.y=slider_info.y;
4709 state&=(~RedrawListState);
4712 Wait for next event.
4714 if (north_info.raised && south_info.raised)
4715 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
4719 Brief delay before advancing scroll bar.
4721 XDelay(display,delay);
4723 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
4724 if (north_info.raised == MagickFalse)
4725 if (slider_info.id > 0)
4731 state|=RedrawListState;
4733 if (south_info.raised == MagickFalse)
4734 if (slider_info.id < (int) files)
4740 state|=RedrawListState;
4742 if (event.type != ButtonRelease)
4749 if (MatteIsActive(slider_info,event.xbutton))
4754 slider_info.active=MagickTrue;
4757 if (MatteIsActive(north_info,event.xbutton))
4758 if (slider_info.id > 0)
4763 north_info.raised=MagickFalse;
4765 state|=RedrawListState;
4768 if (MatteIsActive(south_info,event.xbutton))
4769 if (slider_info.id < (int) files)
4774 south_info.raised=MagickFalse;
4776 state|=RedrawListState;
4779 if (MatteIsActive(scroll_info,event.xbutton))
4784 if (event.xbutton.y < slider_info.y)
4785 slider_info.id-=(visible_files-1);
4787 slider_info.id+=(visible_files-1);
4788 state|=RedrawListState;
4791 if (MatteIsActive(list_info,event.xbutton))
4797 User pressed file matte.
4799 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
4800 selection_info.height;
4801 if (id >= (int) files)
4803 (void) CopyMagickString(reply_info.text,filelist[id],MaxTextExtent);
4804 reply_info.highlight=MagickFalse;
4805 reply_info.marker=reply_info.text;
4806 reply_info.cursor=reply_info.text+Extent(reply_info.text);
4807 XDrawMatteText(display,&windows->widget,&reply_info);
4808 if (id == list_info.id)
4813 p=reply_info.text+strlen(reply_info.text)-1;
4814 if (*p == *DirectorySeparator)
4815 ChopPathComponents(reply_info.text,1);
4816 (void) ConcatenateMagickString(working_path,DirectorySeparator,
4818 (void) ConcatenateMagickString(working_path,reply_info.text,
4821 state|=UpdateListState;
4823 selection_info.id=(~0);
4825 state|=RedrawListState;
4828 if (MatteIsActive(up_info,event.xbutton))
4831 User pressed Up button.
4833 up_info.raised=MagickFalse;
4834 XDrawBeveledButton(display,&windows->widget,&up_info);
4837 if (MatteIsActive(home_info,event.xbutton))
4840 User pressed Home button.
4842 home_info.raised=MagickFalse;
4843 XDrawBeveledButton(display,&windows->widget,&home_info);
4846 if (MatteIsActive(special_info,event.xbutton))
4849 User pressed Special button.
4851 special_info.raised=MagickFalse;
4852 XDrawBeveledButton(display,&windows->widget,&special_info);
4855 if (MatteIsActive(action_info,event.xbutton))
4858 User pressed action button.
4860 action_info.raised=MagickFalse;
4861 XDrawBeveledButton(display,&windows->widget,&action_info);
4864 if (MatteIsActive(cancel_info,event.xbutton))
4867 User pressed Cancel button.
4869 cancel_info.raised=MagickFalse;
4870 XDrawBeveledButton(display,&windows->widget,&cancel_info);
4873 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
4875 if (event.xbutton.button != Button2)
4881 Move text cursor to position of button press.
4883 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
4884 for (i=1; i <= (ssize_t) Extent(reply_info.marker); i++)
4885 if (XTextWidth(font_info,reply_info.marker,(int) i) > x)
4887 reply_info.cursor=reply_info.marker+i-1;
4888 if (event.xbutton.time > (click_time+DoubleClick))
4889 reply_info.highlight=MagickFalse;
4893 Become the XA_PRIMARY selection owner.
4895 (void) CopyMagickString(primary_selection,reply_info.text,
4897 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
4898 event.xbutton.time);
4899 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
4900 windows->widget.id ? MagickTrue : MagickFalse;
4902 XDrawMatteText(display,&windows->widget,&reply_info);
4903 click_time=event.xbutton.time;
4907 Request primary selection.
4909 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
4910 windows->widget.id,event.xbutton.time);
4915 if (windows->widget.mapped == MagickFalse)
4917 if (north_info.raised == MagickFalse)
4920 User released up button.
4922 delay=SuspendTime << 2;
4923 north_info.raised=MagickTrue;
4924 XDrawTriangleNorth(display,&windows->widget,&north_info);
4926 if (south_info.raised == MagickFalse)
4929 User released down button.
4931 delay=SuspendTime << 2;
4932 south_info.raised=MagickTrue;
4933 XDrawTriangleSouth(display,&windows->widget,&south_info);
4935 if (slider_info.active)
4938 Stop tracking slider.
4940 slider_info.active=MagickFalse;
4943 if (up_info.raised == MagickFalse)
4945 if (event.xbutton.window == windows->widget.id)
4946 if (MatteIsActive(up_info,event.xbutton))
4948 ChopPathComponents(working_path,1);
4949 if (*working_path == '\0')
4950 (void) CopyMagickString(working_path,DirectorySeparator,
4952 state|=UpdateListState;
4954 up_info.raised=MagickTrue;
4955 XDrawBeveledButton(display,&windows->widget,&up_info);
4957 if (home_info.raised == MagickFalse)
4959 if (event.xbutton.window == windows->widget.id)
4960 if (MatteIsActive(home_info,event.xbutton))
4962 (void) CopyMagickString(working_path,home_directory,
4964 state|=UpdateListState;
4966 home_info.raised=MagickTrue;
4967 XDrawBeveledButton(display,&windows->widget,&home_info);
4969 if (special_info.raised == MagickFalse)
4971 if (anomaly == MagickFalse)
4983 Let user select image format.
4985 exception=AcquireExceptionInfo();
4986 formats=GetMagickList("*",&number_formats,exception);
4987 exception=DestroyExceptionInfo(exception);
4988 (void) XCheckDefineCursor(display,windows->widget.id,
4989 windows->widget.busy_cursor);
4990 windows->popup.x=windows->widget.x+60;
4991 windows->popup.y=windows->widget.y+60;
4992 XListBrowserWidget(display,windows,&windows->popup,
4993 (const char **) formats,"Select","Select image format type:",
4995 XSetCursorState(display,windows,MagickTrue);
4996 (void) XCheckDefineCursor(display,windows->widget.id,
4997 windows->widget.cursor);
4998 LocaleLower(format);
4999 AppendImageFormat(format,reply_info.text);
5000 reply_info.cursor=reply_info.text+Extent(reply_info.text);
5001 XDrawMatteText(display,&windows->widget,&reply_info);
5002 special_info.raised=MagickTrue;
5003 XDrawBeveledButton(display,&windows->widget,&special_info);
5004 for (i=0; i < (ssize_t) number_formats; i++)
5005 formats[i]=DestroyString(formats[i]);
5006 formats=(char **) RelinquishMagickMemory(formats);
5009 if (event.xbutton.window == windows->widget.id)
5010 if (MatteIsActive(special_info,event.xbutton))
5012 (void) CopyMagickString(working_path,"x:",MaxTextExtent);
5015 special_info.raised=MagickTrue;
5016 XDrawBeveledButton(display,&windows->widget,&special_info);
5018 if (action_info.raised == MagickFalse)
5020 if (event.xbutton.window == windows->widget.id)
5022 if (MatteIsActive(action_info,event.xbutton))
5024 if (*reply_info.text == '\0')
5025 (void) XBell(display,0);
5030 action_info.raised=MagickTrue;
5031 XDrawBeveledButton(display,&windows->widget,&action_info);
5033 if (cancel_info.raised == MagickFalse)
5035 if (event.xbutton.window == windows->widget.id)
5036 if (MatteIsActive(cancel_info,event.xbutton))
5038 *reply_info.text='\0';
5042 cancel_info.raised=MagickTrue;
5043 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5050 If client window delete message, exit.
5052 if (event.xclient.message_type != windows->wm_protocols)
5054 if (*event.xclient.data.l == (int) windows->wm_take_focus)
5056 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
5057 (Time) event.xclient.data.l[1]);
5060 if (*event.xclient.data.l != (int) windows->wm_delete_window)
5062 if (event.xclient.window == windows->widget.id)
5064 *reply_info.text='\0';
5070 case ConfigureNotify:
5073 Update widget configuration.
5075 if (event.xconfigure.window != windows->widget.id)
5077 if ((event.xconfigure.width == (int) windows->widget.width) &&
5078 (event.xconfigure.height == (int) windows->widget.height))
5080 windows->widget.width=(unsigned int)
5081 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
5082 windows->widget.height=(unsigned int)
5083 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
5084 state|=UpdateConfigurationState;
5089 if (event.xcrossing.window != windows->widget.id)
5091 state&=(~InactiveWidgetState);
5096 if (event.xexpose.window != windows->widget.id)
5098 if (event.xexpose.count != 0)
5100 state|=RedrawWidgetState;
5106 command[MaxTextExtent];
5115 Respond to a user key press.
5117 if (event.xkey.window != windows->widget.id)
5119 length=XLookupString((XKeyEvent *) &event.xkey,command,
5120 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5121 *(command+length)='\0';
5122 if (AreaIsActive(scroll_info,event.xkey))
5127 switch ((int) key_symbol)
5150 slider_info.id-=visible_files;
5156 slider_info.id+=visible_files;
5162 slider_info.id=(int) files;
5166 state|=RedrawListState;
5169 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
5172 Read new directory or glob patterm.
5174 if (*reply_info.text == '\0')
5176 if (IsGlob(reply_info.text))
5177 (void) CopyMagickString(glob_pattern,reply_info.text,
5181 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5183 (void) ConcatenateMagickString(working_path,reply_info.text,
5185 if (*working_path == '~')
5186 ExpandFilename(working_path);
5189 state|=UpdateListState;
5192 if (key_symbol == XK_Control_L)
5194 state|=ControlState;
5197 if (state & ControlState)
5198 switch ((int) key_symbol)
5204 Erase the entire line of text.
5206 *reply_info.text='\0';
5207 reply_info.cursor=reply_info.text;
5208 reply_info.marker=reply_info.text;
5209 reply_info.highlight=MagickFalse;
5215 XEditText(display,&reply_info,key_symbol,command,state);
5216 XDrawMatteText(display,&windows->widget,&reply_info);
5217 state|=JumpListState;
5223 command[MaxTextExtent];
5229 Respond to a user key release.
5231 if (event.xkey.window != windows->widget.id)
5233 (void) XLookupString((XKeyEvent *) &event.xkey,command,
5234 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5235 if (key_symbol == XK_Control_L)
5236 state&=(~ControlState);
5241 if (event.xcrossing.window != windows->widget.id)
5243 state|=InactiveWidgetState;
5255 Discard pending button motion events.
5257 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
5258 if (slider_info.active)
5263 slider_info.y=event.xmotion.y-
5264 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
5265 if (slider_info.y < slider_info.min_y)
5266 slider_info.y=slider_info.min_y;
5267 if (slider_info.y > slider_info.max_y)
5268 slider_info.y=slider_info.max_y;
5270 if (slider_info.y != slider_info.min_y)
5271 slider_info.id=(int) ((files*(slider_info.y-slider_info.min_y+1))/
5272 (slider_info.max_y-slider_info.min_y+1));
5273 state|=RedrawListState;
5276 if (state & InactiveWidgetState)
5278 if (up_info.raised == MatteIsActive(up_info,event.xmotion))
5281 Up button status changed.
5283 up_info.raised=!up_info.raised;
5284 XDrawBeveledButton(display,&windows->widget,&up_info);
5287 if (home_info.raised == MatteIsActive(home_info,event.xmotion))
5290 Home button status changed.
5292 home_info.raised=!home_info.raised;
5293 XDrawBeveledButton(display,&windows->widget,&home_info);
5296 if (special_info.raised == MatteIsActive(special_info,event.xmotion))
5299 Grab button status changed.
5301 special_info.raised=!special_info.raised;
5302 XDrawBeveledButton(display,&windows->widget,&special_info);
5305 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
5308 Action button status changed.
5310 action_info.raised=action_info.raised == MagickFalse ?
5311 MagickTrue : MagickFalse;
5312 XDrawBeveledButton(display,&windows->widget,&action_info);
5315 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
5318 Cancel button status changed.
5320 cancel_info.raised=cancel_info.raised == MagickFalse ?
5321 MagickTrue : MagickFalse;
5322 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5327 case SelectionClear:
5329 reply_info.highlight=MagickFalse;
5330 XDrawMatteText(display,&windows->widget,&reply_info);
5333 case SelectionNotify:
5349 Obtain response from primary selection.
5351 if (event.xselection.property == (Atom) None)
5353 status=XGetWindowProperty(display,event.xselection.requestor,
5354 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
5355 &format,&length,&after,&data);
5356 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
5359 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
5360 (void) XBell(display,0);
5364 Insert primary selection in reply text.
5366 *(data+length)='\0';
5367 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
5369 XDrawMatteText(display,&windows->widget,&reply_info);
5370 state|=JumpListState;
5371 state|=RedrawActionState;
5373 (void) XFree((void *) data);
5376 case SelectionRequest:
5381 XSelectionRequestEvent
5384 if (reply_info.highlight == MagickFalse)
5387 Set primary selection.
5389 request=(&(event.xselectionrequest));
5390 (void) XChangeProperty(request->display,request->requestor,
5391 request->property,request->target,8,PropModeReplace,
5392 (unsigned char *) primary_selection,Extent(primary_selection));
5393 notify.type=SelectionNotify;
5394 notify.display=request->display;
5395 notify.requestor=request->requestor;
5396 notify.selection=request->selection;
5397 notify.target=request->target;
5398 notify.time=request->time;
5399 if (request->property == None)
5400 notify.property=request->target;
5402 notify.property=request->property;
5403 (void) XSendEvent(request->display,request->requestor,False,0,
5404 (XEvent *) ¬ify);
5409 } while ((state & ExitState) == 0);
5410 XSetCursorState(display,windows,MagickFalse);
5411 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
5412 XCheckRefreshWindows(display,windows);
5416 for (i=0; i < (ssize_t) files; i++)
5417 filelist[i]=DestroyString(filelist[i]);
5418 if (filelist != (char **) NULL)
5419 filelist=(char **) RelinquishMagickMemory(filelist);
5422 (void) ConcatenateMagickString(working_path,DirectorySeparator,
5424 (void) ConcatenateMagickString(working_path,reply,MaxTextExtent);
5426 (void) CopyMagickString(reply,working_path,MaxTextExtent);
5428 ExpandFilename(reply);
5432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5436 % X F o n t B r o w s e r W i d g e t %
5440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5442 % XFontBrowserWidget() displays a Font Browser widget with a font query to the
5443 % user. The user keys a reply and presses the Action or Cancel button to
5444 % exit. The typed text is returned as the reply function parameter.
5446 % The format of the XFontBrowserWidget method is:
5448 % void XFontBrowserWidget(Display *display,XWindows *windows,
5449 % const char *action,char *reply)
5451 % A description of each parameter follows:
5453 % o display: Specifies a connection to an X server; returned from
5456 % o window: Specifies a pointer to a XWindows structure.
5458 % o action: Specifies a pointer to the action of this widget.
5460 % o reply: the response from the user is returned in this parameter.
5465 #if defined(__cplusplus) || defined(c_plusplus)
5469 static int FontCompare(const void *x,const void *y)
5475 p=(char *) *((char **) x);
5476 q=(char *) *((char **) y);
5477 while ((*p != '\0') && (*q != '\0') && (*p == *q))
5485 #if defined(__cplusplus) || defined(c_plusplus)
5489 MagickPrivate void XFontBrowserWidget(Display *display,XWindows *windows,
5490 const char *action,char *reply)
5492 #define BackButtonText "Back"
5493 #define CancelButtonText "Cancel"
5494 #define FontnameText "Name:"
5495 #define FontPatternText "Pattern:"
5496 #define ResetButtonText "Reset"
5499 back_pattern[MaxTextExtent],
5502 primary_selection[MaxTextExtent],
5503 reset_pattern[MaxTextExtent],
5504 text[MaxTextExtent];
5515 glob_pattern[MaxTextExtent] = "*";
5517 static MagickStatusType
5518 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
5562 Get font list and sort in ascending order.
5564 assert(display != (Display *) NULL);
5565 assert(windows != (XWindows *) NULL);
5566 assert(action != (char *) NULL);
5567 assert(reply != (char *) NULL);
5568 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
5569 XSetCursorState(display,windows,MagickTrue);
5570 XCheckRefreshWindows(display,windows);
5571 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
5572 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
5573 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5577 Pattern failed, obtain all the fonts.
5579 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5581 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
5582 fontlist=XListFonts(display,glob_pattern,32767,&fonts);
5583 if (fontlist == (char **) NULL)
5585 XNoticeWidget(display,windows,"Unable to obtain fonts names:",
5591 Sort font list in ascending order.
5594 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,sizeof(*fontlist));
5595 if (fontlist == (char **) NULL)
5597 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5598 "UnableToViewFonts");
5601 for (i=0; i < fonts; i++)
5602 fontlist[i]=listhead[i];
5603 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5605 Determine Font Browser widget attributes.
5607 font_info=windows->widget.font_info;
5609 for (i=0; i < fonts; i++)
5610 if (WidgetTextWidth(font_info,fontlist[i]) > text_width)
5611 text_width=WidgetTextWidth(font_info,fontlist[i]);
5612 width=WidgetTextWidth(font_info,(char *) action);
5613 if (WidgetTextWidth(font_info,CancelButtonText) > width)
5614 width=WidgetTextWidth(font_info,CancelButtonText);
5615 if (WidgetTextWidth(font_info,ResetButtonText) > width)
5616 width=WidgetTextWidth(font_info,ResetButtonText);
5617 if (WidgetTextWidth(font_info,BackButtonText) > width)
5618 width=WidgetTextWidth(font_info,BackButtonText);
5619 width+=QuantumMargin;
5620 if (WidgetTextWidth(font_info,FontPatternText) > width)
5621 width=WidgetTextWidth(font_info,FontPatternText);
5622 if (WidgetTextWidth(font_info,FontnameText) > width)
5623 width=WidgetTextWidth(font_info,FontnameText);
5624 height=(unsigned int) (font_info->ascent+font_info->descent);
5626 Position Font Browser widget.
5628 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+
5630 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin;
5631 if (windows->widget.width < windows->widget.min_width)
5632 windows->widget.width=windows->widget.min_width;
5633 windows->widget.height=(unsigned int)
5634 (((85*height) >> 2)+((13*QuantumMargin) >> 1)+4);
5635 windows->widget.min_height=(unsigned int)
5636 (((27*height) >> 1)+((13*QuantumMargin) >> 1)+4);
5637 if (windows->widget.height < windows->widget.min_height)
5638 windows->widget.height=windows->widget.min_height;
5639 XConstrainWindowPosition(display,&windows->widget);
5641 Map Font Browser widget.
5643 (void) CopyMagickString(windows->widget.name,"Browse and Select a Font",
5645 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
5646 if (status != False)
5648 XSetWMName(display,windows->widget.id,&window_name);
5649 XSetWMIconName(display,windows->widget.id,&window_name);
5650 (void) XFree((void *) window_name.value);
5652 window_changes.width=(int) windows->widget.width;
5653 window_changes.height=(int) windows->widget.height;
5654 window_changes.x=windows->widget.x;
5655 window_changes.y=windows->widget.y;
5656 (void) XReconfigureWMWindow(display,windows->widget.id,
5657 windows->widget.screen,mask,&window_changes);
5658 (void) XMapRaised(display,windows->widget.id);
5659 windows->widget.mapped=MagickFalse;
5661 Respond to X events.
5663 XGetWidgetInfo((char *) NULL,&slider_info);
5664 XGetWidgetInfo((char *) NULL,&north_info);
5665 XGetWidgetInfo((char *) NULL,&south_info);
5666 XGetWidgetInfo((char *) NULL,&expose_info);
5668 delay=SuspendTime << 2;
5669 state=UpdateConfigurationState;
5672 if (state & UpdateConfigurationState)
5678 Initialize button information.
5680 XGetWidgetInfo(CancelButtonText,&cancel_info);
5681 cancel_info.width=width;
5682 cancel_info.height=(unsigned int) ((3*height) >> 1);
5684 (windows->widget.width-cancel_info.width-QuantumMargin-2);
5686 (windows->widget.height-cancel_info.height-QuantumMargin);
5687 XGetWidgetInfo(action,&action_info);
5688 action_info.width=width;
5689 action_info.height=(unsigned int) ((3*height) >> 1);
5690 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
5691 (action_info.bevel_width << 1));
5692 action_info.y=cancel_info.y;
5693 XGetWidgetInfo(BackButtonText,&back_info);
5694 back_info.width=width;
5695 back_info.height=(unsigned int) ((3*height) >> 1);
5696 back_info.x=QuantumMargin;
5697 back_info.y=((5*QuantumMargin) >> 1)+height;
5698 XGetWidgetInfo(ResetButtonText,&reset_info);
5699 reset_info.width=width;
5700 reset_info.height=(unsigned int) ((3*height) >> 1);
5701 reset_info.x=QuantumMargin;
5702 reset_info.y=back_info.y+back_info.height+QuantumMargin;
5704 Initialize reply information.
5706 XGetWidgetInfo(reply,&reply_info);
5707 reply_info.raised=MagickFalse;
5708 reply_info.bevel_width--;
5709 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
5710 reply_info.height=height << 1;
5711 reply_info.x=(int) (width+(QuantumMargin << 1));
5712 reply_info.y=action_info.y-(action_info.height << 1)-QuantumMargin;
5714 Initialize mode information.
5716 XGetWidgetInfo(reply,&mode_info);
5717 mode_info.bevel_width=0;
5718 mode_info.width=(unsigned int)
5719 (action_info.x-reply_info.x-QuantumMargin);
5720 mode_info.height=action_info.height << 1;
5721 mode_info.x=reply_info.x;
5722 mode_info.y=action_info.y-action_info.height+action_info.bevel_width;
5724 Initialize scroll information.
5726 XGetWidgetInfo((char *) NULL,&scroll_info);
5727 scroll_info.bevel_width--;
5728 scroll_info.width=height;
5729 scroll_info.height=(unsigned int)
5730 (reply_info.y-back_info.y-(QuantumMargin >> 1));
5731 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
5732 scroll_info.y=back_info.y-reply_info.bevel_width;
5733 scroll_info.raised=MagickFalse;
5734 scroll_info.trough=MagickTrue;
5735 north_info=scroll_info;
5736 north_info.raised=MagickTrue;
5737 north_info.width-=(north_info.bevel_width << 1);
5738 north_info.height=north_info.width-1;
5739 north_info.x+=north_info.bevel_width;
5740 north_info.y+=north_info.bevel_width;
5741 south_info=north_info;
5742 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
5745 slider_info=north_info;
5747 slider_info.width-=2;
5748 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
5749 slider_info.bevel_width+2;
5750 slider_info.height=scroll_info.height-((slider_info.min_y-
5751 scroll_info.y+1) << 1)+4;
5752 visible_fonts=scroll_info.height/(height+(height >> 3));
5753 if (fonts > (int) visible_fonts)
5754 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5755 slider_info.max_y=south_info.y-south_info.bevel_width-
5756 slider_info.bevel_width-2;
5757 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
5758 slider_info.y=slider_info.min_y;
5759 expose_info=scroll_info;
5760 expose_info.y=slider_info.y;
5762 Initialize list information.
5764 XGetWidgetInfo((char *) NULL,&list_info);
5765 list_info.raised=MagickFalse;
5766 list_info.bevel_width--;
5767 list_info.width=(unsigned int)
5768 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
5769 list_info.height=scroll_info.height;
5770 list_info.x=reply_info.x;
5771 list_info.y=scroll_info.y;
5772 if (windows->widget.mapped == MagickFalse)
5773 state|=JumpListState;
5775 Initialize text information.
5778 XGetWidgetInfo(text,&text_info);
5779 text_info.center=MagickFalse;
5780 text_info.width=reply_info.width;
5781 text_info.height=height;
5782 text_info.x=list_info.x-(QuantumMargin >> 1);
5783 text_info.y=QuantumMargin;
5785 Initialize selection information.
5787 XGetWidgetInfo((char *) NULL,&selection_info);
5788 selection_info.center=MagickFalse;
5789 selection_info.width=list_info.width;
5790 selection_info.height=(unsigned int) ((9*height) >> 3);
5791 selection_info.x=list_info.x;
5792 state&=(~UpdateConfigurationState);
5794 if (state & RedrawWidgetState)
5797 Redraw Font Browser window.
5800 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
5801 (void) XDrawString(display,windows->widget.id,
5802 windows->widget.annotate_context,x,y,FontPatternText,
5803 Extent(FontPatternText));
5804 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5805 XDrawWidgetText(display,&windows->widget,&text_info);
5806 XDrawBeveledButton(display,&windows->widget,&back_info);
5807 XDrawBeveledButton(display,&windows->widget,&reset_info);
5808 XDrawBeveledMatte(display,&windows->widget,&list_info);
5809 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5810 XDrawTriangleNorth(display,&windows->widget,&north_info);
5811 XDrawBeveledButton(display,&windows->widget,&slider_info);
5812 XDrawTriangleSouth(display,&windows->widget,&south_info);
5814 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
5815 (void) XDrawString(display,windows->widget.id,
5816 windows->widget.annotate_context,x,y,FontnameText,
5817 Extent(FontnameText));
5818 XDrawBeveledMatte(display,&windows->widget,&reply_info);
5819 XDrawMatteText(display,&windows->widget,&reply_info);
5820 XDrawBeveledButton(display,&windows->widget,&action_info);
5821 XDrawBeveledButton(display,&windows->widget,&cancel_info);
5822 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5823 selection_info.id=(~0);
5824 state|=RedrawActionState;
5825 state|=RedrawListState;
5826 state&=(~RedrawWidgetState);
5828 if (state & UpdateListState)
5839 checklist=XListFonts(display,glob_pattern,32767,&number_fonts);
5840 if (checklist == (char **) NULL)
5842 if ((strchr(glob_pattern,'*') == (char *) NULL) &&
5843 (strchr(glob_pattern,'?') == (char *) NULL))
5846 Might be a scaleable font-- exit.
5848 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
5849 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5850 action_info.raised=MagickFalse;
5851 XDrawBeveledButton(display,&windows->widget,&action_info);
5854 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5855 (void) XBell(display,0);
5858 if (number_fonts == 1)
5861 Reply is a single font name-- exit.
5863 (void) CopyMagickString(reply,checklist[0],MaxTextExtent);
5864 (void) CopyMagickString(glob_pattern,back_pattern,MaxTextExtent);
5865 (void) XFreeFontNames(checklist);
5866 action_info.raised=MagickFalse;
5867 XDrawBeveledButton(display,&windows->widget,&action_info);
5872 (void) XFreeFontNames(listhead);
5873 fontlist=(char **) RelinquishMagickMemory(fontlist);
5878 Sort font list in ascending order.
5881 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,
5883 if (fontlist == (char **) NULL)
5885 XNoticeWidget(display,windows,"MemoryAllocationFailed",
5886 "UnableToViewFonts");
5889 for (i=0; i < fonts; i++)
5890 fontlist[i]=listhead[i];
5891 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare);
5893 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
5894 if (fonts > (int) visible_fonts)
5895 slider_info.height=(visible_fonts*slider_info.height)/fonts;
5896 slider_info.max_y=south_info.y-south_info.bevel_width-
5897 slider_info.bevel_width-2;
5899 slider_info.y=slider_info.min_y;
5900 expose_info.y=slider_info.y;
5901 selection_info.id=(~0);
5903 state|=RedrawListState;
5905 Redraw font name & reply.
5907 *reply_info.text='\0';
5908 reply_info.cursor=reply_info.text;
5909 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
5910 XDrawWidgetText(display,&windows->widget,&text_info);
5911 XDrawMatteText(display,&windows->widget,&reply_info);
5912 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
5913 XDrawTriangleNorth(display,&windows->widget,&north_info);
5914 XDrawBeveledButton(display,&windows->widget,&slider_info);
5915 XDrawTriangleSouth(display,&windows->widget,&south_info);
5916 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
5917 state&=(~UpdateListState);
5919 if (state & JumpListState)
5922 Jump scroll to match user font.
5925 for (i=0; i < fonts; i++)
5926 if (LocaleCompare(fontlist[i],reply) >= 0)
5928 list_info.id=LocaleCompare(fontlist[i],reply) == 0 ? i : ~0;
5931 if ((i < slider_info.id) || (i >= (int) (slider_info.id+visible_fonts)))
5932 slider_info.id=i-(visible_fonts >> 1);
5933 selection_info.id=(~0);
5934 state|=RedrawListState;
5935 state&=(~JumpListState);
5937 if (state & RedrawListState)
5940 Determine slider id and position.
5942 if (slider_info.id >= (int) (fonts-visible_fonts))
5943 slider_info.id=fonts-visible_fonts;
5944 if ((slider_info.id < 0) || (fonts <= (int) visible_fonts))
5946 slider_info.y=slider_info.min_y;
5949 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/fonts;
5950 if (slider_info.id != selection_info.id)
5953 Redraw scroll bar and file names.
5955 selection_info.id=slider_info.id;
5956 selection_info.y=list_info.y+(height >> 3)+2;
5957 for (i=0; i < (int) visible_fonts; i++)
5959 selection_info.raised=(slider_info.id+i) != list_info.id ?
5960 MagickTrue : MagickFalse;
5961 selection_info.text=(char *) NULL;
5962 if ((slider_info.id+i) < fonts)
5963 selection_info.text=fontlist[slider_info.id+i];
5964 XDrawWidgetText(display,&windows->widget,&selection_info);
5965 selection_info.y+=(int) selection_info.height;
5970 if (slider_info.y > expose_info.y)
5972 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
5973 expose_info.y=slider_info.y-expose_info.height-
5974 slider_info.bevel_width-1;
5978 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
5979 expose_info.y=slider_info.y+slider_info.height+
5980 slider_info.bevel_width+1;
5982 XDrawTriangleNorth(display,&windows->widget,&north_info);
5983 XDrawMatte(display,&windows->widget,&expose_info);
5984 XDrawBeveledButton(display,&windows->widget,&slider_info);
5985 XDrawTriangleSouth(display,&windows->widget,&south_info);
5986 expose_info.y=slider_info.y;
5988 state&=(~RedrawListState);
5990 if (state & RedrawActionState)
5996 Display the selected font in a drawing area.
5998 save_info=windows->widget.font_info;
5999 font_info=XLoadQueryFont(display,reply_info.text);
6000 if (font_info != (XFontStruct *) NULL)
6002 windows->widget.font_info=font_info;
6003 (void) XSetFont(display,windows->widget.widget_context,
6006 XDrawBeveledButton(display,&windows->widget,&mode_info);
6007 windows->widget.font_info=save_info;
6008 if (font_info != (XFontStruct *) NULL)
6010 (void) XSetFont(display,windows->widget.widget_context,
6011 windows->widget.font_info->fid);
6012 (void) XFreeFont(display,font_info);
6014 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
6015 XDrawMatteText(display,&windows->widget,&reply_info);
6016 state&=(~RedrawActionState);
6019 Wait for next event.
6021 if (north_info.raised && south_info.raised)
6022 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
6026 Brief delay before advancing scroll bar.
6028 XDelay(display,delay);
6030 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
6031 if (north_info.raised == MagickFalse)
6032 if (slider_info.id > 0)
6038 state|=RedrawListState;
6040 if (south_info.raised == MagickFalse)
6041 if (slider_info.id < fonts)
6047 state|=RedrawListState;
6049 if (event.type != ButtonRelease)
6056 if (MatteIsActive(slider_info,event.xbutton))
6061 slider_info.active=MagickTrue;
6064 if (MatteIsActive(north_info,event.xbutton))
6065 if (slider_info.id > 0)
6070 north_info.raised=MagickFalse;
6072 state|=RedrawListState;
6075 if (MatteIsActive(south_info,event.xbutton))
6076 if (slider_info.id < fonts)
6081 south_info.raised=MagickFalse;
6083 state|=RedrawListState;
6086 if (MatteIsActive(scroll_info,event.xbutton))
6091 if (event.xbutton.y < slider_info.y)
6092 slider_info.id-=(visible_fonts-1);
6094 slider_info.id+=(visible_fonts-1);
6095 state|=RedrawListState;
6098 if (MatteIsActive(list_info,event.xbutton))
6104 User pressed list matte.
6106 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
6107 selection_info.height;
6108 if (id >= (int) fonts)
6110 (void) CopyMagickString(reply_info.text,fontlist[id],MaxTextExtent);
6111 reply_info.highlight=MagickFalse;
6112 reply_info.marker=reply_info.text;
6113 reply_info.cursor=reply_info.text+Extent(reply_info.text);
6114 XDrawMatteText(display,&windows->widget,&reply_info);
6115 state|=RedrawActionState;
6116 if (id == list_info.id)
6118 (void) CopyMagickString(glob_pattern,reply_info.text,
6120 state|=UpdateListState;
6122 selection_info.id=(~0);
6124 state|=RedrawListState;
6127 if (MatteIsActive(back_info,event.xbutton))
6130 User pressed Back button.
6132 back_info.raised=MagickFalse;
6133 XDrawBeveledButton(display,&windows->widget,&back_info);
6136 if (MatteIsActive(reset_info,event.xbutton))
6139 User pressed Reset button.
6141 reset_info.raised=MagickFalse;
6142 XDrawBeveledButton(display,&windows->widget,&reset_info);
6145 if (MatteIsActive(action_info,event.xbutton))
6148 User pressed action button.
6150 action_info.raised=MagickFalse;
6151 XDrawBeveledButton(display,&windows->widget,&action_info);
6154 if (MatteIsActive(cancel_info,event.xbutton))
6157 User pressed Cancel button.
6159 cancel_info.raised=MagickFalse;
6160 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6163 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
6165 if (event.xbutton.button != Button2)
6171 Move text cursor to position of button press.
6173 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
6174 for (i=1; i <= Extent(reply_info.marker); i++)
6175 if (XTextWidth(font_info,reply_info.marker,i) > x)
6177 reply_info.cursor=reply_info.marker+i-1;
6178 if (event.xbutton.time > (click_time+DoubleClick))
6179 reply_info.highlight=MagickFalse;
6183 Become the XA_PRIMARY selection owner.
6185 (void) CopyMagickString(primary_selection,reply_info.text,
6187 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
6188 event.xbutton.time);
6189 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
6190 windows->widget.id ? MagickTrue : MagickFalse;
6192 XDrawMatteText(display,&windows->widget,&reply_info);
6193 click_time=event.xbutton.time;
6197 Request primary selection.
6199 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
6200 windows->widget.id,event.xbutton.time);
6205 if (windows->widget.mapped == MagickFalse)
6207 if (north_info.raised == MagickFalse)
6210 User released up button.
6212 delay=SuspendTime << 2;
6213 north_info.raised=MagickTrue;
6214 XDrawTriangleNorth(display,&windows->widget,&north_info);
6216 if (south_info.raised == MagickFalse)
6219 User released down button.
6221 delay=SuspendTime << 2;
6222 south_info.raised=MagickTrue;
6223 XDrawTriangleSouth(display,&windows->widget,&south_info);
6225 if (slider_info.active)
6228 Stop tracking slider.
6230 slider_info.active=MagickFalse;
6233 if (back_info.raised == MagickFalse)
6235 if (event.xbutton.window == windows->widget.id)
6236 if (MatteIsActive(back_info,event.xbutton))
6238 (void) CopyMagickString(glob_pattern,back_pattern,
6240 state|=UpdateListState;
6242 back_info.raised=MagickTrue;
6243 XDrawBeveledButton(display,&windows->widget,&back_info);
6245 if (reset_info.raised == MagickFalse)
6247 if (event.xbutton.window == windows->widget.id)
6248 if (MatteIsActive(reset_info,event.xbutton))
6250 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6251 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
6252 state|=UpdateListState;
6254 reset_info.raised=MagickTrue;
6255 XDrawBeveledButton(display,&windows->widget,&reset_info);
6257 if (action_info.raised == MagickFalse)
6259 if (event.xbutton.window == windows->widget.id)
6261 if (MatteIsActive(action_info,event.xbutton))
6263 if (*reply_info.text == '\0')
6264 (void) XBell(display,0);
6269 action_info.raised=MagickTrue;
6270 XDrawBeveledButton(display,&windows->widget,&action_info);
6272 if (cancel_info.raised == MagickFalse)
6274 if (event.xbutton.window == windows->widget.id)
6275 if (MatteIsActive(cancel_info,event.xbutton))
6277 *reply_info.text='\0';
6280 cancel_info.raised=MagickTrue;
6281 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6288 If client window delete message, exit.
6290 if (event.xclient.message_type != windows->wm_protocols)
6292 if (*event.xclient.data.l == (int) windows->wm_take_focus)
6294 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
6295 (Time) event.xclient.data.l[1]);
6298 if (*event.xclient.data.l != (int) windows->wm_delete_window)
6300 if (event.xclient.window == windows->widget.id)
6302 *reply_info.text='\0';
6308 case ConfigureNotify:
6311 Update widget configuration.
6313 if (event.xconfigure.window != windows->widget.id)
6315 if ((event.xconfigure.width == (int) windows->widget.width) &&
6316 (event.xconfigure.height == (int) windows->widget.height))
6318 windows->widget.width=(unsigned int)
6319 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
6320 windows->widget.height=(unsigned int)
6321 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
6322 state|=UpdateConfigurationState;
6327 if (event.xcrossing.window != windows->widget.id)
6329 state&=(~InactiveWidgetState);
6334 if (event.xexpose.window != windows->widget.id)
6336 if (event.xexpose.count != 0)
6338 state|=RedrawWidgetState;
6344 command[MaxTextExtent];
6353 Respond to a user key press.
6355 if (event.xkey.window != windows->widget.id)
6357 length=XLookupString((XKeyEvent *) &event.xkey,command,
6358 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6359 *(command+length)='\0';
6360 if (AreaIsActive(scroll_info,event.xkey))
6365 switch ((int) key_symbol)
6388 slider_info.id-=visible_fonts;
6394 slider_info.id+=visible_fonts;
6400 slider_info.id=fonts;
6404 state|=RedrawListState;
6407 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
6410 Read new font or glob patterm.
6412 if (*reply_info.text == '\0')
6414 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent);
6415 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
6416 state|=UpdateListState;
6419 if (key_symbol == XK_Control_L)
6421 state|=ControlState;
6424 if (state & ControlState)
6425 switch ((int) key_symbol)
6431 Erase the entire line of text.
6433 *reply_info.text='\0';
6434 reply_info.cursor=reply_info.text;
6435 reply_info.marker=reply_info.text;
6436 reply_info.highlight=MagickFalse;
6442 XEditText(display,&reply_info,key_symbol,command,state);
6443 XDrawMatteText(display,&windows->widget,&reply_info);
6444 state|=JumpListState;
6450 command[MaxTextExtent];
6456 Respond to a user key release.
6458 if (event.xkey.window != windows->widget.id)
6460 (void) XLookupString((XKeyEvent *) &event.xkey,command,
6461 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
6462 if (key_symbol == XK_Control_L)
6463 state&=(~ControlState);
6468 if (event.xcrossing.window != windows->widget.id)
6470 state|=InactiveWidgetState;
6482 Discard pending button motion events.
6484 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
6485 if (slider_info.active)
6490 slider_info.y=event.xmotion.y-
6491 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
6492 if (slider_info.y < slider_info.min_y)
6493 slider_info.y=slider_info.min_y;
6494 if (slider_info.y > slider_info.max_y)
6495 slider_info.y=slider_info.max_y;
6497 if (slider_info.y != slider_info.min_y)
6498 slider_info.id=(fonts*(slider_info.y-slider_info.min_y+1))/
6499 (slider_info.max_y-slider_info.min_y+1);
6500 state|=RedrawListState;
6503 if (state & InactiveWidgetState)
6505 if (back_info.raised == MatteIsActive(back_info,event.xmotion))
6508 Back button status changed.
6510 back_info.raised=!back_info.raised;
6511 XDrawBeveledButton(display,&windows->widget,&back_info);
6514 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
6517 Reset button status changed.
6519 reset_info.raised=!reset_info.raised;
6520 XDrawBeveledButton(display,&windows->widget,&reset_info);
6523 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
6526 Action button status changed.
6528 action_info.raised=action_info.raised == MagickFalse ?
6529 MagickTrue : MagickFalse;
6530 XDrawBeveledButton(display,&windows->widget,&action_info);
6533 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
6536 Cancel button status changed.
6538 cancel_info.raised=cancel_info.raised == MagickFalse ?
6539 MagickTrue : MagickFalse;
6540 XDrawBeveledButton(display,&windows->widget,&cancel_info);
6545 case SelectionClear:
6547 reply_info.highlight=MagickFalse;
6548 XDrawMatteText(display,&windows->widget,&reply_info);
6551 case SelectionNotify:
6567 Obtain response from primary selection.
6569 if (event.xselection.property == (Atom) None)
6571 status=XGetWindowProperty(display,event.xselection.requestor,
6572 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
6573 &format,&length,&after,&data);
6574 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
6577 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
6578 (void) XBell(display,0);
6582 Insert primary selection in reply text.
6584 *(data+length)='\0';
6585 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
6587 XDrawMatteText(display,&windows->widget,&reply_info);
6588 state|=JumpListState;
6589 state|=RedrawActionState;
6591 (void) XFree((void *) data);
6594 case SelectionRequest:
6599 XSelectionRequestEvent
6603 Set XA_PRIMARY selection.
6605 request=(&(event.xselectionrequest));
6606 (void) XChangeProperty(request->display,request->requestor,
6607 request->property,request->target,8,PropModeReplace,
6608 (unsigned char *) primary_selection,Extent(primary_selection));
6609 notify.type=SelectionNotify;
6610 notify.display=request->display;
6611 notify.requestor=request->requestor;
6612 notify.selection=request->selection;
6613 notify.target=request->target;
6614 notify.time=request->time;
6615 if (request->property == None)
6616 notify.property=request->target;
6618 notify.property=request->property;
6619 (void) XSendEvent(request->display,request->requestor,False,0,
6620 (XEvent *) ¬ify);
6625 } while ((state & ExitState) == 0);
6626 XSetCursorState(display,windows,MagickFalse);
6627 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
6628 XCheckRefreshWindows(display,windows);
6632 (void) XFreeFontNames(listhead);
6633 fontlist=(char **) RelinquishMagickMemory(fontlist);
6637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6641 % X I n f o W i d g e t %
6645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6647 % XInfoWidget() displays text in the Info widget. The purpose is to inform
6648 % the user that what activity is currently being performed (e.g. reading
6649 % an image, rotating an image, etc.).
6651 % The format of the XInfoWidget method is:
6653 % void XInfoWidget(Display *display,XWindows *windows,const char *activity)
6655 % A description of each parameter follows:
6657 % o display: Specifies a connection to an X server; returned from
6660 % o window: Specifies a pointer to a XWindows structure.
6662 % o activity: This character string reflects the current activity and is
6663 % displayed in the Info widget.
6666 MagickPrivate void XInfoWidget(Display *display,XWindows *windows,
6667 const char *activity)
6683 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
6684 assert(display != (Display *) NULL);
6685 assert(windows != (XWindows *) NULL);
6686 assert(activity != (char *) NULL);
6687 font_info=windows->info.font_info;
6688 width=WidgetTextWidth(font_info,(char *) activity)+((3*QuantumMargin) >> 1)+4;
6689 height=(unsigned int) (((6*(font_info->ascent+font_info->descent)) >> 2)+4);
6690 if ((windows->info.width != width) || (windows->info.height != height))
6693 Size Info widget to accommodate the activity text.
6695 windows->info.width=width;
6696 windows->info.height=height;
6697 window_changes.width=(int) width;
6698 window_changes.height=(int) height;
6699 (void) XReconfigureWMWindow(display,windows->info.id,windows->info.screen,
6700 (unsigned int) (CWWidth | CWHeight),&window_changes);
6702 if (windows->info.mapped == MagickFalse)
6704 (void) XMapRaised(display,windows->info.id);
6705 windows->info.mapped=MagickTrue;
6708 Initialize Info matte information.
6710 height=(unsigned int) (font_info->ascent+font_info->descent);
6711 XGetWidgetInfo(activity,&monitor_info);
6712 monitor_info.bevel_width--;
6713 margin=monitor_info.bevel_width+((windows->info.height-height) >> 1)-2;
6714 monitor_info.center=MagickFalse;
6715 monitor_info.x=(int) margin;
6716 monitor_info.y=(int) margin;
6717 monitor_info.width=windows->info.width-(margin << 1);
6718 monitor_info.height=windows->info.height-(margin << 1)+1;
6722 monitor_info.raised=MagickFalse;
6723 XDrawBeveledMatte(display,&windows->info,&monitor_info);
6724 monitor_info.raised=MagickTrue;
6725 XDrawWidgetText(display,&windows->info,&monitor_info);
6729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6733 % X L i s t B r o w s e r W i d g e t %
6737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6739 % XListBrowserWidget() displays a List Browser widget with a query to the
6740 % user. The user keys a reply or select a reply from the list. Finally, the
6741 % user presses the Action or Cancel button to exit. The typed text is
6742 % returned as the reply function parameter.
6744 % The format of the XListBrowserWidget method is:
6746 % void XListBrowserWidget(Display *display,XWindows *windows,
6747 % XWindowInfo *window_info,const char **list,const char *action,
6748 % const char *query,char *reply)
6750 % A description of each parameter follows:
6752 % o display: Specifies a connection to an X server; returned from
6755 % o window: Specifies a pointer to a XWindows structure.
6757 % o list: Specifies a pointer to an array of strings. The user can
6758 % select from these strings as a possible reply value.
6760 % o action: Specifies a pointer to the action of this widget.
6762 % o query: Specifies a pointer to the query to present to the user.
6764 % o reply: the response from the user is returned in this parameter.
6767 MagickPrivate void XListBrowserWidget(Display *display,XWindows *windows,
6768 XWindowInfo *window_info,const char **list,const char *action,
6769 const char *query,char *reply)
6771 #define CancelButtonText "Cancel"
6774 primary_selection[MaxTextExtent];
6782 static MagickStatusType
6783 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
6825 Count the number of entries in the list.
6827 assert(display != (Display *) NULL);
6828 assert(windows != (XWindows *) NULL);
6829 assert(window_info != (XWindowInfo *) NULL);
6830 assert(list != (const char **) NULL);
6831 assert(action != (char *) NULL);
6832 assert(query != (char *) NULL);
6833 assert(reply != (char *) NULL);
6834 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
6835 XSetCursorState(display,windows,MagickTrue);
6836 XCheckRefreshWindows(display,windows);
6837 if (list == (const char **) NULL)
6839 XNoticeWidget(display,windows,"No text to browse:",(char *) NULL);
6842 for (entries=0; ; entries++)
6843 if (list[entries] == (char *) NULL)
6846 Determine Font Browser widget attributes.
6848 font_info=window_info->font_info;
6849 text_width=WidgetTextWidth(font_info,(char *) query);
6850 for (i=0; i < (int) entries; i++)
6851 if (WidgetTextWidth(font_info,(char *) list[i]) > text_width)
6852 text_width=WidgetTextWidth(font_info,(char *) list[i]);
6853 width=WidgetTextWidth(font_info,(char *) action);
6854 if (WidgetTextWidth(font_info,CancelButtonText) > width)
6855 width=WidgetTextWidth(font_info,CancelButtonText);
6856 width+=QuantumMargin;
6857 height=(unsigned int) (font_info->ascent+font_info->descent);
6859 Position List Browser widget.
6861 window_info->width=(unsigned int) MagickMin((int) text_width,(int)
6862 MaxTextWidth)+((9*QuantumMargin) >> 1);
6863 window_info->min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
6864 if (window_info->width < window_info->min_width)
6865 window_info->width=window_info->min_width;
6866 window_info->height=(unsigned int)
6867 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4);
6868 window_info->min_height=(unsigned int)
6869 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
6870 if (window_info->height < window_info->min_height)
6871 window_info->height=window_info->min_height;
6872 XConstrainWindowPosition(display,window_info);
6874 Map List Browser widget.
6876 (void) CopyMagickString(window_info->name,"Browse",MaxTextExtent);
6877 status=XStringListToTextProperty(&window_info->name,1,&window_name);
6878 if (status != False)
6880 XSetWMName(display,window_info->id,&window_name);
6881 XSetWMIconName(display,windows->widget.id,&window_name);
6882 (void) XFree((void *) window_name.value);
6884 window_changes.width=(int) window_info->width;
6885 window_changes.height=(int) window_info->height;
6886 window_changes.x=window_info->x;
6887 window_changes.y=window_info->y;
6888 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,mask,
6890 (void) XMapRaised(display,window_info->id);
6891 window_info->mapped=MagickFalse;
6893 Respond to X events.
6895 XGetWidgetInfo((char *) NULL,&slider_info);
6896 XGetWidgetInfo((char *) NULL,&north_info);
6897 XGetWidgetInfo((char *) NULL,&south_info);
6898 XGetWidgetInfo((char *) NULL,&expose_info);
6899 XGetWidgetInfo((char *) NULL,&selection_info);
6901 delay=SuspendTime << 2;
6902 state=UpdateConfigurationState;
6905 if (state & UpdateConfigurationState)
6911 Initialize button information.
6913 XGetWidgetInfo(CancelButtonText,&cancel_info);
6914 cancel_info.width=width;
6915 cancel_info.height=(unsigned int) ((3*height) >> 1);
6917 (window_info->width-cancel_info.width-QuantumMargin-2);
6919 (window_info->height-cancel_info.height-QuantumMargin);
6920 XGetWidgetInfo(action,&action_info);
6921 action_info.width=width;
6922 action_info.height=(unsigned int) ((3*height) >> 1);
6923 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
6924 (action_info.bevel_width << 1));
6925 action_info.y=cancel_info.y;
6927 Initialize reply information.
6929 XGetWidgetInfo(reply,&reply_info);
6930 reply_info.raised=MagickFalse;
6931 reply_info.bevel_width--;
6932 reply_info.width=window_info->width-((4*QuantumMargin) >> 1);
6933 reply_info.height=height << 1;
6934 reply_info.x=QuantumMargin;
6935 reply_info.y=action_info.y-reply_info.height-QuantumMargin;
6937 Initialize scroll information.
6939 XGetWidgetInfo((char *) NULL,&scroll_info);
6940 scroll_info.bevel_width--;
6941 scroll_info.width=height;
6942 scroll_info.height=(unsigned int)
6943 (reply_info.y-((6*QuantumMargin) >> 1)-height);
6944 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
6945 scroll_info.y=((5*QuantumMargin) >> 1)+height-reply_info.bevel_width;
6946 scroll_info.raised=MagickFalse;
6947 scroll_info.trough=MagickTrue;
6948 north_info=scroll_info;
6949 north_info.raised=MagickTrue;
6950 north_info.width-=(north_info.bevel_width << 1);
6951 north_info.height=north_info.width-1;
6952 north_info.x+=north_info.bevel_width;
6953 north_info.y+=north_info.bevel_width;
6954 south_info=north_info;
6955 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
6958 slider_info=north_info;
6960 slider_info.width-=2;
6961 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
6962 slider_info.bevel_width+2;
6963 slider_info.height=scroll_info.height-((slider_info.min_y-
6964 scroll_info.y+1) << 1)+4;
6965 visible_entries=scroll_info.height/(height+(height >> 3));
6966 if (entries > visible_entries)
6967 slider_info.height=(visible_entries*slider_info.height)/entries;
6968 slider_info.max_y=south_info.y-south_info.bevel_width-
6969 slider_info.bevel_width-2;
6970 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
6971 slider_info.y=slider_info.min_y;
6972 expose_info=scroll_info;
6973 expose_info.y=slider_info.y;
6975 Initialize list information.
6977 XGetWidgetInfo((char *) NULL,&list_info);
6978 list_info.raised=MagickFalse;
6979 list_info.bevel_width--;
6980 list_info.width=(unsigned int)
6981 (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
6982 list_info.height=scroll_info.height;
6983 list_info.x=reply_info.x;
6984 list_info.y=scroll_info.y;
6985 if (window_info->mapped == MagickFalse)
6986 for (i=0; i < (int) entries; i++)
6987 if (LocaleCompare(list[i],reply) == 0)
6990 slider_info.id=i-(visible_entries >> 1);
6991 if (slider_info.id < 0)
6995 Initialize text information.
6997 XGetWidgetInfo(query,&text_info);
6998 text_info.width=reply_info.width;
6999 text_info.height=height;
7000 text_info.x=list_info.x-(QuantumMargin >> 1);
7001 text_info.y=QuantumMargin;
7003 Initialize selection information.
7005 XGetWidgetInfo((char *) NULL,&selection_info);
7006 selection_info.center=MagickFalse;
7007 selection_info.width=list_info.width;
7008 selection_info.height=(unsigned int) ((9*height) >> 3);
7009 selection_info.x=list_info.x;
7010 state&=(~UpdateConfigurationState);
7012 if (state & RedrawWidgetState)
7015 Redraw List Browser window.
7017 XDrawWidgetText(display,window_info,&text_info);
7018 XDrawBeveledMatte(display,window_info,&list_info);
7019 XDrawBeveledMatte(display,window_info,&scroll_info);
7020 XDrawTriangleNorth(display,window_info,&north_info);
7021 XDrawBeveledButton(display,window_info,&slider_info);
7022 XDrawTriangleSouth(display,window_info,&south_info);
7023 XDrawBeveledMatte(display,window_info,&reply_info);
7024 XDrawMatteText(display,window_info,&reply_info);
7025 XDrawBeveledButton(display,window_info,&action_info);
7026 XDrawBeveledButton(display,window_info,&cancel_info);
7027 XHighlightWidget(display,window_info,BorderOffset,BorderOffset);
7028 selection_info.id=(~0);
7029 state|=RedrawActionState;
7030 state|=RedrawListState;
7031 state&=(~RedrawWidgetState);
7033 if (state & RedrawListState)
7036 Determine slider id and position.
7038 if (slider_info.id >= (int) (entries-visible_entries))
7039 slider_info.id=(int) (entries-visible_entries);
7040 if ((slider_info.id < 0) || (entries <= visible_entries))
7042 slider_info.y=slider_info.min_y;
7045 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/entries;
7046 if (slider_info.id != selection_info.id)
7049 Redraw scroll bar and file names.
7051 selection_info.id=slider_info.id;
7052 selection_info.y=list_info.y+(height >> 3)+2;
7053 for (i=0; i < (int) visible_entries; i++)
7055 selection_info.raised=(slider_info.id+i) != list_info.id ?
7056 MagickTrue : MagickFalse;
7057 selection_info.text=(char *) NULL;
7058 if ((slider_info.id+i) < (int) entries)
7059 selection_info.text=(char *) list[slider_info.id+i];
7060 XDrawWidgetText(display,window_info,&selection_info);
7061 selection_info.y+=(int) selection_info.height;
7066 if (slider_info.y > expose_info.y)
7068 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
7069 expose_info.y=slider_info.y-expose_info.height-
7070 slider_info.bevel_width-1;
7074 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
7075 expose_info.y=slider_info.y+slider_info.height+
7076 slider_info.bevel_width+1;
7078 XDrawTriangleNorth(display,window_info,&north_info);
7079 XDrawMatte(display,window_info,&expose_info);
7080 XDrawBeveledButton(display,window_info,&slider_info);
7081 XDrawTriangleSouth(display,window_info,&south_info);
7082 expose_info.y=slider_info.y;
7084 state&=(~RedrawListState);
7087 Wait for next event.
7089 if (north_info.raised && south_info.raised)
7090 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7094 Brief delay before advancing scroll bar.
7096 XDelay(display,delay);
7098 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
7099 if (north_info.raised == MagickFalse)
7100 if (slider_info.id > 0)
7106 state|=RedrawListState;
7108 if (south_info.raised == MagickFalse)
7109 if (slider_info.id < (int) entries)
7115 state|=RedrawListState;
7117 if (event.type != ButtonRelease)
7124 if (MatteIsActive(slider_info,event.xbutton))
7129 slider_info.active=MagickTrue;
7132 if (MatteIsActive(north_info,event.xbutton))
7133 if (slider_info.id > 0)
7138 north_info.raised=MagickFalse;
7140 state|=RedrawListState;
7143 if (MatteIsActive(south_info,event.xbutton))
7144 if (slider_info.id < (int) entries)
7149 south_info.raised=MagickFalse;
7151 state|=RedrawListState;
7154 if (MatteIsActive(scroll_info,event.xbutton))
7159 if (event.xbutton.y < slider_info.y)
7160 slider_info.id-=(visible_entries-1);
7162 slider_info.id+=(visible_entries-1);
7163 state|=RedrawListState;
7166 if (MatteIsActive(list_info,event.xbutton))
7172 User pressed list matte.
7174 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
7175 selection_info.height;
7176 if (id >= (int) entries)
7178 (void) CopyMagickString(reply_info.text,list[id],MaxTextExtent);
7179 reply_info.highlight=MagickFalse;
7180 reply_info.marker=reply_info.text;
7181 reply_info.cursor=reply_info.text+Extent(reply_info.text);
7182 XDrawMatteText(display,window_info,&reply_info);
7183 selection_info.id=(~0);
7184 if (id == list_info.id)
7186 action_info.raised=MagickFalse;
7187 XDrawBeveledButton(display,window_info,&action_info);
7191 state|=RedrawListState;
7194 if (MatteIsActive(action_info,event.xbutton))
7197 User pressed action button.
7199 action_info.raised=MagickFalse;
7200 XDrawBeveledButton(display,window_info,&action_info);
7203 if (MatteIsActive(cancel_info,event.xbutton))
7206 User pressed Cancel button.
7208 cancel_info.raised=MagickFalse;
7209 XDrawBeveledButton(display,window_info,&cancel_info);
7212 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7214 if (event.xbutton.button != Button2)
7220 Move text cursor to position of button press.
7222 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
7223 for (i=1; i <= Extent(reply_info.marker); i++)
7224 if (XTextWidth(font_info,reply_info.marker,i) > x)
7226 reply_info.cursor=reply_info.marker+i-1;
7227 if (event.xbutton.time > (click_time+DoubleClick))
7228 reply_info.highlight=MagickFalse;
7232 Become the XA_PRIMARY selection owner.
7234 (void) CopyMagickString(primary_selection,reply_info.text,
7236 (void) XSetSelectionOwner(display,XA_PRIMARY,window_info->id,
7237 event.xbutton.time);
7238 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
7239 window_info->id ? MagickTrue : MagickFalse;
7241 XDrawMatteText(display,window_info,&reply_info);
7242 click_time=event.xbutton.time;
7246 Request primary selection.
7248 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
7249 window_info->id,event.xbutton.time);
7254 if (window_info->mapped == MagickFalse)
7256 if (north_info.raised == MagickFalse)
7259 User released up button.
7261 delay=SuspendTime << 2;
7262 north_info.raised=MagickTrue;
7263 XDrawTriangleNorth(display,window_info,&north_info);
7265 if (south_info.raised == MagickFalse)
7268 User released down button.
7270 delay=SuspendTime << 2;
7271 south_info.raised=MagickTrue;
7272 XDrawTriangleSouth(display,window_info,&south_info);
7274 if (slider_info.active)
7277 Stop tracking slider.
7279 slider_info.active=MagickFalse;
7282 if (action_info.raised == MagickFalse)
7284 if (event.xbutton.window == window_info->id)
7286 if (MatteIsActive(action_info,event.xbutton))
7288 if (*reply_info.text == '\0')
7289 (void) XBell(display,0);
7294 action_info.raised=MagickTrue;
7295 XDrawBeveledButton(display,window_info,&action_info);
7297 if (cancel_info.raised == MagickFalse)
7299 if (event.xbutton.window == window_info->id)
7300 if (MatteIsActive(cancel_info,event.xbutton))
7302 *reply_info.text='\0';
7305 cancel_info.raised=MagickTrue;
7306 XDrawBeveledButton(display,window_info,&cancel_info);
7308 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
7315 If client window delete message, exit.
7317 if (event.xclient.message_type != windows->wm_protocols)
7319 if (*event.xclient.data.l == (int) windows->wm_take_focus)
7321 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
7322 (Time) event.xclient.data.l[1]);
7325 if (*event.xclient.data.l != (int) windows->wm_delete_window)
7327 if (event.xclient.window == window_info->id)
7329 *reply_info.text='\0';
7335 case ConfigureNotify:
7338 Update widget configuration.
7340 if (event.xconfigure.window != window_info->id)
7342 if ((event.xconfigure.width == (int) window_info->width) &&
7343 (event.xconfigure.height == (int) window_info->height))
7345 window_info->width=(unsigned int)
7346 MagickMax(event.xconfigure.width,(int) window_info->min_width);
7347 window_info->height=(unsigned int)
7348 MagickMax(event.xconfigure.height,(int) window_info->min_height);
7349 state|=UpdateConfigurationState;
7354 if (event.xcrossing.window != window_info->id)
7356 state&=(~InactiveWidgetState);
7361 if (event.xexpose.window != window_info->id)
7363 if (event.xexpose.count != 0)
7365 state|=RedrawWidgetState;
7371 command[MaxTextExtent];
7380 Respond to a user key press.
7382 if (event.xkey.window != window_info->id)
7384 length=XLookupString((XKeyEvent *) &event.xkey,command,
7385 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7386 *(command+length)='\0';
7387 if (AreaIsActive(scroll_info,event.xkey))
7392 switch ((int) key_symbol)
7415 slider_info.id-=visible_entries;
7421 slider_info.id+=visible_entries;
7427 slider_info.id=(int) entries;
7431 state|=RedrawListState;
7434 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
7439 if (*reply_info.text == '\0')
7441 action_info.raised=MagickFalse;
7442 XDrawBeveledButton(display,window_info,&action_info);
7446 if (key_symbol == XK_Control_L)
7448 state|=ControlState;
7451 if (state & ControlState)
7452 switch ((int) key_symbol)
7458 Erase the entire line of text.
7460 *reply_info.text='\0';
7461 reply_info.cursor=reply_info.text;
7462 reply_info.marker=reply_info.text;
7463 reply_info.highlight=MagickFalse;
7469 XEditText(display,&reply_info,key_symbol,command,state);
7470 XDrawMatteText(display,window_info,&reply_info);
7476 command[MaxTextExtent];
7482 Respond to a user key release.
7484 if (event.xkey.window != window_info->id)
7486 (void) XLookupString((XKeyEvent *) &event.xkey,command,
7487 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
7488 if (key_symbol == XK_Control_L)
7489 state&=(~ControlState);
7494 if (event.xcrossing.window != window_info->id)
7496 state|=InactiveWidgetState;
7508 Discard pending button motion events.
7510 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
7511 if (slider_info.active)
7516 slider_info.y=event.xmotion.y-
7517 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
7518 if (slider_info.y < slider_info.min_y)
7519 slider_info.y=slider_info.min_y;
7520 if (slider_info.y > slider_info.max_y)
7521 slider_info.y=slider_info.max_y;
7523 if (slider_info.y != slider_info.min_y)
7524 slider_info.id=(int) ((entries*(slider_info.y-
7525 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
7526 state|=RedrawListState;
7529 if (state & InactiveWidgetState)
7531 if (action_info.raised == MatteIsActive(action_info,event.xmotion))
7534 Action button status changed.
7536 action_info.raised=action_info.raised == MagickFalse ?
7537 MagickTrue : MagickFalse;
7538 XDrawBeveledButton(display,window_info,&action_info);
7541 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
7544 Cancel button status changed.
7546 cancel_info.raised=cancel_info.raised == MagickFalse ?
7547 MagickTrue : MagickFalse;
7548 XDrawBeveledButton(display,window_info,&cancel_info);
7553 case SelectionClear:
7555 reply_info.highlight=MagickFalse;
7556 XDrawMatteText(display,window_info,&reply_info);
7559 case SelectionNotify:
7575 Obtain response from primary selection.
7577 if (event.xselection.property == (Atom) None)
7579 status=XGetWindowProperty(display,
7580 event.xselection.requestor,event.xselection.property,0L,2047L,
7581 MagickTrue,XA_STRING,&type,&format,&length,&after,&data);
7582 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
7585 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1))
7586 (void) XBell(display,0);
7590 Insert primary selection in reply text.
7592 *(data+length)='\0';
7593 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
7595 XDrawMatteText(display,window_info,&reply_info);
7596 state|=RedrawActionState;
7598 (void) XFree((void *) data);
7601 case SelectionRequest:
7606 XSelectionRequestEvent
7609 if (reply_info.highlight == MagickFalse)
7612 Set primary selection.
7614 request=(&(event.xselectionrequest));
7615 (void) XChangeProperty(request->display,request->requestor,
7616 request->property,request->target,8,PropModeReplace,
7617 (unsigned char *) primary_selection,Extent(primary_selection));
7618 notify.type=SelectionNotify;
7619 notify.send_event=MagickTrue;
7620 notify.display=request->display;
7621 notify.requestor=request->requestor;
7622 notify.selection=request->selection;
7623 notify.target=request->target;
7624 notify.time=request->time;
7625 if (request->property == None)
7626 notify.property=request->target;
7628 notify.property=request->property;
7629 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
7630 (XEvent *) ¬ify);
7635 } while ((state & ExitState) == 0);
7636 XSetCursorState(display,windows,MagickFalse);
7637 (void) XWithdrawWindow(display,window_info->id,window_info->screen);
7638 XCheckRefreshWindows(display,windows);
7642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7646 % X M e n u W i d g e t %
7650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7652 % XMenuWidget() maps a menu and returns the command pointed to by the user
7653 % when the button is released.
7655 % The format of the XMenuWidget method is:
7657 % int XMenuWidget(Display *display,XWindows *windows,const char *title,
7658 % const char **selections,char *item)
7660 % A description of each parameter follows:
7662 % o selection_number: Specifies the number of the selection that the
7665 % o display: Specifies a connection to an X server; returned from
7668 % o window: Specifies a pointer to a XWindows structure.
7670 % o title: Specifies a character string that describes the menu selections.
7672 % o selections: Specifies a pointer to one or more strings that comprise
7673 % the choices in the menu.
7675 % o item: Specifies a character array. The item selected from the menu
7679 MagickPrivate int XMenuWidget(Display *display,XWindows *windows,
7680 const char *title,const char **selections,char *item)
7706 XSetWindowAttributes
7718 Determine Menu widget attributes.
7720 assert(display != (Display *) NULL);
7721 assert(windows != (XWindows *) NULL);
7722 assert(title != (char *) NULL);
7723 assert(selections != (const char **) NULL);
7724 assert(item != (char *) NULL);
7725 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
7726 font_info=windows->widget.font_info;
7727 windows->widget.width=submenu_info.active == 0 ?
7728 WidgetTextWidth(font_info,(char *) title) : 0;
7729 for (id=0; selections[id] != (char *) NULL; id++)
7731 width=WidgetTextWidth(font_info,(char *) selections[id]);
7732 if (width > windows->widget.width)
7733 windows->widget.width=width;
7735 number_selections=(unsigned int) id;
7736 XGetWidgetInfo((char *) NULL,&menu_info);
7737 title_height=(unsigned int) (submenu_info.active == 0 ?
7738 (3*(font_info->descent+font_info->ascent) >> 1)+5 : 2);
7739 width=WidgetTextWidth(font_info,(char *) title);
7740 height=(unsigned int) ((3*(font_info->ascent+font_info->descent)) >> 1);
7742 Position Menu widget.
7744 windows->widget.width+=QuantumMargin+(menu_info.bevel_width << 1);
7745 top_offset=title_height+menu_info.bevel_width-1;
7746 windows->widget.height=top_offset+number_selections*height+4;
7747 windows->widget.min_width=windows->widget.width;
7748 windows->widget.min_height=windows->widget.height;
7749 XQueryPosition(display,windows->widget.root,&x,&y);
7750 windows->widget.x=x-(QuantumMargin >> 1);
7751 if (submenu_info.active != 0)
7754 windows->command.x+windows->command.width-QuantumMargin;
7755 toggle_info.raised=MagickTrue;
7756 XDrawTriangleEast(display,&windows->command,&toggle_info);
7758 windows->widget.y=submenu_info.active == 0 ? y-(int)
7759 ((3*title_height) >> 2) : y;
7760 if (submenu_info.active != 0)
7761 windows->widget.y=windows->command.y+submenu_info.y;
7762 XConstrainWindowPosition(display,&windows->widget);
7766 window_attributes.override_redirect=MagickTrue;
7767 (void) XChangeWindowAttributes(display,windows->widget.id,
7768 (size_t) CWOverrideRedirect,&window_attributes);
7769 window_changes.width=(int) windows->widget.width;
7770 window_changes.height=(int) windows->widget.height;
7771 window_changes.x=windows->widget.x;
7772 window_changes.y=windows->widget.y;
7773 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
7774 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
7775 (void) XMapRaised(display,windows->widget.id);
7776 windows->widget.mapped=MagickFalse;
7778 Respond to X events.
7780 selection_info.height=height;
7781 cursor=XCreateFontCursor(display,XC_right_ptr);
7782 (void) XCheckDefineCursor(display,windows->image.id,cursor);
7783 (void) XCheckDefineCursor(display,windows->command.id,cursor);
7784 (void) XCheckDefineCursor(display,windows->widget.id,cursor);
7785 state=UpdateConfigurationState;
7788 if (state & UpdateConfigurationState)
7791 Initialize selection information.
7793 XGetWidgetInfo((char *) NULL,&menu_info);
7794 menu_info.bevel_width--;
7795 menu_info.width=windows->widget.width-((menu_info.bevel_width) << 1);
7796 menu_info.height=windows->widget.height-((menu_info.bevel_width) << 1);
7797 menu_info.x=(int) menu_info.bevel_width;
7798 menu_info.y=(int) menu_info.bevel_width;
7799 XGetWidgetInfo((char *) NULL,&selection_info);
7800 selection_info.center=MagickFalse;
7801 selection_info.width=menu_info.width;
7802 selection_info.height=height;
7803 selection_info.x=menu_info.x;
7804 highlight_info=selection_info;
7805 highlight_info.bevel_width--;
7806 highlight_info.width-=(highlight_info.bevel_width << 1);
7807 highlight_info.height-=(highlight_info.bevel_width << 1);
7808 highlight_info.x+=highlight_info.bevel_width;
7809 state&=(~UpdateConfigurationState);
7811 if (state & RedrawWidgetState)
7816 if (submenu_info.active == 0)
7818 y=(int) title_height;
7819 XSetBevelColor(display,&windows->widget,MagickFalse);
7820 (void) XDrawLine(display,windows->widget.id,
7821 windows->widget.widget_context,selection_info.x,y-1,
7822 (int) selection_info.width,y-1);
7823 XSetBevelColor(display,&windows->widget,MagickTrue);
7824 (void) XDrawLine(display,windows->widget.id,
7825 windows->widget.widget_context,selection_info.x,y,
7826 (int) selection_info.width,y);
7827 (void) XSetFillStyle(display,windows->widget.widget_context,
7831 Draw menu selections.
7833 selection_info.center=MagickTrue;
7834 selection_info.y=(int) menu_info.bevel_width;
7835 selection_info.text=(char *) title;
7836 if (submenu_info.active == 0)
7837 XDrawWidgetText(display,&windows->widget,&selection_info);
7838 selection_info.center=MagickFalse;
7839 selection_info.y=(int) top_offset;
7840 for (id=0; id < (int) number_selections; id++)
7842 selection_info.text=(char *) selections[id];
7843 XDrawWidgetText(display,&windows->widget,&selection_info);
7844 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7845 if (id == selection_info.id)
7846 XDrawBevel(display,&windows->widget,&highlight_info);
7847 selection_info.y+=(int) selection_info.height;
7849 XDrawBevel(display,&windows->widget,&menu_info);
7850 state&=(~RedrawWidgetState);
7852 if (number_selections > 2)
7857 y=(int) (top_offset+selection_info.height*(number_selections-1));
7858 XSetBevelColor(display,&windows->widget,MagickFalse);
7859 (void) XDrawLine(display,windows->widget.id,
7860 windows->widget.widget_context,selection_info.x,y-1,
7861 (int) selection_info.width,y-1);
7862 XSetBevelColor(display,&windows->widget,MagickTrue);
7863 (void) XDrawLine(display,windows->widget.id,
7864 windows->widget.widget_context,selection_info.x,y,
7865 (int) selection_info.width,y);
7866 (void) XSetFillStyle(display,windows->widget.widget_context,FillSolid);
7869 Wait for next event.
7871 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
7876 if (event.xbutton.window != windows->widget.id)
7881 if (event.xbutton.window == windows->command.id)
7882 (void) XPutBackEvent(display,&event);
7883 selection_info.id=(~0);
7888 state&=(~InactiveWidgetState);
7889 id=(event.xbutton.y-top_offset)/(int) selection_info.height;
7890 selection_info.id=id;
7891 if ((id < 0) || (id >= (int) number_selections))
7894 Highlight this selection.
7896 selection_info.y=(int) (top_offset+id*selection_info.height);
7897 selection_info.text=(char *) selections[id];
7898 XDrawWidgetText(display,&windows->widget,&selection_info);
7899 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7900 XDrawBevel(display,&windows->widget,&highlight_info);
7905 if (windows->widget.mapped == MagickFalse)
7907 if (event.xbutton.window == windows->command.id)
7908 if ((state & InactiveWidgetState) == 0)
7913 XSetCursorState(display,windows,MagickFalse);
7918 case ConfigureNotify:
7921 Update widget configuration.
7923 if (event.xconfigure.window != windows->widget.id)
7925 if ((event.xconfigure.width == (int) windows->widget.width) &&
7926 (event.xconfigure.height == (int) windows->widget.height))
7928 windows->widget.width=(unsigned int)
7929 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
7930 windows->widget.height=(unsigned int)
7931 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
7932 state|=UpdateConfigurationState;
7937 if (event.xcrossing.window != windows->widget.id)
7939 if (event.xcrossing.state == 0)
7941 state&=(~InactiveWidgetState);
7942 id=((event.xcrossing.y-top_offset)/(int) selection_info.height);
7943 if ((selection_info.id >= 0) &&
7944 (selection_info.id < (int) number_selections))
7947 Unhighlight last selection.
7949 if (id == selection_info.id)
7951 selection_info.y=(int)
7952 (top_offset+selection_info.id*selection_info.height);
7953 selection_info.text=(char *) selections[selection_info.id];
7954 XDrawWidgetText(display,&windows->widget,&selection_info);
7956 if ((id < 0) || (id >= (int) number_selections))
7959 Highlight this selection.
7961 selection_info.id=id;
7962 selection_info.y=(int)
7963 (top_offset+selection_info.id*selection_info.height);
7964 selection_info.text=(char *) selections[selection_info.id];
7965 XDrawWidgetText(display,&windows->widget,&selection_info);
7966 highlight_info.y=selection_info.y+highlight_info.bevel_width;
7967 XDrawBevel(display,&windows->widget,&highlight_info);
7972 if (event.xexpose.window != windows->widget.id)
7974 if (event.xexpose.count != 0)
7976 state|=RedrawWidgetState;
7981 if (event.xcrossing.window != windows->widget.id)
7983 state|=InactiveWidgetState;
7984 id=selection_info.id;
7985 if ((id < 0) || (id >= (int) number_selections))
7988 Unhighlight last selection.
7990 selection_info.y=(int) (top_offset+id*selection_info.height);
7991 selection_info.id=(~0);
7992 selection_info.text=(char *) selections[id];
7993 XDrawWidgetText(display,&windows->widget,&selection_info);
7999 Discard pending button motion events.
8001 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8002 if (submenu_info.active != 0)
8003 if (event.xmotion.window == windows->command.id)
8005 if ((state & InactiveWidgetState) == 0)
8007 if (MatteIsActive(submenu_info,event.xmotion) == MagickFalse)
8009 selection_info.id=(~0);
8016 if (WindowIsActive(windows->command,event.xmotion))
8018 selection_info.id=(~0);
8024 if (event.xmotion.window != windows->widget.id)
8026 if (state & InactiveWidgetState)
8028 id=(event.xmotion.y-top_offset)/(int) selection_info.height;
8029 if ((selection_info.id >= 0) &&
8030 (selection_info.id < (int) number_selections))
8033 Unhighlight last selection.
8035 if (id == selection_info.id)
8037 selection_info.y=(int)
8038 (top_offset+selection_info.id*selection_info.height);
8039 selection_info.text=(char *) selections[selection_info.id];
8040 XDrawWidgetText(display,&windows->widget,&selection_info);
8042 selection_info.id=id;
8043 if ((id < 0) || (id >= (int) number_selections))
8046 Highlight this selection.
8048 selection_info.y=(int) (top_offset+id*selection_info.height);
8049 selection_info.text=(char *) selections[id];
8050 XDrawWidgetText(display,&windows->widget,&selection_info);
8051 highlight_info.y=selection_info.y+highlight_info.bevel_width;
8052 XDrawBevel(display,&windows->widget,&highlight_info);
8058 } while ((state & ExitState) == 0);
8059 (void) XFreeCursor(display,cursor);
8060 window_attributes.override_redirect=MagickFalse;
8061 (void) XChangeWindowAttributes(display,windows->widget.id,
8062 (size_t) CWOverrideRedirect,&window_attributes);
8063 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8064 XCheckRefreshWindows(display,windows);
8065 if (submenu_info.active != 0)
8067 submenu_info.active=MagickFalse;
8068 toggle_info.raised=MagickFalse;
8069 XDrawTriangleEast(display,&windows->command,&toggle_info);
8071 if ((selection_info.id < 0) || (selection_info.id >= (int) number_selections))
8073 (void) CopyMagickString(item,selections[selection_info.id],MaxTextExtent);
8074 return(selection_info.id);
8078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8082 % X N o t i c e W i d g e t %
8086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8088 % XNoticeWidget() displays a Notice widget with a notice to the user. The
8089 % function returns when the user presses the "Dismiss" button.
8091 % The format of the XNoticeWidget method is:
8093 % void XNoticeWidget(Display *display,XWindows *windows,
8094 % const char *reason,const char *description)
8096 % A description of each parameter follows:
8098 % o display: Specifies a connection to an X server; returned from
8101 % o window: Specifies a pointer to a XWindows structure.
8103 % o reason: Specifies the message to display before terminating the
8106 % o description: Specifies any description to the message.
8109 MagickPrivate void XNoticeWidget(Display *display,XWindows *windows,
8110 const char *reason,const char *description)
8112 #define DismissButtonText "Dismiss"
8151 Determine Notice widget attributes.
8153 assert(display != (Display *) NULL);
8154 assert(windows != (XWindows *) NULL);
8155 assert(reason != (char *) NULL);
8156 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
8157 XDelay(display,SuspendTime << 3); /* avoid surpise with delay */
8158 XSetCursorState(display,windows,MagickTrue);
8159 XCheckRefreshWindows(display,windows);
8160 font_info=windows->widget.font_info;
8161 width=WidgetTextWidth(font_info,DismissButtonText);
8162 text=GetLocaleExceptionMessage(XServerError,reason);
8163 if (text != (char *) NULL)
8164 if (WidgetTextWidth(font_info,(char *) text) > width)
8165 width=WidgetTextWidth(font_info,(char *) text);
8166 if (description != (char *) NULL)
8168 text=GetLocaleExceptionMessage(XServerError,description);
8169 if (text != (char *) NULL)
8170 if (WidgetTextWidth(font_info,(char *) text) > width)
8171 width=WidgetTextWidth(font_info,(char *) text);
8173 height=(unsigned int) (font_info->ascent+font_info->descent);
8175 Position Notice widget.
8177 windows->widget.width=width+4*QuantumMargin;
8178 windows->widget.min_width=width+QuantumMargin;
8179 if (windows->widget.width < windows->widget.min_width)
8180 windows->widget.width=windows->widget.min_width;
8181 windows->widget.height=(unsigned int) (12*height);
8182 windows->widget.min_height=(unsigned int) (7*height);
8183 if (windows->widget.height < windows->widget.min_height)
8184 windows->widget.height=windows->widget.min_height;
8185 XConstrainWindowPosition(display,&windows->widget);
8189 (void) CopyMagickString(windows->widget.name,"Notice",MaxTextExtent);
8190 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8191 if (status != False)
8193 XSetWMName(display,windows->widget.id,&window_name);
8194 XSetWMIconName(display,windows->widget.id,&window_name);
8195 (void) XFree((void *) window_name.value);
8197 window_changes.width=(int) windows->widget.width;
8198 window_changes.height=(int) windows->widget.height;
8199 window_changes.x=windows->widget.x;
8200 window_changes.y=windows->widget.y;
8201 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8202 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8203 (void) XMapRaised(display,windows->widget.id);
8204 windows->widget.mapped=MagickFalse;
8205 (void) XBell(display,0);
8207 Respond to X events.
8209 timer=time((time_t *) NULL)+Timeout;
8210 state=UpdateConfigurationState;
8213 if (time((time_t *) NULL) > timer)
8215 if (state & UpdateConfigurationState)
8218 Initialize Dismiss button information.
8220 XGetWidgetInfo(DismissButtonText,&dismiss_info);
8221 dismiss_info.width=(unsigned int) QuantumMargin+
8222 WidgetTextWidth(font_info,DismissButtonText);
8223 dismiss_info.height=(unsigned int) ((3*height) >> 1);
8224 dismiss_info.x=(int)
8225 ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
8226 dismiss_info.y=(int)
8227 (windows->widget.height-(dismiss_info.height << 1));
8228 state&=(~UpdateConfigurationState);
8230 if (state & RedrawWidgetState)
8233 Redraw Notice widget.
8235 width=WidgetTextWidth(font_info,(char *) reason);
8236 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8237 y=(int) ((windows->widget.height >> 1)-(height << 1));
8238 (void) XDrawString(display,windows->widget.id,
8239 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
8240 if (description != (char *) NULL)
8242 width=WidgetTextWidth(font_info,(char *) description);
8243 x=(int) ((windows->widget.width >> 1)-(width >> 1));
8245 (void) XDrawString(display,windows->widget.id,
8246 windows->widget.annotate_context,x,y,(char *) description,
8247 Extent(description));
8249 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8250 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8251 state&=(~RedrawWidgetState);
8254 Wait for next event.
8256 if (XCheckIfEvent(display,&event,XScreenEvent,(char *) windows) == MagickFalse)
8259 Do not block if delay > 0.
8261 XDelay(display,SuspendTime << 2);
8268 if (MatteIsActive(dismiss_info,event.xbutton))
8271 User pressed Dismiss button.
8273 dismiss_info.raised=MagickFalse;
8274 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8281 if (windows->widget.mapped == MagickFalse)
8283 if (dismiss_info.raised == MagickFalse)
8285 if (event.xbutton.window == windows->widget.id)
8286 if (MatteIsActive(dismiss_info,event.xbutton))
8288 dismiss_info.raised=MagickTrue;
8289 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8296 If client window delete message, exit.
8298 if (event.xclient.message_type != windows->wm_protocols)
8300 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8302 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8303 (Time) event.xclient.data.l[1]);
8306 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8308 if (event.xclient.window == windows->widget.id)
8315 case ConfigureNotify:
8318 Update widget configuration.
8320 if (event.xconfigure.window != windows->widget.id)
8322 if ((event.xconfigure.width == (int) windows->widget.width) &&
8323 (event.xconfigure.height == (int) windows->widget.height))
8325 windows->widget.width=(unsigned int)
8326 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8327 windows->widget.height=(unsigned int)
8328 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8329 state|=UpdateConfigurationState;
8334 if (event.xcrossing.window != windows->widget.id)
8336 state&=(~InactiveWidgetState);
8341 if (event.xexpose.window != windows->widget.id)
8343 if (event.xexpose.count != 0)
8345 state|=RedrawWidgetState;
8351 command[MaxTextExtent];
8357 Respond to a user key press.
8359 if (event.xkey.window != windows->widget.id)
8361 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8362 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8363 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8365 dismiss_info.raised=MagickFalse;
8366 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8374 if (event.xcrossing.window != windows->widget.id)
8376 state|=InactiveWidgetState;
8382 Discard pending button motion events.
8384 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8385 if (state & InactiveWidgetState)
8387 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
8390 Dismiss button status changed.
8392 dismiss_info.raised=
8393 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8394 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
8402 } while ((state & ExitState) == 0);
8403 XSetCursorState(display,windows,MagickFalse);
8404 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8405 XCheckRefreshWindows(display,windows);
8409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8413 % X P r e f e r e n c e s W i d g e t %
8417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8419 % XPreferencesWidget() displays a Preferences widget with program preferences.
8420 % If the user presses the Apply button, the preferences are stored in a
8421 % configuration file in the users' home directory.
8423 % The format of the XPreferencesWidget method is:
8425 % MagickBooleanType XPreferencesWidget(Display *display,
8426 % XResourceInfo *resource_info,XWindows *windows)
8428 % A description of each parameter follows:
8430 % o display: Specifies a connection to an X server; returned from
8433 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8435 % o window: Specifies a pointer to a XWindows structure.
8438 MagickPrivate MagickBooleanType XPreferencesWidget(Display *display,
8439 XResourceInfo *resource_info,XWindows *windows)
8441 #define ApplyButtonText "Apply"
8442 #define CacheButtonText "%lu mega-bytes of memory in the undo edit cache "
8443 #define CancelButtonText "Cancel"
8444 #define NumberPreferences 8
8449 "display image centered on a backdrop",
8450 "confirm on program exit",
8451 "confirm on image edits",
8452 "correct image for display gamma",
8453 "display warning messages",
8454 "apply Floyd/Steinberg error diffusion to image",
8455 "use a shared colormap for colormapped X visuals",
8456 "display images as an X server pixmap"
8460 cache[MaxTextExtent];
8493 preferences_info[NumberPreferences];
8499 Determine Preferences widget attributes.
8501 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8502 assert(display != (Display *) NULL);
8503 assert(resource_info != (XResourceInfo *) NULL);
8504 assert(windows != (XWindows *) NULL);
8505 XCheckRefreshWindows(display,windows);
8506 font_info=windows->widget.font_info;
8507 text_width=WidgetTextWidth(font_info,CacheButtonText);
8508 for (i=0; i < NumberPreferences; i++)
8509 if (WidgetTextWidth(font_info,(char *) Preferences[i]) > text_width)
8510 text_width=WidgetTextWidth(font_info,(char *) Preferences[i]);
8511 width=WidgetTextWidth(font_info,ApplyButtonText);
8512 if (WidgetTextWidth(font_info,CancelButtonText) > width)
8513 width=WidgetTextWidth(font_info,CancelButtonText);
8514 width+=(unsigned int) QuantumMargin;
8515 height=(unsigned int) (font_info->ascent+font_info->descent);
8517 Position Preferences widget.
8519 windows->widget.width=(unsigned int) (MagickMax((int) (width << 1),
8520 (int) text_width)+6*QuantumMargin);
8521 windows->widget.min_width=(width << 1)+QuantumMargin;
8522 if (windows->widget.width < windows->widget.min_width)
8523 windows->widget.width=windows->widget.min_width;
8524 windows->widget.height=(unsigned int)
8525 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8526 windows->widget.min_height=(unsigned int)
8527 (7*height+NumberPreferences*(height+(QuantumMargin >> 1)));
8528 if (windows->widget.height < windows->widget.min_height)
8529 windows->widget.height=windows->widget.min_height;
8530 XConstrainWindowPosition(display,&windows->widget);
8532 Map Preferences widget.
8534 (void) CopyMagickString(windows->widget.name,"Preferences",MaxTextExtent);
8535 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
8536 if (status != False)
8538 XSetWMName(display,windows->widget.id,&window_name);
8539 XSetWMIconName(display,windows->widget.id,&window_name);
8540 (void) XFree((void *) window_name.value);
8542 window_changes.width=(int) windows->widget.width;
8543 window_changes.height=(int) windows->widget.height;
8544 window_changes.x=windows->widget.x;
8545 window_changes.y=windows->widget.y;
8546 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
8547 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
8548 (void) XMapRaised(display,windows->widget.id);
8549 windows->widget.mapped=MagickFalse;
8551 Respond to X events.
8553 state=UpdateConfigurationState;
8554 XSetCursorState(display,windows,MagickTrue);
8557 if (state & UpdateConfigurationState)
8560 Initialize button information.
8562 XGetWidgetInfo(CancelButtonText,&cancel_info);
8563 cancel_info.width=width;
8564 cancel_info.height=(unsigned int) (3*height) >> 1;
8565 cancel_info.x=(int) windows->widget.width-cancel_info.width-
8566 (QuantumMargin << 1);
8567 cancel_info.y=(int) windows->widget.height-
8568 cancel_info.height-QuantumMargin;
8569 XGetWidgetInfo(ApplyButtonText,&apply_info);
8570 apply_info.width=width;
8571 apply_info.height=(unsigned int) (3*height) >> 1;
8572 apply_info.x=QuantumMargin << 1;
8573 apply_info.y=cancel_info.y;
8574 y=(int) (height << 1);
8575 for (i=0; i < NumberPreferences; i++)
8577 XGetWidgetInfo(Preferences[i],&preferences_info[i]);
8578 preferences_info[i].bevel_width--;
8579 preferences_info[i].width=(unsigned int) QuantumMargin >> 1;
8580 preferences_info[i].height=(unsigned int) QuantumMargin >> 1;
8581 preferences_info[i].x=QuantumMargin << 1;
8582 preferences_info[i].y=y;
8583 y+=height+(QuantumMargin >> 1);
8585 preferences_info[0].raised=resource_info->backdrop ==
8586 MagickFalse ? MagickTrue : MagickFalse;
8587 preferences_info[1].raised=resource_info->confirm_exit ==
8588 MagickFalse ? MagickTrue : MagickFalse;
8589 preferences_info[2].raised=resource_info->confirm_edit ==
8590 MagickFalse ? MagickTrue : MagickFalse;
8591 preferences_info[3].raised=resource_info->gamma_correct ==
8592 MagickFalse ? MagickTrue : MagickFalse;
8593 preferences_info[4].raised=resource_info->display_warnings ==
8594 MagickFalse ? MagickTrue : MagickFalse;
8595 preferences_info[5].raised=
8596 resource_info->quantize_info->dither_method == NoDitherMethod ?
8597 MagickTrue : MagickFalse;
8598 preferences_info[6].raised=resource_info->colormap !=
8599 SharedColormap ? MagickTrue : MagickFalse;
8600 preferences_info[7].raised=resource_info->use_pixmap ==
8601 MagickFalse ? MagickTrue : MagickFalse;
8602 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8603 (unsigned long) resource_info->undo_cache);
8604 XGetWidgetInfo(cache,&cache_info);
8605 cache_info.bevel_width--;
8606 cache_info.width=(unsigned int) QuantumMargin >> 1;
8607 cache_info.height=(unsigned int) QuantumMargin >> 1;
8608 cache_info.x=QuantumMargin << 1;
8610 state&=(~UpdateConfigurationState);
8612 if (state & RedrawWidgetState)
8615 Redraw Preferences widget.
8617 XDrawBeveledButton(display,&windows->widget,&apply_info);
8618 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8619 for (i=0; i < NumberPreferences; i++)
8620 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8621 XDrawTriangleEast(display,&windows->widget,&cache_info);
8622 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
8623 state&=(~RedrawWidgetState);
8626 Wait for next event.
8628 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
8633 if (MatteIsActive(apply_info,event.xbutton))
8636 User pressed Apply button.
8638 apply_info.raised=MagickFalse;
8639 XDrawBeveledButton(display,&windows->widget,&apply_info);
8642 if (MatteIsActive(cancel_info,event.xbutton))
8645 User pressed Cancel button.
8647 cancel_info.raised=MagickFalse;
8648 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8651 for (i=0; i < NumberPreferences; i++)
8652 if (MatteIsActive(preferences_info[i],event.xbutton))
8655 User pressed a Preferences button.
8657 preferences_info[i].raised=preferences_info[i].raised ==
8658 MagickFalse ? MagickTrue : MagickFalse;
8659 XDrawBeveledButton(display,&windows->widget,&preferences_info[i]);
8662 if (MatteIsActive(cache_info,event.xbutton))
8665 User pressed Cache button.
8667 x=cache_info.x+cache_info.width+cache_info.bevel_width+
8668 (QuantumMargin >> 1);
8669 y=cache_info.y+((cache_info.height-height) >> 1);
8670 width=WidgetTextWidth(font_info,cache);
8671 (void) XClearArea(display,windows->widget.id,x,y,width,height,
8673 resource_info->undo_cache<<=1;
8674 if (resource_info->undo_cache > 256)
8675 resource_info->undo_cache=1;
8676 (void) FormatLocaleString(cache,MaxTextExtent,CacheButtonText,
8677 (unsigned long) resource_info->undo_cache);
8678 cache_info.raised=MagickFalse;
8679 XDrawTriangleEast(display,&windows->widget,&cache_info);
8686 if (windows->widget.mapped == MagickFalse)
8688 if (apply_info.raised == MagickFalse)
8690 if (event.xbutton.window == windows->widget.id)
8691 if (MatteIsActive(apply_info,event.xbutton))
8693 apply_info.raised=MagickTrue;
8694 XDrawBeveledButton(display,&windows->widget,&apply_info);
8695 apply_info.raised=MagickFalse;
8697 if (cancel_info.raised == MagickFalse)
8699 if (event.xbutton.window == windows->widget.id)
8700 if (MatteIsActive(cancel_info,event.xbutton))
8702 cancel_info.raised=MagickTrue;
8703 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8705 if (cache_info.raised == MagickFalse)
8707 cache_info.raised=MagickTrue;
8708 XDrawTriangleEast(display,&windows->widget,&cache_info);
8715 If client window delete message, exit.
8717 if (event.xclient.message_type != windows->wm_protocols)
8719 if (*event.xclient.data.l == (int) windows->wm_take_focus)
8721 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
8722 (Time) event.xclient.data.l[1]);
8725 if (*event.xclient.data.l != (int) windows->wm_delete_window)
8727 if (event.xclient.window == windows->widget.id)
8734 case ConfigureNotify:
8737 Update widget configuration.
8739 if (event.xconfigure.window != windows->widget.id)
8741 if ((event.xconfigure.width == (int) windows->widget.width) &&
8742 (event.xconfigure.height == (int) windows->widget.height))
8744 windows->widget.width=(unsigned int)
8745 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
8746 windows->widget.height=(unsigned int)
8747 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
8748 state|=UpdateConfigurationState;
8753 if (event.xcrossing.window != windows->widget.id)
8755 state&=(~InactiveWidgetState);
8760 if (event.xexpose.window != windows->widget.id)
8762 if (event.xexpose.count != 0)
8764 state|=RedrawWidgetState;
8770 command[MaxTextExtent];
8776 Respond to a user key press.
8778 if (event.xkey.window != windows->widget.id)
8780 (void) XLookupString((XKeyEvent *) &event.xkey,command,
8781 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
8782 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
8784 apply_info.raised=MagickFalse;
8785 XDrawBeveledButton(display,&windows->widget,&apply_info);
8793 if (event.xcrossing.window != windows->widget.id)
8795 state|=InactiveWidgetState;
8801 Discard pending button motion events.
8803 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
8804 if (state & InactiveWidgetState)
8806 if (apply_info.raised == MatteIsActive(apply_info,event.xmotion))
8809 Apply button status changed.
8812 apply_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8813 XDrawBeveledButton(display,&windows->widget,&apply_info);
8816 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
8819 Cancel button status changed.
8822 cancel_info.raised == MagickFalse ? MagickTrue : MagickFalse;
8823 XDrawBeveledButton(display,&windows->widget,&cancel_info);
8831 } while ((state & ExitState) == 0);
8832 XSetCursorState(display,windows,MagickFalse);
8833 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
8834 XCheckRefreshWindows(display,windows);
8835 if (apply_info.raised)
8836 return(MagickFalse);
8838 Save user preferences to the client configuration file.
8840 resource_info->backdrop=
8841 preferences_info[0].raised == MagickFalse ? MagickTrue : MagickFalse;
8842 resource_info->confirm_exit=
8843 preferences_info[1].raised == MagickFalse ? MagickTrue : MagickFalse;
8844 resource_info->confirm_edit=
8845 preferences_info[2].raised == MagickFalse ? MagickTrue : MagickFalse;
8846 resource_info->gamma_correct=
8847 preferences_info[3].raised == MagickFalse ? MagickTrue : MagickFalse;
8848 resource_info->display_warnings=
8849 preferences_info[4].raised == MagickFalse ? MagickTrue : MagickFalse;
8850 resource_info->quantize_info->dither_method=
8851 preferences_info[5].raised == MagickFalse ?
8852 RiemersmaDitherMethod : NoDitherMethod;
8853 resource_info->colormap=SharedColormap;
8854 if (preferences_info[6].raised)
8855 resource_info->colormap=PrivateColormap;
8856 resource_info->use_pixmap=
8857 preferences_info[7].raised == MagickFalse ? MagickTrue : MagickFalse;
8858 XUserPreferences(resource_info);
8863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8867 % X P r o g r e s s M o n i t o r W i d g e t %
8871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8873 % XProgressMonitorWidget() displays the progress a task is making in
8874 % completing a task. A span of zero toggles the active status. An inactive
8875 % state disables the progress monitor.
8877 % The format of the XProgressMonitorWidget method is:
8879 % void XProgressMonitorWidget(Display *display,XWindows *windows,
8880 % const char *task,const MagickOffsetType offset,
8881 % const MagickSizeType span)
8883 % A description of each parameter follows:
8885 % o display: Specifies a connection to an X server; returned from
8888 % o window: Specifies a pointer to a XWindows structure.
8890 % o task: Identifies the task in progress.
8892 % o offset: Specifies the offset position within the span which represents
8893 % how much progress has been made in completing a task.
8895 % o span: Specifies the span relative to completing a task.
8898 MagickPrivate void XProgressMonitorWidget(Display *display,XWindows *windows,
8899 const char *task,const MagickOffsetType offset,const MagickSizeType span)
8907 assert(display != (Display *) NULL);
8908 assert(windows != (XWindows *) NULL);
8909 assert(task != (const char *) NULL);
8910 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",task);
8914 Update image windows if there is a pending expose event.
8916 while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
8917 (void) XCommandWidget(display,windows,(const char **) NULL,&event);
8918 while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
8919 XRefreshWindow(display,&windows->image,&event);
8920 while (XCheckTypedWindowEvent(display,windows->info.id,Expose,&event))
8921 if (monitor_info.text != (char *) NULL)
8922 XInfoWidget(display,windows,monitor_info.text);
8924 Draw progress monitor bar to represent percent completion of a task.
8926 if ((windows->info.mapped == MagickFalse) || (task != monitor_info.text))
8927 XInfoWidget(display,windows,task);
8928 width=(unsigned int) (((offset+1)*(windows->info.width-
8929 (2*monitor_info.x)))/span);
8930 if (width < monitor_info.width)
8932 monitor_info.raised=MagickTrue;
8933 XDrawWidgetText(display,&windows->info,&monitor_info);
8934 monitor_info.raised=MagickFalse;
8936 monitor_info.width=width;
8937 XDrawWidgetText(display,&windows->info,&monitor_info);
8938 (void) XFlush(display);
8942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8946 % X T e x t V i e w W i d g e t %
8950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8952 % XTextViewWidget() displays text in a Text View widget.
8954 % The format of the XTextViewWidget method is:
8956 % void XTextViewWidget(Display *display,const XResourceInfo *resource_info,
8957 % XWindows *windows,const MagickBooleanType mono,const char *title,
8958 % const char **textlist)
8960 % A description of each parameter follows:
8962 % o display: Specifies a connection to an X server; returned from
8965 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
8967 % o window: Specifies a pointer to a XWindows structure.
8969 % o mono: Use mono-spaced font when displaying text.
8971 % o title: This character string is displayed at the top of the widget
8974 % o textlist: This string list is displayed within the Text View widget.
8977 MagickPrivate void XTextViewWidget(Display *display,
8978 const XResourceInfo *resource_info,XWindows *windows,
8979 const MagickBooleanType mono,const char *title,const char **textlist)
8981 #define DismissButtonText "Dismiss"
8984 primary_selection[MaxTextExtent];
8989 static MagickStatusType
8990 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
9030 Convert text string to a text list.
9032 assert(display != (Display *) NULL);
9033 assert(resource_info != (XResourceInfo *) NULL);
9034 assert(windows != (XWindows *) NULL);
9035 assert(title != (const char *) NULL);
9036 assert(textlist != (const char **) NULL);
9037 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",title);
9038 XSetCursorState(display,windows,MagickTrue);
9039 XCheckRefreshWindows(display,windows);
9040 if (textlist == (const char **) NULL)
9042 XNoticeWidget(display,windows,"No text to view:",(char *) NULL);
9046 Determine Text View widget attributes.
9048 font_info=windows->widget.font_info;
9049 text_info=(XFontStruct *) NULL;
9050 if (mono != MagickFalse)
9051 text_info=XBestFont(display,resource_info,MagickTrue);
9052 if (text_info == (XFontStruct *) NULL)
9053 text_info=windows->widget.font_info;
9055 for (i=0; textlist[i] != (char *) NULL; i++)
9056 if (WidgetTextWidth(text_info,(char *) textlist[i]) > text_width)
9057 text_width=(unsigned int) XTextWidth(text_info,(char *) textlist[i],
9058 MagickMin(Extent(textlist[i]),160));
9059 lines=(unsigned int) i;
9060 width=WidgetTextWidth(font_info,DismissButtonText);
9061 width+=QuantumMargin;
9062 height=(unsigned int) (text_info->ascent+text_info->descent);
9064 Position Text View widget.
9066 windows->widget.width=(unsigned int) (MagickMin((int) text_width,
9067 (int) MaxTextWidth)+5*QuantumMargin);
9068 windows->widget.min_width=(unsigned int) (MinTextWidth+4*QuantumMargin);
9069 if (windows->widget.width < windows->widget.min_width)
9070 windows->widget.width=windows->widget.min_width;
9071 windows->widget.height=(unsigned int) (MagickMin(MagickMax((int) lines,3),32)*
9072 height+((13*height) >> 1)+((9*QuantumMargin) >> 1));
9073 windows->widget.min_height=(unsigned int) (3*height+((13*height) >> 1)+((9*
9074 QuantumMargin) >> 1));
9075 if (windows->widget.height < windows->widget.min_height)
9076 windows->widget.height=windows->widget.min_height;
9077 XConstrainWindowPosition(display,&windows->widget);
9079 Map Text View widget.
9081 (void) CopyMagickString(windows->widget.name,title,MaxTextExtent);
9082 status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
9083 if (status != False)
9085 XSetWMName(display,windows->widget.id,&window_name);
9086 XSetWMIconName(display,windows->widget.id,&window_name);
9087 (void) XFree((void *) window_name.value);
9089 window_changes.width=(int) windows->widget.width;
9090 window_changes.height=(int) windows->widget.height;
9091 window_changes.x=windows->widget.x;
9092 window_changes.y=windows->widget.y;
9093 (void) XReconfigureWMWindow(display,windows->widget.id,
9094 windows->widget.screen,(unsigned int) mask,&window_changes);
9095 (void) XMapRaised(display,windows->widget.id);
9096 windows->widget.mapped=MagickFalse;
9098 Respond to X events.
9100 XGetWidgetInfo((char *) NULL,&slider_info);
9101 XGetWidgetInfo((char *) NULL,&north_info);
9102 XGetWidgetInfo((char *) NULL,&south_info);
9103 XGetWidgetInfo((char *) NULL,&expose_info);
9104 XGetWidgetInfo((char *) NULL,&selection_info);
9106 delay=SuspendTime << 2;
9107 height=(unsigned int) (font_info->ascent+font_info->descent);
9108 state=UpdateConfigurationState;
9111 if (state & UpdateConfigurationState)
9117 Initialize button information.
9119 XGetWidgetInfo(DismissButtonText,&dismiss_info);
9120 dismiss_info.width=width;
9121 dismiss_info.height=(unsigned int) ((3*height) >> 1);
9122 dismiss_info.x=(int) windows->widget.width-dismiss_info.width-
9124 dismiss_info.y=(int) windows->widget.height-dismiss_info.height-
9127 Initialize scroll information.
9129 XGetWidgetInfo((char *) NULL,&scroll_info);
9130 scroll_info.bevel_width--;
9131 scroll_info.width=height;
9132 scroll_info.height=(unsigned int) (dismiss_info.y-((5*QuantumMargin) >>
9134 scroll_info.x=(int) windows->widget.width-QuantumMargin-
9136 scroll_info.y=(3*QuantumMargin) >> 1;
9137 scroll_info.raised=MagickFalse;
9138 scroll_info.trough=MagickTrue;
9139 north_info=scroll_info;
9140 north_info.raised=MagickTrue;
9141 north_info.width-=(north_info.bevel_width << 1);
9142 north_info.height=north_info.width-1;
9143 north_info.x+=north_info.bevel_width;
9144 north_info.y+=north_info.bevel_width;
9145 south_info=north_info;
9146 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
9149 slider_info=north_info;
9151 slider_info.width-=2;
9152 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
9153 slider_info.bevel_width+2;
9154 slider_info.height=scroll_info.height-((slider_info.min_y-
9155 scroll_info.y+1) << 1)+4;
9156 visible_lines=scroll_info.height/(text_info->ascent+text_info->descent+
9157 ((text_info->ascent+text_info->descent) >> 3));
9158 if (lines > visible_lines)
9159 slider_info.height=(unsigned int) (visible_lines*slider_info.height)/
9161 slider_info.max_y=south_info.y-south_info.bevel_width-
9162 slider_info.bevel_width-2;
9163 slider_info.x=scroll_info.x+slider_info.bevel_width+1;
9164 slider_info.y=slider_info.min_y;
9165 expose_info=scroll_info;
9166 expose_info.y=slider_info.y;
9168 Initialize list information.
9170 XGetWidgetInfo((char *) NULL,&list_info);
9171 list_info.raised=MagickFalse;
9172 list_info.bevel_width--;
9173 list_info.width=(unsigned int) scroll_info.x-((3*QuantumMargin) >> 1);
9174 list_info.height=scroll_info.height;
9175 list_info.x=QuantumMargin;
9176 list_info.y=scroll_info.y;
9178 Initialize selection information.
9180 XGetWidgetInfo((char *) NULL,&selection_info);
9181 selection_info.center=MagickFalse;
9182 selection_info.width=list_info.width;
9183 selection_info.height=(unsigned int)
9184 (9*(text_info->ascent+text_info->descent)) >> 3;
9185 selection_info.x=list_info.x;
9186 state&=(~UpdateConfigurationState);
9188 if (state & RedrawWidgetState)
9191 Redraw Text View window.
9193 XDrawBeveledMatte(display,&windows->widget,&list_info);
9194 XDrawBeveledMatte(display,&windows->widget,&scroll_info);
9195 XDrawTriangleNorth(display,&windows->widget,&north_info);
9196 XDrawBeveledButton(display,&windows->widget,&slider_info);
9197 XDrawTriangleSouth(display,&windows->widget,&south_info);
9198 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9199 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
9200 selection_info.id=(~0);
9201 state|=RedrawListState;
9202 state&=(~RedrawWidgetState);
9204 if (state & RedrawListState)
9207 Determine slider id and position.
9209 if (slider_info.id >= (int) (lines-visible_lines))
9210 slider_info.id=(int) lines-visible_lines;
9211 if ((slider_info.id < 0) || (lines <= visible_lines))
9213 slider_info.y=slider_info.min_y;
9216 slider_info.id*(slider_info.max_y-slider_info.min_y+1)/lines;
9217 if (slider_info.id != selection_info.id)
9220 Redraw scroll bar and text.
9222 windows->widget.font_info=text_info;
9223 (void) XSetFont(display,windows->widget.annotate_context,
9225 (void) XSetFont(display,windows->widget.highlight_context,
9227 selection_info.id=slider_info.id;
9228 selection_info.y=list_info.y+(height >> 3)+2;
9229 for (i=0; i < (int) visible_lines; i++)
9231 selection_info.raised=
9232 (slider_info.id+i) != list_info.id ? MagickTrue : MagickFalse;
9233 selection_info.text=(char *) NULL;
9234 if ((slider_info.id+i) < (int) lines)
9235 selection_info.text=(char *) textlist[slider_info.id+i];
9236 XDrawWidgetText(display,&windows->widget,&selection_info);
9237 selection_info.y+=(int) selection_info.height;
9239 windows->widget.font_info=font_info;
9240 (void) XSetFont(display,windows->widget.annotate_context,
9242 (void) XSetFont(display,windows->widget.highlight_context,
9247 if (slider_info.y > expose_info.y)
9249 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
9250 expose_info.y=slider_info.y-expose_info.height-
9251 slider_info.bevel_width-1;
9255 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
9256 expose_info.y=slider_info.y+slider_info.height+
9257 slider_info.bevel_width+1;
9259 XDrawTriangleNorth(display,&windows->widget,&north_info);
9260 XDrawMatte(display,&windows->widget,&expose_info);
9261 XDrawBeveledButton(display,&windows->widget,&slider_info);
9262 XDrawTriangleSouth(display,&windows->widget,&south_info);
9263 expose_info.y=slider_info.y;
9265 state&=(~RedrawListState);
9268 Wait for next event.
9270 if (north_info.raised && south_info.raised)
9271 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
9275 Brief delay before advancing scroll bar.
9277 XDelay(display,delay);
9279 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
9280 if (north_info.raised == MagickFalse)
9281 if (slider_info.id > 0)
9287 state|=RedrawListState;
9289 if (south_info.raised == MagickFalse)
9290 if (slider_info.id < (int) lines)
9296 state|=RedrawListState;
9298 if (event.type != ButtonRelease)
9305 if (MatteIsActive(slider_info,event.xbutton))
9310 slider_info.active=MagickTrue;
9313 if (MatteIsActive(north_info,event.xbutton))
9314 if (slider_info.id > 0)
9319 north_info.raised=MagickFalse;
9321 state|=RedrawListState;
9324 if (MatteIsActive(south_info,event.xbutton))
9325 if (slider_info.id < (int) lines)
9330 south_info.raised=MagickFalse;
9332 state|=RedrawListState;
9335 if (MatteIsActive(scroll_info,event.xbutton))
9340 if (event.xbutton.y < slider_info.y)
9341 slider_info.id-=(visible_lines-1);
9343 slider_info.id+=(visible_lines-1);
9344 state|=RedrawListState;
9347 if (MatteIsActive(dismiss_info,event.xbutton))
9350 User pressed Dismiss button.
9352 dismiss_info.raised=MagickFalse;
9353 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9356 if (MatteIsActive(list_info,event.xbutton))
9365 User pressed list matte.
9367 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
9368 selection_info.height;
9369 if (id >= (int) lines)
9371 if (id != list_info.id)
9374 click_time=event.xbutton.time;
9378 if (event.xbutton.time >= (click_time+DoubleClick))
9380 click_time=event.xbutton.time;
9383 click_time=event.xbutton.time;
9385 Become the XA_PRIMARY selection owner.
9387 (void) CopyMagickString(primary_selection,textlist[list_info.id],
9389 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
9390 event.xbutton.time);
9391 if (XGetSelectionOwner(display,XA_PRIMARY) != windows->widget.id)
9393 selection_info.id=(~0);
9395 state|=RedrawListState;
9402 if (windows->widget.mapped == MagickFalse)
9404 if (north_info.raised == MagickFalse)
9407 User released up button.
9409 delay=SuspendTime << 2;
9410 north_info.raised=MagickTrue;
9411 XDrawTriangleNorth(display,&windows->widget,&north_info);
9413 if (south_info.raised == MagickFalse)
9416 User released down button.
9418 delay=SuspendTime << 2;
9419 south_info.raised=MagickTrue;
9420 XDrawTriangleSouth(display,&windows->widget,&south_info);
9422 if (slider_info.active)
9425 Stop tracking slider.
9427 slider_info.active=MagickFalse;
9430 if (dismiss_info.raised == MagickFalse)
9432 if (event.xbutton.window == windows->widget.id)
9433 if (MatteIsActive(dismiss_info,event.xbutton))
9435 dismiss_info.raised=MagickTrue;
9436 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9443 If client window delete message, exit.
9445 if (event.xclient.message_type != windows->wm_protocols)
9447 if (*event.xclient.data.l == (int) windows->wm_take_focus)
9449 (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
9450 (Time) event.xclient.data.l[1]);
9453 if (*event.xclient.data.l != (int) windows->wm_delete_window)
9455 if (event.xclient.window == windows->widget.id)
9462 case ConfigureNotify:
9465 Update widget configuration.
9467 if (event.xconfigure.window != windows->widget.id)
9469 if ((event.xconfigure.width == (int) windows->widget.width) &&
9470 (event.xconfigure.height == (int) windows->widget.height))
9472 windows->widget.width=(unsigned int)
9473 MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
9474 windows->widget.height=(unsigned int)
9475 MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
9476 state|=UpdateConfigurationState;
9481 if (event.xcrossing.window != windows->widget.id)
9483 state&=(~InactiveWidgetState);
9488 if (event.xexpose.window != windows->widget.id)
9490 if (event.xexpose.count != 0)
9492 state|=RedrawWidgetState;
9498 command[MaxTextExtent];
9507 Respond to a user key press.
9509 if (event.xkey.window != windows->widget.id)
9511 length=XLookupString((XKeyEvent *) &event.xkey,command,
9512 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9513 *(command+length)='\0';
9514 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
9516 dismiss_info.raised=MagickFalse;
9517 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9521 if (AreaIsActive(scroll_info,event.xkey))
9526 switch ((int) key_symbol)
9549 slider_info.id-=visible_lines;
9555 slider_info.id+=visible_lines;
9561 slider_info.id=(int) lines;
9565 state|=RedrawListState;
9574 if (event.xcrossing.window != windows->widget.id)
9576 state|=InactiveWidgetState;
9588 Discard pending button motion events.
9590 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9591 if (slider_info.active)
9596 slider_info.y=event.xmotion.y-
9597 ((slider_info.height+slider_info.bevel_width) >> 1)+1;
9598 if (slider_info.y < slider_info.min_y)
9599 slider_info.y=slider_info.min_y;
9600 if (slider_info.y > slider_info.max_y)
9601 slider_info.y=slider_info.max_y;
9603 if (slider_info.y != slider_info.min_y)
9604 slider_info.id=(int) (lines*(slider_info.y-slider_info.min_y+1))/
9605 (slider_info.max_y-slider_info.min_y+1);
9606 state|=RedrawListState;
9609 if (state & InactiveWidgetState)
9611 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
9614 Dismiss button status changed.
9616 dismiss_info.raised=
9617 dismiss_info.raised == MagickFalse ? MagickTrue : MagickFalse;
9618 XDrawBeveledButton(display,&windows->widget,&dismiss_info);
9623 case SelectionClear:
9626 selection_info.id=(~0);
9627 state|=RedrawListState;
9630 case SelectionRequest:
9635 XSelectionRequestEvent
9638 if (list_info.id == (~0))
9641 Set primary selection.
9643 request=(&(event.xselectionrequest));
9644 (void) XChangeProperty(request->display,request->requestor,
9645 request->property,request->target,8,PropModeReplace,
9646 (unsigned char *) primary_selection,Extent(primary_selection));
9647 notify.type=SelectionNotify;
9648 notify.send_event=MagickTrue;
9649 notify.display=request->display;
9650 notify.requestor=request->requestor;
9651 notify.selection=request->selection;
9652 notify.target=request->target;
9653 notify.time=request->time;
9654 if (request->property == None)
9655 notify.property=request->target;
9657 notify.property=request->property;
9658 (void) XSendEvent(request->display,request->requestor,False,NoEventMask,
9659 (XEvent *) ¬ify);
9664 } while ((state & ExitState) == 0);
9665 if (text_info != windows->widget.font_info)
9666 (void) XFreeFont(display,text_info);
9667 XSetCursorState(display,windows,MagickFalse);
9668 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
9669 XCheckRefreshWindows(display,windows);