widget.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                                                                             %
00007 %                  W   W  IIIII  DDDD    GGGG  EEEEE  TTTTT                   %
00008 %                  W   W    I    D   D  G      E        T                     %
00009 %                  W W W    I    D   D  G  GG  EEE      T                     %
00010 %                  WW WW    I    D   D  G   G  E        T                     %
00011 %                  W   W  IIIII  DDDD    GGGG  EEEEE    T                     %
00012 %                                                                             %
00013 %                                                                             %
00014 %                   MagickCore X11 User Interface Methods                     %
00015 %                                                                             %
00016 %                              Software Design                                %
00017 %                                John Cristy                                  %
00018 %                              September 1993                                 %
00019 %                                                                             %
00020 %                                                                             %
00021 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
00022 %  dedicated to making software imaging solutions freely available.           %
00023 %                                                                             %
00024 %  You may not use this file except in compliance with the License.  You may  %
00025 %  obtain a copy of the License at                                            %
00026 %                                                                             %
00027 %    http://www.imagemagick.org/script/license.php                            %
00028 %                                                                             %
00029 %  Unless required by applicable law or agreed to in writing, software        %
00030 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00031 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00032 %  See the License for the specific language governing permissions and        %
00033 %  limitations under the License.                                             %
00034 %                                                                             %
00035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00036 %
00037 %
00038 */
00039 
00040 /*
00041   Include declarations.
00042 */
00043 #include "magick/studio.h"
00044 #include "magick/color.h"
00045 #include "magick/color-private.h"
00046 #include "magick/exception.h"
00047 #include "magick/exception-private.h"
00048 #include "magick/image.h"
00049 #include "magick/magick.h"
00050 #include "magick/memory_.h"
00051 #include "magick/PreRvIcccm.h"
00052 #include "magick/string_.h"
00053 #include "magick/token.h"
00054 #include "magick/utility.h"
00055 #include "magick/xwindow-private.h"
00056 #include "magick/widget.h"
00057 
00058 #if defined(MAGICKCORE_X11_DELEGATE)
00059 
00060 /*
00061   Define declarations.
00062 */
00063 #define AreaIsActive(matte_info,position)  ( \
00064   ((position.y >= (int) (matte_info.y-matte_info.bevel_width)) &&  \
00065    (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
00066    ? MagickTrue : MagickFalse)
00067 #define Extent(s)  ((int) strlen(s))
00068 #define MatteIsActive(matte_info,position)  ( \
00069   ((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \
00070    (position.y >= (int) (matte_info.y-matte_info.bevel_width)) &&  \
00071    (position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) &&  \
00072    (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
00073    ? MagickTrue : MagickFalse)
00074 #define MaxTextWidth  ((unsigned int) (255*XTextWidth(font_info,"_",1)))
00075 #define MinTextWidth  (26*XTextWidth(font_info,"_",1))
00076 #define QuantumMargin   MagickMax(font_info->max_bounds.width,12)
00077 #define WidgetTextWidth(font_info,text)  \
00078   ((unsigned int) XTextWidth(font_info,text,Extent(text)))
00079 #define WindowIsActive(window_info,position)  ( \
00080   ((position.x >= 0) && (position.y >= 0) &&  \
00081    (position.x < (int) window_info.width) &&  \
00082    (position.y < (int) window_info.height)) ? MagickTrue : MagickFalse)
00083 
00084 /*
00085   Enum declarations.
00086 */
00087 typedef enum
00088 {
00089   ControlState = 0x0001,
00090   InactiveWidgetState = 0x0004,
00091   JumpListState = 0x0008,
00092   RedrawActionState = 0x0010,
00093   RedrawListState = 0x0020,
00094   RedrawWidgetState = 0x0040,
00095   UpdateListState = 0x0100
00096 } WidgetState;
00097 
00098 /*
00099   Typedef declarations.
00100 */
00101 typedef struct _XWidgetInfo
00102 {
00103   char
00104     *cursor,
00105     *text,
00106     *marker;
00107 
00108   int
00109     id;
00110 
00111   unsigned int
00112     bevel_width,
00113     width,
00114     height;
00115 
00116   int
00117     x,
00118     y,
00119     min_y,
00120     max_y;
00121 
00122   MagickStatusType
00123     raised,
00124     active,
00125     center,
00126     trough,
00127     highlight;
00128 } XWidgetInfo;
00129 
00130 /*
00131   Variable declarations.
00132 */
00133 static XWidgetInfo
00134   monitor_info =
00135   {
00136     (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
00137     MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
00138   },
00139   submenu_info =
00140   {
00141     (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
00142     MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
00143   },
00144   *selection_info = (XWidgetInfo *) NULL,
00145   toggle_info =
00146   {
00147     (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
00148     MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
00149   };
00150 
00151 /*
00152   Constant declarations.
00153 */
00154 static const int
00155   BorderOffset = 4,
00156   DoubleClick = 250;
00157 
00158 /*
00159   Method prototypes.
00160 */
00161 static void
00162   XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *),
00163   XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType),
00164   XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType),
00165   XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType);
00166 
00167 /*
00168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00169 %                                                                             %
00170 %                                                                             %
00171 %                                                                             %
00172 %   D e s t r o y X W i d g e t                                               %
00173 %                                                                             %
00174 %                                                                             %
00175 %                                                                             %
00176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00177 %
00178 %  DestroyXWidget() destroys resources associated with the X widget.
00179 %
00180 %  The format of the DestroyXWidget method is:
00181 %
00182 %      void DestroyXWidget()
00183 %
00184 %  A description of each parameter follows:
00185 %
00186 */
00187 MagickExport void DestroyXWidget(void)
00188 {
00189   if (selection_info != (XWidgetInfo *) NULL)
00190     selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
00191 }
00192 
00193 /*
00194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00195 %                                                                             %
00196 %                                                                             %
00197 %                                                                             %
00198 +   X D r a w B e v e l                                                       %
00199 %                                                                             %
00200 %                                                                             %
00201 %                                                                             %
00202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00203 %
00204 %  XDrawBevel() "sets off" an area with a highlighted upper and left bevel and
00205 %  a shadowed lower and right bevel.  The highlighted and shadowed bevels
00206 %  create a 3-D effect.
00207 %
00208 %  The format of the XDrawBevel function is:
00209 %
00210 %      XDrawBevel(display,window_info,bevel_info)
00211 %
00212 %  A description of each parameter follows:
00213 %
00214 %    o display: Specifies a pointer to the Display structure;  returned from
00215 %      XOpenDisplay.
00216 %
00217 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00218 %
00219 %    o bevel_info: Specifies a pointer to a XWidgetInfo structure.  It
00220 %      contains the extents of the bevel.
00221 %
00222 */
00223 static void XDrawBevel(Display *display,const XWindowInfo *window_info,
00224   const XWidgetInfo *bevel_info)
00225 {
00226   int
00227     x1,
00228     x2,
00229     y1,
00230     y2;
00231 
00232   unsigned int
00233     bevel_width;
00234 
00235   XPoint
00236     points[6];
00237 
00238   /*
00239     Draw upper and left beveled border.
00240   */
00241   x1=bevel_info->x;
00242   y1=bevel_info->y+bevel_info->height;
00243   x2=bevel_info->x+bevel_info->width;
00244   y2=bevel_info->y;
00245   bevel_width=bevel_info->bevel_width;
00246   points[0].x=x1;
00247   points[0].y=y1;
00248   points[1].x=x1;
00249   points[1].y=y2;
00250   points[2].x=x2;
00251   points[2].y=y2;
00252   points[3].x=x2+bevel_width;
00253   points[3].y=y2-bevel_width;
00254   points[4].x=x1-bevel_width;
00255   points[4].y=y2-bevel_width;
00256   points[5].x=x1-bevel_width;
00257   points[5].y=y1+bevel_width;
00258   XSetBevelColor(display,window_info,bevel_info->raised);
00259   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00260     points,6,Complex,CoordModeOrigin);
00261   /*
00262     Draw lower and right beveled border.
00263   */
00264   points[0].x=x1;
00265   points[0].y=y1;
00266   points[1].x=x2;
00267   points[1].y=y1;
00268   points[2].x=x2;
00269   points[2].y=y2;
00270   points[3].x=x2+bevel_width;
00271   points[3].y=y2-bevel_width;
00272   points[4].x=x2+bevel_width;
00273   points[4].y=y1+bevel_width;
00274   points[5].x=x1-bevel_width;
00275   points[5].y=y1+bevel_width;
00276   XSetBevelColor(display,window_info,!bevel_info->raised);
00277   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00278     points,6,Complex,CoordModeOrigin);
00279   (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
00280 }
00281 
00282 /*
00283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00284 %                                                                             %
00285 %                                                                             %
00286 %                                                                             %
00287 +   X D r a w B e v e l e d B u t t o n                                       %
00288 %                                                                             %
00289 %                                                                             %
00290 %                                                                             %
00291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00292 %
00293 %  XDrawBeveledButton() draws a button with a highlighted upper and left bevel
00294 %  and a shadowed lower and right bevel.  The highlighted and shadowed bevels
00295 %  create a 3-D effect.
00296 %
00297 %  The format of the XDrawBeveledButton function is:
00298 %
00299 %      XDrawBeveledButton(display,window_info,button_info)
00300 %
00301 %  A description of each parameter follows:
00302 %
00303 %    o display: Specifies a pointer to the Display structure;  returned from
00304 %      XOpenDisplay.
00305 %
00306 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00307 %
00308 %    o button_info: Specifies a pointer to a XWidgetInfo structure.  It
00309 %      contains the extents of the button.
00310 %
00311 */
00312 
00313 static inline int MagickAbsoluteValue(const int x)
00314 {
00315   if (x < 0)
00316     return(-x);
00317   return(x);
00318 }
00319 
00320 static inline int MagickMax(const int x,const int y)
00321 {
00322   if (x > y)
00323     return(x);
00324   return(y);
00325 }
00326 
00327 static inline int MagickMin(const int x,const int y)
00328 {
00329   if (x < y)
00330     return(x);
00331   return(y);
00332 }
00333 
00334 static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info,
00335   const XWidgetInfo *button_info)
00336 {
00337   int
00338     x,
00339     y;
00340 
00341   unsigned int
00342     width;
00343 
00344   XFontStruct
00345     *font_info;
00346 
00347   XRectangle
00348     crop_info;
00349 
00350   /*
00351     Draw matte.
00352   */
00353   XDrawBevel(display,window_info,button_info);
00354   XSetMatteColor(display,window_info,button_info->raised);
00355   (void) XFillRectangle(display,window_info->id,window_info->widget_context,
00356     button_info->x,button_info->y,button_info->width,button_info->height);
00357   x=button_info->x-button_info->bevel_width-1;
00358   y=button_info->y-button_info->bevel_width-1;
00359   (void) XSetForeground(display,window_info->widget_context,
00360     window_info->pixel_info->trough_color.pixel);
00361   if (button_info->raised || (window_info->depth == 1))
00362     (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
00363       x,y,button_info->width+(button_info->bevel_width << 1)+1,
00364       button_info->height+(button_info->bevel_width << 1)+1);
00365   if (button_info->text == (char *) NULL)
00366     return;
00367   /*
00368     Set cropping region.
00369   */
00370   crop_info.width=(unsigned short) button_info->width;
00371   crop_info.height=(unsigned short) button_info->height;
00372   crop_info.x=button_info->x;
00373   crop_info.y=button_info->y;
00374   /*
00375     Draw text.
00376   */
00377   font_info=window_info->font_info;
00378   width=WidgetTextWidth(font_info,button_info->text);
00379   x=button_info->x+(QuantumMargin >> 1);
00380   if (button_info->center)
00381     x=button_info->x+(button_info->width >> 1)-(width >> 1);
00382   y=button_info->y+((button_info->height-
00383     (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
00384   if ((int) button_info->width == (QuantumMargin >> 1))
00385     {
00386       /*
00387         Option button-- write label to right of button.
00388       */
00389       XSetTextColor(display,window_info,MagickTrue);
00390       x=button_info->x+button_info->width+button_info->bevel_width+
00391         (QuantumMargin >> 1);
00392       (void) XDrawString(display,window_info->id,window_info->widget_context,
00393         x,y,button_info->text,Extent(button_info->text));
00394       return;
00395     }
00396   (void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info,
00397     1,Unsorted);
00398   XSetTextColor(display,window_info,button_info->raised);
00399   (void) XDrawString(display,window_info->id,window_info->widget_context,x,y,
00400     button_info->text,Extent(button_info->text));
00401   (void) XSetClipMask(display,window_info->widget_context,None);
00402   if (button_info->raised == MagickFalse)
00403     XDelay(display,SuspendTime << 2);
00404 }
00405 
00406 /*
00407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00408 %                                                                             %
00409 %                                                                             %
00410 %                                                                             %
00411 +   X D r a w B e v e l e d M a t t e                                         %
00412 %                                                                             %
00413 %                                                                             %
00414 %                                                                             %
00415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00416 %
00417 %  XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and
00418 %  a highlighted lower and right bevel.  The highlighted and shadowed bevels
00419 %  create a 3-D effect.
00420 %
00421 %  The format of the XDrawBeveledMatte function is:
00422 %
00423 %      XDrawBeveledMatte(display,window_info,matte_info)
00424 %
00425 %  A description of each parameter follows:
00426 %
00427 %    o display: Specifies a pointer to the Display structure;  returned from
00428 %      XOpenDisplay.
00429 %
00430 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00431 %
00432 %    o matte_info: Specifies a pointer to a XWidgetInfo structure.  It
00433 %      contains the extents of the matte.
00434 %
00435 */
00436 static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info,
00437   const XWidgetInfo *matte_info)
00438 {
00439   /*
00440     Draw matte.
00441   */
00442   XDrawBevel(display,window_info,matte_info);
00443   XDrawMatte(display,window_info,matte_info);
00444 }
00445 
00446 /*
00447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00448 %                                                                             %
00449 %                                                                             %
00450 %                                                                             %
00451 +   X D r a w M a t t e                                                       %
00452 %                                                                             %
00453 %                                                                             %
00454 %                                                                             %
00455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00456 %
00457 %  XDrawMatte() fills a rectangular area with the matte color.
00458 %
00459 %  The format of the XDrawMatte function is:
00460 %
00461 %      XDrawMatte(display,window_info,matte_info)
00462 %
00463 %  A description of each parameter follows:
00464 %
00465 %    o display: Specifies a pointer to the Display structure;  returned from
00466 %      XOpenDisplay.
00467 %
00468 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00469 %
00470 %    o matte_info: Specifies a pointer to a XWidgetInfo structure.  It
00471 %      contains the extents of the matte.
00472 %
00473 */
00474 static void XDrawMatte(Display *display,const XWindowInfo *window_info,
00475   const XWidgetInfo *matte_info)
00476 {
00477   /*
00478     Draw matte.
00479   */
00480   if ((matte_info->trough == MagickFalse) || (window_info->depth == 1))
00481     (void) XFillRectangle(display,window_info->id,
00482       window_info->highlight_context,matte_info->x,matte_info->y,
00483       matte_info->width,matte_info->height);
00484   else
00485     {
00486       (void) XSetForeground(display,window_info->widget_context,
00487         window_info->pixel_info->trough_color.pixel);
00488       (void) XFillRectangle(display,window_info->id,window_info->widget_context,
00489         matte_info->x,matte_info->y,matte_info->width,matte_info->height);
00490     }
00491 }
00492 
00493 /*
00494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00495 %                                                                             %
00496 %                                                                             %
00497 %                                                                             %
00498 +   X D r a w M a t t e T e x t                                               %
00499 %                                                                             %
00500 %                                                                             %
00501 %                                                                             %
00502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00503 %
00504 %  XDrawMatteText() draws a matte with text.  If the text exceeds the extents
00505 %  of the text, a portion of the text relative to the cursor is displayed.
00506 %
00507 %  The format of the XDrawMatteText function is:
00508 %
00509 %      XDrawMatteText(display,window_info,text_info)
00510 %
00511 %  A description of each parameter follows:
00512 %
00513 %    o display: Specifies a pointer to the Display structure;  returned from
00514 %      XOpenDisplay.
00515 %
00516 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00517 %
00518 %    o text_info: Specifies a pointer to a XWidgetInfo structure.  It
00519 %      contains the extents of the text.
00520 %
00521 */
00522 static void XDrawMatteText(Display *display,const XWindowInfo *window_info,
00523   XWidgetInfo *text_info)
00524 {
00525   const char
00526     *text;
00527 
00528   int
00529     n,
00530     x,
00531     y;
00532 
00533   register int
00534     i;
00535 
00536   unsigned int
00537     height,
00538     width;
00539 
00540   XFontStruct
00541     *font_info;
00542 
00543   XRectangle
00544     crop_info;
00545 
00546   /*
00547     Clear the text area.
00548   */
00549   XSetMatteColor(display,window_info,MagickFalse);
00550   (void) XFillRectangle(display,window_info->id,window_info->widget_context,
00551     text_info->x,text_info->y,text_info->width,text_info->height);
00552   if (text_info->text == (char *) NULL)
00553     return;
00554   XSetTextColor(display,window_info,text_info->highlight);
00555   font_info=window_info->font_info;
00556   x=text_info->x+(QuantumMargin >> 2);
00557   y=text_info->y+font_info->ascent+(text_info->height >> 2);
00558   width=text_info->width-(QuantumMargin >> 1);
00559   height=(unsigned int) (font_info->ascent+font_info->descent);
00560   if (*text_info->text == '\0')
00561     {
00562       /*
00563         No text-- just draw cursor.
00564       */
00565       (void) XDrawLine(display,window_info->id,window_info->annotate_context,
00566         x,y+3,x,y-height+3);
00567       return;
00568     }
00569   /*
00570     Set cropping region.
00571   */
00572   crop_info.width=(unsigned short) text_info->width;
00573   crop_info.height=(unsigned short) text_info->height;
00574   crop_info.x=text_info->x;
00575   crop_info.y=text_info->y;
00576   /*
00577     Determine beginning of the visible text.
00578   */
00579   if (text_info->cursor < text_info->marker)
00580     text_info->marker=text_info->cursor;
00581   else
00582     {
00583       text=text_info->marker;
00584       if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) >
00585           (int) width)
00586         {
00587           text=text_info->text;
00588           for (i=0; i < Extent(text); i++)
00589           {
00590             n=XTextWidth(font_info,(char *) text+i,(int)
00591               (text_info->cursor-text-i));
00592             if (n <= (int) width)
00593               break;
00594           }
00595           text_info->marker=(char *) text+i;
00596         }
00597     }
00598   /*
00599     Draw text and cursor.
00600   */
00601   if (text_info->highlight == MagickFalse)
00602     {
00603       (void) XSetClipRectangles(display,window_info->widget_context,0,0,
00604         &crop_info,1,Unsorted);
00605       (void) XDrawString(display,window_info->id,window_info->widget_context,
00606         x,y,text_info->marker,Extent(text_info->marker));
00607       (void) XSetClipMask(display,window_info->widget_context,None);
00608     }
00609   else
00610     {
00611       (void) XSetClipRectangles(display,window_info->annotate_context,0,0,
00612         &crop_info,1,Unsorted);
00613       width=WidgetTextWidth(font_info,text_info->marker);
00614       (void) XFillRectangle(display,window_info->id,
00615         window_info->annotate_context,x,y-font_info->ascent,width,height);
00616       (void) XSetClipMask(display,window_info->annotate_context,None);
00617       (void) XSetClipRectangles(display,window_info->highlight_context,0,0,
00618         &crop_info,1,Unsorted);
00619       (void) XDrawString(display,window_info->id,
00620         window_info->highlight_context,x,y,text_info->marker,
00621         Extent(text_info->marker));
00622       (void) XSetClipMask(display,window_info->highlight_context,None);
00623     }
00624   x+=XTextWidth(font_info,text_info->marker,(int)
00625     (text_info->cursor-text_info->marker));
00626   (void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3,
00627     x,y-height+3);
00628 }
00629 
00630 /*
00631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00632 %                                                                             %
00633 %                                                                             %
00634 %                                                                             %
00635 +   X D r a w T r i a n g l e E a s t                                         %
00636 %                                                                             %
00637 %                                                                             %
00638 %                                                                             %
00639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00640 %
00641 %  XDrawTriangleEast() draws a triangle with a highlighted left bevel and a
00642 %  shadowed right and lower bevel.  The highlighted and shadowed bevels create
00643 %  a 3-D effect.
00644 %
00645 %  The format of the XDrawTriangleEast function is:
00646 %
00647 %      XDrawTriangleEast(display,window_info,triangle_info)
00648 %
00649 %  A description of each parameter follows:
00650 %
00651 %    o display: Specifies a pointer to the Display structure;  returned from
00652 %      XOpenDisplay.
00653 %
00654 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00655 %
00656 %    o triangle_info: Specifies a pointer to a XWidgetInfo structure.  It
00657 %      contains the extents of the triangle.
00658 %
00659 */
00660 static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info,
00661   const XWidgetInfo *triangle_info)
00662 {
00663   int
00664     x1,
00665     x2,
00666     x3,
00667     y1,
00668     y2,
00669     y3;
00670 
00671   unsigned int
00672     bevel_width;
00673 
00674   XFontStruct
00675     *font_info;
00676 
00677   XPoint
00678     points[4];
00679 
00680   /*
00681     Draw triangle matte.
00682   */
00683   x1=triangle_info->x;
00684   y1=triangle_info->y;
00685   x2=triangle_info->x+triangle_info->width;
00686   y2=triangle_info->y+(triangle_info->height >> 1);
00687   x3=triangle_info->x;
00688   y3=triangle_info->y+triangle_info->height;
00689   bevel_width=triangle_info->bevel_width;
00690   points[0].x=x1;
00691   points[0].y=y1;
00692   points[1].x=x2;
00693   points[1].y=y2;
00694   points[2].x=x3;
00695   points[2].y=y3;
00696   XSetMatteColor(display,window_info,triangle_info->raised);
00697   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00698     points,3,Complex,CoordModeOrigin);
00699   /*
00700     Draw bottom bevel.
00701   */
00702   points[0].x=x2;
00703   points[0].y=y2;
00704   points[1].x=x3;
00705   points[1].y=y3;
00706   points[2].x=x3-bevel_width;
00707   points[2].y=y3+bevel_width;
00708   points[3].x=x2+bevel_width;
00709   points[3].y=y2;
00710   XSetBevelColor(display,window_info,!triangle_info->raised);
00711   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00712     points,4,Complex,CoordModeOrigin);
00713   /*
00714     Draw Left bevel.
00715   */
00716   points[0].x=x3;
00717   points[0].y=y3;
00718   points[1].x=x1;
00719   points[1].y=y1;
00720   points[2].x=x1-bevel_width+1;
00721   points[2].y=y1-bevel_width;
00722   points[3].x=x3-bevel_width+1;
00723   points[3].y=y3+bevel_width;
00724   XSetBevelColor(display,window_info,triangle_info->raised);
00725   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00726     points,4,Complex,CoordModeOrigin);
00727   /*
00728     Draw top bevel.
00729   */
00730   points[0].x=x1;
00731   points[0].y=y1;
00732   points[1].x=x2;
00733   points[1].y=y2;
00734   points[2].x=x2+bevel_width;
00735   points[2].y=y2;
00736   points[3].x=x1-bevel_width;
00737   points[3].y=y1-bevel_width;
00738   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00739     points,4,Complex,CoordModeOrigin);
00740   (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
00741   if (triangle_info->text == (char *) NULL)
00742     return;
00743   /*
00744     Write label to right of triangle.
00745   */
00746   font_info=window_info->font_info;
00747   XSetTextColor(display,window_info,MagickTrue);
00748   x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+
00749     (QuantumMargin >> 1);
00750   y1=triangle_info->y+((triangle_info->height-
00751     (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
00752   (void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1,
00753     triangle_info->text,Extent(triangle_info->text));
00754 }
00755 
00756 /*
00757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00758 %                                                                             %
00759 %                                                                             %
00760 %                                                                             %
00761 +   X D r a w T r i a n g l e N o r t h                                       %
00762 %                                                                             %
00763 %                                                                             %
00764 %                                                                             %
00765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00766 %
00767 %  XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a
00768 %  shadowed right and lower bevel.  The highlighted and shadowed bevels create
00769 %  a 3-D effect.
00770 %
00771 %  The format of the XDrawTriangleNorth function is:
00772 %
00773 %      XDrawTriangleNorth(display,window_info,triangle_info)
00774 %
00775 %  A description of each parameter follows:
00776 %
00777 %    o display: Specifies a pointer to the Display structure;  returned from
00778 %      XOpenDisplay.
00779 %
00780 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00781 %
00782 %    o triangle_info: Specifies a pointer to a XWidgetInfo structure.  It
00783 %      contains the extents of the triangle.
00784 %
00785 */
00786 static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info,
00787   const XWidgetInfo *triangle_info)
00788 {
00789   int
00790     x1,
00791     x2,
00792     x3,
00793     y1,
00794     y2,
00795     y3;
00796 
00797   unsigned int
00798     bevel_width;
00799 
00800   XPoint
00801     points[4];
00802 
00803   /*
00804     Draw triangle matte.
00805   */
00806   x1=triangle_info->x;
00807   y1=triangle_info->y+triangle_info->height;
00808   x2=triangle_info->x+(triangle_info->width >> 1);
00809   y2=triangle_info->y;
00810   x3=triangle_info->x+triangle_info->width;
00811   y3=triangle_info->y+triangle_info->height;
00812   bevel_width=triangle_info->bevel_width;
00813   points[0].x=x1;
00814   points[0].y=y1;
00815   points[1].x=x2;
00816   points[1].y=y2;
00817   points[2].x=x3;
00818   points[2].y=y3;
00819   XSetMatteColor(display,window_info,triangle_info->raised);
00820   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00821     points,3,Complex,CoordModeOrigin);
00822   /*
00823     Draw left bevel.
00824   */
00825   points[0].x=x1;
00826   points[0].y=y1;
00827   points[1].x=x2;
00828   points[1].y=y2;
00829   points[2].x=x2;
00830   points[2].y=y2-bevel_width-2;
00831   points[3].x=x1-bevel_width-1;
00832   points[3].y=y1+bevel_width;
00833   XSetBevelColor(display,window_info,triangle_info->raised);
00834   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00835     points,4,Complex,CoordModeOrigin);
00836   /*
00837     Draw right bevel.
00838   */
00839   points[0].x=x2;
00840   points[0].y=y2;
00841   points[1].x=x3;
00842   points[1].y=y3;
00843   points[2].x=x3+bevel_width;
00844   points[2].y=y3+bevel_width;
00845   points[3].x=x2;
00846   points[3].y=y2-bevel_width;
00847   XSetBevelColor(display,window_info,!triangle_info->raised);
00848   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00849     points,4,Complex,CoordModeOrigin);
00850   /*
00851     Draw lower bevel.
00852   */
00853   points[0].x=x3;
00854   points[0].y=y3;
00855   points[1].x=x1;
00856   points[1].y=y1;
00857   points[2].x=x1-bevel_width;
00858   points[2].y=y1+bevel_width;
00859   points[3].x=x3+bevel_width;
00860   points[3].y=y3+bevel_width;
00861   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00862     points,4,Complex,CoordModeOrigin);
00863   (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
00864 }
00865 
00866 /*
00867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00868 %                                                                             %
00869 %                                                                             %
00870 %                                                                             %
00871 +   X D r a w T r i a n g l e S o u t h                                       %
00872 %                                                                             %
00873 %                                                                             %
00874 %                                                                             %
00875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00876 %
00877 %  XDrawTriangleSouth() draws a border with a highlighted left and right bevel
00878 %  and a shadowed lower bevel.  The highlighted and shadowed bevels create a
00879 %  3-D effect.
00880 %
00881 %  The format of the XDrawTriangleSouth function is:
00882 %
00883 %      XDrawTriangleSouth(display,window_info,triangle_info)
00884 %
00885 %  A description of each parameter follows:
00886 %
00887 %    o display: Specifies a pointer to the Display structure;  returned from
00888 %      XOpenDisplay.
00889 %
00890 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
00891 %
00892 %    o triangle_info: Specifies a pointer to a XWidgetInfo structure.  It
00893 %      contains the extents of the triangle.
00894 %
00895 */
00896 static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info,
00897   const XWidgetInfo *triangle_info)
00898 {
00899   int
00900     x1,
00901     x2,
00902     x3,
00903     y1,
00904     y2,
00905     y3;
00906 
00907   unsigned int
00908     bevel_width;
00909 
00910   XPoint
00911     points[4];
00912 
00913   /*
00914     Draw triangle matte.
00915   */
00916   x1=triangle_info->x;
00917   y1=triangle_info->y;
00918   x2=triangle_info->x+(triangle_info->width >> 1);
00919   y2=triangle_info->y+triangle_info->height;
00920   x3=triangle_info->x+triangle_info->width;
00921   y3=triangle_info->y;
00922   bevel_width=triangle_info->bevel_width;
00923   points[0].x=x1;
00924   points[0].y=y1;
00925   points[1].x=x2;
00926   points[1].y=y2;
00927   points[2].x=x3;
00928   points[2].y=y3;
00929   XSetMatteColor(display,window_info,triangle_info->raised);
00930   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00931     points,3,Complex,CoordModeOrigin);
00932   /*
00933     Draw top bevel.
00934   */
00935   points[0].x=x3;
00936   points[0].y=y3;
00937   points[1].x=x1;
00938   points[1].y=y1;
00939   points[2].x=x1-bevel_width;
00940   points[2].y=y1-bevel_width;
00941   points[3].x=x3+bevel_width;
00942   points[3].y=y3-bevel_width;
00943   XSetBevelColor(display,window_info,triangle_info->raised);
00944   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00945     points,4,Complex,CoordModeOrigin);
00946   /*
00947     Draw right bevel.
00948   */
00949   points[0].x=x2;
00950   points[0].y=y2;
00951   points[1].x=x3+1;
00952   points[1].y=y3-bevel_width;
00953   points[2].x=x3+bevel_width;
00954   points[2].y=y3-bevel_width;
00955   points[3].x=x2;
00956   points[3].y=y2+bevel_width;
00957   XSetBevelColor(display,window_info,!triangle_info->raised);
00958   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00959     points,4,Complex,CoordModeOrigin);
00960   /*
00961     Draw left bevel.
00962   */
00963   points[0].x=x1;
00964   points[0].y=y1;
00965   points[1].x=x2;
00966   points[1].y=y2;
00967   points[2].x=x2;
00968   points[2].y=y2+bevel_width;
00969   points[3].x=x1-bevel_width;
00970   points[3].y=y1-bevel_width;
00971   XSetBevelColor(display,window_info,triangle_info->raised);
00972   (void) XFillPolygon(display,window_info->id,window_info->widget_context,
00973     points,4,Complex,CoordModeOrigin);
00974   (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
00975 }
00976 
00977 /*
00978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00979 %                                                                             %
00980 %                                                                             %
00981 %                                                                             %
00982 +   X D r a w W i d g e t T e x t                                             %
00983 %                                                                             %
00984 %                                                                             %
00985 %                                                                             %
00986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00987 %
00988 %  XDrawWidgetText() first clears the widget and draws a text string justifed
00989 %  left (or center) in the x-direction and centered within the y-direction.
00990 %
00991 %  The format of the XDrawWidgetText function is:
00992 %
00993 %      XDrawWidgetText(display,window_info,text_info)
00994 %
00995 %  A description of each parameter follows:
00996 %
00997 %    o display: Specifies a pointer to the Display structure;  returned from
00998 %      XOpenDisplay.
00999 %
01000 %    o window_info: Specifies a pointer to a XWindowText structure.
01001 %
01002 %    o text_info: Specifies a pointer to XWidgetInfo structure.
01003 %
01004 */
01005 static void XDrawWidgetText(Display *display,const XWindowInfo *window_info,
01006   XWidgetInfo *text_info)
01007 {
01008   GC
01009     widget_context;
01010 
01011   int
01012     x,
01013     y;
01014 
01015   unsigned int
01016     height,
01017     width;
01018 
01019   XFontStruct
01020     *font_info;
01021 
01022   XRectangle
01023     crop_info;
01024 
01025   /*
01026     Clear the text area.
01027   */
01028   widget_context=window_info->annotate_context;
01029   if (text_info->raised)
01030     (void) XClearArea(display,window_info->id,text_info->x,text_info->y,
01031       text_info->width,text_info->height,MagickFalse);
01032   else
01033     {
01034       (void) XFillRectangle(display,window_info->id,widget_context,text_info->x,
01035         text_info->y,text_info->width,text_info->height);
01036       widget_context=window_info->highlight_context;
01037     }
01038   if (text_info->text == (char *) NULL)
01039     return;
01040   if (*text_info->text == '\0')
01041     return;
01042   /*
01043     Set cropping region.
01044   */
01045   font_info=window_info->font_info;
01046   crop_info.width=(unsigned short) text_info->width;
01047   crop_info.height=(unsigned short) text_info->height;
01048   crop_info.x=text_info->x;
01049   crop_info.y=text_info->y;
01050   /*
01051     Draw text.
01052   */
01053   width=WidgetTextWidth(font_info,text_info->text);
01054   x=text_info->x+(QuantumMargin >> 1);
01055   if (text_info->center)
01056     x=text_info->x+(text_info->width >> 1)-(width >> 1);
01057   if (text_info->raised)
01058     if (width > (text_info->width-QuantumMargin))
01059       x+=(text_info->width-QuantumMargin-width);
01060   height=(unsigned int) (font_info->ascent+font_info->descent);
01061   y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent;
01062   (void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted);
01063   (void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text,
01064     Extent(text_info->text));
01065   (void) XSetClipMask(display,widget_context,None);
01066   if (x < text_info->x)
01067     (void) XDrawLine(display,window_info->id,window_info->annotate_context,
01068       text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1);
01069 }
01070 
01071 /*
01072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01073 %                                                                             %
01074 %                                                                             %
01075 %                                                                             %
01076 +   X E d i t T e x t                                                         %
01077 %                                                                             %
01078 %                                                                             %
01079 %                                                                             %
01080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01081 %
01082 %  XEditText() edits a text string as indicated by the key symbol.
01083 %
01084 %  The format of the XEditText function is:
01085 %
01086 %      XEditText(display,text_info,key_symbol,text,state)
01087 %
01088 %  A description of each parameter follows:
01089 %
01090 %    o display: Specifies a connection to an X server;  returned from
01091 %      XOpenDisplay.
01092 %
01093 %    o text_info: Specifies a pointer to a XWidgetInfo structure.  It
01094 %      contains the extents of the text.
01095 %
01096 %    o key_symbol:  A X11 KeySym that indicates what editing function to
01097 %      perform to the text.
01098 %
01099 %    o text: A character string to insert into the text.
01100 %
01101 %    o state:  An unsigned long that indicates whether the key symbol is a
01102 %      control character or not.
01103 %
01104 */
01105 static void XEditText(Display *display,XWidgetInfo *text_info,
01106   const KeySym key_symbol,char *text,const unsigned long state)
01107 {
01108   switch ((int) key_symbol)
01109   {
01110     case XK_BackSpace:
01111     case XK_Delete:
01112     {
01113       if (text_info->highlight)
01114         {
01115           /*
01116             Erase the entire line of text.
01117           */
01118           *text_info->text='\0';
01119           text_info->cursor=text_info->text;
01120           text_info->marker=text_info->text;
01121           text_info->highlight=MagickFalse;
01122         }
01123       /*
01124         Erase one character.
01125       */
01126       if (text_info->cursor != text_info->text)
01127         {
01128           text_info->cursor--;
01129           (void) CopyMagickString(text_info->cursor,text_info->cursor+1,
01130             MaxTextExtent);
01131           text_info->highlight=MagickFalse;
01132           break;
01133         }
01134     }
01135     case XK_Left:
01136     case XK_KP_Left:
01137     {
01138       /*
01139         Move cursor one position left.
01140       */
01141       if (text_info->cursor == text_info->text)
01142         break;
01143       text_info->cursor--;
01144       break;
01145     }
01146     case XK_Right:
01147     case XK_KP_Right:
01148     {
01149       /*
01150         Move cursor one position right.
01151       */
01152       if (text_info->cursor == (text_info->text+Extent(text_info->text)))
01153         break;
01154       text_info->cursor++;
01155       break;
01156     }
01157     default:
01158     {
01159       register char
01160         *p,
01161         *q;
01162 
01163       register int
01164         i;
01165 
01166       if (state & ControlState)
01167         break;
01168       if (*text == '\0')
01169         break;
01170       if ((Extent(text_info->text)+1) >= (long) MaxTextExtent)
01171         (void) XBell(display,0);
01172       else
01173         {
01174           if (text_info->highlight)
01175             {
01176               /*
01177                 Erase the entire line of text.
01178               */
01179               *text_info->text='\0';
01180               text_info->cursor=text_info->text;
01181               text_info->marker=text_info->text;
01182               text_info->highlight=MagickFalse;
01183             }
01184           /*
01185             Insert a string into the text.
01186           */
01187           q=text_info->text+Extent(text_info->text)+strlen(text);
01188           for (i=0; i <= Extent(text_info->cursor); i++)
01189           {
01190             *q=(*(q-Extent(text)));
01191             q--;
01192           }
01193           p=text;
01194           for (i=0; i < Extent(text); i++)
01195             *text_info->cursor++=(*p++);
01196         }
01197       break;
01198     }
01199   }
01200 }
01201 
01202 /*
01203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01204 %                                                                             %
01205 %                                                                             %
01206 %                                                                             %
01207 +   X G e t W i d g e t I n f o                                               %
01208 %                                                                             %
01209 %                                                                             %
01210 %                                                                             %
01211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01212 %
01213 %  XGetWidgetInfo() initializes the XWidgetInfo structure.
01214 %
01215 %  The format of the XGetWidgetInfo function is:
01216 %
01217 %      XGetWidgetInfo(text,widget_info)
01218 %
01219 %  A description of each parameter follows:
01220 %
01221 %    o text: A string of characters associated with the widget.
01222 %
01223 %    o widget_info: Specifies a pointer to a X11 XWidgetInfo structure.
01224 %
01225 */
01226 static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info)
01227 {
01228   /*
01229     Initialize widget info.
01230   */
01231   widget_info->id=(~0);
01232   widget_info->bevel_width=3;
01233   widget_info->width=1;
01234   widget_info->height=1;
01235   widget_info->x=0;
01236   widget_info->y=0;
01237   widget_info->min_y=0;
01238   widget_info->max_y=0;
01239   widget_info->raised=MagickTrue;
01240   widget_info->active=MagickFalse;
01241   widget_info->center=MagickTrue;
01242   widget_info->trough=MagickFalse;
01243   widget_info->highlight=MagickFalse;
01244   widget_info->text=(char *) text;
01245   widget_info->cursor=(char *) text;
01246   if (text != (char *) NULL)
01247     widget_info->cursor+=Extent(text);
01248   widget_info->marker=(char *) text;
01249 }
01250 
01251 /*
01252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01253 %                                                                             %
01254 %                                                                             %
01255 %                                                                             %
01256 +   X H i g h l i g h t W i d g e t                                           %
01257 %                                                                             %
01258 %                                                                             %
01259 %                                                                             %
01260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01261 %
01262 %  XHighlightWidget() draws a highlighted border around a window.
01263 %
01264 %  The format of the XHighlightWidget function is:
01265 %
01266 %      XHighlightWidget(display,window_info,x,y)
01267 %
01268 %  A description of each parameter follows:
01269 %
01270 %    o display: Specifies a pointer to the Display structure;  returned from
01271 %      XOpenDisplay.
01272 %
01273 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
01274 %
01275 %    o x: Specifies an integer representing the rectangle offset in the
01276 %      x-direction.
01277 %
01278 %    o y: Specifies an integer representing the rectangle offset in the
01279 %      y-direction.
01280 %
01281 */
01282 static void XHighlightWidget(Display *display,const XWindowInfo *window_info,
01283   const int x,const int y)
01284 {
01285   /*
01286     Draw the widget highlighting rectangle.
01287   */
01288   XSetBevelColor(display,window_info,MagickTrue);
01289   (void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y,
01290     window_info->width-(x << 1),window_info->height-(y << 1));
01291   (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
01292     x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1);
01293   XSetBevelColor(display,window_info,MagickFalse);
01294   (void) XDrawRectangle(display,window_info->id,window_info->widget_context,
01295     x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1));
01296   (void) XSetFillStyle(display,window_info->widget_context,FillSolid);
01297 }
01298 
01299 /*
01300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01301 %                                                                             %
01302 %                                                                             %
01303 %                                                                             %
01304 +   X S c r e e n E v e n t                                                   %
01305 %                                                                             %
01306 %                                                                             %
01307 %                                                                             %
01308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01309 %
01310 %  XScreenEvent() returns MagickTrue if the any event on the X server queue is
01311 %  associated with the widget window.
01312 %
01313 %  The format of the XScreenEvent function is:
01314 %
01315 %      int XScreenEvent(Display *display,XEvent *event,char *data)
01316 %
01317 %  A description of each parameter follows:
01318 %
01319 %    o display: Specifies a pointer to the Display structure;  returned from
01320 %      XOpenDisplay.
01321 %
01322 %    o event: Specifies a pointer to a X11 XEvent structure.
01323 %
01324 %    o data: Specifies a pointer to a XWindows structure.
01325 %
01326 */
01327 
01328 #if defined(__cplusplus) || defined(c_plusplus)
01329 extern "C" {
01330 #endif
01331 
01332 static int XScreenEvent(Display *display,XEvent *event,char *data)
01333 {
01334   XWindows
01335     *windows;
01336 
01337   windows=(XWindows *) data;
01338   if (event->xany.window == windows->popup.id)
01339     {
01340       if (event->type == MapNotify)
01341         windows->popup.mapped=MagickTrue;
01342       if (event->type == UnmapNotify)
01343         windows->popup.mapped=MagickFalse;
01344       return(MagickTrue);
01345     }
01346   if (event->xany.window == windows->widget.id)
01347     {
01348       if (event->type == MapNotify)
01349         windows->widget.mapped=MagickTrue;
01350       if (event->type == UnmapNotify)
01351         windows->widget.mapped=MagickFalse;
01352       return(MagickTrue);
01353     }
01354   switch (event->type)
01355   {
01356     case ButtonPress:
01357     {
01358       if ((event->xbutton.button == Button3) &&
01359           (event->xbutton.state & Mod1Mask))
01360         {
01361           /*
01362             Convert Alt-Button3 to Button2.
01363           */
01364           event->xbutton.button=Button2;
01365           event->xbutton.state&=(~Mod1Mask);
01366         }
01367       return(MagickTrue);
01368     }
01369     case Expose:
01370     {
01371       if (event->xexpose.window == windows->image.id)
01372         {
01373           XRefreshWindow(display,&windows->image,event);
01374           break;
01375         }
01376       if (event->xexpose.window == windows->magnify.id)
01377         if (event->xexpose.count == 0)
01378           if (windows->magnify.mapped)
01379             {
01380               XMakeMagnifyImage(display,windows);
01381               break;
01382             }
01383       if (event->xexpose.window == windows->command.id)
01384         if (event->xexpose.count == 0)
01385           {
01386             (void) XCommandWidget(display,windows,(const char **) NULL,event);
01387             break;
01388           }
01389       break;
01390     }
01391     case FocusOut:
01392     {
01393       /*
01394         Set input focus for backdrop window.
01395       */
01396       if (event->xfocus.window == windows->image.id)
01397         (void) XSetInputFocus(display,windows->image.id,RevertToNone,
01398           CurrentTime);
01399       return(MagickTrue);
01400     }
01401     case ButtonRelease:
01402     case KeyPress:
01403     case KeyRelease:
01404     case MotionNotify:
01405     case SelectionNotify:
01406       return(MagickTrue);
01407     default:
01408       break;
01409   }
01410   return(MagickFalse);
01411 }
01412 
01413 #if defined(__cplusplus) || defined(c_plusplus)
01414 }
01415 #endif
01416 
01417 /*
01418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01419 %                                                                             %
01420 %                                                                             %
01421 %                                                                             %
01422 +   X S e t B e v e l C o l o r                                               %
01423 %                                                                             %
01424 %                                                                             %
01425 %                                                                             %
01426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01427 %
01428 %  XSetBevelColor() sets the graphic context for drawing a beveled border.
01429 %
01430 %  The format of the XSetBevelColor function is:
01431 %
01432 %      XSetBevelColor(display,window_info,raised)
01433 %
01434 %  A description of each parameter follows:
01435 %
01436 %    o display: Specifies a pointer to the Display structure;  returned from
01437 %      XOpenDisplay.
01438 %
01439 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
01440 %
01441 %    o raised: A value other than zero indicates the color show be a
01442 %      "highlight" color, otherwise the "shadow" color is set.
01443 %
01444 */
01445 static void XSetBevelColor(Display *display,const XWindowInfo *window_info,
01446   const MagickStatusType raised)
01447 {
01448   if (window_info->depth == 1)
01449     {
01450       Pixmap
01451         stipple;
01452 
01453       /*
01454         Monochrome window.
01455       */
01456       (void) XSetBackground(display,window_info->widget_context,
01457         XBlackPixel(display,window_info->screen));
01458       (void) XSetForeground(display,window_info->widget_context,
01459         XWhitePixel(display,window_info->screen));
01460       (void) XSetFillStyle(display,window_info->widget_context,
01461         FillOpaqueStippled);
01462       stipple=window_info->highlight_stipple;
01463       if (raised == MagickFalse)
01464         stipple=window_info->shadow_stipple;
01465       (void) XSetStipple(display,window_info->widget_context,stipple);
01466     }
01467   else
01468     if (raised)
01469       (void) XSetForeground(display,window_info->widget_context,
01470         window_info->pixel_info->highlight_color.pixel);
01471     else
01472       (void) XSetForeground(display,window_info->widget_context,
01473         window_info->pixel_info->shadow_color.pixel);
01474 }
01475 
01476 /*
01477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01478 %                                                                             %
01479 %                                                                             %
01480 %                                                                             %
01481 +   X S e t M a t t e C o l o r                                               %
01482 %                                                                             %
01483 %                                                                             %
01484 %                                                                             %
01485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01486 %
01487 %  XSetMatteColor() sets the graphic context for drawing the matte.
01488 %
01489 %  The format of the XSetMatteColor function is:
01490 %
01491 %      XSetMatteColor(display,window_info,raised)
01492 %
01493 %  A description of each parameter follows:
01494 %
01495 %    o display: Specifies a pointer to the Display structure;  returned from
01496 %      XOpenDisplay.
01497 %
01498 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
01499 %
01500 %    o raised: A value other than zero indicates the matte is active.
01501 %
01502 */
01503 static void XSetMatteColor(Display *display,const XWindowInfo *window_info,
01504   const MagickStatusType raised)
01505 {
01506   if (window_info->depth == 1)
01507     {
01508       /*
01509         Monochrome window.
01510       */
01511       if (raised)
01512         (void) XSetForeground(display,window_info->widget_context,
01513           XWhitePixel(display,window_info->screen));
01514       else
01515         (void) XSetForeground(display,window_info->widget_context,
01516           XBlackPixel(display,window_info->screen));
01517     }
01518   else
01519     if (raised)
01520       (void) XSetForeground(display,window_info->widget_context,
01521         window_info->pixel_info->matte_color.pixel);
01522     else
01523       (void) XSetForeground(display,window_info->widget_context,
01524         window_info->pixel_info->depth_color.pixel);
01525 }
01526 
01527 /*
01528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01529 %                                                                             %
01530 %                                                                             %
01531 %                                                                             %
01532 +   X S e t T e x t C o l o r                                                 %
01533 %                                                                             %
01534 %                                                                             %
01535 %                                                                             %
01536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01537 %
01538 %  XSetTextColor() sets the graphic context for drawing text on a matte.
01539 %
01540 %  The format of the XSetTextColor function is:
01541 %
01542 %      XSetTextColor(display,window_info,raised)
01543 %
01544 %  A description of each parameter follows:
01545 %
01546 %    o display: Specifies a pointer to the Display structure;  returned from
01547 %      XOpenDisplay.
01548 %
01549 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
01550 %
01551 %    o raised: A value other than zero indicates the color show be a
01552 %      "highlight" color, otherwise the "shadow" color is set.
01553 %
01554 */
01555 static void XSetTextColor(Display *display,const XWindowInfo *window_info,
01556   const MagickStatusType raised)
01557 {
01558   long
01559     foreground,
01560     matte;
01561 
01562   if (window_info->depth == 1)
01563     {
01564       /*
01565         Monochrome window.
01566       */
01567       if (raised)
01568         (void) XSetForeground(display,window_info->widget_context,
01569           XBlackPixel(display,window_info->screen));
01570       else
01571         (void) XSetForeground(display,window_info->widget_context,
01572           XWhitePixel(display,window_info->screen));
01573       return;
01574     }
01575   foreground=(long) XPixelIntensity(&window_info->pixel_info->foreground_color);
01576   matte=(long) XPixelIntensity(&window_info->pixel_info->matte_color);
01577   if (MagickAbsoluteValue(foreground-matte) > (65535L >> 3))
01578     (void) XSetForeground(display,window_info->widget_context,
01579       window_info->pixel_info->foreground_color.pixel);
01580   else
01581     (void) XSetForeground(display,window_info->widget_context,
01582       window_info->pixel_info->background_color.pixel);
01583 }
01584 
01585 /*
01586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01587 %                                                                             %
01588 %                                                                             %
01589 %                                                                             %
01590 %   X C o l o r B r o w s e r W i d g e t                                     %
01591 %                                                                             %
01592 %                                                                             %
01593 %                                                                             %
01594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01595 %
01596 %  XColorBrowserWidget() displays a Color Browser widget with a color query
01597 %  to the user.  The user keys a reply and presses the Action or Cancel button
01598 %  to exit.  The typed text is returned as the reply function parameter.
01599 %
01600 %  The format of the XColorBrowserWidget method is:
01601 %
01602 %      void XColorBrowserWidget(Display *display,XWindows *windows,
01603 %        const char *action,char *reply)
01604 %
01605 %  A description of each parameter follows:
01606 %
01607 %    o display: Specifies a connection to an X server;  returned from
01608 %      XOpenDisplay.
01609 %
01610 %    o window: Specifies a pointer to a XWindows structure.
01611 %
01612 %    o action: Specifies a pointer to the action of this widget.
01613 %
01614 %    o reply: the response from the user is returned in this parameter.
01615 %
01616 */
01617 MagickExport void XColorBrowserWidget(Display *display,XWindows *windows,
01618   const char *action,char *reply)
01619 {
01620 #define CancelButtonText  "Cancel"
01621 #define ColornameText  "Name:"
01622 #define ColorPatternText  "Pattern:"
01623 #define GrabButtonText  "Grab"
01624 #define ResetButtonText  "Reset"
01625 
01626   char
01627     **colorlist,
01628     primary_selection[MaxTextExtent],
01629     reset_pattern[MaxTextExtent],
01630     text[MaxTextExtent];
01631 
01632   ExceptionInfo
01633     *exception;
01634 
01635   int
01636     x,
01637     y;
01638 
01639   register int
01640     i;
01641 
01642   static char
01643     glob_pattern[MaxTextExtent] = "*";
01644 
01645   static MagickStatusType
01646     mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
01647 
01648   Status
01649     status;
01650 
01651   unsigned int
01652     height,
01653     text_width,
01654     visible_colors,
01655     width;
01656 
01657   unsigned long
01658     colors,
01659     delay,
01660     state;
01661 
01662   XColor
01663     color;
01664 
01665   XEvent
01666     event;
01667 
01668   XFontStruct
01669     *font_info;
01670 
01671   XTextProperty
01672     window_name;
01673 
01674   XWidgetInfo
01675     action_info,
01676     cancel_info,
01677     expose_info,
01678     grab_info,
01679     list_info,
01680     mode_info,
01681     north_info,
01682     reply_info,
01683     reset_info,
01684     scroll_info,
01685     selection_info,
01686     slider_info,
01687     south_info,
01688     text_info;
01689 
01690   XWindowChanges
01691     window_changes;
01692 
01693   /*
01694     Get color list and sort in ascending order.
01695   */
01696   assert(display != (Display *) NULL);
01697   assert(windows != (XWindows *) NULL);
01698   assert(action != (char *) NULL);
01699   assert(reply != (char *) NULL);
01700   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
01701   XSetCursorState(display,windows,MagickTrue);
01702   XCheckRefreshWindows(display,windows);
01703   (void) CopyMagickString(reset_pattern,"*",MaxTextExtent);
01704   exception=AcquireExceptionInfo();
01705   colorlist=GetColorList(glob_pattern,&colors,exception);
01706   if (colorlist == (char **) NULL)
01707     {
01708       /*
01709         Pattern failed, obtain all the colors.
01710       */
01711       (void) CopyMagickString(glob_pattern,"*",MaxTextExtent);
01712       colorlist=GetColorList(glob_pattern,&colors,exception);
01713       if (colorlist == (char **) NULL)
01714         {
01715           XNoticeWidget(display,windows,"Unable to obtain colors names:",
01716             glob_pattern);
01717           (void) XDialogWidget(display,windows,action,"Enter color name:",
01718             reply);
01719           return;
01720         }
01721     }
01722   /*
01723     Determine Color Browser widget attributes.
01724   */
01725   font_info=windows->widget.font_info;
01726   text_width=0;
01727   for (i=0; i < (long) colors; i++)
01728     if (WidgetTextWidth(font_info,colorlist[i]) > text_width)
01729       text_width=WidgetTextWidth(font_info,colorlist[i]);
01730   width=WidgetTextWidth(font_info,(char *) action);
01731   if (WidgetTextWidth(font_info,CancelButtonText) > width)
01732     width=WidgetTextWidth(font_info,CancelButtonText);
01733   if (WidgetTextWidth(font_info,ResetButtonText) > width)
01734     width=WidgetTextWidth(font_info,ResetButtonText);
01735   if (WidgetTextWidth(font_info,GrabButtonText) > width)
01736     width=WidgetTextWidth(font_info,GrabButtonText);
01737   width+=QuantumMargin;
01738   if (WidgetTextWidth(font_info,ColorPatternText) > width)
01739     width=WidgetTextWidth(font_info,ColorPatternText);
01740   if (WidgetTextWidth(font_info,ColornameText) > width)
01741     width=WidgetTextWidth(font_info,ColornameText);
01742   height=(unsigned int) (font_info->ascent+font_info->descent);
01743   /*
01744     Position Color Browser widget.
01745   */
01746   windows->widget.width=(unsigned int)
01747     (width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin);
01748   windows->widget.min_width=(unsigned int)
01749     (width+MinTextWidth+4*QuantumMargin);
01750   if (windows->widget.width < windows->widget.min_width)
01751     windows->widget.width=windows->widget.min_width;
01752   windows->widget.height=(unsigned int)
01753     ((81*height) >> 2)+((13*QuantumMargin) >> 1)+4;
01754   windows->widget.min_height=(unsigned int)
01755     (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
01756   if (windows->widget.height < windows->widget.min_height)
01757     windows->widget.height=windows->widget.min_height;
01758   XConstrainWindowPosition(display,&windows->widget);
01759   /*
01760     Map Color Browser widget.
01761   */
01762   (void) CopyMagickString(windows->widget.name,"Browse and Select a Color",
01763     MaxTextExtent);
01764   status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
01765   if (status != False)
01766     {
01767       XSetWMName(display,windows->widget.id,&window_name);
01768       XSetWMIconName(display,windows->widget.id,&window_name);
01769       (void) XFree((void *) window_name.value);
01770     }
01771   window_changes.width=(int) windows->widget.width;
01772   window_changes.height=(int) windows->widget.height;
01773   window_changes.x=windows->widget.x;
01774   window_changes.y=windows->widget.y;
01775   (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
01776     mask,&window_changes);
01777   (void) XMapRaised(display,windows->widget.id);
01778   windows->widget.mapped=MagickFalse;
01779   /*
01780     Respond to X events.
01781   */
01782   XGetWidgetInfo((char *) NULL,&slider_info);
01783   XGetWidgetInfo((char *) NULL,&north_info);
01784   XGetWidgetInfo((char *) NULL,&south_info);
01785   XGetWidgetInfo((char *) NULL,&expose_info);
01786   visible_colors=0;
01787   delay=SuspendTime << 2;
01788   state=UpdateConfigurationState;
01789   do
01790   {
01791     if (state & UpdateConfigurationState)
01792       {
01793         int
01794           id;
01795 
01796         /*
01797           Initialize button information.
01798         */
01799         XGetWidgetInfo(CancelButtonText,&cancel_info);
01800         cancel_info.width=width;
01801         cancel_info.height=(unsigned int) ((3*height) >> 1);
01802         cancel_info.x=(int)
01803           (windows->widget.width-cancel_info.width-QuantumMargin-2);
01804         cancel_info.y=(int)
01805           (windows->widget.height-cancel_info.height-QuantumMargin);
01806         XGetWidgetInfo(action,&action_info);
01807         action_info.width=width;
01808         action_info.height=(unsigned int) ((3*height) >> 1);
01809         action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
01810           (action_info.bevel_width << 1));
01811         action_info.y=cancel_info.y;
01812         XGetWidgetInfo(GrabButtonText,&grab_info);
01813         grab_info.width=width;
01814         grab_info.height=(unsigned int) ((3*height) >> 1);
01815         grab_info.x=QuantumMargin;
01816         grab_info.y=((5*QuantumMargin) >> 1)+height;
01817         XGetWidgetInfo(ResetButtonText,&reset_info);
01818         reset_info.width=width;
01819         reset_info.height=(unsigned int) ((3*height) >> 1);
01820         reset_info.x=QuantumMargin;
01821         reset_info.y=grab_info.y+grab_info.height+QuantumMargin;
01822         /*
01823           Initialize reply information.
01824         */
01825         XGetWidgetInfo(reply,&reply_info);
01826         reply_info.raised=MagickFalse;
01827         reply_info.bevel_width--;
01828         reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
01829         reply_info.height=height << 1;
01830         reply_info.x=(int) (width+(QuantumMargin << 1));
01831         reply_info.y=action_info.y-reply_info.height-QuantumMargin;
01832         /*
01833           Initialize mode information.
01834         */
01835         XGetWidgetInfo((char *) NULL,&mode_info);
01836         mode_info.active=MagickTrue;
01837         mode_info.bevel_width=0;
01838         mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1));
01839         mode_info.height=action_info.height;
01840         mode_info.x=QuantumMargin;
01841         mode_info.y=action_info.y;
01842         /*
01843           Initialize scroll information.
01844         */
01845         XGetWidgetInfo((char *) NULL,&scroll_info);
01846         scroll_info.bevel_width--;
01847         scroll_info.width=height;
01848         scroll_info.height=(unsigned int) (reply_info.y-grab_info.y-
01849           (QuantumMargin >> 1));
01850         scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
01851         scroll_info.y=grab_info.y-reply_info.bevel_width;
01852         scroll_info.raised=MagickFalse;
01853         scroll_info.trough=MagickTrue;
01854         north_info=scroll_info;
01855         north_info.raised=MagickTrue;
01856         north_info.width-=(north_info.bevel_width << 1);
01857         north_info.height=north_info.width-1;
01858         north_info.x+=north_info.bevel_width;
01859         north_info.y+=north_info.bevel_width;
01860         south_info=north_info;
01861         south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
01862           south_info.height;
01863         id=slider_info.id;
01864         slider_info=north_info;
01865         slider_info.id=id;
01866         slider_info.width-=2;
01867         slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
01868           slider_info.bevel_width+2;
01869         slider_info.height=scroll_info.height-((slider_info.min_y-
01870           scroll_info.y+1) << 1)+4;
01871         visible_colors=scroll_info.height/(height+(height >> 3));
01872         if (colors > visible_colors)
01873           slider_info.height=(unsigned int)
01874             ((visible_colors*slider_info.height)/colors);
01875         slider_info.max_y=south_info.y-south_info.bevel_width-
01876           slider_info.bevel_width-2;
01877         slider_info.x=scroll_info.x+slider_info.bevel_width+1;
01878         slider_info.y=slider_info.min_y;
01879         expose_info=scroll_info;
01880         expose_info.y=slider_info.y;
01881         /*
01882           Initialize list information.
01883         */
01884         XGetWidgetInfo((char *) NULL,&list_info);
01885         list_info.raised=MagickFalse;
01886         list_info.bevel_width--;
01887         list_info.width=(unsigned int)
01888           (scroll_info.x-reply_info.x-(QuantumMargin >> 1));
01889         list_info.height=scroll_info.height;
01890         list_info.x=reply_info.x;
01891         list_info.y=scroll_info.y;
01892         if (windows->widget.mapped == MagickFalse)
01893           state|=JumpListState;
01894         /*
01895           Initialize text information.
01896         */
01897         *text='\0';
01898         XGetWidgetInfo(text,&text_info);
01899         text_info.center=MagickFalse;
01900         text_info.width=reply_info.width;
01901         text_info.height=height;
01902         text_info.x=list_info.x-(QuantumMargin >> 1);
01903         text_info.y=QuantumMargin;
01904         /*
01905           Initialize selection information.
01906         */
01907         XGetWidgetInfo((char *) NULL,&selection_info);
01908         selection_info.center=MagickFalse;
01909         selection_info.width=list_info.width;
01910         selection_info.height=(unsigned int) ((9*height) >> 3);
01911         selection_info.x=list_info.x;
01912         state&=(~UpdateConfigurationState);
01913       }
01914     if (state & RedrawWidgetState)
01915       {
01916         /*
01917           Redraw Color Browser window.
01918         */
01919         x=QuantumMargin;
01920         y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
01921         (void) XDrawString(display,windows->widget.id,
01922           windows->widget.annotate_context,x,y,ColorPatternText,
01923           Extent(ColorPatternText));
01924         (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
01925         XDrawWidgetText(display,&windows->widget,&text_info);
01926         XDrawBeveledButton(display,&windows->widget,&grab_info);
01927         XDrawBeveledButton(display,&windows->widget,&reset_info);
01928         XDrawBeveledMatte(display,&windows->widget,&list_info);
01929         XDrawBeveledMatte(display,&windows->widget,&scroll_info);
01930         XDrawTriangleNorth(display,&windows->widget,&north_info);
01931         XDrawBeveledButton(display,&windows->widget,&slider_info);
01932         XDrawTriangleSouth(display,&windows->widget,&south_info);
01933         x=QuantumMargin;
01934         y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
01935         (void) XDrawString(display,windows->widget.id,
01936           windows->widget.annotate_context,x,y,ColornameText,
01937           Extent(ColornameText));
01938         XDrawBeveledMatte(display,&windows->widget,&reply_info);
01939         XDrawMatteText(display,&windows->widget,&reply_info);
01940         XDrawBeveledButton(display,&windows->widget,&action_info);
01941         XDrawBeveledButton(display,&windows->widget,&cancel_info);
01942         XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
01943         selection_info.id=(~0);
01944         state|=RedrawActionState;
01945         state|=RedrawListState;
01946         state&=(~RedrawWidgetState);
01947       }
01948     if (state & UpdateListState)
01949       {
01950         char
01951           **checklist;
01952 
01953         unsigned long
01954           number_colors;
01955 
01956         status=XParseColor(display,windows->widget.map_info->colormap,
01957           glob_pattern,&color);
01958         if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL))
01959           {
01960             /*
01961               Reply is a single color name-- exit.
01962             */
01963             (void) CopyMagickString(reply,glob_pattern,MaxTextExtent);
01964             (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
01965             action_info.raised=MagickFalse;
01966             XDrawBeveledButton(display,&windows->widget,&action_info);
01967             break;
01968           }
01969         /*
01970           Update color list.
01971         */
01972         checklist=GetColorList(glob_pattern,&number_colors,exception);
01973         if (number_colors == 0)
01974           {
01975             (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent);
01976             (void) XBell(display,0);
01977           }
01978         else
01979           {
01980             for (i=0; i < (long) colors; i++)
01981               colorlist[i]=DestroyString(colorlist[i]);
01982             if (colorlist != (char **) NULL)
01983               colorlist=(char **) RelinquishMagickMemory(colorlist);
01984             colorlist=checklist;
01985             colors=number_colors;
01986           }
01987         /*
01988           Sort color list in ascending order.
01989         */
01990         slider_info.height=
01991           scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
01992         if (colors > visible_colors)
01993           slider_info.height=(unsigned int)
01994             ((visible_colors*slider_info.height)/colors);
01995         slider_info.max_y=south_info.y-south_info.bevel_width-
01996           slider_info.bevel_width-2;
01997         slider_info.id=0;
01998         slider_info.y=slider_info.min_y;
01999         expose_info.y=slider_info.y;
02000         selection_info.id=(~0);
02001         list_info.id=(~0);
02002         state|=RedrawListState;
02003         /*
02004           Redraw color name & reply.
02005         */
02006         *reply_info.text='\0';
02007         reply_info.cursor=reply_info.text;
02008         (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent);
02009         XDrawWidgetText(display,&windows->widget,&text_info);
02010         XDrawMatteText(display,&windows->widget,&reply_info);
02011         XDrawBeveledMatte(display,&windows->widget,&scroll_info);
02012         XDrawTriangleNorth(display,&windows->widget,&north_info);
02013         XDrawBeveledButton(display,&windows->widget,&slider_info);
02014         XDrawTriangleSouth(display,&windows->widget,&south_info);
02015         XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
02016         state&=(~UpdateListState);
02017       }
02018     if (state & JumpListState)
02019       {
02020         /*
02021           Jump scroll to match user color.
02022         */
02023         list_info.id=(~0);
02024         for (i=0; i < (long) colors; i++)
02025           if (LocaleCompare(colorlist[i],reply) >= 0)
02026             {
02027               list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0;
02028               break;
02029             }
02030         if ((i < slider_info.id) ||
02031             (i >= (int) (slider_info.id+visible_colors)))
02032           slider_info.id=i-(visible_colors >> 1);
02033         selection_info.id=(~0);
02034         state|=RedrawListState;
02035         state&=(~JumpListState);
02036       }
02037     if (state & RedrawListState)
02038       {
02039         /*
02040           Determine slider id and position.
02041         */
02042         if (slider_info.id >= (int) (colors-visible_colors))
02043           slider_info.id=(int) (colors-visible_colors);
02044         if ((slider_info.id < 0) || (colors <= visible_colors))
02045           slider_info.id=0;
02046         slider_info.y=slider_info.min_y;
02047         if (colors != 0)
02048           slider_info.y+=slider_info.id*(slider_info.max_y-
02049             slider_info.min_y+1)/colors;
02050         if (slider_info.id != selection_info.id)
02051           {
02052             /*
02053               Redraw scroll bar and file names.
02054             */
02055             selection_info.id=slider_info.id;
02056             selection_info.y=list_info.y+(height >> 3)+2;
02057             for (i=0; i < (int) visible_colors; i++)
02058             {
02059               selection_info.raised=(slider_info.id+i) != list_info.id ?
02060                 MagickTrue : MagickFalse;
02061               selection_info.text=(char *) NULL;
02062               if ((slider_info.id+i) < (long) colors)
02063                 selection_info.text=colorlist[slider_info.id+i];
02064               XDrawWidgetText(display,&windows->widget,&selection_info);
02065               selection_info.y+=(int) selection_info.height;
02066             }
02067             /*
02068               Update slider.
02069             */
02070             if (slider_info.y > expose_info.y)
02071               {
02072                 expose_info.height=(unsigned int) slider_info.y-expose_info.y;
02073                 expose_info.y=slider_info.y-expose_info.height-
02074                   slider_info.bevel_width-1;
02075               }
02076             else
02077               {
02078                 expose_info.height=(unsigned int) expose_info.y-slider_info.y;
02079                 expose_info.y=slider_info.y+slider_info.height+
02080                   slider_info.bevel_width+1;
02081               }
02082             XDrawTriangleNorth(display,&windows->widget,&north_info);
02083             XDrawMatte(display,&windows->widget,&expose_info);
02084             XDrawBeveledButton(display,&windows->widget,&slider_info);
02085             XDrawTriangleSouth(display,&windows->widget,&south_info);
02086             expose_info.y=slider_info.y;
02087           }
02088         state&=(~RedrawListState);
02089       }
02090     if (state & RedrawActionState)
02091       {
02092         static char
02093           colorname[MaxTextExtent];
02094 
02095         /*
02096           Display the selected color in a drawing area.
02097         */
02098         color=windows->widget.pixel_info->matte_color;
02099         (void) XParseColor(display,windows->widget.map_info->colormap,
02100           reply_info.text,&windows->widget.pixel_info->matte_color);
02101         XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL,
02102           (unsigned int) windows->widget.visual_info->colormap_size,
02103           &windows->widget.pixel_info->matte_color);
02104         mode_info.text=colorname;
02105         (void) FormatMagickString(mode_info.text,MaxTextExtent,"#%02x%02x%02x",
02106           windows->widget.pixel_info->matte_color.red,
02107           windows->widget.pixel_info->matte_color.green,
02108           windows->widget.pixel_info->matte_color.blue);
02109         XDrawBeveledButton(display,&windows->widget,&mode_info);
02110         windows->widget.pixel_info->matte_color=color;
02111         state&=(~RedrawActionState);
02112       }
02113     /*
02114       Wait for next event.
02115     */
02116     if (north_info.raised && south_info.raised)
02117       (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
02118     else
02119       {
02120         /*
02121           Brief delay before advancing scroll bar.
02122         */
02123         XDelay(display,delay);
02124         delay=SuspendTime;
02125         (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
02126         if (north_info.raised == MagickFalse)
02127           if (slider_info.id > 0)
02128             {
02129               /*
02130                 Move slider up.
02131               */
02132               slider_info.id--;
02133               state|=RedrawListState;
02134             }
02135         if (south_info.raised == MagickFalse)
02136           if (slider_info.id < (long) colors)
02137             {
02138               /*
02139                 Move slider down.
02140               */
02141               slider_info.id++;
02142               state|=RedrawListState;
02143             }
02144         if (event.type != ButtonRelease)
02145           continue;
02146       }
02147     switch (event.type)
02148     {
02149       case ButtonPress:
02150       {
02151         if (MatteIsActive(slider_info,event.xbutton))
02152           {
02153             /*
02154               Track slider.
02155             */
02156             slider_info.active=MagickTrue;
02157             break;
02158           }
02159         if (MatteIsActive(north_info,event.xbutton))
02160           if (slider_info.id > 0)
02161             {
02162               /*
02163                 Move slider up.
02164               */
02165               north_info.raised=MagickFalse;
02166               slider_info.id--;
02167               state|=RedrawListState;
02168               break;
02169             }
02170         if (MatteIsActive(south_info,event.xbutton))
02171           if (slider_info.id < (long) colors)
02172             {
02173               /*
02174                 Move slider down.
02175               */
02176               south_info.raised=MagickFalse;
02177               slider_info.id++;
02178               state|=RedrawListState;
02179               break;
02180             }
02181         if (MatteIsActive(scroll_info,event.xbutton))
02182           {
02183             /*
02184               Move slider.
02185             */
02186             if (event.xbutton.y < slider_info.y)
02187               slider_info.id-=(visible_colors-1);
02188             else
02189               slider_info.id+=(visible_colors-1);
02190             state|=RedrawListState;
02191             break;
02192           }
02193         if (MatteIsActive(list_info,event.xbutton))
02194           {
02195             int
02196               id;
02197 
02198             /*
02199               User pressed list matte.
02200             */
02201             id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
02202               selection_info.height;
02203             if (id >= (int) colors)
02204               break;
02205             (void) CopyMagickString(reply_info.text,colorlist[id],
02206               MaxTextExtent);
02207             reply_info.highlight=MagickFalse;
02208             reply_info.marker=reply_info.text;
02209             reply_info.cursor=reply_info.text+Extent(reply_info.text);
02210             XDrawMatteText(display,&windows->widget,&reply_info);
02211             state|=RedrawActionState;
02212             if (id == list_info.id)
02213               {
02214                 (void) CopyMagickString(glob_pattern,reply_info.text,
02215                   MaxTextExtent);
02216                 state|=UpdateListState;
02217               }
02218             selection_info.id=(~0);
02219             list_info.id=id;
02220             state|=RedrawListState;
02221             break;
02222           }
02223         if (MatteIsActive(grab_info,event.xbutton))
02224           {
02225             /*
02226               User pressed Grab button.
02227             */
02228             grab_info.raised=MagickFalse;
02229             XDrawBeveledButton(display,&windows->widget,&grab_info);
02230             break;
02231           }
02232         if (MatteIsActive(reset_info,event.xbutton))
02233           {
02234             /*
02235               User pressed Reset button.
02236             */
02237             reset_info.raised=MagickFalse;
02238             XDrawBeveledButton(display,&windows->widget,&reset_info);
02239             break;
02240           }
02241         if (MatteIsActive(mode_info,event.xbutton))
02242           {
02243             /*
02244               User pressed mode button.
02245             */
02246             (void) CopyMagickString(reply_info.text,mode_info.text,
02247               MaxTextExtent);
02248             (void) CopyMagickString(primary_selection,reply_info.text,
02249               MaxTextExtent);
02250             (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
02251               event.xbutton.time);
02252             reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
02253               windows->widget.id ? MagickTrue : MagickFalse;
02254             reply_info.marker=reply_info.text;
02255             reply_info.cursor=reply_info.text+Extent(reply_info.text);
02256             XDrawMatteText(display,&windows->widget,&reply_info);
02257             break;
02258           }
02259         if (MatteIsActive(action_info,event.xbutton))
02260           {
02261             /*
02262               User pressed action button.
02263             */
02264             action_info.raised=MagickFalse;
02265             XDrawBeveledButton(display,&windows->widget,&action_info);
02266             break;
02267           }
02268         if (MatteIsActive(cancel_info,event.xbutton))
02269           {
02270             /*
02271               User pressed Cancel button.
02272             */
02273             cancel_info.raised=MagickFalse;
02274             XDrawBeveledButton(display,&windows->widget,&cancel_info);
02275             break;
02276           }
02277         if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
02278           break;
02279         if (event.xbutton.button != Button2)
02280           {
02281             static Time
02282               click_time;
02283 
02284             /*
02285               Move text cursor to position of button press.
02286             */
02287             x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
02288             for (i=1; i <= Extent(reply_info.marker); i++)
02289               if (XTextWidth(font_info,reply_info.marker,i) > x)
02290                 break;
02291             reply_info.cursor=reply_info.marker+i-1;
02292             if (event.xbutton.time > (click_time+DoubleClick))
02293               reply_info.highlight=MagickFalse;
02294             else
02295               {
02296                 /*
02297                   Become the XA_PRIMARY selection owner.
02298                 */
02299                 (void) CopyMagickString(primary_selection,reply_info.text,
02300                   MaxTextExtent);
02301                 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
02302                   event.xbutton.time);
02303                 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
02304                   windows->widget.id ? MagickTrue : MagickFalse;
02305               }
02306             XDrawMatteText(display,&windows->widget,&reply_info);
02307             click_time=event.xbutton.time;
02308             break;
02309           }
02310         /*
02311           Request primary selection.
02312         */
02313         (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
02314           windows->widget.id,event.xbutton.time);
02315         break;
02316       }
02317       case ButtonRelease:
02318       {
02319         if (windows->widget.mapped == MagickFalse)
02320           break;
02321         if (north_info.raised == MagickFalse)
02322           {
02323             /*
02324               User released up button.
02325             */
02326             delay=SuspendTime << 2;
02327             north_info.raised=MagickTrue;
02328             XDrawTriangleNorth(display,&windows->widget,&north_info);
02329           }
02330         if (south_info.raised == MagickFalse)
02331           {
02332             /*
02333               User released down button.
02334             */
02335             delay=SuspendTime << 2;
02336             south_info.raised=MagickTrue;
02337             XDrawTriangleSouth(display,&windows->widget,&south_info);
02338           }
02339         if (slider_info.active)
02340           {
02341             /*
02342               Stop tracking slider.
02343             */
02344             slider_info.active=MagickFalse;
02345             break;
02346           }
02347         if (grab_info.raised == MagickFalse)
02348           {
02349             if (event.xbutton.window == windows->widget.id)
02350               if (MatteIsActive(grab_info,event.xbutton))
02351                 {
02352                   /*
02353                     Select a pen color from the X server.
02354                   */
02355                   (void) XGetWindowColor(display,windows,reply_info.text);
02356                   reply_info.marker=reply_info.text;
02357                   reply_info.cursor=reply_info.text+Extent(reply_info.text);
02358                   XDrawMatteText(display,&windows->widget,&reply_info);
02359                   state|=RedrawActionState;
02360                 }
02361             grab_info.raised=MagickTrue;
02362             XDrawBeveledButton(display,&windows->widget,&grab_info);
02363           }
02364         if (reset_info.raised == MagickFalse)
02365           {
02366             if (event.xbutton.window == windows->widget.id)
02367               if (MatteIsActive(reset_info,event.xbutton))
02368                 {
02369                   (void) CopyMagickString(glob_pattern,reset_pattern,
02370                     MaxTextExtent);
02371                   state|=UpdateListState;
02372                 }
02373             reset_info.raised=MagickTrue;
02374             XDrawBeveledButton(display,&windows->widget,&reset_info);
02375           }
02376         if (action_info.raised == MagickFalse)
02377           {
02378             if (event.xbutton.window == windows->widget.id)
02379               {
02380                 if (MatteIsActive(action_info,event.xbutton))
02381                   {
02382                     if (*reply_info.text == '\0')
02383                       (void) XBell(display,0);
02384                     else
02385                       state|=ExitState;
02386                   }
02387               }
02388             action_info.raised=MagickTrue;
02389             XDrawBeveledButton(display,&windows->widget,&action_info);
02390           }
02391         if (cancel_info.raised == MagickFalse)
02392           {
02393             if (event.xbutton.window == windows->widget.id)
02394               if (MatteIsActive(cancel_info,event.xbutton))
02395                 {
02396                   *reply_info.text='\0';
02397                   state|=ExitState;
02398                 }
02399             cancel_info.raised=MagickTrue;
02400             XDrawBeveledButton(display,&windows->widget,&cancel_info);
02401           }
02402         if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
02403           break;
02404         break;
02405       }
02406       case ClientMessage:
02407       {
02408         /*
02409           If client window delete message, exit.
02410         */
02411         if (event.xclient.message_type != windows->wm_protocols)
02412           break;
02413         if (*event.xclient.data.l == (int) windows->wm_take_focus)
02414           {
02415             (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
02416               (Time) event.xclient.data.l[1]);
02417             break;
02418           }
02419         if (*event.xclient.data.l != (int) windows->wm_delete_window)
02420           break;
02421         if (event.xclient.window == windows->widget.id)
02422           {
02423             *reply_info.text='\0';
02424             state|=ExitState;
02425             break;
02426           }
02427         break;
02428       }
02429       case ConfigureNotify:
02430       {
02431         /*
02432           Update widget configuration.
02433         */
02434         if (event.xconfigure.window != windows->widget.id)
02435           break;
02436         if ((event.xconfigure.width == (int) windows->widget.width) &&
02437             (event.xconfigure.height == (int) windows->widget.height))
02438           break;
02439         windows->widget.width=(unsigned int)
02440           MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
02441         windows->widget.height=(unsigned int)
02442           MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
02443         state|=UpdateConfigurationState;
02444         break;
02445       }
02446       case EnterNotify:
02447       {
02448         if (event.xcrossing.window != windows->widget.id)
02449           break;
02450         state&=(~InactiveWidgetState);
02451         break;
02452       }
02453       case Expose:
02454       {
02455         if (event.xexpose.window != windows->widget.id)
02456           break;
02457         if (event.xexpose.count != 0)
02458           break;
02459         state|=RedrawWidgetState;
02460         break;
02461       }
02462       case KeyPress:
02463       {
02464         static char
02465           command[MaxTextExtent];
02466 
02467         static int
02468           length;
02469 
02470         static KeySym
02471           key_symbol;
02472 
02473         /*
02474           Respond to a user key press.
02475         */
02476         if (event.xkey.window != windows->widget.id)
02477           break;
02478         length=XLookupString((XKeyEvent *) &event.xkey,command,
02479           (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02480         *(command+length)='\0';
02481         if (AreaIsActive(scroll_info,event.xkey))
02482           {
02483             /*
02484               Move slider.
02485             */
02486             switch ((int) key_symbol)
02487             {
02488               case XK_Home:
02489               case XK_KP_Home:
02490               {
02491                 slider_info.id=0;
02492                 break;
02493               }
02494               case XK_Up:
02495               case XK_KP_Up:
02496               {
02497                 slider_info.id--;
02498                 break;
02499               }
02500               case XK_Down:
02501               case XK_KP_Down:
02502               {
02503                 slider_info.id++;
02504                 break;
02505               }
02506               case XK_Prior:
02507               case XK_KP_Prior:
02508               {
02509                 slider_info.id-=visible_colors;
02510                 break;
02511               }
02512               case XK_Next:
02513               case XK_KP_Next:
02514               {
02515                 slider_info.id+=visible_colors;
02516                 break;
02517               }
02518               case XK_End:
02519               case XK_KP_End:
02520               {
02521                 slider_info.id=(int) colors;
02522                 break;
02523               }
02524             }
02525             state|=RedrawListState;
02526             break;
02527           }
02528         if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
02529           {
02530             /*
02531               Read new color or glob patterm.
02532             */
02533             if (*reply_info.text == '\0')
02534               break;
02535             (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent);
02536             state|=UpdateListState;
02537             break;
02538           }
02539         if (key_symbol == XK_Control_L)
02540           {
02541             state|=ControlState;
02542             break;
02543           }
02544         if (state & ControlState)
02545           switch ((int) key_symbol)
02546           {
02547             case XK_u:
02548             case XK_U:
02549             {
02550               /*
02551                 Erase the entire line of text.
02552               */
02553               *reply_info.text='\0';
02554               reply_info.cursor=reply_info.text;
02555               reply_info.marker=reply_info.text;
02556               reply_info.highlight=MagickFalse;
02557               break;
02558             }
02559             default:
02560               break;
02561           }
02562         XEditText(display,&reply_info,key_symbol,command,state);
02563         XDrawMatteText(display,&windows->widget,&reply_info);
02564         state|=JumpListState;
02565         status=XParseColor(display,windows->widget.map_info->colormap,
02566           reply_info.text,&color);
02567         if (status != False)
02568           state|=RedrawActionState;
02569         break;
02570       }
02571       case KeyRelease:
02572       {
02573         static char
02574           command[MaxTextExtent];
02575 
02576         static KeySym
02577           key_symbol;
02578 
02579         /*
02580           Respond to a user key release.
02581         */
02582         if (event.xkey.window != windows->widget.id)
02583           break;
02584         (void) XLookupString((XKeyEvent *) &event.xkey,command,
02585           (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02586         if (key_symbol == XK_Control_L)
02587           state&=(~ControlState);
02588         break;
02589       }
02590       case LeaveNotify:
02591       {
02592         if (event.xcrossing.window != windows->widget.id)
02593           break;
02594         state|=InactiveWidgetState;
02595         break;
02596       }
02597       case MapNotify:
02598       {
02599         mask&=(~CWX);
02600         mask&=(~CWY);
02601         break;
02602       }
02603       case MotionNotify:
02604       {
02605         /*
02606           Discard pending button motion events.
02607         */
02608         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
02609         if (slider_info.active)
02610           {
02611             /*
02612               Move slider matte.
02613             */
02614             slider_info.y=event.xmotion.y-
02615               ((slider_info.height+slider_info.bevel_width) >> 1)+1;
02616             if (slider_info.y < slider_info.min_y)
02617               slider_info.y=slider_info.min_y;
02618             if (slider_info.y > slider_info.max_y)
02619               slider_info.y=slider_info.max_y;
02620             slider_info.id=0;
02621             if (slider_info.y != slider_info.min_y)
02622               slider_info.id=(int) ((colors*(slider_info.y-
02623                 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
02624             state|=RedrawListState;
02625             break;
02626           }
02627         if (state & InactiveWidgetState)
02628           break;
02629         if (grab_info.raised == MatteIsActive(grab_info,event.xmotion))
02630           {
02631             /*
02632               Grab button status changed.
02633             */
02634             grab_info.raised=!grab_info.raised;
02635             XDrawBeveledButton(display,&windows->widget,&grab_info);
02636             break;
02637           }
02638         if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
02639           {
02640             /*
02641               Reset button status changed.
02642             */
02643             reset_info.raised=!reset_info.raised;
02644             XDrawBeveledButton(display,&windows->widget,&reset_info);
02645             break;
02646           }
02647         if (action_info.raised == MatteIsActive(action_info,event.xmotion))
02648           {
02649             /*
02650               Action button status changed.
02651             */
02652             action_info.raised=action_info.raised == MagickFalse ?
02653               MagickTrue : MagickFalse;
02654             XDrawBeveledButton(display,&windows->widget,&action_info);
02655             break;
02656           }
02657         if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
02658           {
02659             /*
02660               Cancel button status changed.
02661             */
02662             cancel_info.raised=cancel_info.raised == MagickFalse ?
02663               MagickTrue : MagickFalse;
02664             XDrawBeveledButton(display,&windows->widget,&cancel_info);
02665             break;
02666           }
02667         break;
02668       }
02669       case SelectionClear:
02670       {
02671         reply_info.highlight=MagickFalse;
02672         XDrawMatteText(display,&windows->widget,&reply_info);
02673         break;
02674       }
02675       case SelectionNotify:
02676       {
02677         Atom
02678           type;
02679 
02680         int
02681           format;
02682 
02683         unsigned char
02684           *data;
02685 
02686         unsigned long
02687           after,
02688           length;
02689 
02690         /*
02691           Obtain response from primary selection.
02692         */
02693         if (event.xselection.property == (Atom) None)
02694           break;
02695         status=XGetWindowProperty(display,event.xselection.requestor,
02696           event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type,
02697           &format,&length,&after,&data);
02698         if ((status != Success) || (type != XA_STRING) || (format == 32) ||
02699             (length == 0))
02700           break;
02701         if ((Extent(reply_info.text)+length) >= MaxTextExtent)
02702           (void) XBell(display,0);
02703         else
02704           {
02705             /*
02706               Insert primary selection in reply text.
02707             */
02708             *(data+length)='\0';
02709             XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data,
02710               state);
02711             XDrawMatteText(display,&windows->widget,&reply_info);
02712             state|=JumpListState;
02713             state|=RedrawActionState;
02714           }
02715         (void) XFree((void *) data);
02716         break;
02717       }
02718       case SelectionRequest:
02719       {
02720         XSelectionEvent
02721           notify;
02722 
02723         XSelectionRequestEvent
02724           *request;
02725 
02726         if (reply_info.highlight == MagickFalse)
02727           break;
02728         /*
02729           Set primary selection.
02730         */
02731         request=(&(event.xselectionrequest));
02732         (void) XChangeProperty(request->display,request->requestor,
02733           request->property,request->target,8,PropModeReplace,
02734           (unsigned char *) primary_selection,Extent(primary_selection));
02735         notify.type=SelectionNotify;
02736         notify.send_event=MagickTrue;
02737         notify.display=request->display;
02738         notify.requestor=request->requestor;
02739         notify.selection=request->selection;
02740         notify.target=request->target;
02741         notify.time=request->time;
02742         if (request->property == None)
02743           notify.property=request->target;
02744         else
02745           notify.property=request->property;
02746         (void) XSendEvent(request->display,request->requestor,False,
02747           NoEventMask,(XEvent *) &notify);
02748       }
02749       default:
02750         break;
02751     }
02752   } while ((state & ExitState) == 0);
02753   XSetCursorState(display,windows,MagickFalse);
02754   (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
02755   XCheckRefreshWindows(display,windows);
02756   /*
02757     Free color list.
02758   */
02759   for (i=0; i < (long) colors; i++)
02760     colorlist[i]=DestroyString(colorlist[i]);
02761   if (colorlist != (char **) NULL)
02762     colorlist=(char **) RelinquishMagickMemory(colorlist);
02763   exception=DestroyExceptionInfo(exception);
02764   if ((*reply == '\0') || (strchr(reply,'-') != (char *) NULL))
02765     return;
02766   status=XParseColor(display,windows->widget.map_info->colormap,reply,&color);
02767   if (status != False)
02768     return;
02769   XNoticeWidget(display,windows,"Color is unknown to X server:",reply);
02770   (void) CopyMagickString(reply,"gray",MaxTextExtent);
02771 }
02772 
02773 /*
02774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02775 %                                                                             %
02776 %                                                                             %
02777 %                                                                             %
02778 %   X C o m m a n d W i d g e t                                               %
02779 %                                                                             %
02780 %                                                                             %
02781 %                                                                             %
02782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02783 %
02784 %  XCommandWidget() maps a menu and returns the command pointed to by the user
02785 %  when the button is released.
02786 %
02787 %  The format of the XCommandWidget method is:
02788 %
02789 %      int XCommandWidget(Display *display,XWindows *windows,
02790 %        const char **selections,XEvent *event)
02791 %
02792 %  A description of each parameter follows:
02793 %
02794 %    o selection_number: Specifies the number of the selection that the
02795 %      user choose.
02796 %
02797 %    o display: Specifies a connection to an X server;  returned from
02798 %      XOpenDisplay.
02799 %
02800 %    o window: Specifies a pointer to a XWindows structure.
02801 %
02802 %    o selections: Specifies a pointer to one or more strings that comprise
02803 %      the choices in the menu.
02804 %
02805 %    o event: Specifies a pointer to a X11 XEvent structure.
02806 %
02807 */
02808 MagickExport int XCommandWidget(Display *display,XWindows *windows,
02809   const char **selections,XEvent *event)
02810 {
02811 #define tile_width 112
02812 #define tile_height 70
02813 
02814   static const unsigned char
02815     tile_bits[]=
02816     {
02817       0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02818       0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02819       0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02820       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
02821       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
02822       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
02823       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02824       0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02825       0x00, 0x00, 0x1e, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02826       0x00, 0x00, 0x00, 0x00, 0x1e, 0xbc, 0x9f, 0x03, 0x00, 0x3e, 0x00, 0xc0,
02827       0x1f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x0f, 0x80, 0x3f,
02828       0x00, 0xf0, 0x1f, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x1f,
02829       0xe0, 0x3f, 0x00, 0xfc, 0x1f, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc,
02830       0xff, 0x1f, 0xf0, 0x3f, 0x00, 0xfe, 0x1f, 0xf8, 0x0f, 0x00, 0x00, 0x00,
02831       0x1e, 0xfc, 0xfc, 0x3f, 0xf8, 0x3f, 0x00, 0xff, 0x1e, 0xfc, 0x0f, 0x00,
02832       0x00, 0x00, 0x1e, 0x7c, 0xfc, 0x3e, 0xf8, 0x3c, 0x80, 0x1f, 0x1e, 0x7c,
02833       0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 0xc0, 0x0f,
02834       0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c,
02835       0xc0, 0x07, 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c,
02836       0x7c, 0x7c, 0xc0, 0x0f, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78,
02837       0x78, 0x3c, 0xfc, 0x7c, 0x80, 0x7f, 0x1e, 0x7c, 0x00, 0x00, 0x00, 0x00,
02838       0x1e, 0xf8, 0x78, 0x7c, 0xf8, 0xff, 0x00, 0xff, 0x1f, 0xf8, 0xff, 0x00,
02839       0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xfe, 0x1f, 0xf8,
02840       0xff, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xf8,
02841       0x1f, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xc0, 0xef,
02842       0x07, 0xe0, 0x1f, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0x70, 0x40, 0x78,
02843       0x00, 0xc7, 0x07, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00,
02844       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
02845       0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
02846       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
02847       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
02848       0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02849       0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02850       0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02851       0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
02852       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00,
02853       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
02854       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
02855       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02856       0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00,
02857       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
02858       0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02859       0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02860       0x60, 0x00, 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02861       0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
02862       0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00,
02863       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0x9f, 0x7f, 0x00,
02864       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0xdf,
02865       0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00,
02866       0xe0, 0xdf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0c,
02867       0x78, 0x30, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
02868       0x00, 0x0f, 0xf8, 0x70, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x1f, 0x00, 0xe0,
02869       0x0f, 0x1e, 0x80, 0x0f, 0xf8, 0x78, 0xf0, 0xfd, 0xf9, 0x00, 0xc0, 0x1f,
02870       0x00, 0xf8, 0x0f, 0x00, 0xe0, 0x1f, 0xf8, 0x7c, 0xf0, 0xfc, 0xf9, 0x00,
02871       0xf0, 0x1f, 0x00, 0xfe, 0x0f, 0x00, 0xf0, 0x07, 0xf8, 0x3e, 0xf8, 0xfc,
02872       0xf0, 0x01, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x1e, 0xf0, 0x03, 0xf8, 0x3f,
02873       0xf8, 0xf8, 0xf0, 0x01, 0xfc, 0x1f, 0x80, 0x7f, 0x0f, 0x1e, 0xf8, 0x00,
02874       0xf8, 0x1f, 0x78, 0x18, 0xf0, 0x01, 0x7c, 0x1e, 0xc0, 0x0f, 0x0f, 0x1e,
02875       0x7c, 0x00, 0xf0, 0x0f, 0x78, 0x00, 0xf0, 0x01, 0x3e, 0x1e, 0xe0, 0x07,
02876       0x0f, 0x1e, 0x7c, 0x00, 0xf0, 0x07, 0x7c, 0x00, 0xe0, 0x01, 0x3e, 0x1e,
02877       0xe0, 0x03, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x0f, 0x7c, 0x00, 0xe0, 0x03,
02878       0x3e, 0x3e, 0xe0, 0x07, 0x0f, 0x1e, 0x1e, 0x00, 0xf0, 0x1f, 0x3c, 0x00,
02879       0xe0, 0x03, 0x7e, 0x3e, 0xc0, 0x3f, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x1f,
02880       0x3e, 0x00, 0xe0, 0x03, 0xfc, 0x7f, 0x80, 0xff, 0x0f, 0x1e, 0xfc, 0x00,
02881       0xf0, 0x3e, 0x3e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xff, 0x0f, 0x1e,
02882       0xfc, 0x07, 0xf0, 0x7c, 0x1e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xfc,
02883       0x0f, 0x1e, 0xf8, 0x1f, 0xf0, 0xf8, 0x1e, 0x00, 0xc0, 0x03, 0xe0, 0xf7,
02884       0x03, 0xf0, 0x0f, 0x1e, 0xe0, 0x3f, 0xf0, 0x78, 0x1c, 0x00, 0x80, 0x03,
02885       0x80, 0xe3, 0x03, 0x00, 0x0f, 0x1e, 0xc0, 0x3f, 0xf0, 0x30, 0x00, 0x00,
02886       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x3e, 0x00, 0x00,
02887       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x10,
02888       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00,
02889       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
02890       0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02891       0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02892       0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02893       0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
02894       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
02895       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
02896       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
02897       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02898       0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
02899     };
02900 
02901   int
02902     id,
02903     y;
02904 
02905   register int
02906     i;
02907 
02908   static unsigned int
02909     number_selections;
02910 
02911   unsigned int
02912     height;
02913 
02914   unsigned long
02915     state;
02916 
02917   XFontStruct
02918     *font_info;
02919 
02920   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02921   assert(display != (Display *) NULL);
02922   assert(windows != (XWindows *) NULL);
02923   font_info=windows->command.font_info;
02924   height=(unsigned int) (font_info->ascent+font_info->descent);
02925   id=(~0);
02926   state=DefaultState;
02927   if (event == (XEvent *) NULL)
02928     {
02929       unsigned int
02930         width;
02931 
02932       XTextProperty
02933         window_name;
02934 
02935       XWindowChanges
02936         window_changes;
02937 
02938       /*
02939         Determine command window attributes.
02940       */
02941       assert(selections != (const char **) NULL);
02942       windows->command.width=0;
02943       for (i=0; selections[i] != (char *) NULL; i++)
02944       {
02945         width=WidgetTextWidth(font_info,(char *) selections[i]);
02946         if (width > windows->command.width)
02947           windows->command.width=width;
02948       }
02949       number_selections=(unsigned int) i;
02950       windows->command.width+=3*QuantumMargin+10;
02951       if ((int) windows->command.width < (tile_width+QuantumMargin+10))
02952         windows->command.width=(unsigned  int) (tile_width+QuantumMargin+10);
02953       windows->command.height=(unsigned  int) (number_selections*
02954         (((3*height) >> 1)+10)+tile_height+20);
02955       windows->command.min_width=windows->command.width;
02956       windows->command.min_height=windows->command.height;
02957       XConstrainWindowPosition(display,&windows->command);
02958       if (windows->command.id != (Window) NULL)
02959         {
02960           Status
02961             status;
02962 
02963           /*
02964             Reconfigure command window.
02965           */
02966           status=XStringListToTextProperty(&windows->command.name,1,
02967             &window_name);
02968           if (status != False)
02969             {
02970               XSetWMName(display,windows->command.id,&window_name);
02971               XSetWMIconName(display,windows->command.id,&window_name);
02972               (void) XFree((void *) window_name.value);
02973             }
02974           window_changes.width=(int) windows->command.width;
02975           window_changes.height=(int) windows->command.height;
02976           (void) XReconfigureWMWindow(display,windows->command.id,
02977             windows->command.screen,(unsigned int) (CWWidth | CWHeight),
02978             &window_changes);
02979         }
02980       /*
02981         Allocate selection info memory.
02982       */
02983       if (selection_info != (XWidgetInfo *) NULL)
02984         selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
02985       selection_info=(XWidgetInfo *) AcquireQuantumMemory(number_selections,
02986         sizeof(*selection_info));
02987       if (selection_info == (XWidgetInfo *) NULL)
02988         {
02989           ThrowXWindowFatalException(ResourceLimitError,
02990             "MemoryAllocationFailed","...");
02991           return(id);
02992         }
02993       state|=UpdateConfigurationState | RedrawWidgetState;
02994     }
02995   /*
02996     Wait for next event.
02997   */
02998   if (event != (XEvent *) NULL)
02999     switch (event->type)
03000     {
03001       case ButtonPress:
03002       {
03003         for (i=0; i < (int) number_selections; i++)
03004         {
03005           if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
03006             continue;
03007           if (i >= (int) windows->command.data)
03008             {
03009               selection_info[i].raised=MagickFalse;
03010               XDrawBeveledButton(display,&windows->command,&selection_info[i]);
03011               break;
03012             }
03013           submenu_info=selection_info[i];
03014           submenu_info.active=MagickTrue;
03015           toggle_info.y=
03016             submenu_info.y+(submenu_info.height >> 1)-(toggle_info.height >> 1);
03017           id=i;
03018           (void) XCheckWindowEvent(display,windows->widget.id,LeaveWindowMask,
03019             event);
03020           break;
03021         }
03022         break;
03023       }
03024       case ButtonRelease:
03025       {
03026         for (i=0; i < (int) number_selections; i++)
03027         {
03028           if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse)
03029             continue;
03030           id=i;
03031           if (id >= (int) windows->command.data)
03032             {
03033               selection_info[id].raised=MagickTrue;
03034               XDrawBeveledButton(display,&windows->command,&selection_info[id]);
03035               break;
03036             }
03037           break;
03038         }
03039         break;
03040       }
03041       case ClientMessage:
03042       {
03043         /*
03044           If client window delete message, withdraw command widget.
03045         */
03046         if (event->xclient.message_type != windows->wm_protocols)
03047           break;
03048         if (*event->xclient.data.l != (int) windows->wm_delete_window)
03049           break;
03050         (void) XWithdrawWindow(display,windows->command.id,
03051           windows->command.screen);
03052         break;
03053       }
03054       case ConfigureNotify:
03055       {
03056         /*
03057           Update widget configuration.
03058         */
03059         if (event->xconfigure.window != windows->command.id)
03060           break;
03061         if (event->xconfigure.send_event != 0)
03062           {
03063             windows->command.x=event->xconfigure.x;
03064             windows->command.y=event->xconfigure.y;
03065           }
03066         if ((event->xconfigure.width == (int) windows->command.width) &&
03067             (event->xconfigure.height == (int) windows->command.height))
03068           break;
03069         windows->command.width=(unsigned int)
03070           MagickMax(event->xconfigure.width,(int) windows->command.min_width);
03071         windows->command.height=(unsigned int)
03072           MagickMax(event->xconfigure.height,(int) windows->command.min_height);
03073         state|=UpdateConfigurationState;
03074         break;
03075       }
03076       case Expose:
03077       {
03078         if (event->xexpose.window != windows->command.id)
03079           break;
03080         if (event->xexpose.count != 0)
03081           break;
03082         state|=RedrawWidgetState;
03083         break;
03084       }
03085       case MotionNotify:
03086       {
03087         /*
03088           Return the ID of the highlighted menu entry.
03089         */
03090         for ( ; ; )
03091         {
03092           for (i=0; i < (int) number_selections; i++)
03093           {
03094             if (i >= (int) windows->command.data)
03095               {
03096                 if (selection_info[i].raised ==
03097                     MatteIsActive(selection_info[i],event->xmotion))
03098                   {
03099                     /*
03100                       Button status changed.
03101                     */
03102                     selection_info[i].raised=!selection_info[i].raised;
03103                     XDrawBeveledButton(display,&windows->command,
03104                       &selection_info[i]);
03105                   }
03106                 continue;
03107               }
03108             if (MatteIsActive(selection_info[i],event->xmotion) == MagickFalse)
03109               continue;
03110             submenu_info=selection_info[i];
03111             submenu_info.active=MagickTrue;
03112             toggle_info.raised=MagickTrue;
03113             toggle_info.y=submenu_info.y+(submenu_info.height >> 1)-
03114               (toggle_info.height >> 1);
03115             XDrawTriangleEast(display,&windows->command,&toggle_info);
03116             id=i;
03117           }
03118           XDelay(display,SuspendTime);
03119           if (XCheckMaskEvent(display,ButtonMotionMask,event) == MagickFalse)
03120             break;
03121           while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
03122           toggle_info.raised=MagickFalse;
03123           if (windows->command.data != 0)
03124             XDrawTriangleEast(display,&windows->command,&toggle_info);
03125         }
03126         break;
03127       }
03128       case MapNotify:
03129       {
03130         windows->command.mapped=MagickTrue;
03131         break;
03132       }
03133       case UnmapNotify:
03134       {
03135         windows->command.mapped=MagickFalse;
03136         break;
03137       }
03138       default:
03139         break;
03140     }
03141   if (state & UpdateConfigurationState)
03142     {
03143       /*
03144         Initialize button information.
03145       */
03146       assert(selections != (const char **) NULL);
03147       y=tile_height+20;
03148       for (i=0; i < (int) number_selections; i++)
03149       {
03150         XGetWidgetInfo(selections[i],&selection_info[i]);
03151         selection_info[i].center=MagickFalse;
03152         selection_info[i].bevel_width--;
03153         selection_info[i].height=(unsigned int) ((3*height) >> 1);
03154         selection_info[i].x=(QuantumMargin >> 1)+4;
03155         selection_info[i].width=(unsigned int)
03156           (windows->command.width-(selection_info[i].x << 1));
03157         selection_info[i].y=y;
03158         y+=selection_info[i].height+(selection_info[i].bevel_width << 1)+6;
03159       }
03160       XGetWidgetInfo((char *) NULL,&toggle_info);
03161       toggle_info.bevel_width--;
03162       toggle_info.width=(unsigned int)
03163         (((5*height) >> 3)-(toggle_info.bevel_width << 1));
03164       toggle_info.height=toggle_info.width;
03165       toggle_info.x=selection_info[0].x+selection_info[0].width-
03166         toggle_info.width-(QuantumMargin >> 1);
03167       if (windows->command.mapped)
03168         (void) XClearWindow(display,windows->command.id);
03169     }
03170   if (state & RedrawWidgetState)
03171     {
03172       Pixmap
03173         tile_pixmap;
03174 
03175       /*
03176         Draw command buttons.
03177       */
03178       tile_pixmap=XCreatePixmapFromBitmapData(display,windows->command.id,
03179         (char *) tile_bits,tile_width,tile_height,1L,0L,1);
03180       if (tile_pixmap != (Pixmap) NULL)
03181         {
03182           (void) XCopyPlane(display,tile_pixmap,windows->command.id,
03183             windows->command.annotate_context,0,0,tile_width,tile_height,
03184             (int) ((windows->command.width-tile_width) >> 1),10,1L);
03185           (void) XFreePixmap(display,tile_pixmap);
03186         }
03187       for (i=0; i < (int) number_selections; i++)
03188       {
03189         XDrawBeveledButton(display,&windows->command,&selection_info[i]);
03190         if (i >= (int) windows->command.data)
03191           continue;
03192         toggle_info.raised=i == id ? MagickTrue : MagickFalse;
03193         toggle_info.y=selection_info[i].y+
03194           (selection_info[i].height >> 1)-(toggle_info.height >> 1);
03195         XDrawTriangleEast(display,&windows->command,&toggle_info);
03196       }
03197       XHighlightWidget(display,&windows->command,BorderOffset,BorderOffset);
03198     }
03199   return(id);
03200 }
03201 
03202 /*
03203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03204 %                                                                             %
03205 %                                                                             %
03206 %                                                                             %
03207 %   X C o n f i r m W i d g e t                                               %
03208 %                                                                             %
03209 %                                                                             %
03210 %                                                                             %
03211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03212 %
03213 %  XConfirmWidget() displays a Confirm widget with a notice to the user. The
03214 %  function returns -1 if Dismiss is pressed, 0 for Cancel, and 1 for Yes.
03215 %
03216 %  The format of the XConfirmWidget method is:
03217 %
03218 %      int XConfirmWidget(Display *display,XWindows *windows,
03219 %        const char *reason,const char *description)
03220 %
03221 %  A description of each parameter follows:
03222 %
03223 %    o display: Specifies a connection to an X server;  returned from
03224 %      XOpenDisplay.
03225 %
03226 %    o window: Specifies a pointer to a XWindows structure.
03227 %
03228 %    o reason: Specifies the message to display before terminating the
03229 %      program.
03230 %
03231 %    o description: Specifies any description to the message.
03232 %
03233 */
03234 MagickExport int XConfirmWidget(Display *display,XWindows *windows,
03235   const char *reason,const char *description)
03236 {
03237 #define CancelButtonText  "Cancel"
03238 #define DismissButtonText  "Dismiss"
03239 #define YesButtonText  "Yes"
03240 
03241   int
03242     confirm,
03243     x,
03244     y;
03245 
03246   Status
03247     status;
03248 
03249   unsigned int
03250     height,
03251     width;
03252 
03253   unsigned long
03254     state;
03255 
03256   XEvent
03257     event;
03258 
03259   XFontStruct
03260     *font_info;
03261 
03262   XTextProperty
03263     window_name;
03264 
03265   XWidgetInfo
03266     cancel_info,
03267     dismiss_info,
03268     yes_info;
03269 
03270   XWindowChanges
03271     window_changes;
03272 
03273   /*
03274     Determine Confirm widget attributes.
03275   */
03276   assert(display != (Display *) NULL);
03277   assert(windows != (XWindows *) NULL);
03278   assert(reason != (char *) NULL);
03279   assert(description != (char *) NULL);
03280   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason);
03281   XCheckRefreshWindows(display,windows);
03282   font_info=windows->widget.font_info;
03283   width=WidgetTextWidth(font_info,CancelButtonText);
03284   if (WidgetTextWidth(font_info,DismissButtonText) > width)
03285     width=WidgetTextWidth(font_info,DismissButtonText);
03286   if (WidgetTextWidth(font_info,YesButtonText) > width)
03287     width=WidgetTextWidth(font_info,YesButtonText);
03288   width<<=1;
03289   if (description != (char *) NULL)
03290     if (WidgetTextWidth(font_info,(char *) description) > width)
03291       width=WidgetTextWidth(font_info,(char *) description);
03292   height=(unsigned int) (font_info->ascent+font_info->descent);
03293   /*
03294     Position Confirm widget.
03295   */
03296   windows->widget.width=(unsigned int) (width+9*QuantumMargin);
03297   windows->widget.min_width=(unsigned int) (9*QuantumMargin+
03298     WidgetTextWidth(font_info,CancelButtonText)+
03299     WidgetTextWidth(font_info,DismissButtonText)+
03300     WidgetTextWidth(font_info,YesButtonText));
03301   if (windows->widget.width < windows->widget.min_width)
03302     windows->widget.width=windows->widget.min_width;
03303   windows->widget.height=(unsigned int) (12*height);
03304   windows->widget.min_height=(unsigned int) (7*height);
03305   if (windows->widget.height < windows->widget.min_height)
03306     windows->widget.height=windows->widget.min_height;
03307   XConstrainWindowPosition(display,&windows->widget);
03308   /*
03309     Map Confirm widget.
03310   */
03311   (void) CopyMagickString(windows->widget.name,"Confirm",MaxTextExtent);
03312   status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
03313   if (status != False)
03314     {
03315       XSetWMName(display,windows->widget.id,&window_name);
03316       XSetWMIconName(display,windows->widget.id,&window_name);
03317       (void) XFree((void *) window_name.value);
03318     }
03319   window_changes.width=(int) windows->widget.width;
03320   window_changes.height=(int) windows->widget.height;
03321   window_changes.x=windows->widget.x;
03322   window_changes.y=windows->widget.y;
03323   (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
03324     (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
03325   (void) XMapRaised(display,windows->widget.id);
03326   windows->widget.mapped=MagickFalse;
03327   /*
03328     Respond to X events.
03329   */
03330   confirm=0;
03331   state=UpdateConfigurationState;
03332   XSetCursorState(display,windows,MagickTrue);
03333   do
03334   {
03335     if (state & UpdateConfigurationState)
03336       {
03337         /*
03338           Initialize button information.
03339         */
03340         XGetWidgetInfo(CancelButtonText,&cancel_info);
03341         cancel_info.width=(unsigned int) QuantumMargin+
03342           WidgetTextWidth(font_info,CancelButtonText);
03343         cancel_info.height=(unsigned int) ((3*height) >> 1);
03344         cancel_info.x=(int) (windows->widget.width-cancel_info.width-
03345           QuantumMargin);
03346         cancel_info.y=(int) (windows->widget.height-(cancel_info.height << 1));
03347         dismiss_info=cancel_info;
03348         dismiss_info.text=(char *) DismissButtonText;
03349         if (LocaleCompare(description,"Do you want to save it") == 0)
03350           dismiss_info.text=(char *) "Don't Save";
03351         dismiss_info.width=(unsigned int) QuantumMargin+
03352           WidgetTextWidth(font_info,dismiss_info.text);
03353         dismiss_info.x=(int)
03354           ((windows->widget.width >> 1)-(dismiss_info.width >> 1));
03355         yes_info=cancel_info;
03356         yes_info.text=(char *) YesButtonText;
03357         if (LocaleCompare(description,"Do you want to save it") == 0)
03358           yes_info.text=(char *) "Save";
03359         yes_info.width=(unsigned int) QuantumMargin+
03360           WidgetTextWidth(font_info,yes_info.text);
03361         if (yes_info.width < cancel_info.width)
03362           yes_info.width=cancel_info.width;
03363         yes_info.x=QuantumMargin;
03364         state&=(~UpdateConfigurationState);
03365       }
03366     if (state & RedrawWidgetState)
03367       {
03368         /*
03369           Redraw Confirm widget.
03370         */
03371         width=WidgetTextWidth(font_info,(char *) reason);
03372         x=(int) ((windows->widget.width >> 1)-(width >> 1));
03373         y=(int) ((windows->widget.height >> 1)-(height << 1));
03374         (void) XDrawString(display,windows->widget.id,
03375           windows->widget.annotate_context,x,y,(char *) reason,Extent(reason));
03376         if (description != (char *) NULL)
03377           {
03378             char
03379               question[MaxTextExtent];
03380 
03381             (void) CopyMagickString(question,description,MaxTextExtent);
03382             (void) ConcatenateMagickString(question,"?",MaxTextExtent);
03383             width=WidgetTextWidth(font_info,question);
03384             x=(int) ((windows->widget.width >> 1)-(width >> 1));
03385             y+=height;
03386             (void) XDrawString(display,windows->widget.id,
03387               windows->widget.annotate_context,x,y,question,Extent(question));
03388           }
03389         XDrawBeveledButton(display,&windows->widget,&cancel_info);
03390         XDrawBeveledButton(display,&windows->widget,&dismiss_info);
03391         XDrawBeveledButton(display,&windows->widget,&yes_info);
03392         XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
03393         state&=(~RedrawWidgetState);
03394       }
03395     /*
03396       Wait for next event.
03397     */
03398     (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
03399     switch (event.type)
03400     {
03401       case ButtonPress:
03402       {
03403         if (MatteIsActive(cancel_info,event.xbutton))
03404           {
03405             /*
03406               User pressed No button.
03407             */
03408             cancel_info.raised=MagickFalse;
03409             XDrawBeveledButton(display,&windows->widget,&cancel_info);
03410             break;
03411           }
03412         if (MatteIsActive(dismiss_info,event.xbutton))
03413           {
03414             /*
03415               User pressed Dismiss button.
03416             */
03417             dismiss_info.raised=MagickFalse;
03418             XDrawBeveledButton(display,&windows->widget,&dismiss_info);
03419             break;
03420           }
03421         if (MatteIsActive(yes_info,event.xbutton))
03422           {
03423             /*
03424               User pressed Yes button.
03425             */
03426             yes_info.raised=MagickFalse;
03427             XDrawBeveledButton(display,&windows->widget,&yes_info);
03428             break;
03429           }
03430         break;
03431       }
03432       case ButtonRelease:
03433       {
03434         if (windows->widget.mapped == MagickFalse)
03435           break;
03436         if (cancel_info.raised == MagickFalse)
03437           {
03438             if (event.xbutton.window == windows->widget.id)
03439               if (MatteIsActive(cancel_info,event.xbutton))
03440                 {
03441                   confirm=0;
03442                   state|=ExitState;
03443                 }
03444             cancel_info.raised=MagickTrue;
03445             XDrawBeveledButton(display,&windows->widget,&cancel_info);
03446           }
03447         if (dismiss_info.raised == MagickFalse)
03448           {
03449             if (event.xbutton.window == windows->widget.id)
03450               if (MatteIsActive(dismiss_info,event.xbutton))
03451                 {
03452                   confirm=(-1);
03453                   state|=ExitState;
03454                 }
03455             dismiss_info.raised=MagickTrue;
03456             XDrawBeveledButton(display,&windows->widget,&dismiss_info);
03457           }
03458         if (yes_info.raised == MagickFalse)
03459           {
03460             if (event.xbutton.window == windows->widget.id)
03461               if (MatteIsActive(yes_info,event.xbutton))
03462                 {
03463                   confirm=1;
03464                   state|=ExitState;
03465                 }
03466             yes_info.raised=MagickTrue;
03467             XDrawBeveledButton(display,&windows->widget,&yes_info);
03468           }
03469         break;
03470       }
03471       case ClientMessage:
03472       {
03473         /*
03474           If client window delete message, exit.
03475         */
03476         if (event.xclient.message_type != windows->wm_protocols)
03477           break;
03478         if (*event.xclient.data.l == (int) windows->wm_take_focus)
03479           {
03480             (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
03481               (Time) event.xclient.data.l[1]);
03482             break;
03483           }
03484         if (*event.xclient.data.l != (int) windows->wm_delete_window)
03485           break;
03486         if (event.xclient.window == windows->widget.id)
03487           {
03488             state|=ExitState;
03489             break;
03490           }
03491         break;
03492       }
03493       case ConfigureNotify:
03494       {
03495         /*
03496           Update widget configuration.
03497         */
03498         if (event.xconfigure.window != windows->widget.id)
03499           break;
03500         if ((event.xconfigure.width == (int) windows->widget.width) &&
03501             (event.xconfigure.height == (int) windows->widget.height))
03502           break;
03503         windows->widget.width=(unsigned int)
03504           MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
03505         windows->widget.height=(unsigned int)
03506           MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
03507         state|=UpdateConfigurationState;
03508         break;
03509       }
03510       case EnterNotify:
03511       {
03512         if (event.xcrossing.window != windows->widget.id)
03513           break;
03514         state&=(~InactiveWidgetState);
03515         break;
03516       }
03517       case Expose:
03518       {
03519         if (event.xexpose.window != windows->widget.id)
03520           break;
03521         if (event.xexpose.count != 0)
03522           break;
03523         state|=RedrawWidgetState;
03524         break;
03525       }
03526       case KeyPress:
03527       {
03528         static char
03529           command[MaxTextExtent];
03530 
03531         static KeySym
03532           key_symbol;
03533 
03534         /*
03535           Respond to a user key press.
03536         */
03537         if (event.xkey.window != windows->widget.id)
03538           break;
03539         (void) XLookupString((XKeyEvent *) &event.xkey,command,
03540           (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
03541         if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
03542           {
03543             yes_info.raised=MagickFalse;
03544             XDrawBeveledButton(display,&windows->widget,&yes_info);
03545             confirm=1;
03546             state|=ExitState;
03547             break;
03548           }
03549         break;
03550       }
03551       case LeaveNotify:
03552       {
03553         if (event.xcrossing.window != windows->widget.id)
03554           break;
03555         state|=InactiveWidgetState;
03556         break;
03557       }
03558       case MotionNotify:
03559       {
03560         /*
03561           Discard pending button motion events.
03562         */
03563         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
03564         if (state & InactiveWidgetState)
03565           break;
03566         if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
03567           {
03568             /*
03569               Cancel button status changed.
03570             */
03571             cancel_info.raised=cancel_info.raised == MagickFalse ?
03572               MagickTrue : MagickFalse;
03573             XDrawBeveledButton(display,&windows->widget,&cancel_info);
03574             break;
03575           }
03576         if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion))
03577           {
03578             /*
03579               Dismiss button status changed.
03580             */
03581             dismiss_info.raised=cancel_info.raised == MagickFalse ?
03582               MagickTrue : MagickFalse;
03583             XDrawBeveledButton(display,&windows->widget,&dismiss_info);
03584             break;
03585           }
03586         if (yes_info.raised == MatteIsActive(yes_info,event.xmotion))
03587           {
03588             /*
03589               Yes button status changed.
03590             */
03591             yes_info.raised=yes_info.raised == MagickFalse ?
03592               MagickTrue : MagickFalse;
03593             XDrawBeveledButton(display,&windows->widget,&yes_info);
03594             break;
03595           }
03596         break;
03597       }
03598       default:
03599         break;
03600     }
03601   } while ((state & ExitState) == 0);
03602   XSetCursorState(display,windows,MagickFalse);
03603   (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen);
03604   XCheckRefreshWindows(display,windows);
03605   return(confirm);
03606 }
03607 
03608 /*
03609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03610 %                                                                             %
03611 %                                                                             %
03612 %                                                                             %
03613 %   X D i a l o g W i d g e t                                                 %
03614 %                                                                             %
03615 %                                                                             %
03616 %                                                                             %
03617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03618 %
03619 %  XDialogWidget() displays a Dialog widget with a query to the user.  The user
03620 %  keys a reply and presses the Ok or Cancel button to exit.  The typed text is
03621 %  returned as the reply function parameter.
03622 %
03623 %  The format of the XDialogWidget method is:
03624 %
03625 %      int XDialogWidget(Display *display,XWindows *windows,const char *action,
03626 %        const char *query,char *reply)
03627 %
03628 %  A description of each parameter follows:
03629 %
03630 %    o display: Specifies a connection to an X server;  returned from
03631 %      XOpenDisplay.
03632 %
03633 %    o window: Specifies a pointer to a XWindows structure.
03634 %
03635 %    o action: Specifies a pointer to the action of this widget.
03636 %
03637 %    o query: Specifies a pointer to the query to present to the user.
03638 %
03639 %    o reply: the response from the user is returned in this parameter.
03640 %
03641 */
03642 MagickExport int XDialogWidget(Display *display,XWindows *windows,
03643   const char *action,const char *query,char *reply)
03644 {
03645 #define CancelButtonText  "Cancel"
03646 
03647   char
03648     primary_selection[MaxTextExtent];
03649 
03650   int
03651     x;
03652 
03653   register int
03654     i;
03655 
03656   static MagickBooleanType
03657     raised = MagickFalse;
03658 
03659   Status
03660     status;
03661 
03662   unsigned int
03663     anomaly,
03664     height,
03665     width;
03666 
03667   unsigned long
03668     state;
03669 
03670   XEvent
03671     event;
03672 
03673   XFontStruct
03674     *font_info;
03675 
03676   XTextProperty
03677     window_name;
03678 
03679   XWidgetInfo
03680     action_info,
03681     cancel_info,
03682     reply_info,
03683     special_info,
03684     text_info;
03685 
03686   XWindowChanges
03687     window_changes;
03688 
03689   /*
03690     Determine Dialog widget attributes.
03691   */
03692   assert(display != (Display *) NULL);
03693   assert(windows != (XWindows *) NULL);
03694   assert(action != (char *) NULL);
03695   assert(query != (char *) NULL);
03696   assert(reply != (char *) NULL);
03697   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
03698   XCheckRefreshWindows(display,windows);
03699   font_info=windows->widget.font_info;
03700   width=WidgetTextWidth(font_info,(char *) action);
03701   if (WidgetTextWidth(font_info,CancelButtonText) > width)
03702     width=WidgetTextWidth(font_info,CancelButtonText);
03703   width+=(3*QuantumMargin) >> 1;
03704   height=(unsigned int) (font_info->ascent+font_info->descent);
03705   /*
03706     Position Dialog widget.
03707   */
03708   windows->widget.width=(unsigned int) MagickMax(2*width,(int) WidgetTextWidth(
03709     font_info,(char *) query));
03710   if (windows->widget.width < WidgetTextWidth(font_info,reply))
03711     windows->widget.width=WidgetTextWidth(font_info,reply);
03712   windows->widget.width+=6*QuantumMargin;
03713   windows->widget.min_width=(unsigned int)
03714     (width+28*XTextWidth(font_info,"#",1)+4*QuantumMargin);
03715   if (windows->widget.width < windows->widget.min_width)
03716     windows->widget.width=windows->widget.min_width;
03717   windows->widget.height=(unsigned int) (7*height+(QuantumMargin << 1));
03718   windows->widget.min_height=windows->widget.height;
03719   if (windows->widget.height < windows->widget.min_height)
03720     windows->widget.height=windows->widget.min_height;
03721   XConstrainWindowPosition(display,&windows->widget);
03722   /*
03723     Map Dialog widget.
03724   */
03725   (void) CopyMagickString(windows->widget.name,"Dialog",MaxTextExtent);
03726   status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
03727   if (status != False)
03728     {
03729       XSetWMName(display,windows->widget.id,&window_name);
03730       XSetWMIconName(display,windows->widget.id,&window_name);
03731       (void) XFree((void *) window_name.value);
03732     }
03733   window_changes.width=(int) windows->widget.width;
03734   window_changes.height=(int) windows->widget.height;
03735   window_changes.x=windows->widget.x;
03736   window_changes.y=windows->widget.y;
03737   (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
03738     (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes);
03739   (void) XMapRaised(display,windows->widget.id);
03740   windows->widget.mapped=MagickFalse;
03741   /*
03742     Respond to X events.
03743   */
03744   anomaly=(LocaleCompare(action,"Background") == 0) ||
03745     (LocaleCompare(action,"New") == 0) ||
03746     (LocaleCompare(action,"Quantize") == 0) ||
03747     (LocaleCompare(action,"Resize") == 0) ||
03748     (LocaleCompare(action,"Save") == 0) ||
03749     (LocaleCompare(action,"Shade") == 0);
03750   state=UpdateConfigurationState;
03751   XSetCursorState(display,windows,MagickTrue);
03752   do
03753   {
03754     if (state & UpdateConfigurationState)
03755       {
03756         /*
03757           Initialize button information.
03758         */
03759         XGetWidgetInfo(CancelButtonText,&cancel_info);
03760         cancel_info.width=width;
03761         cancel_info.height=(unsigned int) ((3*height) >> 1);
03762         cancel_info.x=(int)
03763           (windows->widget.width-cancel_info.width-((3*QuantumMargin) >> 1));
03764         cancel_info.y=(int)
03765           (windows->widget.height-cancel_info.height-((3*QuantumMargin) >> 1));
03766         XGetWidgetInfo(action,&action_info);
03767         action_info.width=width;
03768         action_info.height=(unsigned int) ((3*height) >> 1);
03769         action_info.x=cancel_info.x-(cancel_info.width+QuantumMargin+
03770           (action_info.bevel_width << 1));
03771         action_info.y=cancel_info.y;
03772         /*
03773           Initialize reply information.
03774         */
03775         XGetWidgetInfo(reply,&reply_info);
03776         reply_info.raised=MagickFalse;
03777         reply_info.bevel_width--;
03778         reply_info.width=windows->widget.width-(3*QuantumMargin);
03779         reply_info.height=height << 1;
03780         reply_info.x=(3*QuantumMargin) >> 1;
03781         reply_info.y=action_info.y-reply_info.height-QuantumMargin;
03782         /*
03783           Initialize option information.
03784         */
03785         XGetWidgetInfo("Dither",&special_info);
03786         special_info.raised=raised;
03787         special_info.bevel_width--;
03788         special_info.width=(unsigned int) QuantumMargin >> 1;
03789         special_info.height=(unsigned int) QuantumMargin >> 1;
03790         special_info.x=reply_info.x;
03791         special_info.y=action_info.y+action_info.height-special_info.height;
03792         if (LocaleCompare(action,"Background") == 0)
03793           special_info.text=(char *) "Backdrop";
03794         if (LocaleCompare(action,"New") == 0)
03795           special_info.text=(char *) "Gradation";
03796         if (LocaleCompare(action,"Resize") == 0)
03797           special_info.text=(char *) "Constrain ratio";
03798         if (LocaleCompare(action,"Save") == 0)
03799           special_info.text=(char *) "Non-progressive";
03800         if (LocaleCompare(action,"Shade") == 0)
03801           special_info.text=(char *) "Color shading";
03802         /*
03803           Initialize text information.
03804         */
03805         XGetWidgetInfo(query,&text_info);
03806         text_info.width=reply_info.width;
03807         text_info.height=height;
03808         text_info.x=reply_info.x-(QuantumMargin >> 1);
03809         text_info.y=QuantumMargin;
03810         text_info.center=MagickFalse;
03811         state&=(~UpdateConfigurationState);
03812       }
03813     if (state & RedrawWidgetState)
03814       {
03815         /*
03816           Redraw Dialog widget.
03817         */
03818         XDrawWidgetText(display,&windows->widget,&text_info);
03819         XDrawBeveledMatte(display,&windows->widget,&reply_info);
03820         XDrawMatteText(display,&windows->widget,&reply_info);
03821         if (anomaly)
03822           XDrawBeveledButton(display,&windows->widget,&special_info);
03823         XDrawBeveledButton(display,&windows->widget,&action_info);
03824         XDrawBeveledButton(display,&windows->widget,&cancel_info);
03825         XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
03826         state&=(~RedrawWidgetState);
03827       }
03828     /*
03829       Wait for next event.
03830     */
03831     (void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
03832     switch (event.type)
03833     {
03834       case ButtonPress:
03835       {
03836         if (anomaly)
03837           if (MatteIsActive(special_info,event.xbutton))
03838             {
03839               /*
03840                 Option button status changed.
03841               */
03842               special_info.raised=!special_info.raised;
03843               XDrawBeveledButton(display,&windows->widget,&special_info);
03844               break;
03845             }
03846         if (MatteIsActive(action_info,event.xbutton))
03847           {
03848             /*
03849               User pressed Action button.
03850             */
03851             action_info.raised=MagickFalse;
03852             XDrawBeveledButton(display,&windows->widget,&action_info);
03853             break;
03854           }
03855         if (MatteIsActive(cancel_info,event.xbutton))
03856           {
03857             /*
03858               User pressed Cancel button.
03859             */
03860             cancel_info.raised=MagickFalse;
03861             XDrawBeveledButton(display,&windows->widget,&cancel_info);
03862             break;
03863           }
03864         if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
03865           break;
03866         if (event.xbutton.button != Button2)
03867           {
03868             static Time
03869               click_time;
03870 
03871             /*
03872               Move text cursor to position of button press.
03873             */
03874             x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
03875             for (i=1; i <= Extent(reply_info.marker); i++)
03876               if (XTextWidth(font_info,reply_info.marker,i) > x)
03877                 break;
03878             reply_info.cursor=reply_info.marker+i-1;
03879             if (event.xbutton.time > (click_time+DoubleClick))
03880               reply_info.highlight=MagickFalse;
03881             else
03882               {
03883                 /*
03884                   Become the XA_PRIMARY selection owner.
03885                 */
03886                 (void) CopyMagickString(primary_selection,reply_info.text,
03887                   MaxTextExtent);
03888                 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
03889                   event.xbutton.time);
03890                 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
03891                   windows->widget.id ? MagickTrue : MagickFalse;
03892               }
03893             XDrawMatteText(display,&windows->widget,&reply_info);
03894             click_time=event.xbutton.time;
03895             break;
03896           }
03897         /*
03898           Request primary selection.
03899         */
03900         (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
03901           windows->widget.id,event.xbutton.time);
03902         break;
03903       }
03904       case ButtonRelease:
03905       {
03906         if (windows->widget.mapped == MagickFalse)
03907           break;
03908         if (action_info.raised == MagickFalse)
03909           {
03910             if (event.xbutton.window == windows->widget.id)
03911               if (MatteIsActive(action_info,event.xbutton))
03912                 state|=ExitState;
03913             action_info.raised=MagickTrue;
03914             XDrawBeveledButton(display,&windows->widget,&action_info);
03915           }
03916         if (cancel_info.raised == MagickFalse)
03917           {
03918             if (event.xbutton.window == windows->widget.id)
03919               if (MatteIsActive(cancel_info,event.xbutton))
03920                 {
03921                   *reply_info.text='\0';
03922                   state|=ExitState;
03923                 }
03924             cancel_info.raised=MagickTrue;
03925