]> granicus.if.org Git - imagemagick/blob - magick/xwindow.c
(no commit message)
[imagemagick] / magick / xwindow.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %              X   X  W   W  IIIII  N   N  DDDD    OOO   W   W                %
7 %               X X   W   W    I    NN  N  D   D  O   O  W   W                %
8 %                X    W   W    I    N N N  D   D  O   O  W   W                %
9 %               X X   W W W    I    N  NN  D   D  O   O  W W W                %
10 %              X   X   W W   IIIII  N   N  DDDD    OOO    W W                 %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore X11 Utility Methods                        %
14 %                                                                             %
15 %                               Software Design                               %
16 %                                 John Cristy                                 %
17 %                                  July 1992                                  %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/animate.h"
44 #include "magick/artifact.h"
45 #include "magick/blob.h"
46 #include "magick/cache.h"
47 #include "magick/client.h"
48 #include "magick/color.h"
49 #include "magick/color-private.h"
50 #include "magick/composite.h"
51 #include "magick/display.h"
52 #include "magick/exception.h"
53 #include "magick/exception-private.h"
54 #include "magick/geometry.h"
55 #include "magick/identify.h"
56 #include "magick/image.h"
57 #include "magick/image-private.h"
58 #include "magick/list.h"
59 #include "magick/locale_.h"
60 #include "magick/log.h"
61 #include "magick/magick.h"
62 #include "magick/memory_.h"
63 #include "magick/monitor.h"
64 #include "magick/option.h"
65 #include "magick/PreRvIcccm.h"
66 #include "magick/quantize.h"
67 #include "magick/quantum.h"
68 #include "magick/quantum-private.h"
69 #include "magick/resource_.h"
70 #include "magick/resize.h"
71 #include "magick/shear.h"
72 #include "magick/statistic.h"
73 #include "magick/string_.h"
74 #include "magick/transform.h"
75 #include "magick/utility.h"
76 #include "magick/widget.h"
77 #include "magick/xwindow.h"
78 #include "magick/xwindow-private.h"
79 #include "magick/version.h"
80 #if defined(__BEOS__)
81 #include <OS.h>
82 #endif
83 #if defined(MAGICKCORE_X11_DELEGATE)
84 #include <X11/Xproto.h>
85 #include <X11/Xlocale.h>
86 #if defined(MAGICK_HAVE_POLL)
87 # include <sys/poll.h>
88 #endif
89 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
90 #if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
91 # include <machine/param.h>
92 #endif
93 #include <sys/ipc.h>
94 #include <sys/shm.h>
95 #include <X11/extensions/XShm.h>
96 #endif
97 #if defined(MAGICKCORE_HAVE_SHAPE)
98 #include <X11/extensions/shape.h>
99 #endif
100 \f
101 /*
102   X defines.
103 */
104 #define XBlueGamma(color) RoundToQuantum(blue_gamma == 1.0 ? (double) \
105   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
106   QuantumRange)))
107 #define XGammaPixel(map,color)  (unsigned long) (map->base_pixel+ \
108   ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
109     map->red_mult)+ \
110   ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
111     map->green_mult)+ \
112   ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
113     map->blue_mult))
114 #define XGreenGamma(color) RoundToQuantum(green_gamma == 1.0 ? (double) \
115   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
116   QuantumRange)))
117 #define XRedGamma(color) RoundToQuantum(red_gamma == 1.0 ? (double) \
118   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
119   QuantumRange)))
120 #define XStandardPixel(map,color)  (unsigned long) (map->base_pixel+ \
121   (((color)->red*map->red_max/65535L)*map->red_mult)+ \
122   (((color)->green*map->green_max/65535L)*map->green_mult)+ \
123   (((color)->blue*map->blue_max/65535L)*map->blue_mult))
124
125 #define AccentuateModulate  ScaleCharToQuantum(80)
126 #define HighlightModulate  ScaleCharToQuantum(125)
127 #define ShadowModulate  ScaleCharToQuantum(135)
128 #define DepthModulate  ScaleCharToQuantum(185)
129 #define TroughModulate  ScaleCharToQuantum(110)
130
131 #define XLIB_ILLEGAL_ACCESS  1
132 #undef ForgetGravity
133 #undef NorthWestGravity
134 #undef NorthGravity
135 #undef NorthEastGravity
136 #undef WestGravity
137 #undef CenterGravity
138 #undef EastGravity
139 #undef SouthWestGravity
140 #undef SouthGravity
141 #undef SouthEastGravity
142 #undef StaticGravity
143
144 #undef index
145 #if defined(hpux9)
146 #define XFD_SET  int
147 #else
148 #define XFD_SET  fd_set
149 #endif
150
151 /*
152   Enumeration declarations.
153 */
154 typedef enum
155 {
156 #undef DoRed
157   DoRed = 0x0001,
158 #undef DoGreen
159   DoGreen = 0x0002,
160 #undef DoBlue
161   DoBlue = 0x0004,
162   DoMatte = 0x0008
163 } XColorFlags;
164
165 /*
166   Typedef declarations.
167 */
168 typedef struct _DiversityPacket
169 {
170   Quantum
171     red,
172     green,
173     blue;
174
175   unsigned short
176     index;
177
178   unsigned long
179     count;
180 } DiversityPacket;
181 \f
182 /*
183   Constant declaractions.
184 */
185 static MagickBooleanType
186   xerror_alert = MagickFalse;
187 \f
188 /*
189   Method prototypes.
190 */
191 static const char
192   *XVisualClassName(const int);
193
194 static MagickRealType
195   blue_gamma = 1.0,
196   green_gamma = 1.0,
197   red_gamma = 1.0;
198
199 static MagickBooleanType
200   XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
201
202 static void
203   XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
204     XImage *,XImage *),
205   XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
206     XImage *,XImage *);
207
208 static Window
209   XSelectWindow(Display *,RectangleInfo *);
210 \f
211 /*
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213 %                                                                             %
214 %                                                                             %
215 %                                                                             %
216 %   D e s t r o y X R e s o u r c e s                                         %
217 %                                                                             %
218 %                                                                             %
219 %                                                                             %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 %
222 %  DestroyXResources() destroys any X resources.
223 %
224 %  The format of the DestroyXResources method is:
225 %
226 %      void DestroyXResources()
227 %
228 %  A description of each parameter follows:
229 %
230 */
231 MagickExport void DestroyXResources(void)
232 {
233   register int
234     i;
235
236   unsigned int
237     number_windows;
238
239   XWindowInfo
240     *magick_windows[MaxXWindows];
241
242   XWindows
243     *windows;
244
245   DestroyXWidget();
246   windows=XSetWindows((XWindows *) ~0);
247   if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
248     return;
249   number_windows=0;
250   magick_windows[number_windows++]=(&windows->context);
251   magick_windows[number_windows++]=(&windows->group_leader);
252   magick_windows[number_windows++]=(&windows->backdrop);
253   magick_windows[number_windows++]=(&windows->icon);
254   magick_windows[number_windows++]=(&windows->image);
255   magick_windows[number_windows++]=(&windows->info);
256   magick_windows[number_windows++]=(&windows->magnify);
257   magick_windows[number_windows++]=(&windows->pan);
258   magick_windows[number_windows++]=(&windows->command);
259   magick_windows[number_windows++]=(&windows->widget);
260   magick_windows[number_windows++]=(&windows->popup);
261   magick_windows[number_windows++]=(&windows->context);
262   for (i=0; i < (int) number_windows; i++)
263   {
264     if (magick_windows[i]->mapped != MagickFalse)
265       {
266         (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
267           magick_windows[i]->screen);
268         magick_windows[i]->mapped=MagickFalse;
269       }
270     if (magick_windows[i]->name != (char *) NULL)
271       magick_windows[i]->name=(char *)
272         RelinquishMagickMemory(magick_windows[i]->name);
273     if (magick_windows[i]->icon_name != (char *) NULL)
274       magick_windows[i]->icon_name=(char *)
275         RelinquishMagickMemory(magick_windows[i]->icon_name);
276     if (magick_windows[i]->cursor != (Cursor) NULL)
277       {
278         (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
279         magick_windows[i]->cursor=(Cursor) NULL;
280       }
281     if (magick_windows[i]->busy_cursor != (Cursor) NULL)
282       {
283         (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
284         magick_windows[i]->busy_cursor=(Cursor) NULL;
285       }
286     if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
287       {
288         (void) XFreePixmap(windows->display,
289           magick_windows[i]->highlight_stipple);
290         magick_windows[i]->highlight_stipple=(Pixmap) NULL;
291       }
292     if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
293       {
294         (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
295         magick_windows[i]->shadow_stipple=(Pixmap) NULL;
296       }
297     if (magick_windows[i]->ximage != (XImage *) NULL)
298       {
299         XDestroyImage(magick_windows[i]->ximage);
300         magick_windows[i]->ximage=(XImage *) NULL;
301       }
302     if (magick_windows[i]->pixmap != (Pixmap) NULL)
303       {
304         (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
305         magick_windows[i]->pixmap=(Pixmap) NULL;
306       }
307     if (magick_windows[i]->id != (Window) NULL)
308       {
309         (void) XDestroyWindow(windows->display,magick_windows[i]->id);
310         magick_windows[i]->id=(Window) NULL;
311       }
312     if (magick_windows[i]->destroy != MagickFalse)
313       {
314         if (magick_windows[i]->image != (Image *) NULL)
315           {
316             magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
317             magick_windows[i]->image=NewImageList();
318           }
319         if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
320           {
321             (void) XFreePixmap(windows->display,
322               magick_windows[i]->matte_pixmap);
323             magick_windows[i]->matte_pixmap=(Pixmap) NULL;
324           }
325       }
326     if (magick_windows[i]->segment_info != (void *) NULL)
327       {
328 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
329         XShmSegmentInfo
330           *segment_info;
331
332         segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
333         if (segment_info != (XShmSegmentInfo *) NULL)
334           if (segment_info[0].shmid >= 0)
335             {
336               if (segment_info[0].shmaddr != NULL)
337                 (void) shmdt(segment_info[0].shmaddr);
338               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
339               segment_info[0].shmaddr=NULL;
340               segment_info[0].shmid=(-1);
341             }
342 #endif
343         magick_windows[i]->segment_info=(void *)
344           RelinquishMagickMemory(magick_windows[i]->segment_info);
345       }
346   }
347   windows->icon_resources=(XResourceInfo *)
348     RelinquishMagickMemory(windows->icon_resources);
349   if (windows->icon_pixel != (XPixelInfo *) NULL)
350     {
351       if (windows->icon_pixel->pixels != (unsigned long *) NULL)
352         windows->icon_pixel->pixels=(unsigned long *)
353           RelinquishMagickMemory(windows->icon_pixel->pixels);
354       if (windows->icon_pixel->annotate_context != (GC) NULL)
355         XFreeGC(windows->display,windows->icon_pixel->annotate_context);
356       windows->icon_pixel=(XPixelInfo *)
357         RelinquishMagickMemory(windows->icon_pixel);
358     }
359   if (windows->pixel_info != (XPixelInfo *) NULL)
360     {
361       if (windows->pixel_info->pixels != (unsigned long *) NULL)
362         windows->pixel_info->pixels=(unsigned long *)
363           RelinquishMagickMemory(windows->pixel_info->pixels);
364       if (windows->pixel_info->annotate_context != (GC) NULL)
365         XFreeGC(windows->display,windows->pixel_info->annotate_context);
366       if (windows->pixel_info->widget_context != (GC) NULL)
367         XFreeGC(windows->display,windows->pixel_info->widget_context);
368       if (windows->pixel_info->highlight_context != (GC) NULL)
369         XFreeGC(windows->display,windows->pixel_info->highlight_context);
370       windows->pixel_info=(XPixelInfo *)
371         RelinquishMagickMemory(windows->pixel_info);
372     }
373   if (windows->font_info != (XFontStruct *) NULL)
374     {
375       XFreeFont(windows->display,windows->font_info);
376       windows->font_info=(XFontStruct *) NULL;
377     }
378   if (windows->class_hints != (XClassHint *) NULL)
379     {
380       if (windows->class_hints->res_name != (char *) NULL)
381         XFree(windows->class_hints->res_name);
382       if (windows->class_hints->res_class != (char *) NULL)
383         XFree(windows->class_hints->res_class);
384       XFree(windows->class_hints);
385       windows->class_hints=(XClassHint *) NULL;
386     }
387   if (windows->manager_hints != (XWMHints *) NULL)
388     {
389       XFree(windows->manager_hints);
390       windows->manager_hints=(XWMHints *) NULL;
391     }
392   if (windows->map_info != (XStandardColormap *) NULL)
393     {
394       XFree(windows->map_info);
395       windows->map_info=(XStandardColormap *) NULL;
396     }
397   if (windows->icon_map != (XStandardColormap *) NULL)
398     {
399       XFree(windows->icon_map);
400       windows->icon_map=(XStandardColormap *) NULL;
401     }
402   if (windows->visual_info != (XVisualInfo *) NULL)
403     {
404       XFree(windows->visual_info);
405       windows->visual_info=(XVisualInfo *) NULL;
406     }
407   if (windows->icon_visual != (XVisualInfo *) NULL)
408     {
409       XFree(windows->icon_visual);
410       windows->icon_visual=(XVisualInfo *) NULL;
411     }
412   (void) XSetWindows((XWindows *) NULL);
413 }
414 \f
415 /*
416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417 %                                                                             %
418 %                                                                             %
419 %                                                                             %
420 %   X A n n o t a t e I m a g e                                               %
421 %                                                                             %
422 %                                                                             %
423 %                                                                             %
424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425 %
426 %  XAnnotateImage() annotates the image with text.
427 %
428 %  The format of the XAnnotateImage method is:
429 %
430 %      MagickBooleanType XAnnotateImage(Display *display,
431 %        const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
432 %
433 %  A description of each parameter follows:
434 %
435 %    o display: Specifies a connection to an X server;  returned from
436 %      XOpenDisplay.
437 %
438 %    o pixel: Specifies a pointer to a XPixelInfo structure.
439 %
440 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
441 %
442 %    o image: the image.
443 %
444 */
445 MagickExport MagickBooleanType XAnnotateImage(Display *display,
446   const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
447 {
448   GC
449     annotate_context;
450
451   ExceptionInfo
452     *exception;
453
454   Image
455     *annotate_image;
456
457   int
458     x,
459     y;
460
461   MagickBooleanType
462     matte;
463
464   Pixmap
465     annotate_pixmap;
466
467   unsigned int
468     depth,
469     height,
470     width;
471
472   Window
473     root_window;
474
475   XGCValues
476     context_values;
477
478   XImage
479     *annotate_ximage;
480
481   /*
482     Initialize annotated image.
483   */
484   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
485   assert(display != (Display *) NULL);
486   assert(pixel != (XPixelInfo *) NULL);
487   assert(annotate_info != (XAnnotateInfo *) NULL);
488   assert(image != (Image *) NULL);
489   /*
490     Initialize annotated pixmap.
491   */
492   root_window=XRootWindow(display,XDefaultScreen(display));
493   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
494   annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
495     annotate_info->height,depth);
496   if (annotate_pixmap == (Pixmap) NULL)
497     return(MagickFalse);
498   /*
499     Initialize graphics info.
500   */
501   context_values.background=0;
502   context_values.foreground=(unsigned long) (~0);
503   context_values.font=annotate_info->font_info->fid;
504   annotate_context=XCreateGC(display,root_window,(unsigned long)
505     GCBackground | GCFont | GCForeground,&context_values);
506   if (annotate_context == (GC) NULL)
507     return(MagickFalse);
508   /*
509     Draw text to pixmap.
510   */
511   (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
512     (int) annotate_info->font_info->ascent,annotate_info->text,
513     (int) strlen(annotate_info->text));
514   (void) XFreeGC(display,annotate_context);
515   /*
516     Initialize annotated X image.
517   */
518   annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
519     annotate_info->height,AllPlanes,ZPixmap);
520   if (annotate_ximage == (XImage *) NULL)
521     return(MagickFalse);
522   (void) XFreePixmap(display,annotate_pixmap);
523   /*
524     Initialize annotated image.
525   */
526   annotate_image=AcquireImage((ImageInfo *) NULL);
527   if (annotate_image == (Image *) NULL)
528     return(MagickFalse);
529   annotate_image->columns=annotate_info->width;
530   annotate_image->rows=annotate_info->height;
531   /*
532     Transfer annotated X image to image.
533   */
534   width=(unsigned int) image->columns;
535   height=(unsigned int) image->rows;
536   x=0;
537   y=0;
538   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
539   (void) GetOneVirtualPixel(image,x,y,&annotate_image->background_color,
540     &image->exception);
541   if (annotate_info->stencil == ForegroundStencil)
542     annotate_image->matte=MagickTrue;
543   exception=(&image->exception);
544   for (y=0; y < (int) annotate_image->rows; y++)
545   {
546     register long
547       x;
548
549     register PixelPacket
550       *__restrict q;
551
552     q=GetAuthenticPixels(annotate_image,0,y,annotate_image->columns,1,
553       exception);
554     if (q == (PixelPacket *) NULL)
555       break;
556     for (x=0; x < (long) annotate_image->columns; x++)
557     {
558       q->opacity=OpaqueOpacity;
559       if (XGetPixel(annotate_ximage,x,y) == 0)
560         {
561           /*
562             Set this pixel to the background color.
563           */
564           q->red=ScaleShortToQuantum(pixel->box_color.red);
565           q->green=ScaleShortToQuantum(pixel->box_color.green);
566           q->blue=ScaleShortToQuantum(pixel->box_color.blue);
567           if ((annotate_info->stencil == ForegroundStencil) ||
568               (annotate_info->stencil == OpaqueStencil))
569             q->opacity=(Quantum) TransparentOpacity;
570         }
571       else
572         {
573           /*
574             Set this pixel to the pen color.
575           */
576           q->red=ScaleShortToQuantum(pixel->pen_color.red);
577           q->green=ScaleShortToQuantum(pixel->pen_color.green);
578           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
579           if (annotate_info->stencil == BackgroundStencil)
580             q->opacity=(Quantum) TransparentOpacity;
581         }
582       q++;
583     }
584     if (SyncAuthenticPixels(annotate_image,exception) == MagickFalse)
585       break;
586   }
587   XDestroyImage(annotate_ximage);
588   /*
589     Determine annotate geometry.
590   */
591   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
592   if ((width != (unsigned int) annotate_image->columns) ||
593       (height != (unsigned int) annotate_image->rows))
594     {
595       char
596         image_geometry[MaxTextExtent];
597
598       /*
599         Scale image.
600       */
601       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
602         width,height);
603       (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
604     }
605   if (annotate_info->degrees != 0.0)
606     {
607       Image
608         *rotate_image;
609
610       int
611         rotations;
612
613       MagickRealType
614         normalized_degrees;
615
616       /*
617         Rotate image.
618       */
619       rotate_image=
620         RotateImage(annotate_image,annotate_info->degrees,&image->exception);
621       if (rotate_image == (Image *) NULL)
622         return(MagickFalse);
623       annotate_image=DestroyImage(annotate_image);
624       annotate_image=rotate_image;
625       /*
626         Annotation is relative to the degree of rotation.
627       */
628       normalized_degrees=annotate_info->degrees;
629       while (normalized_degrees < -45.0)
630         normalized_degrees+=360.0;
631       for (rotations=0; normalized_degrees > 45.0; rotations++)
632         normalized_degrees-=90.0;
633       switch (rotations % 4)
634       {
635         default:
636         case 0:
637           break;
638         case 1:
639         {
640           /*
641             Rotate 90 degrees.
642           */
643           x-=(int) annotate_image->columns/2;
644           y+=(int) annotate_image->columns/2;
645           break;
646         }
647         case 2:
648         {
649           /*
650             Rotate 180 degrees.
651           */
652           x=x-(int) annotate_image->columns;
653           break;
654         }
655         case 3:
656         {
657           /*
658             Rotate 270 degrees.
659           */
660           x=x-(int) annotate_image->columns/2;
661           y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
662           break;
663         }
664       }
665     }
666   /*
667     Composite text onto the image.
668   */
669   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
670   matte=image->matte;
671   (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
672     OverCompositeOp : CopyCompositeOp,annotate_image,x,y);
673   image->matte=matte;
674   annotate_image=DestroyImage(annotate_image);
675   return(MagickTrue);
676 }
677 \f
678 /*
679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
680 %                                                                             %
681 %                                                                             %
682 %                                                                             %
683 %   X B e s t F o n t                                                         %
684 %                                                                             %
685 %                                                                             %
686 %                                                                             %
687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688 %
689 %  XBestFont() returns the "best" font.  "Best" is defined as a font specified
690 %  in the X resource database or a font such that the text width displayed
691 %  with the font does not exceed the specified maximum width.
692 %
693 %  The format of the XBestFont method is:
694 %
695 %      XFontStruct *XBestFont(Display *display,
696 %        const XResourceInfo *resource_info,const MagickBooleanType text_font)
697 %
698 %  A description of each parameter follows:
699 %
700 %    o font: XBestFont returns a pointer to a XFontStruct structure.
701 %
702 %    o display: Specifies a connection to an X server;  returned from
703 %      XOpenDisplay.
704 %
705 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
706 %
707 %    o text_font:  True is font should be mono-spaced (typewriter style).
708 %
709 %
710 */
711
712 static char **FontToList(char *font)
713 {
714   char
715     **fontlist;
716
717   register char
718     *p,
719     *q;
720
721   register int
722     i;
723
724   unsigned int
725     fonts;
726
727   if (font == (char *) NULL)
728     return((char **) NULL);
729   /*
730     Convert string to an ASCII list.
731   */
732   fonts=1U;
733   for (p=font; *p != '\0'; p++)
734     if ((*p == ':') || (*p == ';') || (*p == ','))
735       fonts++;
736   fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
737   if (fontlist == (char **) NULL)
738     {
739       ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
740         font);
741       return((char **) NULL);
742     }
743   p=font;
744   for (i=0; i < (int) fonts; i++)
745   {
746     for (q=p; *q != '\0'; q++)
747       if ((*q == ':') || (*q == ';') || (*q == ','))
748         break;
749     fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
750       sizeof(*fontlist[i]));
751     if (fontlist[i] == (char *) NULL)
752       {
753         ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
754           font);
755         return((char **) NULL);
756       }
757     (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
758     p=q+1;
759   }
760   fontlist[i]=(char *) NULL;
761   return(fontlist);
762 }
763
764 MagickExport XFontStruct *XBestFont(Display *display,
765   const XResourceInfo *resource_info,const MagickBooleanType text_font)
766 {
767   static const char
768     *Fonts[]=
769     {
770       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
771       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
772       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
773       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
774       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
775       "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
776       "variable",
777       "fixed",
778       (char *) NULL
779     },
780     *TextFonts[]=
781     {
782       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
783       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
784       "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
785       "fixed",
786       (char *) NULL
787     };
788
789   char
790     *font_name;
791
792   register const char
793     **p;
794
795   XFontStruct
796     *font_info;
797
798   font_info=(XFontStruct *) NULL;
799   font_name=resource_info->font;
800   if (text_font != MagickFalse)
801     font_name=resource_info->text_font;
802   if ((font_name != (char *) NULL) && (*font_name != '\0'))
803     {
804       char
805         **fontlist;
806
807       register int
808         i;
809
810       /*
811         Load preferred font specified in the X resource database.
812       */
813       fontlist=FontToList(font_name);
814       if (fontlist != (char **) NULL)
815         {
816           for (i=0; fontlist[i] != (char *) NULL; i++)
817           {
818             if (font_info == (XFontStruct *) NULL)
819               font_info=XLoadQueryFont(display,fontlist[i]);
820             fontlist[i]=DestroyString(fontlist[i]);
821           }
822           fontlist=(char **) RelinquishMagickMemory(fontlist);
823         }
824       if (font_info == (XFontStruct *) NULL)
825         ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
826     }
827   /*
828     Load fonts from list of fonts until one is found.
829   */
830   p=Fonts;
831   if (text_font != MagickFalse)
832     p=TextFonts;
833   if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
834     p++;
835   while (*p != (char *) NULL)
836   {
837     if (font_info != (XFontStruct *) NULL)
838       break;
839     font_info=XLoadQueryFont(display,(char *) *p);
840     p++;
841   }
842   return(font_info);
843 }
844 \f
845 /*
846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847 %                                                                             %
848 %                                                                             %
849 %                                                                             %
850 %   X B e s t I c o n S i z e                                                 %
851 %                                                                             %
852 %                                                                             %
853 %                                                                             %
854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855 %
856 %  XBestIconSize() returns the "best" icon size.  "Best" is defined as an icon
857 %  size that maintains the aspect ratio of the image.  If the window manager
858 %  has preferred icon sizes, one of the preferred sizes is used.
859 %
860 %  The format of the XBestIconSize method is:
861 %
862 %      void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
863 %
864 %  A description of each parameter follows:
865 %
866 %    o display: Specifies a connection to an X server;  returned from
867 %      XOpenDisplay.
868 %
869 %    o image: the image.
870 %
871 */
872 MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
873   Image *image)
874 {
875   int
876     i,
877     number_sizes;
878
879   MagickRealType
880     scale_factor;
881
882   unsigned int
883     height,
884     icon_height,
885     icon_width,
886     width;
887
888   Window
889     root_window;
890
891   XIconSize
892     *icon_size,
893     *size_list;
894
895   /*
896     Determine if the window manager has specified preferred icon sizes.
897   */
898   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
899   assert(display != (Display *) NULL);
900   assert(window != (XWindowInfo *) NULL);
901   assert(image != (Image *) NULL);
902   window->width=MaxIconSize;
903   window->height=MaxIconSize;
904   icon_size=(XIconSize *) NULL;
905   number_sizes=0;
906   root_window=XRootWindow(display,window->screen);
907   if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
908     if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
909       icon_size=size_list;
910   if (icon_size == (XIconSize *) NULL)
911     {
912       /*
913         Window manager does not restrict icon size.
914       */
915       icon_size=XAllocIconSize();
916       if (icon_size == (XIconSize *) NULL)
917         {
918           ThrowXWindowFatalException(ResourceLimitError,
919             "MemoryAllocationFailed",image->filename);
920           return;
921         }
922       icon_size->min_width=1;
923       icon_size->max_width=MaxIconSize;
924       icon_size->min_height=1;
925       icon_size->max_height=MaxIconSize;
926       icon_size->width_inc=1;
927       icon_size->height_inc=1;
928     }
929   /*
930     Determine aspect ratio of image.
931   */
932   width=(unsigned int) image->columns;
933   height=(unsigned int) image->rows;
934   i=0;
935   if (window->crop_geometry)
936     (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
937   /*
938     Look for an icon size that maintains the aspect ratio of image.
939   */
940   scale_factor=(MagickRealType) icon_size->max_width/width;
941   if (scale_factor > ((MagickRealType) icon_size->max_height/height))
942     scale_factor=(MagickRealType) icon_size->max_height/height;
943   icon_width=(unsigned int) icon_size->min_width;
944   while ((int) icon_width < icon_size->max_width)
945   {
946     if (icon_width >= (unsigned int) (scale_factor*width+0.5))
947       break;
948     icon_width+=icon_size->width_inc;
949   }
950   icon_height=(unsigned int) icon_size->min_height;
951   while ((int) icon_height < icon_size->max_height)
952   {
953     if (icon_height >= (unsigned int) (scale_factor*height+0.5))
954       break;
955     icon_height+=icon_size->height_inc;
956   }
957   (void) XFree((void *) icon_size);
958   window->width=icon_width;
959   window->height=icon_height;
960 }
961 \f
962 /*
963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964 %                                                                             %
965 %                                                                             %
966 %                                                                             %
967 %   X B e s t P i x e l                                                       %
968 %                                                                             %
969 %                                                                             %
970 %                                                                             %
971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972 %
973 %  XBestPixel() returns a pixel from an array of pixels that is closest to the
974 %  requested color.  If the color array is NULL, the colors are obtained from
975 %  the X server.
976 %
977 %  The format of the XBestPixel method is:
978 %
979 %      void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
980 %        unsigned int number_colors,XColor *color)
981 %
982 %  A description of each parameter follows:
983 %
984 %    o pixel: XBestPixel returns the pixel value closest to the requested
985 %      color.
986 %
987 %    o display: Specifies a connection to an X server;  returned from
988 %      XOpenDisplay.
989 %
990 %    o colormap: Specifies the ID of the X server colormap.
991 %
992 %    o colors: Specifies an array of XColor structures.
993 %
994 %    o number_colors: Specifies the number of XColor structures in the
995 %      color definition array.
996 %
997 %    o color: Specifies the desired RGB value to find in the colors array.
998 %
999 */
1000 MagickExport void XBestPixel(Display *display,const Colormap colormap,
1001   XColor *colors,unsigned int number_colors,XColor *color)
1002 {
1003   MagickBooleanType
1004     query_server;
1005
1006   MagickPixelPacket
1007     pixel;
1008
1009   MagickRealType
1010     min_distance;
1011
1012   register MagickRealType
1013     distance;
1014
1015   register int
1016     i,
1017     j;
1018
1019   Status
1020     status;
1021
1022   /*
1023     Find closest representation for the requested RGB color.
1024   */
1025   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1026   assert(display != (Display *) NULL);
1027   assert(color != (XColor *) NULL);
1028   status=XAllocColor(display,colormap,color);
1029   if (status != False)
1030     return;
1031   query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1032   if (query_server != MagickFalse)
1033     {
1034       /*
1035         Read X server colormap.
1036       */
1037       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1038       if (colors == (XColor *) NULL)
1039         {
1040           ThrowXWindowFatalException(ResourceLimitError,
1041             "MemoryAllocationFailed","...");
1042           return;
1043         }
1044       for (i=0; i < (int) number_colors; i++)
1045         colors[i].pixel=(unsigned long) i;
1046       if (number_colors > 256)
1047         number_colors=256;
1048       (void) XQueryColors(display,colormap,colors,(int) number_colors);
1049     }
1050   min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1051     QuantumRange+1.0);
1052   j=0;
1053   for (i=0; i < (int) number_colors; i++)
1054   {
1055     pixel.red=colors[i].red-(MagickRealType) color->red;
1056     distance=pixel.red*pixel.red;
1057     if (distance > min_distance)
1058       continue;
1059     pixel.green=colors[i].green-(MagickRealType) color->green;
1060     distance+=pixel.green*pixel.green;
1061     if (distance > min_distance)
1062       continue;
1063     pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1064     distance+=pixel.blue*pixel.blue;
1065     if (distance > min_distance)
1066       continue;
1067     min_distance=distance;
1068     color->pixel=colors[i].pixel;
1069     j=i;
1070   }
1071   (void) XAllocColor(display,colormap,&colors[j]);
1072   if (query_server != MagickFalse)
1073     colors=(XColor *) RelinquishMagickMemory(colors);
1074 }
1075 \f
1076 /*
1077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078 %                                                                             %
1079 %                                                                             %
1080 %                                                                             %
1081 %   X B e s t V i s u a l I n f o                                             %
1082 %                                                                             %
1083 %                                                                             %
1084 %                                                                             %
1085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1086 %
1087 %  XBestVisualInfo() returns visual information for a visual that is the "best"
1088 %  the server supports.  "Best" is defined as:
1089 %
1090 %    1. Restrict the visual list to those supported by the default screen.
1091 %
1092 %    2. If a visual type is specified, restrict the visual list to those of
1093 %       that type.
1094 %
1095 %    3. If a map type is specified, choose the visual that matches the id
1096 %       specified by the Standard Colormap.
1097 %
1098 %    4  From the list of visuals, choose one that can display the most
1099 %       simultaneous colors.  If more than one visual can display the same
1100 %       number of simultaneous colors, one is chosen based on a rank.
1101 %
1102 %  The format of the XBestVisualInfo method is:
1103 %
1104 %      XVisualInfo *XBestVisualInfo(Display *display,
1105 %        XStandardColormap *map_info,XResourceInfo *resource_info)
1106 %
1107 %  A description of each parameter follows:
1108 %
1109 %    o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1110 %      structure.
1111 %
1112 %    o display: Specifies a connection to an X server;  returned from
1113 %      XOpenDisplay.
1114 %
1115 %    o map_info: If map_type is specified, this structure is initialized
1116 %      with info from the Standard Colormap.
1117 %
1118 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1119 %
1120 */
1121
1122 static inline int MagickMax(const int x,const int y)
1123 {
1124   if (x > y)
1125     return(x);
1126   return(y);
1127 }
1128
1129 static inline unsigned long MagickMin(const unsigned int x,
1130   const unsigned int y)
1131 {
1132   if (x < y)
1133     return(x);
1134   return(y);
1135 }
1136
1137 MagickExport XVisualInfo *XBestVisualInfo(Display *display,
1138   XStandardColormap *map_info,XResourceInfo *resource_info)
1139 {
1140 #define MaxStandardColormaps  7
1141 #define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1142   (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1143    visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1144    (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1145
1146   char
1147     *map_type,
1148     *visual_type;
1149
1150   long
1151     visual_mask;
1152
1153   register int
1154     i;
1155
1156   static int
1157     number_visuals;
1158
1159   static XVisualInfo
1160     visual_template;
1161
1162   XVisualInfo
1163     *visual_info,
1164     *visual_list;
1165
1166   /*
1167     Restrict visual search by screen number.
1168   */
1169   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1170   assert(display != (Display *) NULL);
1171   assert(map_info != (XStandardColormap *) NULL);
1172   assert(resource_info != (XResourceInfo *) NULL);
1173   map_type=resource_info->map_type;
1174   visual_type=resource_info->visual_type;
1175   visual_mask=VisualScreenMask;
1176   visual_template.screen=XDefaultScreen(display);
1177   visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
1178   if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
1179     if (resource_info->colors <= (1UL << (unsigned long) visual_template.depth))
1180       visual_mask|=VisualDepthMask;
1181   if (visual_type != (char *) NULL)
1182     {
1183       /*
1184         Restrict visual search by class or visual id.
1185       */
1186       if (LocaleCompare("staticgray",visual_type) == 0)
1187         {
1188           visual_mask|=VisualClassMask;
1189           visual_template.klass=StaticGray;
1190         }
1191       else
1192         if (LocaleCompare("grayscale",visual_type) == 0)
1193           {
1194             visual_mask|=VisualClassMask;
1195             visual_template.klass=GrayScale;
1196           }
1197         else
1198           if (LocaleCompare("staticcolor",visual_type) == 0)
1199             {
1200               visual_mask|=VisualClassMask;
1201               visual_template.klass=StaticColor;
1202             }
1203           else
1204             if (LocaleCompare("pseudocolor",visual_type) == 0)
1205               {
1206                 visual_mask|=VisualClassMask;
1207                 visual_template.klass=PseudoColor;
1208               }
1209             else
1210               if (LocaleCompare("truecolor",visual_type) == 0)
1211                 {
1212                   visual_mask|=VisualClassMask;
1213                   visual_template.klass=TrueColor;
1214                 }
1215               else
1216                 if (LocaleCompare("directcolor",visual_type) == 0)
1217                   {
1218                     visual_mask|=VisualClassMask;
1219                     visual_template.klass=DirectColor;
1220                   }
1221                 else
1222                   if (LocaleCompare("default",visual_type) == 0)
1223                     {
1224                       visual_mask|=VisualIDMask;
1225                       visual_template.visualid=XVisualIDFromVisual(
1226                         XDefaultVisual(display,XDefaultScreen(display)));
1227                     }
1228                   else
1229                     if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1230                       {
1231                         visual_mask|=VisualIDMask;
1232                         visual_template.visualid=
1233                           strtol(visual_type,(char **) NULL,0);
1234                       }
1235                     else
1236                       ThrowXWindowFatalException(XServerError,
1237                         "UnrecognizedVisualSpecifier",visual_type);
1238     }
1239   /*
1240     Get all visuals that meet our criteria so far.
1241   */
1242   number_visuals=0;
1243   visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1244     &number_visuals);
1245   visual_mask=VisualScreenMask | VisualIDMask;
1246   if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1247     {
1248       /*
1249         Failed to get visual;  try using the default visual.
1250       */
1251       ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1252         visual_type);
1253       visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1254         XDefaultScreen(display)));
1255       visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1256         &number_visuals);
1257       if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1258         return((XVisualInfo *) NULL);
1259       ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1260         XVisualClassName(visual_list->klass));
1261     }
1262   resource_info->color_recovery=MagickFalse;
1263   if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1264     {
1265       Atom
1266         map_property;
1267
1268       char
1269         map_name[MaxTextExtent];
1270
1271       int
1272         j,
1273         number_maps;
1274
1275       Status
1276         status;
1277
1278       Window
1279         root_window;
1280
1281       XStandardColormap
1282         *map_list;
1283
1284       /*
1285         Choose a visual associated with a standard colormap.
1286       */
1287       root_window=XRootWindow(display,XDefaultScreen(display));
1288       status=False;
1289       if (LocaleCompare(map_type,"list") != 0)
1290         {
1291           /*
1292             User specified Standard Colormap.
1293           */
1294           (void) FormatMagickString((char *) map_name,MaxTextExtent,
1295             "RGB_%s_MAP",map_type);
1296           LocaleUpper(map_name);
1297           map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1298           if (map_property != (Atom) NULL)
1299             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1300               map_property);
1301         }
1302       else
1303         {
1304           static const char
1305             *colormap[MaxStandardColormaps]=
1306             {
1307               "_HP_RGB_SMOOTH_MAP_LIST",
1308               "RGB_BEST_MAP",
1309               "RGB_DEFAULT_MAP",
1310               "RGB_GRAY_MAP",
1311               "RGB_RED_MAP",
1312               "RGB_GREEN_MAP",
1313               "RGB_BLUE_MAP",
1314             };
1315
1316           /*
1317             Choose a standard colormap from a list.
1318           */
1319           for (i=0; i < MaxStandardColormaps; i++)
1320           {
1321             map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1322             if (map_property == (Atom) NULL)
1323               continue;
1324             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1325               map_property);
1326             if (status != False)
1327               break;
1328           }
1329           resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1330         }
1331       if (status == False)
1332         {
1333           ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1334             map_type);
1335           return((XVisualInfo *) NULL);
1336         }
1337       /*
1338         Search all Standard Colormaps and visuals for ids that match.
1339       */
1340       *map_info=map_list[0];
1341 #if !defined(PRE_R4_ICCCM)
1342       visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1343       for (i=0; i < number_maps; i++)
1344         for (j=0; j < number_visuals; j++)
1345           if (map_list[i].visualid ==
1346               XVisualIDFromVisual(visual_list[j].visual))
1347             {
1348               *map_info=map_list[i];
1349               visual_template.visualid=XVisualIDFromVisual(
1350                 visual_list[j].visual);
1351               break;
1352             }
1353       if (map_info->visualid != visual_template.visualid)
1354         {
1355           ThrowXWindowFatalException(XServerError,
1356             "UnableToMatchVisualToStandardColormap",map_type);
1357           return((XVisualInfo *) NULL);
1358         }
1359 #endif
1360       if (map_info->colormap == (Colormap) NULL)
1361         {
1362           ThrowXWindowFatalException(XServerError,
1363             "StandardColormapIsNotInitialized",map_type);
1364           return((XVisualInfo *) NULL);
1365         }
1366       (void) XFree((void *) map_list);
1367     }
1368   else
1369     {
1370       static const unsigned int
1371         rank[]=
1372           {
1373             StaticGray,
1374             GrayScale,
1375             StaticColor,
1376             DirectColor,
1377             TrueColor,
1378             PseudoColor
1379           };
1380
1381       XVisualInfo
1382         *p;
1383
1384       /*
1385         Pick one visual that displays the most simultaneous colors.
1386       */
1387       visual_info=visual_list;
1388       p=visual_list;
1389       for (i=1; i < number_visuals; i++)
1390       {
1391         p++;
1392         if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1393           visual_info=p;
1394         else
1395           if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1396             if (rank[p->klass] > rank[visual_info->klass])
1397               visual_info=p;
1398       }
1399       visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1400     }
1401   (void) XFree((void *) visual_list);
1402   /*
1403     Retrieve only one visual by its screen & id number.
1404   */
1405   visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1406     &number_visuals);
1407   if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1408     return((XVisualInfo *) NULL);
1409   return(visual_info);
1410 }
1411 \f
1412 /*
1413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414 %                                                                             %
1415 %                                                                             %
1416 %                                                                             %
1417 %   X C h e c k D e f i n e C u r s o r                                       %
1418 %                                                                             %
1419 %                                                                             %
1420 %                                                                             %
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 %
1423 %  XCheckDefineCursor() prevents cursor changes on the root window.
1424 %
1425 %  The format of the XXCheckDefineCursor method is:
1426 %
1427 %      XCheckDefineCursor(display,window,cursor)
1428 %
1429 %  A description of each parameter follows:
1430 %
1431 %    o display: Specifies a connection to an X server;  returned from
1432 %      XOpenDisplay.
1433 %
1434 %    o window: the window.
1435 %
1436 %    o cursor: the cursor.
1437 %
1438 */
1439 MagickExport int XCheckDefineCursor(Display *display,Window window,
1440   Cursor cursor)
1441 {
1442   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1443   assert(display != (Display *) NULL);
1444   if (window == XRootWindow(display,XDefaultScreen(display)))
1445     return(0);
1446   return(XDefineCursor(display,window,cursor));
1447 }
1448 \f
1449 /*
1450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1451 %                                                                             %
1452 %                                                                             %
1453 %                                                                             %
1454 %   X C h e c k R e f r e s h W i n d o w s                                   %
1455 %                                                                             %
1456 %                                                                             %
1457 %                                                                             %
1458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1459 %
1460 %  XCheckRefreshWindows() checks the X server for exposure events for a
1461 %  particular window and updates the areassociated with the exposure event.
1462 %
1463 %  The format of the XCheckRefreshWindows method is:
1464 %
1465 %      void XCheckRefreshWindows(Display *display,XWindows *windows)
1466 %
1467 %  A description of each parameter follows:
1468 %
1469 %    o display: Specifies a connection to an X server;  returned from
1470 %      XOpenDisplay.
1471 %
1472 %    o windows: Specifies a pointer to a XWindows structure.
1473 %
1474 */
1475 MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
1476 {
1477   Window
1478     id;
1479
1480   XEvent
1481     event;
1482
1483   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1484   assert(display != (Display *) NULL);
1485   assert(windows != (XWindows *) NULL);
1486   XDelay(display,SuspendTime);
1487   id=windows->command.id;
1488   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1489     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1490   id=windows->image.id;
1491   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1492     XRefreshWindow(display,&windows->image,&event);
1493   XDelay(display,SuspendTime << 1);
1494   id=windows->command.id;
1495   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1496     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1497   id=windows->image.id;
1498   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1499     XRefreshWindow(display,&windows->image,&event);
1500 }
1501 \f
1502 /*
1503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1504 %                                                                             %
1505 %                                                                             %
1506 %                                                                             %
1507 %   X C l i e n t M e s s a g e                                               %
1508 %                                                                             %
1509 %                                                                             %
1510 %                                                                             %
1511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1512 %
1513 %  XClientMessage() sends a reason to a window with XSendEvent.  The reason is
1514 %  initialized with a particular protocol type and atom.
1515 %
1516 %  The format of the XClientMessage function is:
1517 %
1518 %      XClientMessage(display,window,protocol,reason,timestamp)
1519 %
1520 %  A description of each parameter follows:
1521 %
1522 %    o display: Specifies a pointer to the Display structure;  returned from
1523 %      XOpenDisplay.
1524 %
1525 %    o window: Specifies a pointer to a Window structure.
1526 %
1527 %    o protocol: Specifies an atom value.
1528 %
1529 %    o reason: Specifies an atom value which is the reason to send.
1530 %
1531 %    o timestamp: Specifies a value of type Time.
1532 %
1533 */
1534 MagickExport void XClientMessage(Display *display,const Window window,
1535   const Atom protocol,const Atom reason,const Time timestamp)
1536 {
1537   XClientMessageEvent
1538     client_event;
1539
1540   assert(display != (Display *) NULL);
1541   client_event.type=ClientMessage;
1542   client_event.window=window;
1543   client_event.message_type=protocol;
1544   client_event.format=32;
1545   client_event.data.l[0]=(long) reason;
1546   client_event.data.l[1]=(long) timestamp;
1547   (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1548 }
1549 \f
1550 /*
1551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1552 %                                                                             %
1553 %                                                                             %
1554 %                                                                             %
1555 +   X C l i e n t W i n d o w                                                 %
1556 %                                                                             %
1557 %                                                                             %
1558 %                                                                             %
1559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1560 %
1561 %  XClientWindow() finds a window, at or below the specified window, which has
1562 %  a WM_STATE property.  If such a window is found, it is returned, otherwise
1563 %  the argument window is returned.
1564 %
1565 %  The format of the XClientWindow function is:
1566 %
1567 %      client_window=XClientWindow(display,target_window)
1568 %
1569 %  A description of each parameter follows:
1570 %
1571 %    o client_window: XClientWindow returns a window, at or below the specified
1572 %      window, which has a WM_STATE property otherwise the argument
1573 %      target_window is returned.
1574 %
1575 %    o display: Specifies a pointer to the Display structure;  returned from
1576 %      XOpenDisplay.
1577 %
1578 %    o target_window: Specifies the window to find a WM_STATE property.
1579 %
1580 %
1581 */
1582 static Window XClientWindow(Display *display,Window target_window)
1583 {
1584   Atom
1585     state,
1586     type;
1587
1588   int
1589     format;
1590
1591   Status
1592     status;
1593
1594   unsigned char
1595     *data;
1596
1597   unsigned long
1598     after,
1599     number_items;
1600
1601   Window
1602     client_window;
1603
1604   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1605   assert(display != (Display *) NULL);
1606   state=XInternAtom(display,"WM_STATE",MagickTrue);
1607   if (state == (Atom) NULL)
1608     return(target_window);
1609   type=(Atom) NULL;
1610   status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1611     (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1612   if ((status == Success) && (type != (Atom) NULL))
1613     return(target_window);
1614   client_window=XWindowByProperty(display,target_window,state);
1615   if (client_window == (Window) NULL)
1616     return(target_window);
1617   return(client_window);
1618 }
1619 \f
1620 /*
1621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622 %                                                                             %
1623 %                                                                             %
1624 %                                                                             %
1625 %   X C o n f i g u r e I m a g e C o l o r m a p                             %
1626 %                                                                             %
1627 %                                                                             %
1628 %                                                                             %
1629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1630 %
1631 %  XConfigureImageColormap() creates a new X colormap.
1632 %
1633 %  The format of the XConfigureImageColormap method is:
1634 %
1635 %      void XConfigureImageColormap(Display *display,
1636 %        XResourceInfo *resource_info,XWindows *windows,Image *image)
1637 %
1638 %  A description of each parameter follows:
1639 %
1640 %    o display: Specifies a connection to an X server; returned from
1641 %      XOpenDisplay.
1642 %
1643 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1644 %
1645 %    o windows: Specifies a pointer to a XWindows structure.
1646 %
1647 %    o image: the image.
1648 %
1649 */
1650 MagickExport void XConfigureImageColormap(Display *display,
1651   XResourceInfo *resource_info,XWindows *windows,Image *image)
1652 {
1653   Colormap
1654     colormap;
1655
1656   /*
1657     Make standard colormap.
1658   */
1659   XSetCursorState(display,windows,MagickTrue);
1660   XCheckRefreshWindows(display,windows);
1661   XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1662     windows->map_info,windows->pixel_info);
1663   colormap=windows->map_info->colormap;
1664   (void) XSetWindowColormap(display,windows->image.id,colormap);
1665   (void) XSetWindowColormap(display,windows->command.id,colormap);
1666   (void) XSetWindowColormap(display,windows->widget.id,colormap);
1667   if (windows->magnify.mapped != MagickFalse)
1668     (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1669   if (windows->pan.mapped != MagickFalse)
1670     (void) XSetWindowColormap(display,windows->pan.id,colormap);
1671   XSetCursorState(display,windows,MagickFalse);
1672   XClientMessage(display,windows->image.id,windows->im_protocols,
1673     windows->im_update_colormap,CurrentTime);
1674 }
1675 \f
1676 /*
1677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1678 %                                                                             %
1679 %                                                                             %
1680 %                                                                             %
1681 %   X C o n s t r a i n W i n d o w P o s i t i o n                           %
1682 %                                                                             %
1683 %                                                                             %
1684 %                                                                             %
1685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1686 %
1687 %  XConstrainWindowPosition() assures a window is positioned within the X
1688 %  server boundaries.
1689 %
1690 %  The format of the XConstrainWindowPosition method is:
1691 %
1692 %      void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1693 %
1694 %  A description of each parameter follows:
1695 %
1696 %    o display: Specifies a pointer to the Display structure;  returned from
1697 %      XOpenDisplay.
1698 %
1699 %    o window_info: Specifies a pointer to a XWindowInfo structure.
1700 %
1701 */
1702 MagickExport void XConstrainWindowPosition(Display *display,
1703   XWindowInfo *window_info)
1704 {
1705   int
1706     limit;
1707
1708   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1709   assert(display != (Display *) NULL);
1710   assert(window_info != (XWindowInfo *) NULL);
1711   limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1712   if (window_info->x < 0)
1713     window_info->x=0;
1714   else
1715     if (window_info->x > (int) limit)
1716       window_info->x=(int) limit;
1717   limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1718   if (window_info->y < 0)
1719     window_info->y=0;
1720   else
1721     if (window_info->y > limit)
1722       window_info->y=limit;
1723 }
1724 \f
1725 /*
1726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1727 %                                                                             %
1728 %                                                                             %
1729 %                                                                             %
1730 %   X D e l a y                                                               %
1731 %                                                                             %
1732 %                                                                             %
1733 %                                                                             %
1734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1735 %
1736 %  XDelay() suspends program execution for the number of milliseconds
1737 %  specified.
1738 %
1739 %  The format of the Delay method is:
1740 %
1741 %      void XDelay(Display *display,const unsigned long milliseconds)
1742 %
1743 %  A description of each parameter follows:
1744 %
1745 %    o display: Specifies a pointer to the Display structure;  returned from
1746 %      XOpenDisplay.
1747 %
1748 %    o milliseconds: Specifies the number of milliseconds to delay before
1749 %      returning.
1750 %
1751 */
1752 MagickExport void XDelay(Display *display,const unsigned long milliseconds)
1753 {
1754   assert(display != (Display *) NULL);
1755   (void) XFlush(display);
1756   if (milliseconds == 0)
1757     return;
1758 #if defined(__WINDOWS__)
1759   Sleep(milliseconds);
1760 #elif defined(vms)
1761   {
1762     float
1763       timer;
1764
1765     timer=milliseconds/1000.0;
1766     lib$wait(&timer);
1767   }
1768 #elif defined(MAGICKCORE_HAVE_USLEEP)
1769   usleep(1000*milliseconds);
1770 #elif defined(MAGICKCORE_HAVE_SELECT)
1771   {
1772     struct timeval
1773       timer;
1774
1775     timer.tv_sec=(long) milliseconds/1000;
1776     timer.tv_usec=(long) (milliseconds % 1000)*1000;
1777     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1778   }
1779 #elif defined(MAGICKCORE_HAVE_POLL)
1780   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1781 #elif defined(__BEOS__)
1782   snooze(1000*milliseconds);
1783 #else
1784 # error "Time delay method not defined."
1785 #endif
1786 }
1787 \f
1788 /*
1789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1790 %                                                                             %
1791 %                                                                             %
1792 %                                                                             %
1793 %   X D e s t r o y R e s o u r c e I n f o                                   %
1794 %                                                                             %
1795 %                                                                             %
1796 %                                                                             %
1797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1798 %
1799 %  XDestroyResourceInfo() frees memory associated with the XResourceInfo
1800 %  structure.
1801 %
1802 %  The format of the XDestroyResourceInfo method is:
1803 %
1804 %      void XDestroyResourceInfo(XResourceInfo *resource_info)
1805 %
1806 %  A description of each parameter follows:
1807 %
1808 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1809 %
1810 */
1811 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1812 {
1813   if (resource_info->image_geometry != (char *) NULL)
1814     resource_info->image_geometry=(char *)
1815       RelinquishMagickMemory(resource_info->image_geometry);
1816   if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1817     resource_info->quantize_info=DestroyQuantizeInfo(
1818       resource_info->quantize_info);
1819   if (resource_info->client_name != (char *) NULL)
1820     resource_info->client_name=(char *)
1821       RelinquishMagickMemory(resource_info->client_name);
1822   if (resource_info->name != (char *) NULL)
1823     resource_info->name=DestroyString(resource_info->name);
1824   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1825 }
1826 \f
1827 /*
1828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1829 %                                                                             %
1830 %                                                                             %
1831 %                                                                             %
1832 %   X D e s t r o y W i n d o w C o l o r s                                   %
1833 %                                                                             %
1834 %                                                                             %
1835 %                                                                             %
1836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1837 %
1838 %  XDestroyWindowColors() frees X11 color resources previously saved on a
1839 %  window by XRetainWindowColors or programs like xsetroot.
1840 %
1841 %  The format of the XDestroyWindowColors method is:
1842 %
1843 %      void XDestroyWindowColors(Display *display,Window window)
1844 %
1845 %  A description of each parameter follows:
1846 %
1847 %    o display: Specifies a connection to an X server; returned from
1848 %      XOpenDisplay.
1849 %
1850 %    o window: Specifies a pointer to a Window structure.
1851 %
1852 */
1853 MagickExport void XDestroyWindowColors(Display *display,Window window)
1854 {
1855   Atom
1856     property,
1857     type;
1858
1859   int
1860     format;
1861
1862   Status
1863     status;
1864
1865   unsigned char
1866     *data;
1867
1868   unsigned long
1869     after,
1870     length;
1871
1872   /*
1873     If there are previous resources on the root window, destroy them.
1874   */
1875   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1876   assert(display != (Display *) NULL);
1877   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1878   if (property == (Atom) NULL)
1879     {
1880       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1881         "_XSETROOT_ID");
1882       return;
1883     }
1884   status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1885     (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1886   if (status != Success)
1887     return;
1888   if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1889     {
1890       (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1891       (void) XDeleteProperty(display,window,property);
1892     }
1893   if (type != None)
1894     (void) XFree((void *) data);
1895 }
1896 \f
1897 /*
1898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1899 %                                                                             %
1900 %                                                                             %
1901 %                                                                             %
1902 %   X D i s p l a y I m a g e I n f o                                         %
1903 %                                                                             %
1904 %                                                                             %
1905 %                                                                             %
1906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1907 %
1908 %  XDisplayImageInfo() displays information about an X image.
1909 %
1910 %  The format of the XDisplayImageInfo method is:
1911 %
1912 %      void XDisplayImageInfo(Display *display,
1913 %        const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1914 %        Image *image)
1915 %
1916 %  A description of each parameter follows:
1917 %
1918 %    o display: Specifies a connection to an X server;  returned from
1919 %      XOpenDisplay.
1920 %
1921 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1922 %
1923 %    o windows: Specifies a pointer to a XWindows structure.
1924 %
1925 %    o undo_image: the undo image.
1926 %
1927 %    o image: the image.
1928 %
1929 */
1930 MagickExport void XDisplayImageInfo(Display *display,
1931   const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1932   Image *image)
1933 {
1934   char
1935     filename[MaxTextExtent],
1936     *text,
1937     **textlist;
1938
1939   FILE
1940     *file;
1941
1942   int
1943     unique_file;
1944
1945   long
1946     bytes;
1947
1948   register long
1949     i;
1950
1951   unsigned int
1952     levels;
1953
1954   unsigned long
1955     number_pixels;
1956
1957   /*
1958     Write info about the X server to a file.
1959   */
1960   assert(display != (Display *) NULL);
1961   assert(resource_info != (XResourceInfo *) NULL);
1962   assert(windows != (XWindows *) NULL);
1963   assert(image != (Image *) NULL);
1964   if (image->debug)
1965     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1966   file=(FILE *) NULL;
1967   unique_file=AcquireUniqueFileResource(filename);
1968   if (unique_file != -1)
1969     file=fdopen(unique_file,"w");
1970   if ((unique_file == -1) || (file == (FILE *) NULL))
1971     {
1972       XNoticeWidget(display,windows,"Unable to display image info",filename);
1973       return;
1974     }
1975   if (resource_info->gamma_correct != MagickFalse)
1976     if (resource_info->display_gamma != (char *) NULL)
1977       (void) fprintf(file,"Display\n  gamma: %s\n\n",
1978         resource_info->display_gamma);
1979   /*
1980     Write info about the X image to a file.
1981   */
1982   (void) fprintf(file,"X\n  visual: %s\n",
1983     XVisualClassName((int) windows->image.storage_class));
1984   (void) fprintf(file,"  depth: %d\n",windows->image.ximage->depth);
1985   if (windows->visual_info->colormap_size != 0)
1986     (void) fprintf(file,"  colormap size: %d\n",
1987       windows->visual_info->colormap_size);
1988   if (resource_info->colormap== SharedColormap)
1989     (void) fprintf(file,"  colormap type: Shared\n");
1990   else
1991     (void) fprintf(file,"  colormap type: Private\n");
1992   (void) fprintf(file,"  geometry: %dx%d\n",windows->image.ximage->width,
1993     windows->image.ximage->height);
1994   if (windows->image.crop_geometry != (char *) NULL)
1995     (void) fprintf(file,"  crop geometry: %s\n",windows->image.crop_geometry);
1996   if (windows->image.pixmap == (Pixmap) NULL)
1997     (void) fprintf(file,"  type: X Image\n");
1998   else
1999     (void) fprintf(file,"  type: Pixmap\n");
2000   if (windows->image.shape != MagickFalse)
2001     (void) fprintf(file,"  non-rectangular shape: True\n");
2002   else
2003     (void) fprintf(file,"  non-rectangular shape: False\n");
2004   if (windows->image.shared_memory != MagickFalse)
2005     (void) fprintf(file,"  shared memory: True\n");
2006   else
2007     (void) fprintf(file,"  shared memory: False\n");
2008   (void) fprintf(file,"\n");
2009   if (resource_info->font != (char *) NULL)
2010     (void) fprintf(file,"Font: %s\n\n",resource_info->font);
2011   if (resource_info->text_font != (char *) NULL)
2012     (void) fprintf(file,"Text font: %s\n\n",resource_info->text_font);
2013   /*
2014     Write info about the undo cache to a file.
2015   */
2016   bytes=0;
2017   for (levels=0; undo_image != (Image *) NULL; levels++)
2018   {
2019     number_pixels=undo_image->list->columns*undo_image->list->rows;
2020     bytes+=number_pixels*sizeof(PixelPacket);
2021     undo_image=GetPreviousImageInList(undo_image);
2022   }
2023   (void) fprintf(file,"Undo Edit Cache\n  levels: %u\n",levels);
2024   (void) fprintf(file,"  bytes: %lumb\n",(unsigned long)
2025     (bytes+(1 << 19)) >> 20);
2026   (void) fprintf(file,"  limit: %lumb\n\n",resource_info->undo_cache);
2027   /*
2028     Write info about the image to a file.
2029   */
2030   (void) IdentifyImage(image,file,MagickTrue);
2031   (void) fclose(file);
2032   text=FileToString(filename,~0,&image->exception);
2033   (void) RelinquishUniqueFileResource(filename);
2034   if (text == (char *) NULL)
2035     {
2036       XNoticeWidget(display,windows,"MemoryAllocationFailed",
2037         "UnableToDisplayImageInfo");
2038       return;
2039     }
2040   textlist=StringToList(text);
2041   if (textlist != (char **) NULL)
2042     {
2043       char
2044         title[MaxTextExtent];
2045
2046       /*
2047         Display information about the image in the Text View widget.
2048       */
2049       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2050       (void) FormatMagickString(title,MaxTextExtent,"Image Info: %s",
2051         image->filename);
2052       XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2053         (char const **) textlist);
2054       for (i=0; textlist[i] != (char *) NULL; i++)
2055         textlist[i]=DestroyString(textlist[i]);
2056       textlist=(char **) RelinquishMagickMemory(textlist);
2057     }
2058   text=DestroyString(text);
2059 }
2060 \f
2061 /*
2062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2063 %                                                                             %
2064 %                                                                             %
2065 %                                                                             %
2066 +     X D i t h e r I m a g e                                                 %
2067 %                                                                             %
2068 %                                                                             %
2069 %                                                                             %
2070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2071 %
2072 %  XDitherImage() dithers the reference image as required by the HP Color
2073 %  Recovery algorithm.  The color values are quantized to 3 bits of red and
2074 %  green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2075 %  standard colormap.
2076 %
2077 %  The format of the XDitherImage method is:
2078 %
2079 %      void XDitherImage(Image *image,XImage *ximage)
2080 %
2081 %  A description of each parameter follows:
2082 %
2083 %    o image: the image.
2084 %
2085 %    o ximage: Specifies a pointer to a XImage structure;  returned from
2086 %      XCreateImage.
2087 %
2088 %
2089 */
2090 static void XDitherImage(Image *image,XImage *ximage)
2091 {
2092   static const short int
2093     dither_red[2][16]=
2094     {
2095       {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
2096       { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
2097     },
2098     dither_green[2][16]=
2099     {
2100       { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
2101       {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
2102     },
2103     dither_blue[2][16]=
2104     {
2105       { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
2106       {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
2107     };
2108
2109   PixelPacket
2110     color;
2111
2112   int
2113     y;
2114
2115   long
2116     value;
2117
2118   register char
2119     *q;
2120
2121   register const PixelPacket
2122     *p;
2123
2124   register int
2125     i,
2126     j,
2127     x;
2128
2129   unsigned int
2130     scanline_pad;
2131
2132   register unsigned long
2133     pixel;
2134
2135   unsigned char
2136     *blue_map[2][16],
2137     *green_map[2][16],
2138     *red_map[2][16];
2139
2140   /*
2141     Allocate and initialize dither maps.
2142   */
2143   for (i=0; i < 2; i++)
2144     for (j=0; j < 16; j++)
2145     {
2146       red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2147         sizeof(*red_map));
2148       green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2149         sizeof(*green_map));
2150       blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2151         sizeof(*blue_map));
2152       if ((red_map[i][j] == (unsigned char *) NULL) ||
2153           (green_map[i][j] == (unsigned char *) NULL) ||
2154           (blue_map[i][j] == (unsigned char *) NULL))
2155         {
2156           ThrowXWindowFatalException(ResourceLimitError,
2157             "MemoryAllocationFailed",image->filename);
2158           return;
2159         }
2160     }
2161   /*
2162     Initialize dither tables.
2163   */
2164   for (i=0; i < 2; i++)
2165     for (j=0; j < 16; j++)
2166       for (x=0; x < 256; x++)
2167       {
2168         value=x-16;
2169         if (x < 48)
2170           value=x/2+8;
2171         value+=dither_red[i][j];
2172         red_map[i][j][x]=(unsigned char)
2173           ((value < 0) ? 0 : (value > 255) ? 255 : value);
2174         value=x-16;
2175         if (x < 48)
2176           value=x/2+8;
2177         value+=dither_green[i][j];
2178         green_map[i][j][x]=(unsigned char)
2179           ((value < 0) ? 0 : (value > 255) ? 255 : value);
2180         value=x-32;
2181         if (x < 112)
2182           value=x/2+24;
2183         value+=((unsigned long) dither_blue[i][j] << 1);
2184         blue_map[i][j][x]=(unsigned char)
2185           ((value < 0) ? 0 : (value > 255) ? 255 : value);
2186       }
2187   /*
2188     Dither image.
2189   */
2190   scanline_pad=(unsigned int) (ximage->bytes_per_line-
2191     ((unsigned long) (ximage->width*ximage->bits_per_pixel) >> 3));
2192   i=0;
2193   j=0;
2194   q=ximage->data;
2195   for (y=0; y < (int) image->rows; y++)
2196   {
2197     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2198     if (p == (const PixelPacket *) NULL)
2199       break;
2200     for (x=0; x < (int) image->columns; x++)
2201     {
2202       color.red=RoundToQuantum((MagickRealType) (red_map[i][j][(int)
2203         ScaleQuantumToChar(p->red)] << 8));
2204       color.green=RoundToQuantum((MagickRealType) (green_map[i][j][(int)
2205         ScaleQuantumToChar(p->green)] << 8));
2206       color.blue=RoundToQuantum((MagickRealType) (blue_map[i][j][(int)
2207         ScaleQuantumToChar(p->blue)] << 8));
2208       pixel=(unsigned long) (((unsigned long) color.red & 0xe0) |
2209         (((unsigned long) color.green & 0xe0) >> 3) |
2210         (((unsigned long) color.blue & 0xc0) >> 6));
2211       *q++=(char) pixel;
2212       p++;
2213       j++;
2214       if (j == 16)
2215         j=0;
2216     }
2217     q+=scanline_pad;
2218     i++;
2219     if (i == 2)
2220       i=0;
2221   }
2222   /*
2223     Free allocated memory.
2224   */
2225   for (i=0; i < 2; i++)
2226     for (j=0; j < 16; j++)
2227     {
2228       green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2229       blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2230       red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2231     }
2232 }
2233 \f
2234 /*
2235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2236 %                                                                             %
2237 %                                                                             %
2238 %                                                                             %
2239 %   X D r a w I m a g e                                                       %
2240 %                                                                             %
2241 %                                                                             %
2242 %                                                                             %
2243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244 %
2245 %  XDrawImage() draws a line on the image.
2246 %
2247 %  The format of the XDrawImage method is:
2248 %
2249 %    MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2250 %
2251 %  A description of each parameter follows:
2252 %
2253 %    o display: Specifies a connection to an X server;  returned from
2254 %      XOpenDisplay.
2255 %
2256 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2257 %
2258 %    o draw_info: Specifies a pointer to a XDrawInfo structure.
2259 %
2260 %    o image: the image.
2261 %
2262 */
2263 MagickExport MagickBooleanType XDrawImage(Display *display,
2264   const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2265 {
2266   ExceptionInfo
2267     *exception;
2268
2269   GC
2270     draw_context;
2271
2272   Image
2273     *draw_image;
2274
2275   int
2276     x,
2277     y;
2278
2279   MagickBooleanType
2280     matte;
2281
2282   Pixmap
2283     draw_pixmap;
2284
2285   unsigned int
2286     depth,
2287     height,
2288     width;
2289
2290   Window
2291     root_window;
2292
2293   XGCValues
2294     context_values;
2295
2296   XImage
2297     *draw_ximage;
2298
2299   /*
2300     Initialize drawd image.
2301   */
2302   assert(display != (Display *) NULL);
2303   assert(pixel != (XPixelInfo *) NULL);
2304   assert(draw_info != (XDrawInfo *) NULL);
2305   assert(image != (Image *) NULL);
2306   if (image->debug != MagickFalse)
2307     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2308   /*
2309     Initialize drawd pixmap.
2310   */
2311   root_window=XRootWindow(display,XDefaultScreen(display));
2312   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2313   draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2314     draw_info->height,depth);
2315   if (draw_pixmap == (Pixmap) NULL)
2316     return(MagickFalse);
2317   /*
2318     Initialize graphics info.
2319   */
2320   context_values.background=(unsigned long) (~0);
2321   context_values.foreground=0;
2322   context_values.line_width=(int) draw_info->line_width;
2323   draw_context=XCreateGC(display,root_window,(unsigned long)
2324     (GCBackground | GCForeground | GCLineWidth),&context_values);
2325   if (draw_context == (GC) NULL)
2326     return(MagickFalse);
2327   /*
2328     Clear pixmap.
2329   */
2330   (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2331     draw_info->height);
2332   /*
2333     Draw line to pixmap.
2334   */
2335   (void) XSetBackground(display,draw_context,0);
2336   (void) XSetForeground(display,draw_context,(unsigned long) (~0));
2337   (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2338   (void) XSetStipple(display,draw_context,draw_info->stipple);
2339   switch (draw_info->element)
2340   {
2341     case PointElement:
2342     default:
2343     {
2344       (void) XDrawLines(display,draw_pixmap,draw_context,
2345         draw_info->coordinate_info,(int) draw_info->number_coordinates,
2346         CoordModeOrigin);
2347       break;
2348     }
2349     case LineElement:
2350     {
2351       (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2352         draw_info->line_info.y1,draw_info->line_info.x2,
2353         draw_info->line_info.y2);
2354       break;
2355     }
2356     case RectangleElement:
2357     {
2358       (void) XDrawRectangle(display,draw_pixmap,draw_context,
2359         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2360         (unsigned int) draw_info->rectangle_info.width,
2361         (unsigned int) draw_info->rectangle_info.height);
2362       break;
2363     }
2364     case FillRectangleElement:
2365     {
2366       (void) XFillRectangle(display,draw_pixmap,draw_context,
2367         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2368         (unsigned int) draw_info->rectangle_info.width,
2369         (unsigned int) draw_info->rectangle_info.height);
2370       break;
2371     }
2372     case CircleElement:
2373     case EllipseElement:
2374     {
2375       (void) XDrawArc(display,draw_pixmap,draw_context,
2376         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2377         (unsigned int) draw_info->rectangle_info.width,
2378         (unsigned int) draw_info->rectangle_info.height,0,360*64);
2379       break;
2380     }
2381     case FillCircleElement:
2382     case FillEllipseElement:
2383     {
2384       (void) XFillArc(display,draw_pixmap,draw_context,
2385         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2386         (unsigned int) draw_info->rectangle_info.width,
2387         (unsigned int) draw_info->rectangle_info.height,0,360*64);
2388       break;
2389     }
2390     case PolygonElement:
2391     {
2392       XPoint
2393         *coordinate_info;
2394
2395       coordinate_info=draw_info->coordinate_info;
2396       (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2397         (int) draw_info->number_coordinates,CoordModeOrigin);
2398       (void) XDrawLine(display,draw_pixmap,draw_context,
2399         coordinate_info[draw_info->number_coordinates-1].x,
2400         coordinate_info[draw_info->number_coordinates-1].y,
2401         coordinate_info[0].x,coordinate_info[0].y);
2402       break;
2403     }
2404     case FillPolygonElement:
2405     {
2406       (void) XFillPolygon(display,draw_pixmap,draw_context,
2407         draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2408         CoordModeOrigin);
2409       break;
2410     }
2411   }
2412   (void) XFreeGC(display,draw_context);
2413   /*
2414     Initialize X image.
2415   */
2416   draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2417     draw_info->height,AllPlanes,ZPixmap);
2418   if (draw_ximage == (XImage *) NULL)
2419     return(MagickFalse);
2420   (void) XFreePixmap(display,draw_pixmap);
2421   /*
2422     Initialize draw image.
2423   */
2424   draw_image=AcquireImage((ImageInfo *) NULL);
2425   if (draw_image == (Image *) NULL)
2426     return(MagickFalse);
2427   draw_image->columns=draw_info->width;
2428   draw_image->rows=draw_info->height;
2429   /*
2430     Transfer drawn X image to image.
2431   */
2432   width=(unsigned int) image->columns;
2433   height=(unsigned int) image->rows;
2434   x=0;
2435   y=0;
2436   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2437   (void) GetOneVirtualPixel(image,x,y,&draw_image->background_color,
2438     &image->exception);
2439   if (SetImageStorageClass(draw_image,DirectClass) == MagickFalse)
2440     return(MagickFalse);
2441   draw_image->matte=MagickTrue;
2442   exception=(&image->exception);
2443   for (y=0; y < (int) draw_image->rows; y++)
2444   {
2445     register long
2446       x;
2447
2448     register PixelPacket
2449       *__restrict q;
2450
2451     q=QueueAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
2452     if (q == (PixelPacket *) NULL)
2453       break;
2454     for (x=0; x < (long) draw_image->columns; x++)
2455     {
2456       if (XGetPixel(draw_ximage,x,y) == 0)
2457         {
2458           /*
2459             Set this pixel to the background color.
2460           */
2461           *q=draw_image->background_color;
2462           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
2463             TransparentOpacity : OpaqueOpacity);
2464         }
2465       else
2466         {
2467           /*
2468             Set this pixel to the pen color.
2469           */
2470           q->red=ScaleShortToQuantum(pixel->pen_color.red);
2471           q->green=ScaleShortToQuantum(pixel->pen_color.green);
2472           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
2473           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
2474             OpaqueOpacity : TransparentOpacity);
2475         }
2476       q++;
2477     }
2478     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
2479       break;
2480   }
2481   XDestroyImage(draw_ximage);
2482   /*
2483     Determine draw geometry.
2484   */
2485   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2486   if ((width != (unsigned int) draw_image->columns) ||
2487       (height != (unsigned int) draw_image->rows))
2488     {
2489       char
2490         image_geometry[MaxTextExtent];
2491
2492       /*
2493         Scale image.
2494       */
2495       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
2496         width,height);
2497       (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2498     }
2499   if (draw_info->degrees != 0.0)
2500     {
2501       Image
2502         *rotate_image;
2503
2504       int
2505         rotations;
2506
2507       MagickRealType
2508         normalized_degrees;
2509
2510       /*
2511         Rotate image.
2512       */
2513       rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2514       if (rotate_image == (Image *) NULL)
2515         return(MagickFalse);
2516       draw_image=DestroyImage(draw_image);
2517       draw_image=rotate_image;
2518       /*
2519         Annotation is relative to the degree of rotation.
2520       */
2521       normalized_degrees=draw_info->degrees;
2522       while (normalized_degrees < -45.0)
2523         normalized_degrees+=360.0;
2524       for (rotations=0; normalized_degrees > 45.0; rotations++)
2525         normalized_degrees-=90.0;
2526       switch (rotations % 4)
2527       {
2528         default:
2529         case 0:
2530           break;
2531         case 1:
2532         {
2533           /*
2534             Rotate 90 degrees.
2535           */
2536           x=x-(int) draw_image->columns/2;
2537           y=y+(int) draw_image->columns/2;
2538           break;
2539         }
2540         case 2:
2541         {
2542           /*
2543             Rotate 180 degrees.
2544           */
2545           x=x-(int) draw_image->columns;
2546           break;
2547         }
2548         case 3:
2549         {
2550           /*
2551             Rotate 270 degrees.
2552           */
2553           x=x-(int) draw_image->columns/2;
2554           y=y-(int) (draw_image->rows-(draw_image->columns/2));
2555           break;
2556         }
2557       }
2558     }
2559   /*
2560     Composite text onto the image.
2561   */
2562   for (y=0; y < (int) draw_image->rows; y++)
2563   {
2564     register long
2565       x;
2566
2567     register PixelPacket
2568       *__restrict q;
2569
2570     q=GetAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
2571     if (q == (PixelPacket *) NULL)
2572       break;
2573     for (x=0; x < (long) draw_image->columns; x++)
2574     {
2575       if (q->opacity != (Quantum) TransparentOpacity)
2576         q->opacity=OpaqueOpacity;
2577       q++;
2578     }
2579     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
2580       break;
2581   }
2582   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2583   if (draw_info->stencil == TransparentStencil)
2584     (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,x,y);
2585   else
2586     {
2587       matte=image->matte;
2588       (void) CompositeImage(image,OverCompositeOp,draw_image,x,y);
2589       image->matte=matte;
2590     }
2591   draw_image=DestroyImage(draw_image);
2592   return(MagickTrue);
2593 }
2594 \f
2595 /*
2596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2597 %                                                                             %
2598 %                                                                             %
2599 %                                                                             %
2600 %   X E r r o r                                                               %
2601 %                                                                             %
2602 %                                                                             %
2603 %                                                                             %
2604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2605 %
2606 %  XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2607 %  and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2608 %  for XQueryColor.  It returns MagickFalse in those cases.  Otherwise it returns
2609 %  True.
2610 %
2611 %  The format of the XError function is:
2612 %
2613 %      XError(display,error)
2614 %
2615 %  A description of each parameter follows:
2616 %
2617 %    o display: Specifies a pointer to the Display structure;  returned from
2618 %      XOpenDisplay.
2619 %
2620 %    o error: Specifies the error event.
2621 %
2622 */
2623
2624 #if defined(__cplusplus) || defined(c_plusplus)
2625 extern "C" {
2626 #endif
2627
2628 MagickExport int XError(Display *display,XErrorEvent *error)
2629 {
2630   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2631   assert(display != (Display *) NULL);
2632   assert(error != (XErrorEvent *) NULL);
2633   xerror_alert=MagickTrue;
2634   switch (error->request_code)
2635   {
2636     case X_GetGeometry:
2637     {
2638       if ((int) error->error_code == BadDrawable)
2639         return(MagickFalse);
2640       break;
2641     }
2642     case X_GetWindowAttributes:
2643     case X_QueryTree:
2644     {
2645       if ((int) error->error_code == BadWindow)
2646         return(MagickFalse);
2647       break;
2648     }
2649     case X_QueryColors:
2650     {
2651       if ((int) error->error_code == BadValue)
2652         return(MagickFalse);
2653       break;
2654     }
2655   }
2656   return(MagickTrue);
2657 }
2658
2659 #if defined(__cplusplus) || defined(c_plusplus)
2660 }
2661 #endif
2662 \f
2663 /*
2664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2665 %                                                                             %
2666 %                                                                             %
2667 %                                                                             %
2668 %   X F r e e R e s o u r c e s                                               %
2669 %                                                                             %
2670 %                                                                             %
2671 %                                                                             %
2672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2673 %
2674 %  XFreeResources() frees X11 resources.
2675 %
2676 %  The format of the XFreeResources method is:
2677 %
2678 %      void XFreeResources(Display *display,XVisualInfo *visual_info,
2679 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2680 %        XResourceInfo *resource_info,XWindowInfo *window_info)
2681 %        resource_info,window_info)
2682 %
2683 %  A description of each parameter follows:
2684 %
2685 %    o display: Specifies a connection to an X server; returned from
2686 %      XOpenDisplay.
2687 %
2688 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2689 %      returned from XGetVisualInfo.
2690 %
2691 %    o map_info: If map_type is specified, this structure is initialized
2692 %      with info from the Standard Colormap.
2693 %
2694 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2695 %
2696 %    o font_info: Specifies a pointer to a XFontStruct structure.
2697 %
2698 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2699 %
2700 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2701 %
2702 */
2703 MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
2704   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2705   XResourceInfo *resource_info,XWindowInfo *window_info)
2706 {
2707   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2708   assert(display != (Display *) NULL);
2709   assert(resource_info != (XResourceInfo *) NULL);
2710   if (window_info != (XWindowInfo *) NULL)
2711     {
2712       /*
2713         Free X image.
2714       */
2715       if (window_info->ximage != (XImage *) NULL)
2716         XDestroyImage(window_info->ximage);
2717       if (window_info->id != (Window) NULL)
2718         {
2719           /*
2720             Free destroy window and free cursors.
2721           */
2722           if (window_info->id != XRootWindow(display,visual_info->screen))
2723             (void) XDestroyWindow(display,window_info->id);
2724           if (window_info->annotate_context != (GC) NULL)
2725             (void) XFreeGC(display,window_info->annotate_context);
2726           if (window_info->highlight_context != (GC) NULL)
2727             (void) XFreeGC(display,window_info->highlight_context);
2728           if (window_info->widget_context != (GC) NULL)
2729             (void) XFreeGC(display,window_info->widget_context);
2730           if (window_info->cursor != (Cursor) NULL)
2731             (void) XFreeCursor(display,window_info->cursor);
2732           window_info->cursor=(Cursor) NULL;
2733           if (window_info->busy_cursor != (Cursor) NULL)
2734             (void) XFreeCursor(display,window_info->busy_cursor);
2735           window_info->busy_cursor=(Cursor) NULL;
2736         }
2737     }
2738   /*
2739     Free font.
2740   */
2741   if (font_info != (XFontStruct *) NULL)
2742     (void) XFreeFont(display,font_info);
2743   if (map_info != (XStandardColormap *) NULL)
2744     {
2745       /*
2746         Free X Standard Colormap.
2747       */
2748       if (resource_info->map_type == (char *) NULL)
2749         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2750       (void) XFree((void *) map_info);
2751     }
2752   /*
2753     Free X visual info.
2754   */
2755   if (visual_info != (XVisualInfo *) NULL)
2756     (void) XFree((void *) visual_info);
2757   if (resource_info->close_server != MagickFalse)
2758     (void) XCloseDisplay(display);
2759 }
2760 \f
2761 /*
2762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2763 %                                                                             %
2764 %                                                                             %
2765 %                                                                             %
2766 %   X F r e e S t a n d a r d C o l o r m a p                                 %
2767 %                                                                             %
2768 %                                                                             %
2769 %                                                                             %
2770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2771 %
2772 %  XFreeStandardColormap() frees an X11 colormap.
2773 %
2774 %  The format of the XFreeStandardColormap method is:
2775 %
2776 %      void XFreeStandardColormap(Display *display,
2777 %        const XVisualInfo *visual_info,XStandardColormap *map_info,
2778 %        XPixelInfo *pixel)
2779 %
2780 %  A description of each parameter follows:
2781 %
2782 %    o display: Specifies a connection to an X server; returned from
2783 %      XOpenDisplay.
2784 %
2785 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2786 %      returned from XGetVisualInfo.
2787 %
2788 %    o map_info: If map_type is specified, this structure is initialized
2789 %      with info from the Standard Colormap.
2790 %
2791 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2792 %
2793 */
2794 MagickExport void XFreeStandardColormap(Display *display,
2795   const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2796 {
2797   /*
2798     Free colormap.
2799   */
2800   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2801   assert(display != (Display *) NULL);
2802   assert(visual_info != (XVisualInfo *) NULL);
2803   assert(map_info != (XStandardColormap *) NULL);
2804   (void) XFlush(display);
2805   if (map_info->colormap != (Colormap) NULL)
2806     {
2807       if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2808         (void) XFreeColormap(display,map_info->colormap);
2809       else
2810         if (pixel != (XPixelInfo *) NULL)
2811           if ((visual_info->klass != TrueColor) &&
2812               (visual_info->klass != DirectColor))
2813             (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2814               (int) pixel->colors,0);
2815     }
2816   map_info->colormap=(Colormap) NULL;
2817   if (pixel != (XPixelInfo *) NULL)
2818     {
2819       if (pixel->pixels != (unsigned long *) NULL)
2820         pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2821       pixel->pixels=(unsigned long *) NULL;
2822     }
2823 }
2824 \f
2825 /*
2826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2827 %                                                                             %
2828 %                                                                             %
2829 %                                                                             %
2830 %   X G e t A n n o t a t e I n f o                                           %
2831 %                                                                             %
2832 %                                                                             %
2833 %                                                                             %
2834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2835 %
2836 %  XGetAnnotateInfo() initializes the AnnotateInfo structure.
2837 %
2838 %  The format of the XGetAnnotateInfo method is:
2839 %
2840 %      void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2841 %
2842 %  A description of each parameter follows:
2843 %
2844 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2845 %
2846 */
2847 MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2848 {
2849   /*
2850     Initialize annotate structure.
2851   */
2852   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2853   assert(annotate_info != (XAnnotateInfo *) NULL);
2854   annotate_info->x=0;
2855   annotate_info->y=0;
2856   annotate_info->width=0;
2857   annotate_info->height=0;
2858   annotate_info->stencil=ForegroundStencil;
2859   annotate_info->degrees=0.0;
2860   annotate_info->font_info=(XFontStruct *) NULL;
2861   annotate_info->text=(char *) NULL;
2862   *annotate_info->geometry='\0';
2863   annotate_info->previous=(XAnnotateInfo *) NULL;
2864   annotate_info->next=(XAnnotateInfo *) NULL;
2865   (void) XSupportsLocale();
2866   (void) XSetLocaleModifiers("");
2867 }
2868 \f
2869 /*
2870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2871 %                                                                             %
2872 %                                                                             %
2873 %                                                                             %
2874 %   X G e t M a p I n f o                                                     %
2875 %                                                                             %
2876 %                                                                             %
2877 %                                                                             %
2878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2879 %
2880 %  XGetMapInfo() initializes the XStandardColormap structure.
2881 %
2882 %  The format of the XStandardColormap method is:
2883 %
2884 %      void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2885 %        XStandardColormap *map_info)
2886 %
2887 %  A description of each parameter follows:
2888 %
2889 %    o colormap: Specifies the ID of the X server colormap.
2890 %
2891 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2892 %      returned from XGetVisualInfo.
2893 %
2894 %    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2895 %
2896 */
2897 MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2898   const Colormap colormap,XStandardColormap *map_info)
2899 {
2900   /*
2901     Initialize map info.
2902   */
2903   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2904   assert(visual_info != (XVisualInfo *) NULL);
2905   assert(map_info != (XStandardColormap *) NULL);
2906   map_info->colormap=colormap;
2907   map_info->red_max=visual_info->red_mask;
2908   map_info->red_mult=(unsigned long) (map_info->red_max != 0 ? 1 : 0);
2909   if (map_info->red_max != 0)
2910     while ((map_info->red_max & 0x01) == 0)
2911     {
2912       map_info->red_max>>=1;
2913       map_info->red_mult<<=1;
2914     }
2915   map_info->green_max=visual_info->green_mask;
2916   map_info->green_mult=(unsigned long) (map_info->green_max != 0 ? 1 : 0);
2917   if (map_info->green_max != 0)
2918     while ((map_info->green_max & 0x01) == 0)
2919     {
2920       map_info->green_max>>=1;
2921       map_info->green_mult<<=1;
2922     }
2923   map_info->blue_max=visual_info->blue_mask;
2924   map_info->blue_mult=(unsigned long) (map_info->blue_max != 0 ? 1 : 0);
2925   if (map_info->blue_max != 0)
2926     while ((map_info->blue_max & 0x01) == 0)
2927     {
2928       map_info->blue_max>>=1;
2929       map_info->blue_mult<<=1;
2930     }
2931   map_info->base_pixel=0;
2932 }
2933 \f
2934 /*
2935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2936 %                                                                             %
2937 %                                                                             %
2938 %                                                                             %
2939 %   X G e t P i x e l I n f o                                                 %
2940 %                                                                             %
2941 %                                                                             %
2942 %                                                                             %
2943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2944 %
2945 %  XGetPixelPacket() initializes the PixelPacket structure.
2946 %
2947 %  The format of the XGetPixelPacket method is:
2948 %
2949 %      void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
2950 %        const XStandardColormap *map_info,const XResourceInfo *resource_info,
2951 %        Image *image,XPixelInfo *pixel)
2952 %        pixel)
2953 %
2954 %  A description of each parameter follows:
2955 %
2956 %    o display: Specifies a connection to an X server; returned from
2957 %      XOpenDisplay.
2958 %
2959 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2960 %      returned from XGetVisualInfo.
2961 %
2962 %    o map_info: If map_type is specified, this structure is initialized
2963 %      with info from the Standard Colormap.
2964 %
2965 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2966 %
2967 %    o image: the image.
2968 %
2969 %    o pixel: Specifies a pointer to a XPixelInfo structure.
2970 %
2971 */
2972 MagickExport void XGetPixelPacket(Display *display,
2973   const XVisualInfo *visual_info,const XStandardColormap *map_info,
2974   const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
2975 {
2976   static const char
2977     *PenColors[MaxNumberPens]=
2978     {
2979       "#000000000000",  /* black */
2980       "#00000000ffff",  /* blue */
2981       "#0000ffffffff",  /* cyan */
2982       "#0000ffff0000",  /* green */
2983       "#bdbdbdbdbdbd",  /* gray */
2984       "#ffff00000000",  /* red */
2985       "#ffff0000ffff",  /* magenta */
2986       "#ffffffff0000",  /* yellow */
2987       "#ffffffffffff",  /* white */
2988       "#bdbdbdbdbdbd",  /* gray */
2989       "#bdbdbdbdbdbd"   /* gray */
2990     };
2991
2992   Colormap
2993     colormap;
2994
2995   register long
2996     i;
2997
2998   Status
2999     status;
3000
3001   unsigned int
3002     packets;
3003
3004   /*
3005     Initialize pixel info.
3006   */
3007   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3008   assert(display != (Display *) NULL);
3009   assert(visual_info != (XVisualInfo *) NULL);
3010   assert(map_info != (XStandardColormap *) NULL);
3011   assert(resource_info != (XResourceInfo *) NULL);
3012   assert(pixel != (XPixelInfo *) NULL);
3013   pixel->colors=0;
3014   if (image != (Image *) NULL)
3015     if (image->storage_class == PseudoClass)
3016       pixel->colors=image->colors;
3017   packets=(unsigned int)
3018     MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
3019   if (pixel->pixels != (unsigned long *) NULL)
3020     pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3021   pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
3022     sizeof(pixel->pixels));
3023   if (pixel->pixels == (unsigned long *) NULL)
3024     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3025       image->filename);
3026   /*
3027     Set foreground color.
3028   */
3029   colormap=map_info->colormap;
3030   (void) XParseColor(display,colormap,(char *) ForegroundColor,
3031     &pixel->foreground_color);
3032   status=XParseColor(display,colormap,resource_info->foreground_color,
3033     &pixel->foreground_color);
3034   if (status == False)
3035     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3036       resource_info->foreground_color);
3037   pixel->foreground_color.pixel=
3038     XStandardPixel(map_info,&pixel->foreground_color);
3039   pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3040   /*
3041     Set background color.
3042   */
3043   (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3044   status=XParseColor(display,colormap,resource_info->background_color,
3045     &pixel->background_color);
3046   if (status == False)
3047     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3048       resource_info->background_color);
3049   pixel->background_color.pixel=
3050     XStandardPixel(map_info,&pixel->background_color);
3051   pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3052   /*
3053     Set border color.
3054   */
3055   (void) XParseColor(display,colormap,(char *) BorderColor,
3056     &pixel->border_color);
3057   status=XParseColor(display,colormap,resource_info->border_color,
3058     &pixel->border_color);
3059   if (status == False)
3060     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3061       resource_info->border_color);
3062   pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3063   pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3064   /*
3065     Set matte color.
3066   */
3067   pixel->matte_color=pixel->background_color;
3068   if (resource_info->matte_color != (char *) NULL)
3069     {
3070       /*
3071         Matte color is specified as a X resource or command line argument.
3072       */
3073       status=XParseColor(display,colormap,resource_info->matte_color,
3074         &pixel->matte_color);
3075       if (status == False)
3076         ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3077           resource_info->matte_color);
3078       pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3079       pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3080     }
3081   /*
3082     Set highlight color.
3083   */
3084   pixel->highlight_color.red=(unsigned short) ((
3085     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3086     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3087   pixel->highlight_color.green=(unsigned short) ((
3088     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3089     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3090   pixel->highlight_color.blue=(unsigned short) ((
3091     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3092     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3093   pixel->highlight_color.pixel=
3094     XStandardPixel(map_info,&pixel->highlight_color);
3095   pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3096   /*
3097     Set shadow color.
3098   */
3099   pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3100     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3101   pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3102     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3103   pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3104     pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3105   pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3106   pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3107   /*
3108     Set depth color.
3109   */
3110   pixel->depth_color.red=(unsigned short) (((MagickRealType)
3111     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3112   pixel->depth_color.green=(unsigned short) (((MagickRealType)
3113     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3114   pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3115     pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3116   pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3117   pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3118   /*
3119     Set trough color.
3120   */
3121   pixel->trough_color.red=(unsigned short) (((MagickRealType)
3122     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3123   pixel->trough_color.green=(unsigned short) (((MagickRealType)
3124     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3125   pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3126     pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3127   pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3128   pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3129   /*
3130     Set pen color.
3131   */
3132   for (i=0; i < MaxNumberPens; i++)
3133   {
3134     (void) XParseColor(display,colormap,(char *) PenColors[i],
3135       &pixel->pen_colors[i]);
3136     status=XParseColor(display,colormap,resource_info->pen_colors[i],
3137       &pixel->pen_colors[i]);
3138     if (status == False)
3139       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3140         resource_info->pen_colors[i]);
3141     pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3142     pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3143   }
3144   pixel->box_color=pixel->background_color;
3145   pixel->pen_color=pixel->foreground_color;
3146   pixel->box_index=0;
3147   pixel->pen_index=1;
3148   if (image != (Image *) NULL)
3149     {
3150       if ((resource_info->gamma_correct != MagickFalse) &&
3151           (image->gamma != 0.0))
3152         {
3153           GeometryInfo
3154             geometry_info;
3155
3156           MagickStatusType
3157             flags;
3158
3159           /*
3160             Initialize map relative to display and image gamma.
3161           */
3162           flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3163           red_gamma=geometry_info.rho;
3164           green_gamma=geometry_info.sigma;
3165           if ((flags & SigmaValue) == 0)
3166             green_gamma=red_gamma;
3167           blue_gamma=geometry_info.xi;
3168           if ((flags & XiValue) == 0)
3169             blue_gamma=red_gamma;
3170           red_gamma*=image->gamma;
3171           green_gamma*=image->gamma;
3172           blue_gamma*=image->gamma;
3173         }
3174       if (image->storage_class == PseudoClass)
3175         {
3176           /*
3177             Initialize pixel array for images of type PseudoClass.
3178           */
3179           for (i=0; i < (long) image->colors; i++)
3180             pixel->pixels[i]=
3181               XGammaPixel(map_info,image->colormap+i);
3182           for (i=0; i < MaxNumberPens; i++)
3183             pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3184           pixel->colors+=MaxNumberPens;
3185         }
3186     }
3187 }
3188 \f
3189 /*
3190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3191 %                                                                             %
3192 %                                                                             %
3193 %                                                                             %
3194 %   X G e t R e s o u r c e C l a s s                                         %
3195 %                                                                             %
3196 %                                                                             %
3197 %                                                                             %
3198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3199 %
3200 %  XGetResourceClass() queries the X server for the specified resource name or
3201 %  class.  If the resource name or class is not defined in the database, the
3202 %  supplied default value is returned.
3203 %
3204 %  The format of the XGetResourceClass method is:
3205 %
3206 %      char *XGetResourceClass(XrmDatabase database,const char *client_name,
3207 %        const char *keyword,char *resource_default)
3208 %
3209 %  A description of each parameter follows:
3210 %
3211 %    o database: Specifies a resource database; returned from
3212 %      XrmGetStringDatabase.
3213 %
3214 %    o client_name:  Specifies the application name used to retrieve resource
3215 %      info from the X server database.
3216 %
3217 %    o keyword: Specifies the keyword of the value being retrieved.
3218 %
3219 %    o resource_default: Specifies the default value to return if the query
3220 %      fails to find the specified keyword/class.
3221 %
3222 */
3223 MagickExport char *XGetResourceClass(XrmDatabase database,
3224   const char *client_name,const char *keyword,char *resource_default)
3225 {
3226   char
3227     resource_class[MaxTextExtent],
3228     resource_name[MaxTextExtent];
3229
3230   static char
3231     *resource_type;
3232
3233   Status
3234     status;
3235
3236   XrmValue
3237     resource_value;
3238
3239   if (database == (XrmDatabase) NULL)
3240     return(resource_default);
3241   *resource_name='\0';
3242   *resource_class='\0';
3243   if (keyword != (char *) NULL)
3244     {
3245       int
3246         c,
3247         k;
3248
3249       /*
3250         Initialize resource keyword and class.
3251       */
3252       (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
3253         client_name,keyword);
3254       c=(int) (*client_name);
3255       if ((c >= XK_a) && (c <= XK_z))
3256         c-=(XK_a-XK_A);
3257       else
3258         if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3259           c-=(XK_agrave-XK_Agrave);
3260         else
3261           if ((c >= XK_oslash) && (c <= XK_thorn))
3262             c-=(XK_oslash-XK_Ooblique);
3263       k=(int) (*keyword);
3264       if ((k >= XK_a) && (k <= XK_z))
3265         k-=(XK_a-XK_A);
3266       else
3267         if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3268           k-=(XK_agrave-XK_Agrave);
3269         else
3270           if ((k >= XK_oslash) && (k <= XK_thorn))
3271             k-=(XK_oslash-XK_Ooblique);
3272       (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
3273         client_name+1,k,keyword+1);
3274     }
3275   status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3276     &resource_value);
3277   if (status == False)
3278     return(resource_default);
3279   return(resource_value.addr);
3280 }
3281 \f
3282 /*
3283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3284 %                                                                             %
3285 %                                                                             %
3286 %                                                                             %
3287 %   X G e t R e s o u r c e D a t a b a s e                                   %
3288 %                                                                             %
3289 %                                                                             %
3290 %                                                                             %
3291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3292 %
3293 %  XGetResourceDatabase() creates a new resource database and initializes it.
3294 %
3295 %  The format of the XGetResourceDatabase method is:
3296 %
3297 %      XrmDatabase XGetResourceDatabase(Display *display,
3298 %        const char *client_name)
3299 %
3300 %  A description of each parameter follows:
3301 %
3302 %    o database: XGetResourceDatabase() returns the database after it is
3303 %      initialized.
3304 %
3305 %    o display: Specifies a connection to an X server;  returned from
3306 %      XOpenDisplay.
3307 %
3308 %    o client_name:  Specifies the application name used to retrieve resource
3309 %      info from the X server database.
3310 %
3311 */
3312 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3313   const char *client_name)
3314 {
3315   char
3316     filename[MaxTextExtent];
3317
3318   int
3319     c;
3320
3321   register const char
3322     *p;
3323
3324   XrmDatabase
3325     resource_database,
3326     server_database;
3327
3328   if (display == (Display *) NULL)
3329     return((XrmDatabase) NULL);
3330   assert(client_name != (char *) NULL);
3331   /*
3332     Initialize resource database.
3333   */
3334   XrmInitialize();
3335   (void) XGetDefault(display,(char *) client_name,"dummy");
3336   resource_database=XrmGetDatabase(display);
3337   /*
3338     Combine application database.
3339   */
3340   if (client_name != (char *) NULL)
3341     {
3342       /*
3343         Get basename of client.
3344       */
3345       p=client_name+(strlen(client_name)-1);
3346       while ((p > client_name) && (*p != '/'))
3347         p--;
3348       if (*p == '/')
3349         client_name=p+1;
3350     }
3351   c=(int) (*client_name);
3352   if ((c >= XK_a) && (c <= XK_z))
3353     c-=(XK_a-XK_A);
3354   else
3355     if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3356       c-=(XK_agrave-XK_Agrave);
3357     else
3358       if ((c >= XK_oslash) && (c <= XK_thorn))
3359         c-=(XK_oslash-XK_Ooblique);
3360 #if defined(X11_APPLICATION_PATH)
3361   (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
3362     X11_APPLICATION_PATH,c,client_name+1);
3363   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3364 #endif
3365   if (XResourceManagerString(display) != (char *) NULL)
3366     {
3367       /*
3368         Combine server database.
3369       */
3370       server_database=XrmGetStringDatabase(XResourceManagerString(display));
3371       XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3372     }
3373   /*
3374     Merge user preferences database.
3375   */
3376 #if defined(X11_PREFERENCES_PATH)
3377   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
3378     X11_PREFERENCES_PATH,client_name);
3379   ExpandFilename(filename);
3380   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3381 #endif
3382   return(resource_database);
3383 }
3384 \f
3385 /*
3386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3387 %                                                                             %
3388 %                                                                             %
3389 %                                                                             %
3390 %   X G e t R e s o u r c e I n f o                                           %
3391 %                                                                             %
3392 %                                                                             %
3393 %                                                                             %
3394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3395 %
3396 %  XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3397 %
3398 %  The format of the XGetResourceInfo method is:
3399 %
3400 %      void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3401 %        const char *client_name,XResourceInfo *resource_info)
3402 %
3403 %  A description of each parameter follows:
3404 %
3405 %    o image_info: the image info.
3406 %
3407 %    o database: Specifies a resource database; returned from
3408 %      XrmGetStringDatabase.
3409 %
3410 %    o client_name:  Specifies the application name used to retrieve
3411 %      resource info from the X server database.
3412 %
3413 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3414 %
3415 */
3416 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3417   XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3418 {
3419   char
3420     *cwd,
3421     *resource_value;
3422
3423   /*
3424     Initialize resource info fields.
3425   */
3426   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3427   assert(resource_info != (XResourceInfo *) NULL);
3428   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3429   resource_info->resource_database=database;
3430   resource_info->image_info=(ImageInfo *) image_info;
3431   (void) SetImageInfoProgressMonitor(resource_info->image_info,
3432     XMagickProgressMonitor,(void *) NULL);
3433   resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3434   resource_info->close_server=MagickTrue;
3435   resource_info->client_name=AcquireString(client_name);
3436   resource_value=XGetResourceClass(database,client_name,"backdrop",
3437     (char *) "False");
3438   resource_info->backdrop=IsMagickTrue(resource_value);
3439   resource_info->background_color=XGetResourceInstance(database,client_name,
3440     "background",(char *) "#d6d6d6d6d6d6");
3441   resource_info->border_color=XGetResourceInstance(database,client_name,
3442     "borderColor",BorderColor);
3443   resource_value=XGetResourceClass(database,client_name,"borderWidth",
3444     (char *) "2");
3445   resource_info->border_width=(unsigned int) atoi(resource_value);
3446   resource_value=XGetResourceClass(database,client_name,"colormap",
3447     (char *) "shared");
3448   resource_info->colormap=UndefinedColormap;
3449   if (LocaleCompare("private",resource_value) == 0)
3450     resource_info->colormap=PrivateColormap;
3451   if (LocaleCompare("shared",resource_value) == 0)
3452     resource_info->colormap=SharedColormap;
3453   if (resource_info->colormap == UndefinedColormap)
3454     ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3455       resource_value);
3456   resource_value=XGetResourceClass(database,client_name,
3457     "colorRecovery",(char *) "False");
3458   resource_info->color_recovery=IsMagickTrue(resource_value);
3459   resource_value=XGetResourceClass(database,client_name,"confirmExit",
3460     (char *) "False");
3461   resource_info->confirm_exit=IsMagickTrue(resource_value);
3462   resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3463     (char *) "False");
3464   resource_info->confirm_edit=IsMagickTrue(resource_value);
3465   resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
3466   resource_info->delay=(unsigned int) atoi(resource_value);
3467   resource_info->display_gamma=XGetResourceClass(database,client_name,
3468     "displayGamma",(char *) "2.2");
3469   resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3470     (char *) "True");
3471   resource_info->display_warnings=IsMagickTrue(resource_value);
3472   resource_info->font=XGetResourceClass(database,client_name,"font",
3473     (char *) NULL);
3474   resource_info->font=XGetResourceClass(database,client_name,"fontList",
3475     resource_info->font);
3476   resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3477     (char *) "fixed");
3478   resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3479     (char *) "variable");
3480   resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3481     (char *) "5x8");
3482   resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3483     (char *) "6x10");
3484   resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3485     (char *) "7x13bold");
3486   resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3487     (char *) "8x13bold");
3488   resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3489     (char *) "9x15bold");
3490   resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3491     (char *) "10x20");
3492   resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3493     (char *) "12x24");
3494   resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3495     (char *) "fixed");
3496   resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3497     (char *) "fixed");
3498   resource_info->foreground_color=XGetResourceInstance(database,client_name,
3499     "foreground",ForegroundColor);
3500   resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3501     (char *) "True");
3502   resource_info->gamma_correct=IsMagickTrue(resource_value);
3503   resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3504     client_name,"geometry",(char *) NULL));
3505   resource_value=XGetResourceClass(database,client_name,"gravity",
3506     (char *) "Center");
3507   resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
3508     MagickFalse,resource_value);
3509   cwd=getcwd(resource_info->home_directory,MaxTextExtent);
3510   resource_info->icon_geometry=XGetResourceClass(database,client_name,
3511     "iconGeometry",(char *) NULL);
3512   resource_value=XGetResourceClass(database,client_name,"iconic",
3513     (char *) "False");
3514   resource_info->iconic=IsMagickTrue(resource_value);
3515   resource_value=XGetResourceClass(database,client_name,"immutable",
3516     LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3517     (char *) "False");
3518   resource_info->immutable=IsMagickTrue(resource_value);
3519   resource_value=XGetResourceClass(database,client_name,"magnify",
3520     (char *) "3");
3521   resource_info->magnify=(unsigned int) atoi(resource_value);
3522   resource_info->map_type=XGetResourceClass(database,client_name,"map",
3523     (char *) NULL);
3524   resource_info->matte_color=XGetResourceInstance(database,client_name,
3525     "mattecolor",(char *) NULL);
3526   resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3527     "name",(char *) NULL));
3528   resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3529     (char *) "black");
3530   resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3531     (char *) "blue");
3532   resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3533     (char *) "cyan");
3534   resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3535     (char *) "green");
3536   resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3537     (char *) "gray");
3538   resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3539     (char *) "red");
3540   resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3541     (char *) "magenta");
3542   resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3543     (char *) "yellow");
3544   resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3545     (char *) "white");
3546   resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3547     (char *) "gray");
3548   resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3549     (char *) "gray");
3550   resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
3551   resource_info->pause=(unsigned int) atoi(resource_value);
3552   resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
3553   resource_info->quantum=atoi(resource_value);
3554   resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3555     "font",(char *) "fixed");
3556   resource_info->text_font=XGetResourceClass(database,client_name,
3557     "textFontList",resource_info->text_font);
3558   resource_info->title=XGetResourceClass(database,client_name,"title",
3559     (char *) NULL);
3560   resource_value=XGetResourceClass(database,client_name,"undoCache",
3561     (char *) "16");
3562   resource_info->undo_cache=(unsigned int) atol(resource_value);
3563   resource_value=XGetResourceClass(database,client_name,"update",
3564     (char *) "False");
3565   resource_info->update=IsMagickTrue(resource_value);
3566   resource_value=XGetResourceClass(database,client_name,"usePixmap",
3567     (char *) "True");
3568   resource_info->use_pixmap=IsMagickTrue(resource_value);
3569   resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3570     (char *) "True");
3571   resource_info->use_shared_memory=IsMagickTrue(resource_value);
3572   resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3573     (char *) NULL);
3574   resource_info->window_group=XGetResourceClass(database,client_name,
3575     "windowGroup",(char *) NULL);
3576   resource_info->window_id=XGetResourceClass(database,client_name,"window",
3577     (char *) NULL);
3578   resource_info->write_filename=XGetResourceClass(database,client_name,
3579     "writeFilename",(char *) NULL);
3580 }
3581 \f
3582 /*
3583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3584 %                                                                             %
3585 %                                                                             %
3586 %                                                                             %
3587 %   X G e t R e s o u r c e I n s t a n c e                                   %
3588 %                                                                             %
3589 %                                                                             %
3590 %                                                                             %
3591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3592 %
3593 %  XGetResourceInstance() queries the X server for the specified resource name.
3594 %  If the resource name is not defined in the database, the supplied default
3595 %  value is returned.
3596 %
3597 %  The format of the XGetResourceInstance method is:
3598 %
3599 %      char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3600 %        const char *keyword,const char *resource_default)
3601 %
3602 %  A description of each parameter follows:
3603 %
3604 %    o database: Specifies a resource database; returned from
3605 %      XrmGetStringDatabase.
3606 %
3607 %    o client_name:  Specifies the application name used to retrieve
3608 %      resource info from the X server database.
3609 %
3610 %    o keyword: Specifies the keyword of the value being retrieved.
3611 %
3612 %    o resource_default: Specifies the default value to return if the query
3613 %      fails to find the specified keyword/class.
3614 %
3615 */
3616 MagickExport char *XGetResourceInstance(XrmDatabase database,
3617   const char *client_name,const char *keyword,const char *resource_default)
3618 {
3619   char
3620     *resource_type,
3621     resource_name[MaxTextExtent];
3622
3623   Status
3624     status;
3625
3626   XrmValue
3627     resource_value;
3628
3629   if (database == (XrmDatabase) NULL)
3630     return((char *) resource_default);
3631   *resource_name='\0';
3632   if (keyword != (char *) NULL)
3633     (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
3634       keyword);
3635   status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3636     &resource_value);
3637   if (status == False)
3638     return((char *) resource_default);
3639   return(resource_value.addr);
3640 }
3641 \f
3642 /*
3643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3644 %                                                                             %
3645 %                                                                             %
3646 %                                                                             %
3647 %   X G e t S c r e e n D e n s i t y                                         %
3648 %                                                                             %
3649 %                                                                             %
3650 %                                                                             %
3651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652 %
3653 %  XGetScreenDensity() returns the density of the X server screen in
3654 %  dots-per-inch.
3655 %
3656 %  The format of the XGetScreenDensity method is:
3657 %
3658 %      char *XGetScreenDensity(Display *display)
3659 %
3660 %  A description of each parameter follows:
3661 %
3662 %    o density: XGetScreenDensity() returns the density of the X screen in
3663 %      dots-per-inch.
3664 %
3665 %    o display: Specifies a connection to an X server;  returned from
3666 %      XOpenDisplay.
3667 %
3668 */
3669 MagickExport char *XGetScreenDensity(Display *display)
3670 {
3671   char
3672     density[MaxTextExtent];
3673
3674   double
3675     x_density,
3676     y_density;
3677
3678   /*
3679     Set density as determined by screen size.
3680   */
3681   x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3682     ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3683   y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3684     ((double) DisplayHeightMM(display,XDefaultScreen(display))));
3685   (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,y_density);
3686   return(GetPageGeometry(density));
3687 }
3688 \f
3689 /*
3690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3691 %                                                                             %
3692 %                                                                             %
3693 %                                                                             %
3694 +   X G e t S u b w i n d o w                                                 %
3695 %                                                                             %
3696 %                                                                             %
3697 %                                                                             %
3698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3699 %
3700 %  XGetSubwindow() returns the subwindow of a window chosen the user with the
3701 %  pointer and a button press.
3702 %
3703 %  The format of the XGetSubwindow method is:
3704 %
3705 %      Window XGetSubwindow(Display *display,Window window,int x,int y)
3706 %
3707 %  A description of each parameter follows:
3708 %
3709 %    o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3710 %      otherwise the subwindow is returned.
3711 %
3712 %    o display: Specifies a connection to an X server;  returned from
3713 %      XOpenDisplay.
3714 %
3715 %    o window: Specifies a pointer to a Window.
3716 %
3717 %    o x: the x coordinate of the pointer relative to the origin of the
3718 %      window.
3719 %
3720 %    o y: the y coordinate of the pointer relative to the origin of the
3721 %      window.
3722 %
3723 %
3724 */
3725 static Window XGetSubwindow(Display *display,Window window,int x,int y)
3726 {
3727   int
3728     x_offset,
3729     y_offset;
3730
3731   Status
3732     status;
3733
3734   Window
3735     source_window,
3736     target_window;
3737
3738   assert(display != (Display *) NULL);
3739   source_window=XRootWindow(display,XDefaultScreen(display));
3740   if (window == (Window) NULL)
3741     return(source_window);
3742   target_window=window;
3743   for ( ; ; )
3744   {
3745     status=XTranslateCoordinates(display,source_window,window,x,y,
3746       &x_offset,&y_offset,&target_window);
3747     if (status != True)
3748       break;
3749     if (target_window == (Window) NULL)
3750       break;
3751     source_window=window;
3752     window=target_window;
3753     x=x_offset;
3754     y=y_offset;
3755   }
3756   if (target_window == (Window) NULL)
3757     target_window=window;
3758   return(target_window);
3759 }
3760 \f
3761 /*
3762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3763 %                                                                             %
3764 %                                                                             %
3765 %                                                                             %
3766 %   X G e t W i n d o w C o l o r                                             %
3767 %                                                                             %
3768 %                                                                             %
3769 %                                                                             %
3770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3771 %
3772 %  XGetWindowColor() returns the color of a pixel interactively chosen from the
3773 %  X server.
3774 %
3775 %  The format of the XGetWindowColor method is:
3776 %
3777 %      MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3778 %        char *name)
3779 %
3780 %  A description of each parameter follows:
3781 %
3782 %    o display: Specifies a connection to an X server;  returned from
3783 %      XOpenDisplay.
3784 %
3785 %    o windows: Specifies a pointer to a XWindows structure.
3786 %
3787 %    o name: the name of the color if found in the X Color Database is
3788 %      returned in this character string.
3789 %
3790 */
3791 MagickExport MagickBooleanType XGetWindowColor(Display *display,
3792   XWindows *windows,char *name)
3793 {
3794   int
3795     x,
3796     y;
3797
3798   PixelPacket
3799     pixel;
3800
3801   RectangleInfo
3802     crop_info;
3803
3804   Status
3805     status;
3806
3807   Window
3808     child,
3809     client_window,
3810     root_window,
3811     target_window;
3812
3813   XColor
3814     color;
3815
3816   XImage
3817     *ximage;
3818
3819   XWindowAttributes
3820     window_attributes;
3821
3822   /*
3823     Choose a pixel from the X server.
3824   */
3825   assert(display != (Display *) NULL);
3826   assert(name != (char *) NULL);
3827   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3828   *name='\0';
3829   target_window=XSelectWindow(display,&crop_info);
3830   if (target_window == (Window) NULL)
3831     return(MagickFalse);
3832   root_window=XRootWindow(display,XDefaultScreen(display));
3833   client_window=target_window;
3834   if (target_window != root_window)
3835     {
3836       unsigned int
3837         d;
3838
3839       /*
3840         Get client window.
3841       */
3842       status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3843       if (status != False)
3844         {
3845           client_window=XClientWindow(display,target_window);
3846           target_window=client_window;
3847         }
3848     }
3849   /*
3850     Verify window is viewable.
3851   */
3852   status=XGetWindowAttributes(display,target_window,&window_attributes);
3853   if ((status == False) || (window_attributes.map_state != IsViewable))
3854     return(MagickFalse);
3855   /*
3856     Get window X image.
3857   */
3858   (void) XTranslateCoordinates(display,root_window,target_window,
3859     (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3860   ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3861   if (ximage == (XImage *) NULL)
3862     return(MagickFalse);
3863   color.pixel=XGetPixel(ximage,0,0);
3864   XDestroyImage(ximage);
3865   /*
3866     Match color against the color database.
3867   */
3868   (void) XQueryColor(display,window_attributes.colormap,&color);
3869   pixel.red=ScaleShortToQuantum(color.red);
3870   pixel.green=ScaleShortToQuantum(color.green);
3871   pixel.blue=ScaleShortToQuantum(color.blue);
3872   pixel.opacity=OpaqueOpacity;
3873   (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3874     &windows->image.image->exception);
3875   return(MagickTrue);
3876 }
3877 \f
3878 /*
3879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3880 %                                                                             %
3881 %                                                                             %
3882 %                                                                             %
3883 +   X G e t W i n d o w I m a g e                                             %
3884 %                                                                             %
3885 %                                                                             %
3886 %                                                                             %
3887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3888 %
3889 %  XGetWindowImage() reads an image from the target X window and returns it.
3890 %  XGetWindowImage() optionally descends the window hierarchy and overlays the
3891 %  target image with each child image in an optimized fashion.  Any child
3892 %  window that have the same visual, colormap, and are contained by its parent
3893 %  are exempted.
3894 %
3895 %  The format of the XGetWindowImage method is:
3896 %
3897 %      Image *XGetWindowImage(Display *display,const Window window,
3898 %        const unsigned int borders,const unsigned int level)
3899 %
3900 %  A description of each parameter follows:
3901 %
3902 %    o display: Specifies a connection to an X server;  returned from
3903 %      XOpenDisplay.
3904 %
3905 %    o window: Specifies the window to obtain the image from.
3906 %
3907 %    o borders: Specifies whether borders pixels are to be saved with
3908 %      the image.
3909 %
3910 %    o level: Specifies an unsigned integer representing the level of
3911 %      decent in the window hierarchy.  This value must be zero or one on
3912 %      the initial call to XGetWindowImage.  A value of zero returns after
3913 %      one call.  A value of one causes the function to descend the window
3914 %      hierarchy and overlay the target image with each subwindow image.
3915 %
3916 %
3917 */
3918 static Image *XGetWindowImage(Display *display,const Window window,
3919   const unsigned int borders,const unsigned int level)
3920 {
3921   typedef struct _ColormapInfo
3922   {
3923     Colormap
3924       colormap;
3925
3926     XColor
3927       *colors;
3928
3929     struct _ColormapInfo
3930       *next;
3931   } ColormapInfo;
3932
3933   typedef struct _WindowInfo
3934   {
3935     Window
3936       window,
3937       parent;
3938
3939     Visual
3940       *visual;
3941
3942     Colormap
3943       colormap;
3944
3945     XSegment
3946       bounds;
3947
3948     RectangleInfo
3949       crop_info;
3950   } WindowInfo;
3951
3952   IndexPacket
3953     index;
3954
3955   int
3956     display_height,
3957     display_width,
3958     id,
3959     x_offset,
3960     y_offset;
3961
3962   RectangleInfo
3963     crop_info;
3964
3965   register IndexPacket
3966     *indexes;
3967
3968   register int
3969     i;
3970
3971   static ColormapInfo
3972     *colormap_info = (ColormapInfo *) NULL;
3973
3974   static int
3975     max_windows = 0,
3976     number_windows = 0;
3977
3978   static WindowInfo
3979     *window_info;
3980
3981   Status
3982     status;
3983
3984   Window
3985     child,
3986     root_window;
3987
3988   XWindowAttributes
3989     window_attributes;
3990
3991   /*
3992     Verify window is viewable.
3993   */
3994   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3995   assert(display != (Display *) NULL);
3996   status=XGetWindowAttributes(display,window,&window_attributes);
3997   if ((status == False) || (window_attributes.map_state != IsViewable))
3998     return((Image *) NULL);
3999   /*
4000     Cropping rectangle is relative to root window.
4001   */
4002   root_window=XRootWindow(display,XDefaultScreen(display));
4003   (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4004     &y_offset,&child);
4005   crop_info.x=(long) x_offset;
4006   crop_info.y=(long) y_offset;
4007   crop_info.width=(unsigned long) window_attributes.width;
4008   crop_info.height=(unsigned long) window_attributes.height;
4009   if (borders != MagickFalse)
4010     {
4011       /*
4012         Include border in image.
4013       */
4014       crop_info.x-=(long) window_attributes.border_width;
4015       crop_info.y-=(long) window_attributes.border_width;
4016       crop_info.width+=(unsigned long) (window_attributes.border_width << 1);
4017       crop_info.height+=(unsigned long) (window_attributes.border_width << 1);
4018     }
4019   /*
4020     Crop to root window.
4021   */
4022   if (crop_info.x < 0)
4023     {
4024       crop_info.width+=crop_info.x;
4025       crop_info.x=0;
4026     }
4027   if (crop_info.y < 0)
4028     {
4029       crop_info.height+=crop_info.y;
4030       crop_info.y=0;
4031     }
4032   display_width=XDisplayWidth(display,XDefaultScreen(display));
4033   if ((int) (crop_info.x+crop_info.width) > display_width)
4034     crop_info.width=(unsigned long) (display_width-crop_info.x);
4035   display_height=XDisplayHeight(display,XDefaultScreen(display));
4036   if ((int) (crop_info.y+crop_info.height) > display_height)
4037     crop_info.height=(unsigned long) (display_height-crop_info.y);
4038   /*
4039     Initialize window info attributes.
4040   */
4041   if (number_windows >= max_windows)
4042     {
4043       /*
4044         Allocate or resize window info buffer.
4045       */
4046       max_windows+=1024;
4047       if (window_info == (WindowInfo *) NULL)
4048         window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4049           sizeof(*window_info));
4050       else
4051         window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4052           max_windows,sizeof(*window_info));
4053     }
4054   if (window_info == (WindowInfo *) NULL)
4055     {
4056       ThrowXWindowFatalException(ResourceLimitError,
4057         "MemoryAllocationFailed","...");
4058       return((Image *) NULL);
4059     }
4060   id=number_windows++;
4061   window_info[id].window=window;
4062   window_info[id].visual=window_attributes.visual;
4063   window_info[id].colormap=window_attributes.colormap;
4064   window_info[id].bounds.x1=(short) crop_info.x;
4065   window_info[id].bounds.y1=(short) crop_info.y;
4066   window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4067   window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4068   crop_info.x-=x_offset;
4069   crop_info.y-=y_offset;
4070   window_info[id].crop_info=crop_info;
4071   if (level != 0)
4072     {
4073       unsigned int
4074         number_children;
4075
4076       Window
4077         *children;
4078
4079       /*
4080         Descend the window hierarchy.
4081       */
4082       status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4083         &children,&number_children);
4084       for (i=0; i < id; i++)
4085         if ((window_info[i].window == window_info[id].parent) &&
4086             (window_info[i].visual == window_info[id].visual) &&
4087             (window_info[i].colormap == window_info[id].colormap))
4088           {
4089             if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4090                 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4091                 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4092                 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4093               {
4094                 /*
4095                   Eliminate windows not circumscribed by their parent.
4096                 */
4097                 number_windows--;
4098                 break;
4099               }
4100           }
4101       if ((status == True) && (number_children != 0))
4102         {
4103           for (i=0; i < (int) number_children; i++)
4104             (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4105           (void) XFree((void *) children);
4106         }
4107     }
4108   if (level <= 1)
4109     {
4110       ColormapInfo
4111         *next;
4112
4113       ExceptionInfo
4114         *exception;
4115
4116       Image
4117         *composite_image,
4118         *image;
4119
4120       int
4121         y;
4122
4123       MagickBooleanType
4124         import;
4125
4126       register int
4127         j,
4128         x;
4129
4130       register PixelPacket
4131         *__restrict q;
4132
4133       register unsigned long
4134         pixel;
4135
4136       unsigned int
4137         number_colors;
4138
4139       XColor
4140         *colors;
4141
4142       XImage
4143         *ximage;
4144
4145       /*
4146         Get X image for each window in the list.
4147       */
4148       image=NewImageList();
4149       for (id=0; id < number_windows; id++)
4150       {
4151         /*
4152           Does target window intersect top level window?
4153         */
4154         import=
4155           ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4156            (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4157            (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4158            (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4159           MagickTrue : MagickFalse;
4160         /*
4161           Is target window contained by another window with the same colormap?
4162         */
4163         for (j=0; j < id; j++)
4164           if ((window_info[id].visual == window_info[j].visual) &&
4165               (window_info[id].colormap == window_info[j].colormap))
4166             {
4167               if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4168                   (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4169                   (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4170                   (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4171                   import=MagickFalse;
4172             }
4173           else
4174             if ((window_info[id].visual != window_info[j].visual) ||
4175                 (window_info[id].colormap != window_info[j].colormap))
4176               {
4177                 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4178                     (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4179                     (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4180                     (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4181                   import=MagickTrue;
4182               }
4183         if (import == MagickFalse)
4184           continue;
4185         /*
4186           Get X image.
4187         */
4188         ximage=XGetImage(display,window_info[id].window,(int)
4189           window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4190           (unsigned int) window_info[id].crop_info.width,(unsigned int)
4191           window_info[id].crop_info.height,AllPlanes,ZPixmap);
4192         if (ximage == (XImage *) NULL)
4193           continue;
4194         /*
4195           Initialize window colormap.
4196         */
4197         number_colors=0;
4198         colors=(XColor *) NULL;
4199         if (window_info[id].colormap != (Colormap) NULL)
4200           {
4201             ColormapInfo
4202               *p;
4203
4204             /*
4205               Search colormap list for window colormap.
4206             */
4207             number_colors=(unsigned int) window_info[id].visual->map_entries;
4208             for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4209               if (p->colormap == window_info[id].colormap)
4210                 break;
4211             if (p == (ColormapInfo *) NULL)
4212               {
4213                 /*
4214                   Get the window colormap.
4215                 */
4216                 colors=(XColor *) AcquireQuantumMemory(number_colors,
4217                   sizeof(*colors));
4218                 if (colors == (XColor *) NULL)
4219                   {
4220                     XDestroyImage(ximage);
4221                     return((Image *) NULL);
4222                   }
4223                 if ((window_info[id].visual->klass != DirectColor) &&
4224                     (window_info[id].visual->klass != TrueColor))
4225                   for (i=0; i < (int) number_colors; i++)
4226                   {
4227                     colors[i].pixel=(unsigned long) i;
4228                     colors[i].pad='\0';
4229                   }
4230                 else
4231                   {
4232                     unsigned long
4233                       blue,
4234                       blue_bit,
4235                       green,
4236                       green_bit,
4237                       red,
4238                       red_bit;
4239
4240                     /*
4241                       DirectColor or TrueColor visual.
4242                     */
4243                     red=0;
4244                     green=0;
4245                     blue=0;
4246                     red_bit=window_info[id].visual->red_mask &
4247                       (~(window_info[id].visual->red_mask)+1);
4248                     green_bit=window_info[id].visual->green_mask &
4249                       (~(window_info[id].visual->green_mask)+1);
4250                     blue_bit=window_info[id].visual->blue_mask &
4251                       (~(window_info[id].visual->blue_mask)+1);
4252                     for (i=0; i < (int) number_colors; i++)
4253                     {
4254                       colors[i].pixel=red | green | blue;
4255                       colors[i].pad='\0';
4256                       red+=red_bit;
4257                       if (red > window_info[id].visual->red_mask)
4258                         red=0;
4259                       green+=green_bit;
4260                       if (green > window_info[id].visual->green_mask)
4261                         green=0;
4262                       blue+=blue_bit;
4263                       if (blue > window_info[id].visual->blue_mask)
4264                         blue=0;
4265                     }
4266                   }
4267                 (void) XQueryColors(display,window_info[id].colormap,colors,
4268                   (int) number_colors);
4269                 /*
4270                   Append colormap to colormap list.
4271                 */
4272                 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
4273                 if (p == (ColormapInfo *) NULL)
4274                   return((Image *) NULL);
4275                 p->colormap=window_info[id].colormap;
4276                 p->colors=colors;
4277                 p->next=colormap_info;
4278                 colormap_info=p;
4279               }
4280             colors=p->colors;
4281           }
4282         /*
4283           Allocate image structure.
4284         */
4285         composite_image=AcquireImage((ImageInfo *) NULL);
4286         if (composite_image == (Image *) NULL)
4287           {
4288             XDestroyImage(ximage);
4289             return((Image *) NULL);
4290           }
4291         /*
4292           Convert X image to MIFF format.
4293         */
4294         if ((window_info[id].visual->klass != TrueColor) &&
4295             (window_info[id].visual->klass != DirectColor))
4296           composite_image->storage_class=PseudoClass;
4297         composite_image->columns=(unsigned long) ximage->width;
4298         composite_image->rows=(unsigned long) ximage->height;
4299         exception=(&composite_image->exception);
4300         switch (composite_image->storage_class)
4301         {
4302           case DirectClass:
4303           default:
4304           {
4305             register unsigned long
4306               color,
4307               index;
4308
4309             unsigned long
4310               blue_mask,
4311               blue_shift,
4312               green_mask,
4313               green_shift,
4314               red_mask,
4315               red_shift;
4316
4317             /*
4318               Determine shift and mask for red, green, and blue.
4319             */
4320             red_mask=window_info[id].visual->red_mask;
4321             red_shift=0;
4322             while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4323             {
4324               red_mask>>=1;
4325               red_shift++;
4326             }
4327             green_mask=window_info[id].visual->green_mask;
4328             green_shift=0;
4329             while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4330             {
4331               green_mask>>=1;
4332               green_shift++;
4333             }
4334             blue_mask=window_info[id].visual->blue_mask;
4335             blue_shift=0;
4336             while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4337             {
4338               blue_mask>>=1;
4339               blue_shift++;
4340             }
4341             /*
4342               Convert X image to DirectClass packets.
4343             */
4344             if ((number_colors != 0) &&
4345                 (window_info[id].visual->klass == DirectColor))
4346               for (y=0; y < (int) composite_image->rows; y++)
4347               {
4348                 q=QueueAuthenticPixels(composite_image,0,y,
4349                   composite_image->columns,1,exception);
4350                 if (q == (PixelPacket *) NULL)
4351                   break;
4352                 for (x=0; x < (int) composite_image->columns; x++)
4353                 {
4354                   pixel=XGetPixel(ximage,x,y);
4355                   index=(pixel >> red_shift) & red_mask;
4356                   q->red=ScaleShortToQuantum(colors[index].red);
4357                   index=(pixel >> green_shift) & green_mask;
4358                   q->green=ScaleShortToQuantum(colors[index].green);
4359                   index=(pixel >> blue_shift) & blue_mask;
4360                   q->blue=ScaleShortToQuantum(colors[index].blue);
4361                   q++;
4362                 }
4363                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
4364                   break;
4365               }
4366             else
4367               for (y=0; y < (int) composite_image->rows; y++)
4368               {
4369                 q=QueueAuthenticPixels(composite_image,0,y,
4370                   composite_image->columns,1,exception);
4371                 if (q == (PixelPacket *) NULL)
4372                   break;
4373                 for (x=0; x < (int) composite_image->columns; x++)
4374                 {
4375                   pixel=XGetPixel(ximage,x,y);
4376                   color=(pixel >> red_shift) & red_mask;
4377                   color=(65535UL*color)/red_mask;
4378                   q->red=ScaleShortToQuantum((unsigned short) color);
4379                   color=(pixel >> green_shift) & green_mask;
4380                   color=(65535UL*color)/green_mask;
4381                   q->green=ScaleShortToQuantum((unsigned short) color);
4382                   color=(pixel >> blue_shift) & blue_mask;
4383                   color=(65535UL*color)/blue_mask;
4384                   q->blue=ScaleShortToQuantum((unsigned short) color);
4385                   q++;
4386                 }
4387                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
4388                   break;
4389               }
4390             break;
4391           }
4392           case PseudoClass:
4393           {
4394             /*
4395               Create colormap.
4396             */
4397             if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4398               {
4399                 XDestroyImage(ximage);
4400                 composite_image=DestroyImage(composite_image);
4401                 return((Image *) NULL);
4402               }
4403             for (i=0; i < (int) composite_image->colors; i++)
4404             {
4405               composite_image->colormap[colors[i].pixel].red=
4406                 ScaleShortToQuantum(colors[i].red);
4407               composite_image->colormap[colors[i].pixel].green=
4408                 ScaleShortToQuantum(colors[i].green);
4409               composite_image->colormap[colors[i].pixel].blue=
4410                 ScaleShortToQuantum(colors[i].blue);
4411             }
4412             /*
4413               Convert X image to PseudoClass packets.
4414             */
4415             for (y=0; y < (int) composite_image->rows; y++)
4416             {
4417               q=QueueAuthenticPixels(composite_image,0,y,composite_image->columns,1,exception);
4418               if (q == (PixelPacket *) NULL)
4419                 break;
4420               indexes=GetAuthenticIndexQueue(composite_image);
4421               for (x=0; x < (int) composite_image->columns; x++)
4422               {
4423                 index=(IndexPacket) XGetPixel(ximage,x,y);
4424                 indexes[x]=index;
4425                 *q++=composite_image->colormap[(long) index];
4426               }
4427               if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
4428                 break;
4429             }
4430             break;
4431           }
4432         }
4433         XDestroyImage(ximage);
4434         if (image == (Image *) NULL)
4435           {
4436             image=composite_image;
4437             continue;
4438           }
4439         /*
4440           Composite any children in back-to-front order.
4441         */
4442         (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4443           &x_offset,&y_offset,&child);
4444         x_offset-=(int) crop_info.x;
4445         if (x_offset < 0)
4446           x_offset=0;
4447         y_offset-=(int) crop_info.y;
4448         if (y_offset < 0)
4449           y_offset=0;
4450         (void) CompositeImage(image,CopyCompositeOp,composite_image,x_offset,
4451           y_offset);
4452       }
4453       /*
4454         Relinquish resources.
4455       */
4456       while (colormap_info != (ColormapInfo *) NULL)
4457       {
4458         next=colormap_info->next;
4459         colormap_info->colors=(XColor *)
4460           RelinquishMagickMemory(colormap_info->colors);
4461         colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4462         colormap_info=next;
4463       }
4464       /*
4465         Relinquish resources and restore initial state.
4466       */
4467       window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4468       max_windows=0;
4469       number_windows=0;
4470       colormap_info=(ColormapInfo *) NULL;
4471       return(image);
4472     }
4473   return((Image *) NULL);
4474 }
4475 \f
4476 /*
4477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4478 %                                                                             %
4479 %                                                                             %
4480 %                                                                             %
4481 %   X G e t W i n d o w I n f o                                               %
4482 %                                                                             %
4483 %                                                                             %
4484 %                                                                             %
4485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4486 %
4487 %  XGetWindowInfo() initializes the XWindowInfo structure.
4488 %
4489 %  The format of the XGetWindowInfo method is:
4490 %
4491 %      void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4492 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4493 %        XResourceInfo *resource_info,XWindowInfo *window)
4494 %        resource_info,window)
4495 %
4496 %  A description of each parameter follows:
4497 %
4498 %    o display: Specifies a connection to an X server; returned from
4499 %      XOpenDisplay.
4500 %
4501 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4502 %      returned from XGetVisualInfo.
4503 %
4504 %    o map_info: If map_type is specified, this structure is initialized
4505 %      with info from the Standard Colormap.
4506 %
4507 %    o pixel: Specifies a pointer to a XPixelInfo structure.
4508 %
4509 %    o font_info: Specifies a pointer to a XFontStruct structure.
4510 %
4511 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4512 %
4513 */
4514 MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4515   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4516   XResourceInfo *resource_info,XWindowInfo *window)
4517 {
4518   /*
4519     Initialize window info.
4520   */
4521   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4522   assert(display != (Display *) NULL);
4523   assert(visual_info != (XVisualInfo *) NULL);
4524   assert(map_info != (XStandardColormap *) NULL);
4525   assert(pixel != (XPixelInfo *) NULL);
4526   assert(resource_info != (XResourceInfo *) NULL);
4527   assert(window != (XWindowInfo *) NULL);
4528   if (window->id != (Window) NULL)
4529     {
4530       if (window->cursor != (Cursor) NULL)
4531         (void) XFreeCursor(display,window->cursor);
4532       if (window->busy_cursor != (Cursor) NULL)
4533         (void) XFreeCursor(display,window->busy_cursor);
4534       if (window->highlight_stipple != (Pixmap) NULL)
4535         (void) XFreePixmap(display,window->highlight_stipple);
4536       if (window->shadow_stipple != (Pixmap) NULL)
4537         (void) XFreePixmap(display,window->shadow_stipple);
4538       if (window->name == (char *) NULL)
4539         window->name=AcquireString("");
4540       if (window->icon_name == (char *) NULL)
4541         window->icon_name=AcquireString("");
4542     }
4543   else
4544     {
4545       /*
4546         Initialize these attributes just once.
4547       */
4548       window->id=(Window) NULL;
4549       if (window->name == (char *) NULL)
4550         window->name=AcquireString("");
4551       if (window->icon_name == (char *) NULL)
4552         window->icon_name=AcquireString("");
4553       window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4554       window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4555       window->ximage=(XImage *) NULL;
4556       window->matte_image=(XImage *) NULL;
4557       window->pixmap=(Pixmap) NULL;
4558       window->matte_pixmap=(Pixmap) NULL;
4559       window->mapped=MagickFalse;
4560       window->stasis=MagickFalse;
4561       window->shared_memory=MagickTrue;
4562       window->segment_info=(void *) NULL;
4563 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4564       {
4565         XShmSegmentInfo
4566           *segment_info;
4567
4568         if (window->segment_info == (void *) NULL)
4569           window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4570         segment_info=(XShmSegmentInfo *) window->segment_info;
4571         segment_info[0].shmid=(-1);
4572         segment_info[0].shmaddr=(char *) NULL;
4573         segment_info[1].shmid=(-1);
4574         segment_info[1].shmaddr=(char *) NULL;
4575       }
4576 #endif
4577     }
4578   /*
4579     Initialize these attributes every time function is called.
4580   */
4581   window->screen=visual_info->screen;
4582   window->root=XRootWindow(display,visual_info->screen);
4583   window->visual=visual_info->visual;
4584   window->storage_class=(unsigned int) visual_info->klass;
4585   window->depth=(unsigned int) visual_info->depth;
4586   window->visual_info=visual_info;
4587   window->map_info=map_info;
4588   window->pixel_info=pixel;
4589   window->font_info=font_info;
4590   window->cursor=XCreateFontCursor(display,XC_left_ptr);
4591   window->busy_cursor=XCreateFontCursor(display,XC_watch);
4592   window->geometry=(char *) NULL;
4593   window->icon_geometry=(char *) NULL;
4594   if (resource_info->icon_geometry != (char *) NULL)
4595     (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4596   window->crop_geometry=(char *) NULL;
4597   window->flags=(unsigned long) PSize;
4598   window->width=1;
4599   window->height=1;
4600   window->min_width=1;
4601   window->min_height=1;
4602   window->width_inc=1;
4603   window->height_inc=1;
4604   window->border_width=resource_info->border_width;
4605   window->annotate_context=pixel->annotate_context;
4606   window->highlight_context=pixel->highlight_context;
4607   window->widget_context=pixel->widget_context;
4608   window->shadow_stipple=(Pixmap) NULL;
4609   window->highlight_stipple=(Pixmap) NULL;
4610   window->use_pixmap=MagickTrue;
4611   window->immutable=MagickFalse;
4612   window->shape=MagickFalse;
4613   window->data=0;
4614   window->mask=(unsigned long) (CWBackingStore | CWBackPixel | CWBackPixmap |
4615     CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4616     CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4617   window->attributes.background_pixel=pixel->background_color.pixel;
4618   window->attributes.background_pixmap=(Pixmap) NULL;
4619   window->attributes.bit_gravity=ForgetGravity;
4620   window->attributes.backing_store=WhenMapped;
4621   window->attributes.save_under=MagickTrue;
4622   window->attributes.border_pixel=pixel->border_color.pixel;
4623   window->attributes.colormap=map_info->colormap;
4624   window->attributes.cursor=window->cursor;
4625   window->attributes.do_not_propagate_mask=NoEventMask;
4626   window->attributes.event_mask=NoEventMask;
4627   window->attributes.override_redirect=MagickFalse;
4628   window->attributes.win_gravity=NorthWestGravity;
4629   window->orphan=MagickFalse;
4630 }
4631 \f
4632 /*
4633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4634 %                                                                             %
4635 %                                                                             %
4636 %                                                                             %
4637 %   X H i g h l i g h t E l l i p s e                                         %
4638 %                                                                             %
4639 %                                                                             %
4640 %                                                                             %
4641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4642 %
4643 %  XHighlightEllipse() puts a border on the X server around a region defined by
4644 %  highlight_info.
4645 %
4646 %  The format of the XHighlightEllipse method is:
4647 %
4648 %      void XHighlightEllipse(Display *display,Window window,
4649 %        GC annotate_context,const RectangleInfo *highlight_info)
4650 %
4651 %  A description of each parameter follows:
4652 %
4653 %    o display: Specifies a connection to an X server; returned from
4654 %      XOpenDisplay.
4655 %
4656 %    o window: Specifies a pointer to a Window structure.
4657 %
4658 %    o annotate_context: Specifies a pointer to a GC structure.
4659 %
4660 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4661 %      contains the extents of any highlighting rectangle.
4662 %
4663 */
4664 MagickExport void XHighlightEllipse(Display *display,Window window,
4665   GC annotate_context,const RectangleInfo *highlight_info)
4666 {
4667   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4668   assert(display != (Display *) NULL);
4669   assert(window != (Window) NULL);
4670   assert(annotate_context != (GC) NULL);
4671   assert(highlight_info != (RectangleInfo *) NULL);
4672   if ((highlight_info->width < 4) || (highlight_info->height < 4))
4673     return;
4674   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4675     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4676     (unsigned int) highlight_info->height-1,0,360*64);
4677   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4678     (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4679     (unsigned int) highlight_info->height-3,0,360*64);
4680 }
4681 \f
4682 /*
4683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4684 %                                                                             %
4685 %                                                                             %
4686 %                                                                             %
4687 %   X H i g h l i g h t L i n e                                               %
4688 %                                                                             %
4689 %                                                                             %
4690 %                                                                             %
4691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4692 %
4693 %  XHighlightLine() puts a border on the X server around a region defined by
4694 %  highlight_info.
4695 %
4696 %  The format of the XHighlightLine method is:
4697 %
4698 %      void XHighlightLine(Display *display,Window window,GC annotate_context,
4699 %        const XSegment *highlight_info)
4700 %
4701 %  A description of each parameter follows:
4702 %
4703 %    o display: Specifies a connection to an X server; returned from
4704 %      XOpenDisplay.
4705 %
4706 %    o window: Specifies a pointer to a Window structure.
4707 %
4708 %    o annotate_context: Specifies a pointer to a GC structure.
4709 %
4710 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4711 %      contains the extents of any highlighting rectangle.
4712 %
4713 */
4714 MagickExport void XHighlightLine(Display *display,Window window,
4715   GC annotate_context,const XSegment *highlight_info)
4716 {
4717   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4718   assert(display != (Display *) NULL);
4719   assert(window != (Window) NULL);
4720   assert(annotate_context != (GC) NULL);
4721   assert(highlight_info != (XSegment *) NULL);
4722   (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4723     highlight_info->y1,highlight_info->x2,highlight_info->y2);
4724 }
4725 \f
4726 /*
4727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4728 %                                                                             %
4729 %                                                                             %
4730 %                                                                             %
4731 %   X H i g h l i g h t R e c t a n g l e                                     %
4732 %                                                                             %
4733 %                                                                             %
4734 %                                                                             %
4735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4736 %
4737 %  XHighlightRectangle() puts a border on the X server around a region defined
4738 %  by highlight_info.
4739 %
4740 %  The format of the XHighlightRectangle method is:
4741 %
4742 %      void XHighlightRectangle(Display *display,Window window,
4743 %        GC annotate_context,const RectangleInfo *highlight_info)
4744 %
4745 %  A description of each parameter follows:
4746 %
4747 %    o display: Specifies a connection to an X server; returned from
4748 %      XOpenDisplay.
4749 %
4750 %    o window: Specifies a pointer to a Window structure.
4751 %
4752 %    o annotate_context: Specifies a pointer to a GC structure.
4753 %
4754 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
4755 %      contains the extents of any highlighting rectangle.
4756 %
4757 */
4758 MagickExport void XHighlightRectangle(Display *display,Window window,
4759   GC annotate_context,const RectangleInfo *highlight_info)
4760 {
4761   assert(display != (Display *) NULL);
4762   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4763   assert(window != (Window) NULL);
4764   assert(annotate_context != (GC) NULL);
4765   assert(highlight_info != (RectangleInfo *) NULL);
4766   if ((highlight_info->width < 4) || (highlight_info->height < 4))
4767     return;
4768   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4769     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4770     (unsigned int) highlight_info->height-1);
4771   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4772     1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4773     (unsigned int) highlight_info->height-3);
4774 }
4775 \f
4776 /*
4777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4778 %                                                                             %
4779 %                                                                             %
4780 %                                                                             %
4781 %   X I m p o r t I m a g e                                                   %
4782 %                                                                             %
4783 %                                                                             %
4784 %                                                                             %
4785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4786 %
4787 %  XImportImage() reads an image from an X window.
4788 %
4789 %  The format of the XImportImage method is:
4790 %
4791 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4792 %
4793 %  A description of each parameter follows:
4794 %
4795 %    o image_info: the image info.
4796 %
4797 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
4798 %
4799 */
4800 MagickExport Image *XImportImage(const ImageInfo *image_info,
4801   XImportInfo *ximage_info)
4802 {
4803   Colormap
4804     *colormaps;
4805
4806   Display
4807     *display;
4808
4809   Image
4810     *image;
4811
4812   int
4813     number_colormaps,
4814     number_windows,
4815     x;
4816
4817   RectangleInfo
4818     crop_info;
4819
4820   Status
4821     status;
4822
4823   Window
4824     *children,
4825     client,
4826     prior_target,
4827     root,
4828     target;
4829
4830   XTextProperty
4831     window_name;
4832
4833   /*
4834     Open X server connection.
4835   */
4836   assert(image_info != (const ImageInfo *) NULL);
4837   assert(image_info->signature == MagickSignature);
4838   if (image_info->debug != MagickFalse)
4839     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4840       image_info->filename);
4841   assert(ximage_info != (XImportInfo *) NULL);
4842   display=XOpenDisplay(image_info->server_name);
4843   if (display == (Display *) NULL)
4844     {
4845       ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4846         XDisplayName(image_info->server_name));
4847       return((Image *) NULL);
4848     }
4849   /*
4850     Set our forgiving exception handler.
4851   */
4852   (void) XSetErrorHandler(XError);
4853   /*
4854     Select target window.
4855   */
4856   crop_info.x=0;
4857   crop_info.y=0;
4858   crop_info.width=0;
4859   crop_info.height=0;
4860   root=XRootWindow(display,XDefaultScreen(display));
4861   target=(Window) NULL;
4862   if ((image_info->filename != (char *) NULL) &&
4863       (*image_info->filename != '\0'))
4864     {
4865       if (LocaleCompare(image_info->filename,"root") == 0)
4866         target=root;
4867       else
4868         {
4869           /*
4870             Select window by ID or name.
4871           */
4872           if (isdigit((unsigned char) *image_info->filename) != 0)
4873             target=XWindowByID(display,root,(Window)
4874               strtol(image_info->filename,(char **) NULL,0));
4875           if (target == (Window) NULL)
4876             target=XWindowByName(display,root,image_info->filename);
4877           if (target == (Window) NULL)
4878             ThrowXWindowFatalException(XServerError,
4879               "NoWindowWithSpecifiedIDExists",image_info->filename);
4880         }
4881     }
4882   /*
4883     If target window is not defined, interactively select one.
4884   */
4885   prior_target=target;
4886   if (target == (Window) NULL)
4887     target=XSelectWindow(display,&crop_info);
4888   if (target == (Window) NULL)
4889     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4890       image_info->filename);
4891   client=target;   /* obsolete */
4892   if (target != root)
4893     {
4894       unsigned int
4895         d;
4896
4897       status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4898       if (status != False)
4899         {
4900           for ( ; ; )
4901           {
4902             Window
4903               parent;
4904
4905             /*
4906               Find window manager frame.
4907             */
4908             status=XQueryTree(display,target,&root,&parent,&children,&d);
4909             if ((status != False) && (children != (Window *) NULL))
4910               (void) XFree((char *) children);
4911             if ((status == False) || (parent == (Window) NULL) ||
4912                 (parent == root))
4913               break;
4914             target=parent;
4915           }
4916           /*
4917             Get client window.
4918           */
4919           client=XClientWindow(display,target);
4920           if (ximage_info->frame == MagickFalse)
4921             target=client;
4922           if ((ximage_info->frame == MagickFalse) &&
4923               (prior_target != MagickFalse))
4924             target=prior_target;
4925           XDelay(display,SuspendTime << 4);
4926         }
4927     }
4928   if (ximage_info->screen)
4929     {
4930       int
4931         y;
4932
4933       Window
4934         child;
4935
4936       XWindowAttributes
4937         window_attributes;
4938
4939       /*
4940         Obtain window image directly from screen.
4941       */
4942       status=XGetWindowAttributes(display,target,&window_attributes);
4943       if (status == False)
4944         {
4945           ThrowXWindowFatalException(XServerError,
4946             "UnableToReadXWindowAttributes",image_info->filename);
4947           (void) XCloseDisplay(display);
4948           return((Image *) NULL);
4949         }
4950       (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
4951       crop_info.x=x;
4952       crop_info.y=y;
4953       crop_info.width=(unsigned long) window_attributes.width;
4954       crop_info.height=(unsigned long) window_attributes.height;
4955       if (ximage_info->borders)
4956         {
4957           /*
4958             Include border in image.
4959           */
4960           crop_info.x-=window_attributes.border_width;
4961           crop_info.y-=window_attributes.border_width;
4962           crop_info.width+=window_attributes.border_width << 1;
4963           crop_info.height+=window_attributes.border_width << 1;
4964         }
4965       target=root;
4966     }
4967   /*
4968     If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
4969   */
4970   number_windows=0;
4971   status=XGetWMColormapWindows(display,target,&children,&number_windows);
4972   if ((status == True) && (number_windows > 0))
4973     {
4974       ximage_info->descend=MagickTrue;
4975       (void) XFree ((char *) children);
4976     }
4977   colormaps=XListInstalledColormaps(display,target,&number_colormaps);
4978   if (number_colormaps > 0)
4979     {
4980       if (number_colormaps > 1)
4981         ximage_info->descend=MagickTrue;
4982       (void) XFree((char *) colormaps);
4983     }
4984   /*
4985     Alert the user not to alter the screen.
4986   */
4987   if (ximage_info->silent == MagickFalse)
4988     (void) XBell(display,0);
4989   /*
4990     Get image by window id.
4991   */
4992   (void) XGrabServer(display);
4993   image=XGetWindowImage(display,target,ximage_info->borders,
4994     ximage_info->descend ? 1U : 0U);
4995   (void) XUngrabServer(display);
4996   if (image == (Image *) NULL)
4997     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4998       image_info->filename)
4999   else
5000     {
5001       (void) CopyMagickString(image->filename,image_info->filename,
5002         MaxTextExtent);
5003       if ((crop_info.width != 0) && (crop_info.height != 0))
5004         {
5005           Image
5006             *clone_image,
5007             *crop_image;
5008
5009           /*
5010             Crop image as defined by the cropping rectangle.
5011           */
5012           clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5013           if (clone_image != (Image *) NULL)
5014             {
5015               crop_image=CropImage(clone_image,&crop_info,&image->exception);
5016               if (crop_image != (Image *) NULL)
5017                 {
5018                   image=DestroyImage(image);
5019                   image=crop_image;
5020                 }
5021             }
5022         }
5023       status=XGetWMName(display,target,&window_name);
5024       if (status == True)
5025         {
5026           if ((image_info->filename != (char *) NULL) &&
5027               (*image_info->filename == '\0'))
5028             (void) CopyMagickString(image->filename,(char *) window_name.value,
5029               (size_t) window_name.nitems+1);
5030           (void) XFree((void *) window_name.value);
5031         }
5032     }
5033   if (ximage_info->silent == MagickFalse)
5034     {
5035       /*
5036         Alert the user we're done.
5037       */
5038       (void) XBell(display,0);
5039       (void) XBell(display,0);
5040     }
5041   (void) XCloseDisplay(display);
5042   return(image);
5043 }
5044 \f
5045 /*
5046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5047 %                                                                             %
5048 %                                                                             %
5049 %                                                                             %
5050 %   X I n i t i a l i z e W i n d o w s                                       %
5051 %                                                                             %
5052 %                                                                             %
5053 %                                                                             %
5054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5055 %
5056 %  XInitializeWindows() initializes the XWindows structure.
5057 %
5058 %  The format of the XInitializeWindows method is:
5059 %
5060 %      XWindows *XInitializeWindows(Display *display,
5061 %        XResourceInfo *resource_info)
5062 %
5063 %  A description of each parameter follows:
5064 %
5065 %    o windows: XInitializeWindows returns a pointer to a XWindows structure.
5066 %
5067 %    o display: Specifies a connection to an X server;  returned from
5068 %      XOpenDisplay.
5069 %
5070 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5071 %
5072 */
5073 MagickExport XWindows *XInitializeWindows(Display *display,
5074   XResourceInfo *resource_info)
5075 {
5076   Window
5077     root_window;
5078
5079   XWindows
5080     *windows;
5081
5082   /*
5083     Allocate windows structure.
5084   */
5085   windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
5086   if (windows == (XWindows *) NULL)
5087     {
5088       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5089         "...");
5090       return((XWindows *) NULL);
5091     }
5092   (void) ResetMagickMemory(windows,0,sizeof(*windows));
5093   windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5094     sizeof(*windows->pixel_info));
5095   windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5096     sizeof(*windows->icon_pixel));
5097   windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5098     sizeof(*windows->icon_resources));
5099   if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5100       (windows->icon_pixel == (XPixelInfo *) NULL) ||
5101       (windows->icon_resources == (XResourceInfo *) NULL))
5102     {
5103       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5104         "...");
5105       return((XWindows *) NULL);
5106     }
5107   /*
5108     Initialize windows structure.
5109   */
5110   windows->display=display;
5111   windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5112   windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5113   windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5114   windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5115   windows->im_remote_command=
5116     XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5117   windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5118   windows->im_update_colormap=
5119     XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5120   windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5121   windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5122   windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5123   windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5124   windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
5125 #if defined(__WINDOWS__)
5126   (void) XSynchronize(display,IsWindows95());
5127 #endif
5128   if (IsEventLogging())
5129     {
5130       (void) XSynchronize(display,MagickTrue);
5131       (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
5132         GetMagickVersion((unsigned long *) NULL));
5133       (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5134       (void) LogMagickEvent(X11Event,GetMagickModule(),
5135         "  Window Manager: 0x%lx",windows->wm_protocols);
5136       (void) LogMagickEvent(X11Event,GetMagickModule(),
5137         "    delete window: 0x%lx",windows->wm_delete_window);
5138       (void) LogMagickEvent(X11Event,GetMagickModule(),"    take focus: 0x%lx",
5139         windows->wm_take_focus);
5140       (void) LogMagickEvent(X11Event,GetMagickModule(),"  ImageMagick: 0x%lx",
5141         windows->im_protocols);
5142       (void) LogMagickEvent(X11Event,GetMagickModule(),
5143         "    remote command: 0x%lx",windows->im_remote_command);
5144       (void) LogMagickEvent(X11Event,GetMagickModule(),
5145         "    update widget: 0x%lx",windows->im_update_widget);
5146       (void) LogMagickEvent(X11Event,GetMagickModule(),
5147         "    update colormap: 0x%lx",windows->im_update_colormap);
5148       (void) LogMagickEvent(X11Event,GetMagickModule(),
5149         "    former image: 0x%lx",windows->im_former_image);
5150       (void) LogMagickEvent(X11Event,GetMagickModule(),"    next image: 0x%lx",
5151         windows->im_next_image);
5152       (void) LogMagickEvent(X11Event,GetMagickModule(),
5153         "    retain colors: 0x%lx",windows->im_retain_colors);
5154       (void) LogMagickEvent(X11Event,GetMagickModule(),"    exit: 0x%lx",
5155         windows->im_exit);
5156       (void) LogMagickEvent(X11Event,GetMagickModule(),"  Drag and Drop: 0x%lx",
5157         windows->dnd_protocols);
5158     }
5159   /*
5160     Allocate standard colormap.
5161   */
5162   windows->map_info=XAllocStandardColormap();
5163   windows->icon_map=XAllocStandardColormap();
5164   if ((windows->map_info == (XStandardColormap *) NULL) ||
5165       (windows->icon_map == (XStandardColormap *) NULL))
5166     ThrowXWindowFatalException(ResourceLimitFatalError,
5167       "MemoryAllocationFailed","...");
5168   windows->map_info->colormap=(Colormap) NULL;
5169   windows->icon_map->colormap=(Colormap) NULL;
5170   windows->pixel_info->pixels=(unsigned long *) NULL;
5171   windows->pixel_info->annotate_context=(GC) NULL;
5172   windows->pixel_info->highlight_context=(GC) NULL;
5173   windows->pixel_info->widget_context=(GC) NULL;
5174   windows->font_info=(XFontStruct *) NULL;
5175   windows->icon_pixel->annotate_context=(GC) NULL;
5176   windows->icon_pixel->pixels=(unsigned long *) NULL;
5177   /*
5178     Allocate visual.
5179   */
5180   *windows->icon_resources=(*resource_info);
5181   windows->icon_resources->visual_type=(char *) "default";
5182   windows->icon_resources->colormap=SharedColormap;
5183   windows->visual_info=
5184     XBestVisualInfo(display,windows->map_info,resource_info);
5185   windows->icon_visual=
5186     XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5187   if ((windows->visual_info == (XVisualInfo *) NULL) ||
5188       (windows->icon_visual == (XVisualInfo *) NULL))
5189     ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5190       resource_info->visual_type);
5191   if (IsEventLogging())
5192     {
5193       (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5194       (void) LogMagickEvent(X11Event,GetMagickModule(),"  visual id: 0x%lx",
5195         windows->visual_info->visualid);
5196       (void) LogMagickEvent(X11Event,GetMagickModule(),"  class: %s",
5197         XVisualClassName(windows->visual_info->klass));
5198       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d planes",
5199         windows->visual_info->depth);
5200       (void) LogMagickEvent(X11Event,GetMagickModule(),
5201         "  size of colormap: %d entries",windows->visual_info->colormap_size);
5202       (void) LogMagickEvent(X11Event,GetMagickModule(),
5203         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5204         windows->visual_info->red_mask,windows->visual_info->green_mask,
5205         windows->visual_info->blue_mask);
5206       (void) LogMagickEvent(X11Event,GetMagickModule(),
5207         "  significant bits in color: %d bits",
5208         windows->visual_info->bits_per_rgb);
5209     }
5210   /*
5211     Allocate class and manager hints.
5212   */
5213   windows->class_hints=XAllocClassHint();
5214   windows->manager_hints=XAllocWMHints();
5215   if ((windows->class_hints == (XClassHint *) NULL) ||
5216       (windows->manager_hints == (XWMHints *) NULL))
5217     ThrowXWindowFatalException(ResourceLimitFatalError,
5218       "MemoryAllocationFailed","...");
5219   /*
5220     Determine group leader if we have one.
5221   */
5222   root_window=XRootWindow(display,windows->visual_info->screen);
5223   windows->group_leader.id=(Window) NULL;
5224   if (resource_info->window_group != (char *) NULL)
5225     {
5226       if (isdigit((unsigned char) *resource_info->window_group) != 0)
5227         windows->group_leader.id=XWindowByID(display,root_window,(Window)
5228           strtol((char *) resource_info->window_group,(char **) NULL,0));
5229       if (windows->group_leader.id == (Window) NULL)
5230         windows->group_leader.id=
5231           XWindowByName(display,root_window,resource_info->window_group);
5232     }
5233   return(windows);
5234 }
5235 \f
5236 /*
5237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5238 %                                                                             %
5239 %                                                                             %
5240 %                                                                             %
5241 %   X M a k e C u r s o r                                                     %
5242 %                                                                             %
5243 %                                                                             %
5244 %                                                                             %
5245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5246 %
5247 %  XMakeCursor() creates a crosshairs X11 cursor.
5248 %
5249 %  The format of the XMakeCursor method is:
5250 %
5251 %      Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5252 %        char *background_color,char *foreground_color)
5253 %
5254 %  A description of each parameter follows:
5255 %
5256 %    o display: Specifies a connection to an X server;  returned from
5257 %      XOpenDisplay.
5258 %
5259 %    o window: Specifies the ID of the window for which the cursor is
5260 %      assigned.
5261 %
5262 %    o colormap: Specifies the ID of the colormap from which the background
5263 %      and foreground color will be retrieved.
5264 %
5265 %    o background_color: Specifies the color to use for the cursor background.
5266 %
5267 %    o foreground_color: Specifies the color to use for the cursor foreground.
5268 %
5269 */
5270 MagickExport Cursor XMakeCursor(Display *display,Window window,
5271   Colormap colormap,char *background_color,char *foreground_color)
5272 {
5273 #define scope_height 17
5274 #define scope_x_hot 8
5275 #define scope_y_hot 8
5276 #define scope_width 17
5277
5278   static const unsigned char
5279     scope_bits[] =
5280     {
5281       0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5282       0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5283       0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5284       0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5285       0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5286     },
5287     scope_mask_bits[] =
5288     {
5289       0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5290       0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5291       0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5292       0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5293       0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5294     };
5295
5296   Cursor
5297     cursor;
5298
5299   Pixmap
5300     mask,
5301     source;
5302
5303   XColor
5304     background,
5305     foreground;
5306
5307   assert(display != (Display *) NULL);
5308   assert(window != (Window) NULL);
5309   assert(colormap != (Colormap) NULL);
5310   assert(background_color != (char *) NULL);
5311   assert(foreground_color != (char *) NULL);
5312   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5313   source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5314     scope_height);
5315   mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5316     scope_width,scope_height);
5317   if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5318     {
5319       ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5320       return((Cursor) NULL);
5321     }
5322   (void) XParseColor(display,colormap,background_color,&background);
5323   (void) XParseColor(display,colormap,foreground_color,&foreground);
5324   cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5325     scope_x_hot,scope_y_hot);
5326   (void) XFreePixmap(display,source);
5327   (void) XFreePixmap(display,mask);
5328   return(cursor);
5329 }
5330 \f
5331 /*
5332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5333 %                                                                             %
5334 %                                                                             %
5335 %                                                                             %
5336 %   X M a k e I m a g e                                                       %
5337 %                                                                             %
5338 %                                                                             %
5339 %                                                                             %
5340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5341 %
5342 %  XMakeImage() creates an X11 image.  If the image size differs from the X11
5343 %  image size, the image is first resized.
5344 %
5345 %  The format of the XMakeImage method is:
5346 %
5347 %      MagickBooleanType XMakeImage(Display *display,
5348 %        const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5349 %        unsigned int width,unsigned int height)
5350 %
5351 %  A description of each parameter follows:
5352 %
5353 %    o display: Specifies a connection to an X server; returned from
5354 %      XOpenDisplay.
5355 %
5356 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5357 %
5358 %    o window: Specifies a pointer to a XWindowInfo structure.
5359 %
5360 %    o image: the image.
5361 %
5362 %    o width: Specifies the width in pixels of the rectangular area to
5363 %      display.
5364 %
5365 %    o height: Specifies the height in pixels of the rectangular area to
5366 %      display.
5367 %
5368 */
5369 MagickExport MagickBooleanType XMakeImage(Display *display,
5370   const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5371   unsigned int width,unsigned int height)
5372 {
5373 #define CheckOverflowException(length,width,height) \
5374   (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5375
5376   int
5377     depth,
5378     format;
5379
5380   size_t
5381     length;
5382
5383   XImage
5384     *matte_image,
5385     *ximage;
5386
5387   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5388   assert(display != (Display *) NULL);
5389   assert(resource_info != (XResourceInfo *) NULL);
5390   assert(window != (XWindowInfo *) NULL);
5391   assert(width != 0);
5392   assert(height != 0);
5393   if ((window->width == 0) || (window->height == 0))
5394     return(MagickFalse);
5395   /*
5396     Apply user transforms to the image.
5397   */
5398   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5399   (void) XFlush(display);
5400   depth=(int) window->depth;
5401   if (window->destroy)
5402     window->image=DestroyImage(window->image);
5403   window->image=image;
5404   window->destroy=MagickFalse;
5405   if (window->image != (Image *) NULL)
5406     {
5407       if (window->crop_geometry != (char *) NULL)
5408         {
5409           Image
5410             *crop_image;
5411
5412           RectangleInfo
5413             crop_info;
5414
5415           /*
5416             Crop image.
5417           */
5418           window->image->page.x=0;
5419           window->image->page.y=0;
5420           (void) ParsePageGeometry(window->image,window->crop_geometry,
5421             &crop_info,&image->exception);
5422           crop_image=CropImage(window->image,&crop_info,&image->exception);
5423           if (crop_image != (Image *) NULL)
5424             {
5425               if (window->image != image)
5426                 window->image=DestroyImage(window->image);
5427               window->image=crop_image;
5428               window->destroy=MagickTrue;
5429             }
5430         }
5431       if ((width != (unsigned int) window->image->columns) ||
5432           (height != (unsigned int) window->image->rows))
5433         {
5434           Image
5435             *resize_image;
5436
5437           /*
5438             Resize image.
5439           */
5440           resize_image=NewImageList();
5441           if (window->pixel_info->colors != 0)
5442             resize_image=SampleImage(window->image,width,height,
5443               &image->exception);
5444           else
5445             resize_image=ThumbnailImage(window->image,width,height,
5446               &image->exception);
5447           if (resize_image != (Image *) NULL)
5448             {
5449               if (window->image != image)
5450                 window->image=DestroyImage(window->image);
5451               window->image=resize_image;
5452               window->destroy=MagickTrue;
5453             }
5454         }
5455       width=(unsigned int) window->image->columns;
5456       assert(width == window->image->columns);
5457       height=(unsigned int) window->image->rows;
5458       assert(height == window->image->rows);
5459     }
5460   /*
5461     Create X image.
5462   */
5463   ximage=(XImage *) NULL;
5464   format=(depth == 1) ? XYBitmap : ZPixmap;
5465 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5466   if (window->shared_memory != MagickFalse)
5467     {
5468       XShmSegmentInfo
5469         *segment_info;
5470
5471       segment_info=(XShmSegmentInfo *) window->segment_info;
5472       segment_info[1].shmid=(-1);
5473       segment_info[1].shmaddr=(char *) NULL;
5474       ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5475         (char *) NULL,&segment_info[1],width,height);
5476       if (ximage == (XImage *) NULL)
5477         window->shared_memory=MagickFalse;
5478       length=(size_t) ximage->bytes_per_line*ximage->height;
5479       if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5480         window->shared_memory=MagickFalse;
5481       if (window->shared_memory != MagickFalse)
5482         segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5483       if (window->shared_memory != MagickFalse)
5484         segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5485       if (segment_info[1].shmid < 0)
5486         window->shared_memory=MagickFalse;
5487       if (window->shared_memory != MagickFalse)
5488         (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5489       else
5490         {
5491           if (ximage != (XImage *) NULL)
5492             XDestroyImage(ximage);
5493           ximage=(XImage *) NULL;
5494           if (segment_info[1].shmaddr)
5495             {
5496               (void) shmdt(segment_info[1].shmaddr);
5497               segment_info[1].shmaddr=(char *) NULL;
5498             }
5499           if (segment_info[1].shmid >= 0)
5500             {
5501               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5502               segment_info[1].shmid=(-1);
5503             }
5504         }
5505     }
5506 #endif
5507   /*
5508     Allocate X image pixel data.
5509   */
5510 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5511   if (window->shared_memory)
5512     {
5513       Status
5514         status;
5515
5516       XShmSegmentInfo
5517         *segment_info;
5518
5519       (void) XSync(display,MagickFalse);
5520       xerror_alert=MagickFalse;
5521       segment_info=(XShmSegmentInfo *) window->segment_info;
5522       ximage->data=segment_info[1].shmaddr;
5523       segment_info[1].readOnly=MagickFalse;
5524       status=XShmAttach(display,&segment_info[1]);
5525       if (status != False)
5526         (void) XSync(display,MagickFalse);
5527       if ((status == False) || (xerror_alert != MagickFalse))
5528         {
5529           window->shared_memory=MagickFalse;
5530           if (status != False)
5531             XShmDetach(display,&segment_info[1]);
5532           if (ximage != (XImage *) NULL)
5533             {
5534               ximage->data=NULL;
5535               XDestroyImage(ximage);
5536               ximage=(XImage *) NULL;
5537             }
5538           if (segment_info[1].shmid >= 0)
5539             {
5540               if (segment_info[1].shmaddr != NULL)
5541                 (void) shmdt(segment_info[1].shmaddr);
5542               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5543               segment_info[1].shmid=(-1);
5544               segment_info[1].shmaddr=(char *) NULL;
5545             }
5546         }
5547     }
5548 #endif
5549   if (window->shared_memory == MagickFalse)
5550     ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5551       (char *) NULL,width,height,XBitmapPad(display),0);
5552   if (ximage == (XImage *) NULL)
5553     {
5554       /*
5555         Unable to create X image.
5556       */
5557       (void) XCheckDefineCursor(display,window->id,window->cursor);
5558       return(MagickFalse);
5559     }
5560   length=(size_t) ximage->bytes_per_line*ximage->height;
5561   if (IsEventLogging())
5562     {
5563       (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5564       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %dx%d",
5565         ximage->width,ximage->height);
5566       (void) LogMagickEvent(X11Event,GetMagickModule(),"  format: %d",
5567         ximage->format);
5568       (void) LogMagickEvent(X11Event,GetMagickModule(),"  byte order: %d",
5569         ximage->byte_order);
5570       (void) LogMagickEvent(X11Event,GetMagickModule(),
5571         "  bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5572         ximage->bitmap_bit_order,ximage->bitmap_pad);
5573       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d",
5574         ximage->depth);
5575       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bytes per line: %d",
5576         ximage->bytes_per_line);
5577       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bits per pixel: %d",
5578         ximage->bits_per_pixel);
5579       (void) LogMagickEvent(X11Event,GetMagickModule(),
5580         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5581         ximage->green_mask,ximage->blue_mask);
5582     }
5583   if (window->shared_memory == MagickFalse)
5584     {
5585       if (ximage->format != XYBitmap)
5586         ximage->data=(char *) AcquireQuantumMemory((size_t)
5587           ximage->bytes_per_line,(size_t) ximage->height);
5588       else
5589         ximage->data=(char *) AcquireQuantumMemory((size_t)
5590           ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5591     }
5592   if (ximage->data == (char *) NULL)
5593     {
5594       /*
5595         Unable to allocate pixel data.
5596       */
5597       XDestroyImage(ximage);
5598       ximage=(XImage *) NULL;
5599       (void) XCheckDefineCursor(display,window->id,window->cursor);
5600       return(MagickFalse);
5601     }
5602   if (window->ximage != (XImage *) NULL)
5603     {
5604       /*
5605         Destroy previous X image.
5606       */
5607       length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5608 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5609       if (window->segment_info != (XShmSegmentInfo *) NULL)
5610         {
5611           XShmSegmentInfo
5612             *segment_info;
5613
5614           segment_info=(XShmSegmentInfo *) window->segment_info;
5615           if (segment_info[0].shmid >= 0)
5616             {
5617               (void) XSync(display,MagickFalse);
5618               (void) XShmDetach(display,&segment_info[0]);
5619               (void) XSync(display,MagickFalse);
5620               if (segment_info[0].shmaddr != (char *) NULL)
5621                 (void) shmdt(segment_info[0].shmaddr);
5622               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5623               segment_info[0].shmid=(-1);
5624               segment_info[0].shmaddr=(char *) NULL;
5625               window->ximage->data=(char *) NULL;
5626           }
5627         }
5628 #endif
5629       if (window->ximage->data != (char *) NULL)
5630         free(window->ximage->data);
5631       window->ximage->data=(char *) NULL;
5632       XDestroyImage(window->ximage);
5633       window->ximage=(XImage *) NULL;
5634     }
5635 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5636   if (window->segment_info != (XShmSegmentInfo *) NULL)
5637     {
5638       XShmSegmentInfo
5639         *segment_info;
5640
5641       segment_info=(XShmSegmentInfo *) window->segment_info;
5642       segment_info[0]=segment_info[1];
5643     }
5644 #endif
5645   window->ximage=ximage;
5646   matte_image=(XImage *) NULL;
5647   if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5648     if ((window->image->matte != MagickFalse) &&
5649         ((long) width <= XDisplayWidth(display,window->screen)) &&
5650         ((long) height <= XDisplayHeight(display,window->screen)))
5651       {
5652         /*
5653           Create matte image.
5654         */
5655         matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5656           (char *) NULL,width,height,XBitmapPad(display),0);
5657         if (IsEventLogging())
5658           {
5659             (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5660             (void) LogMagickEvent(X11Event,GetMagickModule(),
5661               "  width, height: %dx%d",matte_image->width,matte_image->height);
5662           }
5663         if (matte_image != (XImage *) NULL)
5664           {
5665             /*
5666               Allocate matte image pixel data.
5667             */
5668             matte_image->data=(char *) AcquireQuantumMemory((size_t)
5669               matte_image->bytes_per_line*matte_image->depth,
5670               (size_t) matte_image->height);
5671             if (matte_image->data == (char *) NULL)
5672               {
5673                 XDestroyImage(matte_image);
5674                 matte_image=(XImage *) NULL;
5675               }
5676           }
5677       }
5678   if (window->matte_image != (XImage *) NULL)
5679     {
5680       /*
5681         Free matte image.
5682       */
5683       if (window->matte_image->data != (char *) NULL)
5684         free(window->matte_image->data);
5685       window->matte_image->data=(char *) NULL;
5686       XDestroyImage(window->matte_image);
5687       window->matte_image=(XImage *) NULL;
5688     }
5689   window->matte_image=matte_image;
5690   if (window->matte_pixmap != (Pixmap) NULL)
5691     {
5692       (void) XFreePixmap(display,window->matte_pixmap);
5693       window->matte_pixmap=(Pixmap) NULL;
5694 #if defined(MAGICKCORE_HAVE_SHAPE)
5695       if (window->shape != MagickFalse)
5696         XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5697 #endif
5698     }
5699   window->stasis=MagickFalse;
5700   /*
5701     Convert pixels to X image data.
5702   */
5703   if (window->image != (Image *) NULL)
5704     {
5705       if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5706           (ximage->bitmap_bit_order == LSBFirst)))
5707         XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5708           matte_image);
5709       else
5710         XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5711           matte_image);
5712     }
5713   if (window->matte_image != (XImage *) NULL)
5714     {
5715       /*
5716         Create matte pixmap.
5717       */
5718       window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5719       if (window->matte_pixmap != (Pixmap) NULL)
5720         {
5721           GC
5722             graphics_context;
5723
5724           XGCValues
5725             context_values;
5726
5727           /*
5728             Copy matte image to matte pixmap.
5729           */
5730           context_values.background=1;
5731           context_values.foreground=0;
5732           graphics_context=XCreateGC(display,window->matte_pixmap,
5733             (unsigned long) (GCBackground | GCForeground),&context_values);
5734           (void) XPutImage(display,window->matte_pixmap,graphics_context,
5735             window->matte_image,0,0,0,0,width,height);
5736           (void) XFreeGC(display,graphics_context);
5737 #if defined(MAGICKCORE_HAVE_SHAPE)
5738           if (window->shape != MagickFalse)
5739             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5740               window->matte_pixmap,ShapeSet);
5741 #endif
5742         }
5743       }
5744   (void) XMakePixmap(display,resource_info,window);
5745   /*
5746     Restore cursor.
5747   */
5748   (void) XCheckDefineCursor(display,window->id,window->cursor);
5749   return(MagickTrue);
5750 }
5751 \f
5752 /*
5753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5754 %                                                                             %
5755 %                                                                             %
5756 %                                                                             %
5757 +   X M a k e I m a g e L S B F i r s t                                       %
5758 %                                                                             %
5759 %                                                                             %
5760 %                                                                             %
5761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5762 %
5763 %  XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5764 %  pixels are copied in least-significant bit and byte first order.  The
5765 %  server's scanline pad is respected.  Rather than using one or two general
5766 %  cases, many special cases are found here to help speed up the image
5767 %  conversion.
5768 %
5769 %  The format of the XMakeImageLSBFirst method is:
5770 %
5771 %      void XMakeImageLSBFirst(Display *display,XWindows *windows)
5772 %
5773 %  A description of each parameter follows:
5774 %
5775 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5776 %
5777 %    o window: Specifies a pointer to a XWindowInfo structure.
5778 %
5779 %    o image: the image.
5780 %
5781 %    o ximage: Specifies a pointer to a XImage structure;  returned from
5782 %      XCreateImage.
5783 %
5784 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
5785 %      XCreateImage.
5786 %
5787 */
5788 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5789   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5790 {
5791   Image
5792     *canvas;
5793
5794   int
5795     y;
5796
5797   register const IndexPacket
5798     *indexes;
5799
5800   register const PixelPacket
5801     *p;
5802
5803   register int
5804     x;
5805
5806   register unsigned char
5807     *q;
5808
5809   unsigned char
5810     bit,
5811     byte;
5812
5813   unsigned int
5814     scanline_pad;
5815
5816   unsigned long
5817     pixel,
5818     *pixels;
5819
5820   XStandardColormap
5821     *map_info;
5822
5823   assert(resource_info != (XResourceInfo *) NULL);
5824   assert(window != (XWindowInfo *) NULL);
5825   assert(image != (Image *) NULL);
5826   if (image->debug != MagickFalse)
5827     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5828   canvas=image;
5829   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
5830     {
5831       char
5832         size[MaxTextExtent];
5833
5834       Image
5835         *pattern;
5836
5837       ImageInfo
5838         *image_info;
5839
5840       image_info=AcquireImageInfo();
5841       (void) CopyMagickString(image_info->filename,
5842         resource_info->image_info->texture != (char *) NULL ?
5843         resource_info->image_info->texture : "pattern:checkerboard",
5844         MaxTextExtent);
5845       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
5846         image->rows);
5847       image_info->size=ConstantString(size);
5848       pattern=ReadImage(image_info,&image->exception);
5849       image_info=DestroyImageInfo(image_info);
5850       if (pattern != (Image *) NULL)
5851         {
5852           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5853           if (canvas != (Image *) NULL)
5854             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5855           pattern=DestroyImage(pattern);
5856         }
5857     }
5858   scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5859     ximage->bits_per_pixel) >> 3));
5860   map_info=window->map_info;
5861   pixels=window->pixel_info->pixels;
5862   q=(unsigned char *) ximage->data;
5863   x=0;
5864   if (ximage->format == XYBitmap)
5865     {
5866       register unsigned short
5867         polarity;
5868
5869       unsigned char
5870         background,
5871         foreground;
5872
5873       /*
5874         Convert canvas to big-endian bitmap.
5875       */
5876       background=(unsigned char)
5877         (XPixelIntensity(&window->pixel_info->foreground_color) <
5878          XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5879       foreground=(unsigned char)
5880         (XPixelIntensity(&window->pixel_info->background_color) <
5881          XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5882       polarity=(unsigned short) ((PixelIntensityToQuantum(
5883         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5884       if (canvas->colors == 2)
5885         polarity=PixelIntensity(&canvas->colormap[0]) <
5886           PixelIntensity(&canvas->colormap[1]);
5887       for (y=0; y < (int) canvas->rows; y++)
5888       {
5889         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5890         if (p == (const PixelPacket *) NULL)
5891           break;
5892         indexes=GetVirtualIndexQueue(canvas);
5893         bit=0;
5894         byte=0;
5895         for (x=0; x < (int) canvas->columns; x++)
5896         {
5897           byte>>=1;
5898           if (indexes[x] == (IndexPacket) polarity)
5899             byte|=foreground;
5900           else
5901             byte|=background;
5902           bit++;
5903           if (bit == 8)
5904             {
5905               *q++=byte;
5906               bit=0;
5907               byte=0;
5908             }
5909         }
5910         if (bit != 0)
5911           *q=byte >> (8-bit);
5912         q+=scanline_pad;
5913       }
5914     }
5915   else
5916     if (window->pixel_info->colors != 0)
5917       switch (ximage->bits_per_pixel)
5918       {
5919         case 2:
5920         {
5921           register unsigned int
5922             nibble;
5923
5924           /*
5925             Convert to 2 bit color-mapped X canvas.
5926           */
5927           for (y=0; y < (int) canvas->rows; y++)
5928           {
5929             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5930             if (p == (const PixelPacket *) NULL)
5931               break;
5932             indexes=GetVirtualIndexQueue(canvas);
5933             nibble=0;
5934             for (x=0; x < (int) canvas->columns; x++)
5935             {
5936               pixel=pixels[(long) indexes[x]] & 0x0f;
5937               switch (nibble)
5938               {
5939                 case 0:
5940                 {
5941                   *q=(unsigned char) pixel;
5942                   nibble++;
5943                   break;
5944                 }
5945                 case 1:
5946                 {
5947                   *q|=(unsigned char) (pixel << 2);
5948                   nibble++;
5949                   break;
5950                 }
5951                 case 2:
5952                 {
5953                   *q|=(unsigned char) (pixel << 4);
5954                   nibble++;
5955                   break;
5956                 }
5957                 case 3:
5958                 {
5959                   *q|=(unsigned char) (pixel << 6);
5960                   q++;
5961                   nibble=0;
5962                   break;
5963                 }
5964               }
5965             }
5966             q+=scanline_pad;
5967           }
5968           break;
5969         }
5970         case 4:
5971         {
5972           register unsigned int
5973             nibble;
5974
5975           /*
5976             Convert to 4 bit color-mapped X canvas.
5977           */
5978           for (y=0; y < (int) canvas->rows; y++)
5979           {
5980             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5981             if (p == (const PixelPacket *) NULL)
5982               break;
5983             indexes=GetVirtualIndexQueue(canvas);
5984             nibble=0;
5985             for (x=0; x < (int) canvas->columns; x++)
5986             {
5987               pixel=pixels[(long) indexes[x]] & 0xf;
5988               switch (nibble)
5989               {
5990                 case 0:
5991                 {
5992                   *q=(unsigned char) pixel;
5993                   nibble++;
5994                   break;
5995                 }
5996                 case 1:
5997                 {
5998                   *q|=(unsigned char) (pixel << 4);
5999                   q++;
6000                   nibble=0;
6001                   break;
6002                 }
6003               }
6004             }
6005             q+=scanline_pad;
6006           }
6007           break;
6008         }
6009         case 6:
6010         case 8:
6011         {
6012           /*
6013             Convert to 8 bit color-mapped X canvas.
6014           */
6015           if (resource_info->color_recovery &&
6016               resource_info->quantize_info->dither)
6017             {
6018               XDitherImage(canvas,ximage);
6019               break;
6020             }
6021           for (y=0; y < (int) canvas->rows; y++)
6022           {
6023             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6024             if (p == (const PixelPacket *) NULL)
6025               break;
6026             indexes=GetVirtualIndexQueue(canvas);
6027             for (x=0; x < (int) canvas->columns; x++)
6028             {
6029               pixel=pixels[(long) indexes[x]];
6030               *q++=(unsigned char) pixel;
6031             }
6032             q+=scanline_pad;
6033           }
6034           break;
6035         }
6036         default:
6037         {
6038           register int
6039             k;
6040
6041           register unsigned int
6042             bytes_per_pixel;
6043
6044           unsigned char
6045             channel[sizeof(unsigned long)];
6046
6047           /*
6048             Convert to multi-byte color-mapped X canvas.
6049           */
6050           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6051           for (y=0; y < (int) canvas->rows; y++)
6052           {
6053             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6054             if (p == (const PixelPacket *) NULL)
6055               break;
6056             indexes=GetVirtualIndexQueue(canvas);
6057             for (x=0; x < (int) canvas->columns; x++)
6058             {
6059               pixel=pixels[(long) indexes[x]];
6060               for (k=0; k < (int) bytes_per_pixel; k++)
6061               {
6062                 channel[k]=(unsigned char) pixel;
6063                 pixel>>=8;
6064               }
6065               for (k=0; k < (int) bytes_per_pixel; k++)
6066                 *q++=channel[k];
6067             }
6068             q+=scanline_pad;
6069           }
6070           break;
6071         }
6072       }
6073     else
6074       switch (ximage->bits_per_pixel)
6075       {
6076         case 2:
6077         {
6078           register unsigned int
6079             nibble;
6080
6081           /*
6082             Convert to contiguous 2 bit continuous-tone X canvas.
6083           */
6084           for (y=0; y < (int) canvas->rows; y++)
6085           {
6086             nibble=0;
6087             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6088             if (p == (const PixelPacket *) NULL)
6089               break;
6090             for (x=0; x < (int) canvas->columns; x++)
6091             {
6092               pixel=XGammaPixel(map_info,p);
6093               pixel&=0xf;
6094               switch (nibble)
6095               {
6096                 case 0:
6097                 {
6098                   *q=(unsigned char) pixel;
6099                   nibble++;
6100                   break;
6101                 }
6102                 case 1:
6103                 {
6104                   *q|=(unsigned char) (pixel << 2);
6105                   nibble++;
6106                   break;
6107                 }
6108                 case 2:
6109                 {
6110                   *q|=(unsigned char) (pixel << 4);
6111                   nibble++;
6112                   break;
6113                 }
6114                 case 3:
6115                 {
6116                   *q|=(unsigned char) (pixel << 6);
6117                   q++;
6118                   nibble=0;
6119                   break;
6120                 }
6121               }
6122               p++;
6123             }
6124             q+=scanline_pad;
6125           }
6126           break;
6127         }
6128         case 4:
6129         {
6130           register unsigned int
6131             nibble;
6132
6133           /*
6134             Convert to contiguous 4 bit continuous-tone X canvas.
6135           */
6136           for (y=0; y < (int) canvas->rows; y++)
6137           {
6138             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6139             if (p == (const PixelPacket *) NULL)
6140               break;
6141             nibble=0;
6142             for (x=0; x < (int) canvas->columns; x++)
6143             {
6144               pixel=XGammaPixel(map_info,p);
6145               pixel&=0xf;
6146               switch (nibble)
6147               {
6148                 case 0:
6149                 {
6150                   *q=(unsigned char) pixel;
6151                   nibble++;
6152                   break;
6153                 }
6154                 case 1:
6155                 {
6156                   *q|=(unsigned char) (pixel << 4);
6157                   q++;
6158                   nibble=0;
6159                   break;
6160                 }
6161               }
6162               p++;
6163             }
6164             q+=scanline_pad;
6165           }
6166           break;
6167         }
6168         case 6:
6169         case 8:
6170         {
6171           /*
6172             Convert to contiguous 8 bit continuous-tone X canvas.
6173           */
6174           if (resource_info->color_recovery &&
6175               resource_info->quantize_info->dither)
6176             {
6177               XDitherImage(canvas,ximage);
6178               break;
6179             }
6180           for (y=0; y < (int) canvas->rows; y++)
6181           {
6182             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6183             if (p == (const PixelPacket *) NULL)
6184               break;
6185             for (x=0; x < (int) canvas->columns; x++)
6186             {
6187               pixel=XGammaPixel(map_info,p);
6188               *q++=(unsigned char) pixel;
6189               p++;
6190             }
6191             q+=scanline_pad;
6192           }
6193           break;
6194         }
6195         default:
6196         {
6197           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6198               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6199               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6200               (map_info->blue_mult == 1))
6201             {
6202               /*
6203                 Convert to 32 bit continuous-tone X canvas.
6204               */
6205               for (y=0; y < (int) canvas->rows; y++)
6206               {
6207                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6208                   &canvas->exception);
6209                 if (p == (const PixelPacket *) NULL)
6210                   break;
6211                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6212                     (blue_gamma != 1.0))
6213                   {
6214                     /*
6215                       Gamma correct canvas.
6216                     */
6217                     for (x=(int) canvas->columns-1; x >= 0; x--)
6218                     {
6219                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6220                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6221                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
6222                       *q++=0;
6223                       p++;
6224                     }
6225                     continue;
6226                   }
6227                 for (x=(int) canvas->columns-1; x >= 0; x--)
6228                 {
6229                   *q++=ScaleQuantumToChar((Quantum) p->blue);
6230                   *q++=ScaleQuantumToChar((Quantum) p->green);
6231                   *q++=ScaleQuantumToChar((Quantum) p->red);
6232                   *q++=0;
6233                   p++;
6234                 }
6235               }
6236             }
6237           else
6238             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6239                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6240                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6241                 (map_info->blue_mult == 65536L))
6242               {
6243                 /*
6244                   Convert to 32 bit continuous-tone X canvas.
6245                 */
6246                 for (y=0; y < (int) canvas->rows; y++)
6247                 {
6248                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6249                     &canvas->exception);
6250                   if (p == (const PixelPacket *) NULL)
6251                     break;
6252                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6253                       (blue_gamma != 1.0))
6254                     {
6255                       /*
6256                         Gamma correct canvas.
6257                       */
6258                       for (x=(int) canvas->columns-1; x >= 0; x--)
6259                       {
6260                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
6261                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6262                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6263                         *q++=0;
6264                         p++;
6265                       }
6266                       continue;
6267                     }
6268                   for (x=(int) canvas->columns-1; x >= 0; x--)
6269                   {
6270                     *q++=ScaleQuantumToChar((Quantum) p->red);
6271                     *q++=ScaleQuantumToChar((Quantum) p->green);
6272                     *q++=ScaleQuantumToChar((Quantum) p->blue);
6273                     *q++=0;
6274                     p++;
6275                   }
6276                 }
6277               }
6278             else
6279               {
6280                 register int
6281                   k;
6282
6283                 register unsigned int
6284                   bytes_per_pixel;
6285
6286                 unsigned char
6287                   channel[sizeof(unsigned long)];
6288
6289                 /*
6290                   Convert to multi-byte continuous-tone X canvas.
6291                 */
6292                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6293                 for (y=0; y < (int) canvas->rows; y++)
6294                 {
6295                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6296                     &canvas->exception);
6297                   if (p == (PixelPacket *) NULL)
6298                     break;
6299                   for (x=0; x < (long) canvas->columns; x++)
6300                   {
6301                     pixel=XGammaPixel(map_info,p);
6302                     for (k=0; k < (int) bytes_per_pixel; k++)
6303                     {
6304                       channel[k]=(unsigned char) pixel;
6305                       pixel>>=8;
6306                     }
6307                     for (k=0; k < (int) bytes_per_pixel; k++)
6308                       *q++=channel[k];
6309                     p++;
6310                   }
6311                   q+=scanline_pad;
6312                 }
6313               }
6314           break;
6315         }
6316       }
6317   if (matte_image != (XImage *) NULL)
6318     {
6319       /*
6320         Initialize matte canvas.
6321       */
6322       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6323         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6324       q=(unsigned char *) matte_image->data;
6325       for (y=0; y < (int) canvas->rows; y++)
6326       {
6327         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6328         if (p == (const PixelPacket *) NULL)
6329           break;
6330         bit=0;
6331         byte=0;
6332         for (x=(int) canvas->columns-1; x >= 0; x--)
6333         {
6334           byte>>=1;
6335           if (p->opacity > (long) (QuantumRange/2))
6336             byte|=0x80;
6337           bit++;
6338           if (bit == 8)
6339             {
6340               *q++=byte;
6341               bit=0;
6342               byte=0;
6343             }
6344           p++;
6345         }
6346         if (bit != 0)
6347           *q=byte >> (8-bit);
6348         q+=scanline_pad;
6349       }
6350     }
6351   if (canvas != image)
6352     canvas=DestroyImage(canvas);
6353 }
6354 \f
6355 /*
6356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6357 %                                                                             %
6358 %                                                                             %
6359 %                                                                             %
6360 +   X M a k e I m a g e M S B F i r s t                                       %
6361 %                                                                             %
6362 %                                                                             %
6363 %                                                                             %
6364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6365 %
6366 %  XMakeImageMSBFirst() initializes the pixel data of an X11 Image.  The X
6367 %  image pixels are copied in most-significant bit and byte first order.  The
6368 %  server's scanline pad is also respected. Rather than using one or two
6369 %  general cases, many special cases are found here to help speed up the image
6370 %  conversion.
6371 %
6372 %  The format of the XMakeImageMSBFirst method is:
6373 %
6374 %      XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6375 %
6376 %  A description of each parameter follows:
6377 %
6378 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6379 %
6380 %    o window: Specifies a pointer to a XWindowInfo structure.
6381 %
6382 %    o image: the image.
6383 %
6384 %    o ximage: Specifies a pointer to a XImage structure;  returned from
6385 %      XCreateImage.
6386 %
6387 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
6388 %      XCreateImage.
6389 %
6390 %
6391 */
6392 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6393   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6394 {
6395   Image
6396     *canvas;
6397
6398   int
6399     y;
6400
6401   register int
6402     x;
6403
6404   register const IndexPacket
6405     *indexes;
6406
6407   register const PixelPacket
6408     *p;
6409
6410   register unsigned char
6411     *q;
6412
6413   unsigned char
6414     bit,
6415     byte;
6416
6417   unsigned int
6418     scanline_pad;
6419
6420   unsigned long
6421     pixel,
6422     *pixels;
6423
6424   XStandardColormap
6425     *map_info;
6426
6427   assert(resource_info != (XResourceInfo *) NULL);
6428   assert(window != (XWindowInfo *) NULL);
6429   assert(image != (Image *) NULL);
6430   if (image->debug != MagickFalse)
6431     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6432   canvas=image;
6433   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
6434     {
6435       char
6436         size[MaxTextExtent];
6437
6438       Image
6439         *pattern;
6440
6441       ImageInfo
6442         *image_info;
6443
6444       image_info=AcquireImageInfo();
6445       (void) CopyMagickString(image_info->filename,
6446         resource_info->image_info->texture != (char *) NULL ?
6447         resource_info->image_info->texture : "pattern:checkerboard",
6448         MaxTextExtent);
6449       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
6450         image->rows);
6451       image_info->size=ConstantString(size);
6452       pattern=ReadImage(image_info,&image->exception);
6453       image_info=DestroyImageInfo(image_info);
6454       if (pattern != (Image *) NULL)
6455         {
6456           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6457           if (canvas != (Image *) NULL)
6458             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6459           pattern=DestroyImage(pattern);
6460         }
6461     }
6462   scanline_pad=(unsigned int) (ximage->bytes_per_line-
6463     ((ximage->width*ximage->bits_per_pixel) >> 3));
6464   map_info=window->map_info;
6465   pixels=window->pixel_info->pixels;
6466   q=(unsigned char *) ximage->data;
6467   x=0;
6468   if (ximage->format == XYBitmap)
6469     {
6470       register unsigned short
6471         polarity;
6472
6473       unsigned char
6474         background,
6475         foreground;
6476
6477       /*
6478         Convert canvas to big-endian bitmap.
6479       */
6480       background=(unsigned char)
6481         (XPixelIntensity(&window->pixel_info->foreground_color) <
6482          XPixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
6483       foreground=(unsigned char)
6484         (XPixelIntensity(&window->pixel_info->background_color) <
6485          XPixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
6486       polarity=(unsigned short) ((PixelIntensityToQuantum(
6487         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6488       if (canvas->colors == 2)
6489         polarity=PixelIntensity(&canvas->colormap[0]) <
6490           PixelIntensity(&canvas->colormap[1]);
6491       for (y=0; y < (int) canvas->rows; y++)
6492       {
6493         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6494         if (p == (const PixelPacket *) NULL)
6495           break;
6496         indexes=GetVirtualIndexQueue(canvas);
6497         bit=0;
6498         byte=0;
6499         for (x=(int) canvas->columns-1; x >= 0; x--)
6500         {
6501           byte<<=1;
6502           if (indexes[x] == (IndexPacket) polarity)
6503             byte|=foreground;
6504           else
6505             byte|=background;
6506           bit++;
6507           if (bit == 8)
6508             {
6509               *q++=byte;
6510               bit=0;
6511               byte=0;
6512             }
6513         }
6514         if (bit != 0)
6515           *q=byte << (8-bit);
6516         q+=scanline_pad;
6517       }
6518     }
6519   else
6520     if (window->pixel_info->colors != 0)
6521       switch (ximage->bits_per_pixel)
6522       {
6523         case 2:
6524         {
6525           register unsigned int
6526             nibble;
6527
6528           /*
6529             Convert to 2 bit color-mapped X canvas.
6530           */
6531           for (y=0; y < (int) canvas->rows; y++)
6532           {
6533             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6534             if (p == (const PixelPacket *) NULL)
6535               break;
6536             indexes=GetVirtualIndexQueue(canvas);
6537             nibble=0;
6538             for (x=0; x < (int) canvas->columns; x++)
6539             {
6540               pixel=pixels[(long) indexes[x]] & 0xf;
6541               switch (nibble)
6542               {
6543                 case 0:
6544                 {
6545                   *q=(unsigned char) (pixel << 6);
6546                   nibble++;
6547                   break;
6548                 }
6549                 case 1:
6550                 {
6551                   *q|=(unsigned char) (pixel << 4);
6552                   nibble++;
6553                   break;
6554                 }
6555                 case 2:
6556                 {
6557                   *q|=(unsigned char) (pixel << 2);
6558                   nibble++;
6559                   break;
6560                 }
6561                 case 3:
6562                 {
6563                   *q|=(unsigned char) pixel;
6564                   q++;
6565                   nibble=0;
6566                   break;
6567                 }
6568               }
6569             }
6570             q+=scanline_pad;
6571           }
6572           break;
6573         }
6574         case 4:
6575         {
6576           register unsigned int
6577             nibble;
6578
6579           /*
6580             Convert to 4 bit color-mapped X canvas.
6581           */
6582           for (y=0; y < (int) canvas->rows; y++)
6583           {
6584             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6585             if (p == (const PixelPacket *) NULL)
6586               break;
6587             indexes=GetVirtualIndexQueue(canvas);
6588             nibble=0;
6589             for (x=0; x < (int) canvas->columns; x++)
6590             {
6591               pixel=pixels[(long) indexes[x]] & 0xf;
6592               switch (nibble)
6593               {
6594                 case 0:
6595                 {
6596                   *q=(unsigned char) (pixel << 4);
6597                   nibble++;
6598                   break;
6599                 }
6600                 case 1:
6601                 {
6602                   *q|=(unsigned char) pixel;
6603                   q++;
6604                   nibble=0;
6605                   break;
6606                 }
6607               }
6608             }
6609             q+=scanline_pad;
6610           }
6611           break;
6612         }
6613         case 6:
6614         case 8:
6615         {
6616           /*
6617             Convert to 8 bit color-mapped X canvas.
6618           */
6619           if (resource_info->color_recovery &&
6620               resource_info->quantize_info->dither)
6621             {
6622               XDitherImage(canvas,ximage);
6623               break;
6624             }
6625           for (y=0; y < (int) canvas->rows; y++)
6626           {
6627             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6628             if (p == (const PixelPacket *) NULL)
6629               break;
6630             indexes=GetVirtualIndexQueue(canvas);
6631             for (x=0; x < (int) canvas->columns; x++)
6632             {
6633               pixel=pixels[(long) indexes[x]];
6634               *q++=(unsigned char) pixel;
6635             }
6636             q+=scanline_pad;
6637           }
6638           break;
6639         }
6640         default:
6641         {
6642           register int
6643             k;
6644
6645           register unsigned int
6646             bytes_per_pixel;
6647
6648           unsigned char
6649             channel[sizeof(unsigned long)];
6650
6651           /*
6652             Convert to 8 bit color-mapped X canvas.
6653           */
6654           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6655           for (y=0; y < (int) canvas->rows; y++)
6656           {
6657             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6658             if (p == (const PixelPacket *) NULL)
6659               break;
6660             indexes=GetVirtualIndexQueue(canvas);
6661             for (x=0; x < (int) canvas->columns; x++)
6662             {
6663               pixel=pixels[(long) indexes[x]];
6664               for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6665               {
6666                 channel[k]=(unsigned char) pixel;
6667                 pixel>>=8;
6668               }
6669               for (k=0; k < (int) bytes_per_pixel; k++)
6670                 *q++=channel[k];
6671             }
6672             q+=scanline_pad;
6673           }
6674           break;
6675         }
6676       }
6677     else
6678       switch (ximage->bits_per_pixel)
6679       {
6680         case 2:
6681         {
6682           register unsigned int
6683             nibble;
6684
6685           /*
6686             Convert to 4 bit continuous-tone X canvas.
6687           */
6688           for (y=0; y < (int) canvas->rows; y++)
6689           {
6690             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6691             if (p == (const PixelPacket *) NULL)
6692               break;
6693             nibble=0;
6694             for (x=(int) canvas->columns-1; x >= 0; x--)
6695             {
6696               pixel=XGammaPixel(map_info,p);
6697               pixel&=0xf;
6698               switch (nibble)
6699               {
6700                 case 0:
6701                 {
6702                   *q=(unsigned char) (pixel << 6);
6703                   nibble++;
6704                   break;
6705                 }
6706                 case 1:
6707                 {
6708                   *q|=(unsigned char) (pixel << 4);
6709                   nibble++;
6710                   break;
6711                 }
6712                 case 2:
6713                 {
6714                   *q|=(unsigned char) (pixel << 2);
6715                   nibble++;
6716                   break;
6717                 }
6718                 case 3:
6719                 {
6720                   *q|=(unsigned char) pixel;
6721                   q++;
6722                   nibble=0;
6723                   break;
6724                 }
6725               }
6726               p++;
6727             }
6728             q+=scanline_pad;
6729           }
6730           break;
6731         }
6732         case 4:
6733         {
6734           register unsigned int
6735             nibble;
6736
6737           /*
6738             Convert to 4 bit continuous-tone X canvas.
6739           */
6740           for (y=0; y < (int) canvas->rows; y++)
6741           {
6742             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6743             if (p == (const PixelPacket *) NULL)
6744               break;
6745             nibble=0;
6746             for (x=(int) canvas->columns-1; x >= 0; x--)
6747             {
6748               pixel=XGammaPixel(map_info,p);
6749               pixel&=0xf;
6750               switch (nibble)
6751               {
6752                 case 0:
6753                 {
6754                   *q=(unsigned char) (pixel << 4);
6755                   nibble++;
6756                   break;
6757                 }
6758                 case 1:
6759                 {
6760                   *q|=(unsigned char) pixel;
6761                   q++;
6762                   nibble=0;
6763                   break;
6764                 }
6765               }
6766               p++;
6767             }
6768             q+=scanline_pad;
6769           }
6770           break;
6771         }
6772         case 6:
6773         case 8:
6774         {
6775           /*
6776             Convert to 8 bit continuous-tone X canvas.
6777           */
6778           if (resource_info->color_recovery &&
6779               resource_info->quantize_info->dither)
6780             {
6781               XDitherImage(canvas,ximage);
6782               break;
6783             }
6784           for (y=0; y < (int) canvas->rows; y++)
6785           {
6786             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6787             if (p == (const PixelPacket *) NULL)
6788               break;
6789             for (x=(int) canvas->columns-1; x >= 0; x--)
6790             {
6791               pixel=XGammaPixel(map_info,p);
6792               *q++=(unsigned char) pixel;
6793               p++;
6794             }
6795             q+=scanline_pad;
6796           }
6797           break;
6798         }
6799         default:
6800         {
6801           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6802               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6803               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6804               (map_info->blue_mult == 1))
6805             {
6806               /*
6807                 Convert to 32 bit continuous-tone X canvas.
6808               */
6809               for (y=0; y < (int) canvas->rows; y++)
6810               {
6811                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6812                   &canvas->exception);
6813                 if (p == (const PixelPacket *) NULL)
6814                   break;
6815                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6816                     (blue_gamma != 1.0))
6817                   {
6818                     /*
6819                       Gamma correct canvas.
6820                     */
6821                     for (x=(int) canvas->columns-1; x >= 0; x--)
6822                     {
6823                       *q++=0;
6824                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
6825                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6826                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6827                       p++;
6828                     }
6829                     continue;
6830                   }
6831                 for (x=(int) canvas->columns-1; x >= 0; x--)
6832                 {
6833                   *q++=0;
6834                   *q++=ScaleQuantumToChar((Quantum) p->red);
6835                   *q++=ScaleQuantumToChar((Quantum) p->green);
6836                   *q++=ScaleQuantumToChar((Quantum) p->blue);
6837                   p++;
6838                 }
6839               }
6840             }
6841           else
6842             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6843                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6844                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6845                 (map_info->blue_mult == 65536L))
6846               {
6847                 /*
6848                   Convert to 32 bit continuous-tone X canvas.
6849                 */
6850                 for (y=0; y < (int) canvas->rows; y++)
6851                 {
6852                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6853                     &canvas->exception);
6854                   if (p == (const PixelPacket *) NULL)
6855                     break;
6856                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6857                       (blue_gamma != 1.0))
6858                     {
6859                       /*
6860                         Gamma correct canvas.
6861                       */
6862                       for (x=(int) canvas->columns-1; x >= 0; x--)
6863                       {
6864                         *q++=0;
6865                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6866                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6867                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
6868                         p++;
6869                       }
6870                       continue;
6871                     }
6872                   for (x=(int) canvas->columns-1; x >= 0; x--)
6873                   {
6874                     *q++=0;
6875                     *q++=ScaleQuantumToChar((Quantum) p->blue);
6876                     *q++=ScaleQuantumToChar((Quantum) p->green);
6877                     *q++=ScaleQuantumToChar((Quantum) p->red);
6878                     p++;
6879                   }
6880                 }
6881               }
6882             else
6883               {
6884                 register int
6885                   k;
6886
6887                 register unsigned int
6888                   bytes_per_pixel;
6889
6890                 unsigned char
6891                   channel[sizeof(unsigned long)];
6892
6893                 /*
6894                   Convert to multi-byte continuous-tone X canvas.
6895                 */
6896                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6897                 for (y=0; y < (int) canvas->rows; y++)
6898                 {
6899                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6900                     &canvas->exception);
6901                   if (p == (const PixelPacket *) NULL)
6902                     break;
6903                   for (x=(int) canvas->columns-1; x >= 0; x--)
6904                   {
6905                     pixel=XGammaPixel(map_info,p);
6906                     for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6907                     {
6908                       channel[k]=(unsigned char) pixel;
6909                       pixel>>=8;
6910                     }
6911                     for (k=0; k < (int) bytes_per_pixel; k++)
6912                       *q++=channel[k];
6913                     p++;
6914                   }
6915                   q+=scanline_pad;
6916                 }
6917               }
6918           break;
6919         }
6920       }
6921   if (matte_image != (XImage *) NULL)
6922     {
6923       /*
6924         Initialize matte canvas.
6925       */
6926       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6927         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6928       q=(unsigned char *) matte_image->data;
6929       for (y=0; y < (int) canvas->rows; y++)
6930       {
6931         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6932         if (p == (const PixelPacket *) NULL)
6933           break;
6934         bit=0;
6935         byte=0;
6936         for (x=(int) canvas->columns-1; x >= 0; x--)
6937         {
6938           byte<<=1;
6939           if (p->opacity > (long) (QuantumRange/2))
6940             byte|=0x01;
6941           bit++;
6942           if (bit == 8)
6943             {
6944               *q++=byte;
6945               bit=0;
6946               byte=0;
6947             }
6948           p++;
6949         }
6950         if (bit != 0)
6951           *q=byte << (8-bit);
6952         q+=scanline_pad;
6953       }
6954     }
6955   if (canvas != image)
6956     canvas=DestroyImage(canvas);
6957 }
6958 \f
6959 /*
6960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6961 %                                                                             %
6962 %                                                                             %
6963 %                                                                             %
6964 %   X M a k e M a g n i f y I m a g e                                         %
6965 %                                                                             %
6966 %                                                                             %
6967 %                                                                             %
6968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6969 %
6970 %  XMakeMagnifyImage() magnifies a region of an X image and displays it.
6971 %
6972 %  The format of the XMakeMagnifyImage method is:
6973 %
6974 %      void XMakeMagnifyImage(display,windows)
6975 %
6976 %  A description of each parameter follows:
6977 %
6978 %    o display: Specifies a connection to an X server;  returned from
6979 %      XOpenDisplay.
6980 %
6981 %    o windows: Specifies a pointer to a XWindows structure.
6982 %
6983 */
6984 MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
6985 {
6986   char
6987     tuple[MaxTextExtent];
6988
6989   int
6990     y;
6991
6992   long
6993     n;
6994
6995   MagickPixelPacket
6996     pixel;
6997
6998   register int
6999     x;
7000
7001   register long
7002     i;
7003
7004   register unsigned char
7005     *p,
7006     *q;
7007
7008   static unsigned int
7009     previous_magnify = 0;
7010
7011   static XWindowInfo
7012     magnify_window;
7013
7014   unsigned int
7015     height,
7016     j,
7017     k,
7018     l,
7019     magnify,
7020     scanline_pad,
7021     width;
7022
7023   XImage
7024     *ximage;
7025
7026   /*
7027     Check boundary conditions.
7028   */
7029   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7030   assert(display != (Display *) NULL);
7031   assert(windows != (XWindows *) NULL);
7032   magnify=1;
7033   for (n=1; n < (long) windows->magnify.data; n++)
7034     magnify<<=1;
7035   while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7036     magnify<<=1;
7037   while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7038     magnify<<=1;
7039   while (magnify > windows->magnify.width)
7040     magnify>>=1;
7041   while (magnify > windows->magnify.height)
7042     magnify>>=1;
7043   if (magnify != previous_magnify)
7044     {
7045       Status
7046         status;
7047
7048       XTextProperty
7049         window_name;
7050
7051       /*
7052         New magnify factor:  update magnify window name.
7053       */
7054       i=0;
7055       while ((1 << i) <= (int) magnify)
7056         i++;
7057       (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
7058         "Magnify %luX",i);
7059       status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7060       if (status != False)
7061         {
7062           XSetWMName(display,windows->magnify.id,&window_name);
7063           XSetWMIconName(display,windows->magnify.id,&window_name);
7064           (void) XFree((void *) window_name.value);
7065         }
7066     }
7067   previous_magnify=magnify;
7068   ximage=windows->image.ximage;
7069   width=(unsigned int) windows->magnify.ximage->width;
7070   height=(unsigned int) windows->magnify.ximage->height;
7071   if ((windows->magnify.x < 0) ||
7072       (windows->magnify.x >= windows->image.ximage->width))
7073     windows->magnify.x=windows->image.ximage->width >> 1;
7074   x=windows->magnify.x-((width/magnify) >> 1);
7075   if (x < 0)
7076     x=0;
7077   else
7078     if (x > (int) (ximage->width-(width/magnify)))
7079       x=ximage->width-width/magnify;
7080   if ((windows->magnify.y < 0) ||
7081       (windows->magnify.y >= windows->image.ximage->height))
7082     windows->magnify.y=windows->image.ximage->height >> 1;
7083   y=windows->magnify.y-((height/magnify) >> 1);
7084   if (y < 0)
7085     y=0;
7086   else
7087     if (y > (int) (ximage->height-(height/magnify)))
7088       y=ximage->height-height/magnify;
7089   q=(unsigned char *) windows->magnify.ximage->data;
7090   scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7091     ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7092   if (ximage->bits_per_pixel < 8)
7093     {
7094       register unsigned char
7095         background,
7096         byte,
7097         foreground,
7098         p_bit,
7099         q_bit;
7100
7101       register unsigned int
7102         plane;
7103
7104       XPixelInfo
7105         *pixel_info;
7106
7107       pixel_info=windows->magnify.pixel_info;
7108       switch (ximage->bitmap_bit_order)
7109       {
7110         case LSBFirst:
7111         {
7112           /*
7113             Magnify little-endian bitmap.
7114           */
7115           background=0x00;
7116           foreground=0x80;
7117           if (ximage->format == XYBitmap)
7118             {
7119               background=(unsigned char)
7120                 (XPixelIntensity(&pixel_info->foreground_color) <
7121                  XPixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
7122               foreground=(unsigned char)
7123                 (XPixelIntensity(&pixel_info->background_color) <
7124                  XPixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
7125               if (windows->magnify.depth > 1)
7126                 Swap(background,foreground);
7127             }
7128           for (i=0; i < (long) height; i+=magnify)
7129           {
7130             /*
7131               Propogate pixel magnify rows.
7132             */
7133             for (j=0; j < magnify; j++)
7134             {
7135               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7136                 ((x*ximage->bits_per_pixel) >> 3);
7137               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7138               q_bit=0;
7139               byte=0;
7140               for (k=0; k < width; k+=magnify)
7141               {
7142                 /*
7143                   Propogate pixel magnify columns.
7144                 */
7145                 for (l=0; l < magnify; l++)
7146                 {
7147                   /*
7148                     Propogate each bit plane.
7149                   */
7150                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7151                   {
7152                     byte>>=1;
7153                     if (*p & (0x01 << (p_bit+plane)))
7154                       byte|=foreground;
7155                     else
7156                       byte|=background;
7157                     q_bit++;
7158                     if (q_bit == 8)
7159                       {
7160                         *q++=byte;
7161                         q_bit=0;
7162                         byte=0;
7163                       }
7164                   }
7165                 }
7166                 p_bit+=ximage->bits_per_pixel;
7167                 if (p_bit == 8)
7168                   {
7169                     p++;
7170                     p_bit=0;
7171                   }
7172                 if (q_bit != 0)
7173                   *q=byte >> (8-q_bit);
7174                 q+=scanline_pad;
7175               }
7176             }
7177             y++;
7178           }
7179           break;
7180         }
7181         case MSBFirst:
7182         default:
7183         {
7184           /*
7185             Magnify big-endian bitmap.
7186           */
7187           background=0x00;
7188           foreground=0x01;
7189           if (ximage->format == XYBitmap)
7190             {
7191               background=(unsigned char)
7192                 (XPixelIntensity(&pixel_info->foreground_color) <
7193                  XPixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
7194               foreground=(unsigned char)
7195                 (XPixelIntensity(&pixel_info->background_color) <
7196                  XPixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
7197               if (windows->magnify.depth > 1)
7198                 Swap(background,foreground);
7199             }
7200           for (i=0; i < (long) height; i+=magnify)
7201           {
7202             /*
7203               Propogate pixel magnify rows.
7204             */
7205             for (j=0; j < magnify; j++)
7206             {
7207               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7208                 ((x*ximage->bits_per_pixel) >> 3);
7209               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7210               q_bit=0;
7211               byte=0;
7212               for (k=0; k < width; k+=magnify)
7213               {
7214                 /*
7215                   Propogate pixel magnify columns.
7216                 */
7217                 for (l=0; l < magnify; l++)
7218                 {
7219                   /*
7220                     Propogate each bit plane.
7221                   */
7222                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7223                   {
7224                     byte<<=1;
7225                     if (*p & (0x80 >> (p_bit+plane)))
7226                       byte|=foreground;
7227                     else
7228                       byte|=background;
7229                     q_bit++;
7230                     if (q_bit == 8)
7231                       {
7232                         *q++=byte;
7233                         q_bit=0;
7234                         byte=0;
7235                       }
7236                   }
7237                 }
7238                 p_bit+=ximage->bits_per_pixel;
7239                 if (p_bit == 8)
7240                   {
7241                     p++;
7242                     p_bit=0;
7243                   }
7244                 if (q_bit != 0)
7245                   *q=byte << (8-q_bit);
7246                 q+=scanline_pad;
7247               }
7248             }
7249             y++;
7250           }
7251           break;
7252         }
7253       }
7254     }
7255   else
7256     switch (ximage->bits_per_pixel)
7257     {
7258       case 6:
7259       case 8:
7260       {
7261         /*
7262           Magnify 8 bit X image.
7263         */
7264         for (i=0; i < (long) height; i+=magnify)
7265         {
7266           /*
7267             Propogate pixel magnify rows.
7268           */
7269           for (j=0; j < magnify; j++)
7270           {
7271             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7272               ((x*ximage->bits_per_pixel) >> 3);
7273             for (k=0; k < width; k+=magnify)
7274             {
7275               /*
7276                 Propogate pixel magnify columns.
7277               */
7278               for (l=0; l < magnify; l++)
7279                 *q++=(*p);
7280               p++;
7281             }
7282             q+=scanline_pad;
7283           }
7284           y++;
7285         }
7286         break;
7287       }
7288       default:
7289       {
7290         register unsigned int
7291           bytes_per_pixel,
7292           m;
7293
7294         /*
7295           Magnify multi-byte X image.
7296         */
7297         bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7298         for (i=0; i < (long) height; i+=magnify)
7299         {
7300           /*
7301             Propogate pixel magnify rows.
7302           */
7303           for (j=0; j < magnify; j++)
7304           {
7305             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7306               ((x*ximage->bits_per_pixel) >> 3);
7307             for (k=0; k < width; k+=magnify)
7308             {
7309               /*
7310                 Propogate pixel magnify columns.
7311               */
7312               for (l=0; l < magnify; l++)
7313                 for (m=0; m < bytes_per_pixel; m++)
7314                   *q++=(*(p+m));
7315               p+=bytes_per_pixel;
7316             }
7317             q+=scanline_pad;
7318           }
7319           y++;
7320         }
7321         break;
7322       }
7323     }
7324   /*
7325     Copy X image to magnify pixmap.
7326   */
7327   x=windows->magnify.x-((width/magnify) >> 1);
7328   if (x < 0)
7329     x=(int) ((width >> 1)-windows->magnify.x*magnify);
7330   else
7331     if (x > (int) (ximage->width-(width/magnify)))
7332       x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7333     else
7334       x=0;
7335   y=windows->magnify.y-((height/magnify) >> 1);
7336   if (y < 0)
7337     y=(int) ((height >> 1)-windows->magnify.y*magnify);
7338   else
7339     if (y > (int) (ximage->height-(height/magnify)))
7340       y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7341     else
7342       y=0;
7343   if ((x != 0) || (y != 0))
7344     (void) XFillRectangle(display,windows->magnify.pixmap,
7345       windows->magnify.annotate_context,0,0,width,height);
7346   (void) XPutImage(display,windows->magnify.pixmap,
7347     windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7348     height-y);
7349   if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7350       (magnify <= (height >> 1))))
7351     {
7352       RectangleInfo
7353         highlight_info;
7354
7355       /*
7356         Highlight center pixel.
7357       */
7358       highlight_info.x=(long) windows->magnify.width >> 1;
7359       highlight_info.y=(long) windows->magnify.height >> 1;
7360       highlight_info.width=magnify;
7361       highlight_info.height=magnify;
7362       (void) XDrawRectangle(display,windows->magnify.pixmap,
7363         windows->magnify.highlight_context,(int) highlight_info.x,
7364         (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7365         (unsigned int) highlight_info.height-1);
7366       if (magnify > 2)
7367         (void) XDrawRectangle(display,windows->magnify.pixmap,
7368           windows->magnify.annotate_context,(int) highlight_info.x+1,
7369           (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7370           (unsigned int) highlight_info.height-3);
7371     }
7372   /*
7373     Show center pixel color.
7374   */
7375   (void) GetOneVirtualMagickPixel(windows->image.image,windows->magnify.x,
7376     windows->magnify.y,&pixel,&windows->image.image->exception);
7377   (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7378     windows->magnify.x,windows->magnify.y);
7379   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7380   ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7381   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7382   ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7383   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7384   ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7385   if (pixel.colorspace == CMYKColorspace)
7386     {
7387       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7388       ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7389     }
7390   if (pixel.matte != MagickFalse)
7391     {
7392       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7393       ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7394     }
7395   (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7396   height=(unsigned int) windows->magnify.font_info->ascent+
7397     windows->magnify.font_info->descent;
7398   x=windows->magnify.font_info->max_bounds.width >> 1;
7399   y=windows->magnify.font_info->ascent+(height >> 2);
7400   (void) XDrawImageString(display,windows->magnify.pixmap,
7401     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7402   GetColorTuple(&pixel,MagickTrue,tuple);
7403   y+=height;
7404   (void) XDrawImageString(display,windows->magnify.pixmap,
7405     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7406   (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7407      &windows->image.image->exception);
7408   y+=height;
7409   (void) XDrawImageString(display,windows->magnify.pixmap,
7410     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7411   /*
7412     Refresh magnify window.
7413   */
7414   magnify_window=windows->magnify;
7415   magnify_window.x=0;
7416   magnify_window.y=0;
7417   XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7418 }
7419 \f
7420 /*
7421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7422 %                                                                             %
7423 %                                                                             %
7424 %                                                                             %
7425 %   X M a k e P i x m a p                                                     %
7426 %                                                                             %
7427 %                                                                             %
7428 %                                                                             %
7429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7430 %
7431 %  XMakePixmap() creates an X11 pixmap.
7432 %
7433 %  The format of the XMakePixmap method is:
7434 %
7435 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7436 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7437 %        XPixelInfo *pixel)
7438 %
7439 %  A description of each parameter follows:
7440 %
7441 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7442 %
7443 %    o display: Specifies a connection to an X server; returned from
7444 %      XOpenDisplay.
7445 %
7446 %    o window: Specifies a pointer to a XWindowInfo structure.
7447 %
7448 %
7449 */
7450 static MagickBooleanType XMakePixmap(Display *display,
7451   const XResourceInfo *resource_info,XWindowInfo *window)
7452 {
7453   unsigned int
7454     height,
7455     width;
7456
7457   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7458   assert(display != (Display *) NULL);
7459   assert(resource_info != (XResourceInfo *) NULL);
7460   assert(window != (XWindowInfo  *) NULL);
7461   if (window->pixmap != (Pixmap) NULL)
7462     {
7463       /*
7464         Destroy previous X pixmap.
7465       */
7466       (void) XFreePixmap(display,window->pixmap);
7467       window->pixmap=(Pixmap) NULL;
7468     }
7469   if (window->use_pixmap == MagickFalse)
7470     return(MagickFalse);
7471   if (window->ximage == (XImage *) NULL)
7472     return(MagickFalse);
7473   /*
7474     Display busy cursor.
7475   */
7476   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7477   (void) XFlush(display);
7478   /*
7479     Create pixmap.
7480   */
7481   width=(unsigned int) window->ximage->width;
7482   height=(unsigned int) window->ximage->height;
7483   window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7484   if (window->pixmap == (Pixmap) NULL)
7485     {
7486       /*
7487         Unable to allocate pixmap.
7488       */
7489       (void) XCheckDefineCursor(display,window->id,window->cursor);
7490       return(MagickFalse);
7491     }
7492   /*
7493     Copy X image to pixmap.
7494   */
7495 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7496   if (window->shared_memory)
7497     (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7498       window->ximage,0,0,0,0,width,height,MagickTrue);
7499 #endif
7500   if (window->shared_memory == MagickFalse)
7501     (void) XPutImage(display,window->pixmap,window->annotate_context,
7502       window->ximage,0,0,0,0,width,height);
7503   if (IsEventLogging())
7504     {
7505       (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7506       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
7507         width,height);
7508     }
7509   /*
7510     Restore cursor.
7511   */
7512   (void) XCheckDefineCursor(display,window->id,window->cursor);
7513   return(MagickTrue);
7514 }
7515 \f
7516 /*
7517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7518 %                                                                             %
7519 %                                                                             %
7520 %                                                                             %
7521 %   X M a k e S t a n d a r d C o l o r m a p                                 %
7522 %                                                                             %
7523 %                                                                             %
7524 %                                                                             %
7525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7526 %
7527 %  XMakeStandardColormap() creates an X11 Standard Colormap.
7528 %
7529 %  The format of the XMakeStandardColormap method is:
7530 %
7531 %      XMakeStandardColormap(display,visual_info,resource_info,image,
7532 %        map_info,pixel)
7533 %
7534 %  A description of each parameter follows:
7535 %
7536 %    o display: Specifies a connection to an X server; returned from
7537 %      XOpenDisplay.
7538 %
7539 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7540 %      returned from XGetVisualInfo.
7541 %
7542 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7543 %
7544 %    o image: the image.
7545 %
7546 %    o map_info: If a Standard Colormap type is specified, this structure is
7547 %      initialized with info from the Standard Colormap.
7548 %
7549 %    o pixel: Specifies a pointer to a XPixelInfo structure.
7550 %
7551 %
7552 */
7553
7554 #if defined(__cplusplus) || defined(c_plusplus)
7555 extern "C" {
7556 #endif
7557
7558 static inline MagickRealType DiversityPixelIntensity(
7559   const DiversityPacket *pixel)
7560 {
7561   MagickRealType
7562     intensity;
7563
7564   intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7565   return(intensity);
7566 }
7567
7568 static int IntensityCompare(const void *x,const void *y)
7569 {
7570   DiversityPacket
7571     *color_1,
7572     *color_2;
7573
7574   int
7575     diversity;
7576
7577   color_1=(DiversityPacket *) x;
7578   color_2=(DiversityPacket *) y;
7579   diversity=(int) (DiversityPixelIntensity(color_2)-
7580     DiversityPixelIntensity(color_1));
7581   return(diversity);
7582 }
7583
7584 static int PopularityCompare(const void *x,const void *y)
7585 {
7586   DiversityPacket
7587     *color_1,
7588     *color_2;
7589
7590   color_1=(DiversityPacket *) x;
7591   color_2=(DiversityPacket *) y;
7592   return((int) color_2->count-(int) color_1->count);
7593 }
7594
7595 #if defined(__cplusplus) || defined(c_plusplus)
7596 }
7597 #endif
7598
7599 static inline Quantum ScaleXToQuantum(const unsigned long x,
7600   const unsigned long scale)
7601 {
7602   return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7603 }
7604
7605 MagickExport void XMakeStandardColormap(Display *display,
7606   XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7607   XStandardColormap *map_info,XPixelInfo *pixel)
7608 {
7609   Colormap
7610     colormap;
7611
7612   ExceptionInfo
7613     *exception;
7614
7615   register IndexPacket
7616     *indexes;
7617
7618   register long
7619     i;
7620
7621   Status
7622     status;
7623
7624   unsigned long
7625     number_colors,
7626     retain_colors;
7627
7628   unsigned short
7629     gray_value;
7630
7631   XColor
7632     color,
7633     *colors,
7634     *p;
7635
7636   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7637   assert(display != (Display *) NULL);
7638   assert(visual_info != (XVisualInfo *) NULL);
7639   assert(map_info != (XStandardColormap *) NULL);
7640   assert(resource_info != (XResourceInfo *) NULL);
7641   assert(pixel != (XPixelInfo *) NULL);
7642   exception=(&image->exception);
7643   if (resource_info->map_type != (char *) NULL)
7644     {
7645       /*
7646         Standard Colormap is already defined (i.e. xstdcmap).
7647       */
7648       XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7649         pixel);
7650       number_colors=(unsigned int) (map_info->base_pixel+
7651         (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7652       if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7653         if ((image->matte == MagickFalse) &&
7654             (resource_info->color_recovery == MagickFalse) &&
7655             resource_info->quantize_info->dither &&
7656             (number_colors < MaxColormapSize))
7657           {
7658             Image
7659               *affinity_image;
7660
7661             register PixelPacket
7662               *__restrict q;
7663
7664             /*
7665               Improve image appearance with error diffusion.
7666             */
7667             affinity_image=AcquireImage((ImageInfo *) NULL);
7668             if (affinity_image == (Image *) NULL)
7669               ThrowXWindowFatalException(ResourceLimitFatalError,
7670                 "UnableToDitherImage",image->filename);
7671             affinity_image->columns=number_colors;
7672             affinity_image->rows=1;
7673             /*
7674               Initialize colormap image.
7675             */
7676             q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7677               1,exception);
7678             if (q != (PixelPacket *) NULL)
7679               {
7680                 for (i=0; i < (long) number_colors; i++)
7681                 {
7682                   q->red=(Quantum) 0;
7683                   if (map_info->red_max != 0)
7684                     q->red=ScaleXToQuantum((unsigned long) (i/
7685                       map_info->red_mult),map_info->red_max);
7686                   q->green=(Quantum) 0;
7687                   if (map_info->green_max != 0)
7688                     q->green=ScaleXToQuantum((unsigned long) ((i/
7689                       map_info->green_mult) % (map_info->green_max+1)),
7690                       map_info->green_max);
7691                   q->blue=(Quantum) 0;
7692                   if (map_info->blue_max != 0)
7693                     q->blue=ScaleXToQuantum((unsigned long) (i %
7694                       map_info->green_mult),map_info->blue_max);
7695                   q->opacity=(Quantum) TransparentOpacity;
7696                   q++;
7697                 }
7698                 (void) SyncAuthenticPixels(affinity_image,exception);
7699                 (void) RemapImage(resource_info->quantize_info,image,
7700                   affinity_image);
7701               }
7702             XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7703               pixel);
7704             (void) SetImageStorageClass(image,DirectClass);
7705             affinity_image=DestroyImage(affinity_image);
7706           }
7707       if (IsEventLogging())
7708         {
7709           (void) LogMagickEvent(X11Event,GetMagickModule(),
7710             "Standard Colormap:");
7711           (void) LogMagickEvent(X11Event,GetMagickModule(),
7712             "  colormap id: 0x%lx",map_info->colormap);
7713           (void) LogMagickEvent(X11Event,GetMagickModule(),
7714             "  red, green, blue max: %lu %lu %lu",map_info->red_max,
7715             map_info->green_max,map_info->blue_max);
7716           (void) LogMagickEvent(X11Event,GetMagickModule(),
7717             "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7718             map_info->green_mult,map_info->blue_mult);
7719         }
7720       return;
7721     }
7722   if ((visual_info->klass != DirectColor) &&
7723       (visual_info->klass != TrueColor))
7724     if ((image->storage_class == DirectClass) ||
7725         ((int) image->colors > visual_info->colormap_size))
7726       {
7727         QuantizeInfo
7728           quantize_info;
7729
7730         /*
7731           Image has more colors than the visual supports.
7732         */
7733         quantize_info=(*resource_info->quantize_info);
7734         quantize_info.number_colors=(unsigned long) visual_info->colormap_size;
7735         (void) QuantizeImage(&quantize_info,image);
7736       }
7737   /*
7738     Free previous and create new colormap.
7739   */
7740   (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7741   colormap=XDefaultColormap(display,visual_info->screen);
7742   if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7743     colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7744       visual_info->visual,visual_info->klass == DirectColor ?
7745       AllocAll : AllocNone);
7746   if (colormap == (Colormap) NULL)
7747     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7748       image->filename);
7749   /*
7750     Initialize the map and pixel info structures.
7751   */
7752   XGetMapInfo(visual_info,colormap,map_info);
7753   XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7754   /*
7755     Allocating colors in server colormap is based on visual class.
7756   */
7757   switch (visual_info->klass)
7758   {
7759     case StaticGray:
7760     case StaticColor:
7761     {
7762       /*
7763         Define Standard Colormap for StaticGray or StaticColor visual.
7764       */
7765       number_colors=image->colors;
7766       colors=(XColor *) AcquireQuantumMemory((size_t)
7767         visual_info->colormap_size,sizeof(*colors));
7768       if (colors == (XColor *) NULL)
7769         ThrowXWindowFatalException(ResourceLimitFatalError,
7770           "UnableToCreateColormap",image->filename);
7771       p=colors;
7772       color.flags=(char) (DoRed | DoGreen | DoBlue);
7773       for (i=0; i < (long) image->colors; i++)
7774       {
7775         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7776         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7777         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7778         if (visual_info->klass != StaticColor)
7779           {
7780             gray_value=(unsigned short) XPixelIntensity(&color);
7781             color.red=gray_value;
7782             color.green=gray_value;
7783             color.blue=gray_value;
7784           }
7785         status=XAllocColor(display,colormap,&color);
7786         if (status == False)
7787           {
7788             colormap=XCopyColormapAndFree(display,colormap);
7789             (void) XAllocColor(display,colormap,&color);
7790           }
7791         pixel->pixels[i]=color.pixel;
7792         *p++=color;
7793       }
7794       break;
7795     }
7796     case GrayScale:
7797     case PseudoColor:
7798     {
7799       unsigned int
7800         colormap_type;
7801
7802       /*
7803         Define Standard Colormap for GrayScale or PseudoColor visual.
7804       */
7805       number_colors=image->colors;
7806       colors=(XColor *) AcquireQuantumMemory((size_t)
7807         visual_info->colormap_size,sizeof(*colors));
7808       if (colors == (XColor *) NULL)
7809         ThrowXWindowFatalException(ResourceLimitFatalError,
7810           "UnableToCreateColormap",image->filename);
7811       /*
7812         Preallocate our GUI colors.
7813       */
7814       (void) XAllocColor(display,colormap,&pixel->foreground_color);
7815       (void) XAllocColor(display,colormap,&pixel->background_color);
7816       (void) XAllocColor(display,colormap,&pixel->border_color);
7817       (void) XAllocColor(display,colormap,&pixel->matte_color);
7818       (void) XAllocColor(display,colormap,&pixel->highlight_color);
7819       (void) XAllocColor(display,colormap,&pixel->shadow_color);
7820       (void) XAllocColor(display,colormap,&pixel->depth_color);
7821       (void) XAllocColor(display,colormap,&pixel->trough_color);
7822       for (i=0; i < MaxNumberPens; i++)
7823         (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7824       /*
7825         Determine if image colors will "fit" into X server colormap.
7826       */
7827       colormap_type=resource_info->colormap;
7828       status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7829         NULL,0,pixel->pixels,(unsigned int) image->colors);
7830       if (status != False)
7831         colormap_type=PrivateColormap;
7832       if (colormap_type == SharedColormap)
7833         {
7834           DiversityPacket
7835             *diversity;
7836
7837           int
7838             y;
7839
7840           register int
7841             x;
7842
7843           unsigned short
7844             index;
7845
7846           XColor
7847             *server_colors;
7848
7849           /*
7850             Define Standard colormap for shared GrayScale or PseudoColor visual.
7851           */
7852           diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7853             sizeof(*diversity));
7854           if (diversity == (DiversityPacket *) NULL)
7855             ThrowXWindowFatalException(ResourceLimitFatalError,
7856               "UnableToCreateColormap",image->filename);
7857           for (i=0; i < (long) image->colors; i++)
7858           {
7859             diversity[i].red=image->colormap[i].red;
7860             diversity[i].green=image->colormap[i].green;
7861             diversity[i].blue=image->colormap[i].blue;
7862             diversity[i].index=(unsigned short) i;
7863             diversity[i].count=0;
7864           }
7865           for (y=0; y < (int) image->rows; y++)
7866           {
7867             register long
7868               x;
7869
7870             register PixelPacket
7871               *__restrict q;
7872
7873             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
7874             if (q == (PixelPacket *) NULL)
7875               break;
7876             indexes=GetAuthenticIndexQueue(image);
7877             for (x=(long) image->columns-1; x >= 0; x--)
7878               diversity[(long) indexes[x]].count++;
7879           }
7880           /*
7881             Sort colors by decreasing intensity.
7882           */
7883           qsort((void *) diversity,image->colors,sizeof(*diversity),
7884             IntensityCompare);
7885           for (i=0; i < (long) image->colors; )
7886           {
7887             diversity[i].count<<=4;  /* increase this colors popularity */
7888             i+=MagickMax((long) (image->colors >> 4),2);
7889           }
7890           diversity[image->colors-1].count<<=4;
7891           qsort((void *) diversity,image->colors,sizeof(*diversity),
7892             PopularityCompare);
7893           /*
7894             Allocate colors.
7895           */
7896           p=colors;
7897           color.flags=(char) (DoRed | DoGreen | DoBlue);
7898           for (i=0; i < (long) image->colors; i++)
7899           {
7900             index=diversity[i].index;
7901             color.red=
7902               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7903             color.green=
7904               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7905             color.blue=
7906               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7907             if (visual_info->klass != PseudoColor)
7908               {
7909                 gray_value=(unsigned short) XPixelIntensity(&color);
7910                 color.red=gray_value;
7911                 color.green=gray_value;
7912                 color.blue=gray_value;
7913               }
7914             status=XAllocColor(display,colormap,&color);
7915             if (status == False)
7916               break;
7917             pixel->pixels[index]=color.pixel;
7918             *p++=color;
7919           }
7920           /*
7921             Read X server colormap.
7922           */
7923           server_colors=(XColor *) AcquireQuantumMemory((size_t)
7924             visual_info->colormap_size,sizeof(*server_colors));
7925           if (server_colors == (XColor *) NULL)
7926             ThrowXWindowFatalException(ResourceLimitFatalError,
7927               "UnableToCreateColormap",image->filename);
7928           for (x=visual_info->colormap_size-1; x >= 0; x--)
7929             server_colors[x].pixel=(unsigned long) x;
7930           (void) XQueryColors(display,colormap,server_colors,
7931             (int) MagickMin((unsigned int) visual_info->colormap_size,256));
7932           /*
7933             Select remaining colors from X server colormap.
7934           */
7935           for (; i < (long) image->colors; i++)
7936           {
7937             index=diversity[i].index;
7938             color.red=
7939               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7940             color.green=
7941               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7942             color.blue=
7943               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7944             if (visual_info->klass != PseudoColor)
7945               {
7946                 gray_value=(unsigned short) XPixelIntensity(&color);
7947                 color.red=gray_value;
7948                 color.green=gray_value;
7949                 color.blue=gray_value;
7950               }
7951             XBestPixel(display,colormap,server_colors,(unsigned int)
7952               visual_info->colormap_size,&color);
7953             pixel->pixels[index]=color.pixel;
7954             *p++=color;
7955           }
7956           if ((int) image->colors < visual_info->colormap_size)
7957             {
7958               /*
7959                 Fill up colors array-- more choices for pen colors.
7960               */
7961               retain_colors=MagickMin((unsigned int)
7962                (visual_info->colormap_size-image->colors),256);
7963               for (i=0; i < (long) retain_colors; i++)
7964                 *p++=server_colors[i];
7965               number_colors+=retain_colors;
7966             }
7967           server_colors=(XColor *) RelinquishMagickMemory(server_colors);
7968           diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
7969           break;
7970         }
7971       /*
7972         Define Standard colormap for private GrayScale or PseudoColor visual.
7973       */
7974       if (status == False)
7975         {
7976           /*
7977             Not enough colormap entries in the colormap-- Create a new colormap.
7978           */
7979           colormap=XCreateColormap(display,
7980             XRootWindow(display,visual_info->screen),visual_info->visual,
7981             AllocNone);
7982           if (colormap == (Colormap) NULL)
7983             ThrowXWindowFatalException(ResourceLimitFatalError,
7984               "UnableToCreateColormap",image->filename);
7985           map_info->colormap=colormap;
7986           if ((int) image->colors < visual_info->colormap_size)
7987             {
7988               /*
7989                 Retain colors from the default colormap to help lessens the
7990                 effects of colormap flashing.
7991               */
7992               retain_colors=MagickMin((unsigned int)
7993                 (visual_info->colormap_size-image->colors),256);
7994               p=colors+image->colors;
7995               for (i=0; i < (long) retain_colors; i++)
7996               {
7997                 p->pixel=(unsigned long) i;
7998                 p++;
7999               }
8000               (void) XQueryColors(display,
8001                 XDefaultColormap(display,visual_info->screen),
8002                 colors+image->colors,(int) retain_colors);
8003               /*
8004                 Transfer colors from default to private colormap.
8005               */
8006               (void) XAllocColorCells(display,colormap,MagickFalse,
8007                 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8008                 retain_colors);
8009               p=colors+image->colors;
8010               for (i=0; i < (long) retain_colors; i++)
8011               {
8012                 p->pixel=pixel->pixels[i];
8013                 p++;
8014               }
8015               (void) XStoreColors(display,colormap,colors+image->colors,
8016                 (int) retain_colors);
8017               number_colors+=retain_colors;
8018             }
8019           (void) XAllocColorCells(display,colormap,MagickFalse,
8020             (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8021             image->colors);
8022         }
8023       /*
8024         Store the image colormap.
8025       */
8026       p=colors;
8027       color.flags=(char) (DoRed | DoGreen | DoBlue);
8028       for (i=0; i < (long) image->colors; i++)
8029       {
8030         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8031         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8032         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8033         if (visual_info->klass != PseudoColor)
8034           {
8035             gray_value=(unsigned short) XPixelIntensity(&color);
8036             color.red=gray_value;
8037             color.green=gray_value;
8038             color.blue=gray_value;
8039           }
8040         color.pixel=pixel->pixels[i];
8041         *p++=color;
8042       }
8043       (void) XStoreColors(display,colormap,colors,(int) image->colors);
8044       break;
8045     }
8046     case TrueColor:
8047     case DirectColor:
8048     default:
8049     {
8050       MagickBooleanType
8051         linear_colormap;
8052
8053       /*
8054         Define Standard Colormap for TrueColor or DirectColor visual.
8055       */
8056       number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8057         (map_info->green_max*map_info->green_mult)+
8058         (map_info->blue_max*map_info->blue_mult)+1);
8059       linear_colormap=(number_colors > 4096) ||
8060         (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8061          ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8062          ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8063          MagickTrue : MagickFalse;
8064       if (linear_colormap != MagickFalse)
8065         number_colors=(unsigned long) visual_info->colormap_size;
8066       /*
8067         Allocate color array.
8068       */
8069       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8070       if (colors == (XColor *) NULL)
8071         ThrowXWindowFatalException(ResourceLimitFatalError,
8072           "UnableToCreateColormap",image->filename);
8073       /*
8074         Initialize linear color ramp.
8075       */
8076       p=colors;
8077       color.flags=(char) (DoRed | DoGreen | DoBlue);
8078       if (linear_colormap != MagickFalse)
8079         for (i=0; i < (long) number_colors; i++)
8080         {
8081           color.blue=(unsigned short) 0;
8082           if (map_info->blue_max != 0)
8083             color.blue=(unsigned short) ((unsigned long)
8084               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8085           color.green=color.blue;
8086           color.red=color.blue;
8087           color.pixel=XStandardPixel(map_info,&color);
8088           *p++=color;
8089         }
8090       else
8091         for (i=0; i < (long) number_colors; i++)
8092         {
8093           color.red=(unsigned short) 0;
8094           if (map_info->red_max != 0)
8095             color.red=(unsigned short) ((unsigned long)
8096               ((65535L*(i/map_info->red_mult))/map_info->red_max));
8097           color.green=(unsigned int) 0;
8098           if (map_info->green_max != 0)
8099             color.green=(unsigned short) ((unsigned long)
8100               ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8101                 map_info->green_max));
8102           color.blue=(unsigned short) 0;
8103           if (map_info->blue_max != 0)
8104             color.blue=(unsigned short) ((unsigned long)
8105               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8106           color.pixel=XStandardPixel(map_info,&color);
8107           *p++=color;
8108         }
8109       if ((visual_info->klass == DirectColor) &&
8110           (colormap != XDefaultColormap(display,visual_info->screen)))
8111         (void) XStoreColors(display,colormap,colors,(int) number_colors);
8112       else
8113         for (i=0; i < (long) number_colors; i++)
8114           (void) XAllocColor(display,colormap,&colors[i]);
8115       break;
8116     }
8117   }
8118   if ((visual_info->klass != DirectColor) &&
8119       (visual_info->klass != TrueColor))
8120     {
8121       /*
8122         Set foreground, background, border, etc. pixels.
8123       */
8124       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8125         &pixel->foreground_color);
8126       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8127         &pixel->background_color);
8128       if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8129         {
8130           /*
8131             Foreground and background colors must differ.
8132           */
8133           pixel->background_color.red=(~pixel->foreground_color.red);
8134           pixel->background_color.green=
8135             (~pixel->foreground_color.green);
8136           pixel->background_color.blue=
8137             (~pixel->foreground_color.blue);
8138           XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8139             &pixel->background_color);
8140         }
8141       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8142         &pixel->border_color);
8143       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8144         &pixel->matte_color);
8145       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8146         &pixel->highlight_color);
8147       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8148         &pixel->shadow_color);
8149       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8150         &pixel->depth_color);
8151       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8152         &pixel->trough_color);
8153       for (i=0; i < MaxNumberPens; i++)
8154       {
8155         XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8156           &pixel->pen_colors[i]);
8157         pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8158       }
8159       pixel->colors=image->colors+MaxNumberPens;
8160     }
8161   colors=(XColor *) RelinquishMagickMemory(colors);
8162   if (IsEventLogging())
8163     {
8164       (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8165       (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
8166         map_info->colormap);
8167       (void) LogMagickEvent(X11Event,GetMagickModule(),
8168         "  red, green, blue max: %lu %lu %lu",map_info->red_max,
8169         map_info->green_max,map_info->blue_max);
8170       (void) LogMagickEvent(X11Event,GetMagickModule(),
8171         "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8172         map_info->green_mult,map_info->blue_mult);
8173     }
8174 }
8175 \f
8176 /*
8177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8178 %                                                                             %
8179 %                                                                             %
8180 %                                                                             %
8181 %   X M a k e W i n d o w                                                     %
8182 %                                                                             %
8183 %                                                                             %
8184 %                                                                             %
8185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8186 %
8187 %  XMakeWindow() creates an X11 window.
8188 %
8189 %  The format of the XMakeWindow method is:
8190 %
8191 %      void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8192 %        XClassHint *class_hint,XWMHints *manager_hints,
8193 %        XWindowInfo *window_info)
8194 %
8195 %  A description of each parameter follows:
8196 %
8197 %    o display: Specifies a connection to an X server; returned from
8198 %      XOpenDisplay.
8199 %
8200 %    o parent: Specifies the parent window_info.
8201 %
8202 %    o argv: Specifies the application's argument list.
8203 %
8204 %    o argc: Specifies the number of arguments.
8205 %
8206 %    o class_hint: Specifies a pointer to a X11 XClassHint structure.
8207 %
8208 %    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8209 %
8210 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8211 %
8212 */
8213 MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8214   int argc,XClassHint *class_hint,XWMHints *manager_hints,
8215   XWindowInfo *window_info)
8216 {
8217 #define MinWindowSize  64
8218
8219   Atom
8220     atom_list[2];
8221
8222   int
8223     gravity;
8224
8225   static XTextProperty
8226     icon_name,
8227     window_name;
8228
8229   Status
8230     status;
8231
8232   XSizeHints
8233     *size_hints;
8234
8235   /*
8236     Set window info hints.
8237   */
8238   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8239   assert(display != (Display *) NULL);
8240   assert(window_info != (XWindowInfo *) NULL);
8241   size_hints=XAllocSizeHints();
8242   if (size_hints == (XSizeHints *) NULL)
8243     ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8244   size_hints->flags=(long) window_info->flags;
8245   size_hints->x=window_info->x;
8246   size_hints->y=window_info->y;
8247   size_hints->width=(int) window_info->width;
8248   size_hints->height=(int) window_info->height;
8249   if (window_info->immutable != MagickFalse)
8250     {
8251       /*
8252         Window size cannot be changed.
8253       */
8254       size_hints->min_width=size_hints->width;
8255       size_hints->min_height=size_hints->height;
8256       size_hints->max_width=size_hints->width;
8257       size_hints->max_height=size_hints->height;
8258       size_hints->flags|=PMinSize;
8259       size_hints->flags|=PMaxSize;
8260     }
8261   else
8262     {
8263       /*
8264         Window size can be changed.
8265       */
8266       size_hints->min_width=(int) window_info->min_width;
8267       size_hints->min_height=(int) window_info->min_height;
8268       size_hints->flags|=PResizeInc;
8269       size_hints->width_inc=(int) window_info->width_inc;
8270       size_hints->height_inc=(int) window_info->height_inc;
8271 #if !defined(PRE_R4_ICCCM)
8272       size_hints->flags|=PBaseSize;
8273       size_hints->base_width=size_hints->width_inc;
8274       size_hints->base_height=size_hints->height_inc;
8275 #endif
8276     }
8277   gravity=NorthWestGravity;
8278   if (window_info->geometry != (char *) NULL)
8279     {
8280       char
8281         default_geometry[MaxTextExtent],
8282         geometry[MaxTextExtent];
8283
8284       int
8285         flags;
8286
8287       register char
8288         *p;
8289
8290       /*
8291         User specified geometry.
8292       */
8293       (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8294         size_hints->width,size_hints->height);
8295       (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8296       p=geometry;
8297       while (strlen(p) != 0)
8298       {
8299         if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8300           p++;
8301         else
8302           (void) CopyMagickString(p,p+1,MaxTextExtent);
8303       }
8304       flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8305         window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8306         &size_hints->width,&size_hints->height,&gravity);
8307       if ((flags & WidthValue) && (flags & HeightValue))
8308         size_hints->flags|=USSize;
8309       if ((flags & XValue) && (flags & YValue))
8310         {
8311           size_hints->flags|=USPosition;
8312           window_info->x=size_hints->x;
8313           window_info->y=size_hints->y;
8314         }
8315     }
8316 #if !defined(PRE_R4_ICCCM)
8317   size_hints->win_gravity=gravity;
8318   size_hints->flags|=PWinGravity;
8319 #endif
8320   if (window_info->id == (Window) NULL)
8321     window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8322       (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8323       window_info->border_width,(int) window_info->depth,InputOutput,
8324       window_info->visual,window_info->mask,&window_info->attributes);
8325   else
8326     {
8327       MagickStatusType
8328         mask;
8329
8330       XEvent
8331         sans_event;
8332
8333       XWindowChanges
8334         window_changes;
8335
8336       /*
8337         Window already exists;  change relevant attributes.
8338       */
8339       (void) XChangeWindowAttributes(display,window_info->id,window_info->mask,
8340         &window_info->attributes);
8341       mask=ConfigureNotify;
8342       while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8343       window_changes.x=window_info->x;
8344       window_changes.y=window_info->y;
8345       window_changes.width=(int) window_info->width;
8346       window_changes.height=(int) window_info->height;
8347       mask=(MagickStatusType) (CWWidth | CWHeight);
8348       if (window_info->flags & USPosition)
8349         mask|=CWX | CWY;
8350       (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8351         mask,&window_changes);
8352     }
8353   if (window_info->id == (Window) NULL)
8354     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8355       window_info->name);
8356   status=XStringListToTextProperty(&window_info->name,1,&window_name);
8357   if (status == False)
8358     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8359       window_info->name);
8360   status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8361   if (status == False)
8362     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8363       window_info->icon_name);
8364   if (window_info->icon_geometry != (char *) NULL)
8365     {
8366       int
8367         flags,
8368         height,
8369         width;
8370
8371       /*
8372         User specified icon geometry.
8373       */
8374       size_hints->flags|=USPosition;
8375       flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8376         (char *) NULL,0,size_hints,&manager_hints->icon_x,
8377         &manager_hints->icon_y,&width,&height,&gravity);
8378       if ((flags & XValue) && (flags & YValue))
8379         manager_hints->flags|=IconPositionHint;
8380     }
8381   XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8382     size_hints,manager_hints,class_hint);
8383   if (window_name.value != (void *) NULL)
8384     {
8385       (void) XFree((void *) window_name.value);
8386       window_name.value=(unsigned char *) NULL;
8387       window_name.nitems=0;
8388     }
8389   if (icon_name.value != (void *) NULL)
8390     {
8391       (void) XFree((void *) icon_name.value);
8392       icon_name.value=(unsigned char *) NULL;
8393       icon_name.nitems=0;
8394     }
8395   atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8396   atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8397   (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8398   (void) XFree((void *) size_hints);
8399   if (window_info->shape != MagickFalse)
8400     {
8401 #if defined(MAGICKCORE_HAVE_SHAPE)
8402       int
8403         error_base,
8404         event_base;
8405
8406       /*
8407         Can we apply a non-rectangular shaping mask?
8408       */
8409       error_base=0;
8410       event_base=0;
8411       if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8412         window_info->shape=MagickFalse;
8413 #else
8414       window_info->shape=MagickFalse;
8415 #endif
8416     }
8417   if (window_info->shared_memory)
8418     {
8419 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8420       /*
8421         Can we use shared memory with this window?
8422       */
8423       if (XShmQueryExtension(display) == 0)
8424         window_info->shared_memory=MagickFalse;
8425 #else
8426       window_info->shared_memory=MagickFalse;
8427 #endif
8428     }
8429   window_info->image=NewImageList();
8430   window_info->destroy=MagickFalse;
8431 }
8432 \f
8433 /*
8434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8435 %                                                                             %
8436 %                                                                             %
8437 %                                                                             %
8438 %   X M a g i c k P r o g r e s s M o n i t o r                               %
8439 %                                                                             %
8440 %                                                                             %
8441 %                                                                             %
8442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8443 %
8444 %  XMagickProgressMonitor() displays the progress a task is making in
8445 %  completing a task.
8446 %
8447 %  The format of the XMagickProgressMonitor method is:
8448 %
8449 %      void XMagickProgressMonitor(const char *task,
8450 %        const MagickOffsetType quantum,const MagickSizeType span,
8451 %        void *client_data)
8452 %
8453 %  A description of each parameter follows:
8454 %
8455 %    o task: Identifies the task in progress.
8456 %
8457 %    o quantum: Specifies the quantum position within the span which represents
8458 %      how much progress has been made in completing a task.
8459 %
8460 %    o span: Specifies the span relative to completing a task.
8461 %
8462 %    o client_data: Pointer to any client data.
8463 %
8464 */
8465
8466 static const char *GetLocaleMonitorMessage(const char *text)
8467 {
8468   char
8469     message[MaxTextExtent],
8470     tag[MaxTextExtent];
8471
8472   const char
8473     *locale_message;
8474
8475   register char
8476     *p;
8477
8478   (void) CopyMagickMemory(tag,text,MaxTextExtent);
8479   p=strrchr(tag,'/');
8480   if (p != (char *) NULL)
8481     *p='\0';
8482   (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8483   locale_message=GetLocaleMessage(message);
8484   if (locale_message == message)
8485     return(text);
8486   return(locale_message);
8487 }
8488
8489 MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8490   const MagickOffsetType quantum,const MagickSizeType span,
8491   void *magick_unused(client_data))
8492 {
8493   XWindows
8494     *windows;
8495
8496   windows=XSetWindows((XWindows *) ~0);
8497   if (windows == (XWindows *) NULL)
8498     return(MagickTrue);
8499   if (windows->info.mapped != MagickFalse)
8500     XProgressMonitorWidget(windows->display,windows,
8501       GetLocaleMonitorMessage(tag),quantum,span);
8502   return(MagickTrue);
8503 }
8504 \f
8505 /*
8506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8507 %                                                                             %
8508 %                                                                             %
8509 %                                                                             %
8510 %   X Q u e r y C o l o r D a t a b a s e                                     %
8511 %                                                                             %
8512 %                                                                             %
8513 %                                                                             %
8514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8515 %
8516 %  XQueryColorDatabase() looks up a RGB values for a color given in the target
8517 %  string.
8518 %
8519 %  The format of the XQueryColorDatabase method is:
8520 %
8521 %      MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8522 %
8523 %  A description of each parameter follows:
8524 %
8525 %    o target: Specifies the color to lookup in the X color database.
8526 %
8527 %    o color: A pointer to an PixelPacket structure.  The RGB value of the target
8528 %      color is returned as this value.
8529 %
8530 */
8531 MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8532   XColor *color)
8533 {
8534   Colormap
8535     colormap;
8536
8537   static Display
8538     *display = (Display *) NULL;
8539
8540   Status
8541     status;
8542
8543   XColor
8544     xcolor;
8545
8546   /*
8547     Initialize color return value.
8548   */
8549   assert(color != (XColor *) NULL);
8550   color->red=0;
8551   color->green=0;
8552   color->blue=0;
8553   color->flags=(char) (DoRed | DoGreen | DoBlue);
8554   if ((target == (char *) NULL) || (*target == '\0'))
8555     target="#ffffffffffff";
8556   /*
8557     Let the X server define the color for us.
8558   */
8559   if (display == (Display *) NULL)
8560     display=XOpenDisplay((char *) NULL);
8561   if (display == (Display *) NULL)
8562     {
8563       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8564       return(MagickFalse);
8565     }
8566   colormap=XDefaultColormap(display,XDefaultScreen(display));
8567   status=XParseColor(display,colormap,(char *) target,&xcolor);
8568   if (status == False)
8569     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8570   else
8571     {
8572       color->red=xcolor.red;
8573       color->green=xcolor.green;
8574       color->blue=xcolor.blue;
8575       color->flags=xcolor.flags;
8576     }
8577   return(status != False ? MagickTrue : MagickFalse);
8578 }
8579 \f
8580 /*
8581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8582 %                                                                             %
8583 %                                                                             %
8584 %                                                                             %
8585 %   X Q u e r y P o s i t i o n                                               %
8586 %                                                                             %
8587 %                                                                             %
8588 %                                                                             %
8589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8590 %
8591 %  XQueryPosition() gets the pointer coordinates relative to a window.
8592 %
8593 %  The format of the XQueryPosition method is:
8594 %
8595 %      void XQueryPosition(Display *display,const Window window,int *x,int *y)
8596 %
8597 %  A description of each parameter follows:
8598 %
8599 %    o display: Specifies a connection to an X server;  returned from
8600 %      XOpenDisplay.
8601 %
8602 %    o window: Specifies a pointer to a Window.
8603 %
8604 %    o x: Return the x coordinate of the pointer relative to the origin of the
8605 %      window.
8606 %
8607 %    o y: Return the y coordinate of the pointer relative to the origin of the
8608 %      window.
8609 %
8610 */
8611 MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8612 {
8613   int
8614     x_root,
8615     y_root;
8616
8617   unsigned int
8618     mask;
8619
8620   Window
8621     root_window;
8622
8623   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8624   assert(display != (Display *) NULL);
8625   assert(window != (Window) NULL);
8626   assert(x != (int *) NULL);
8627   assert(y != (int *) NULL);
8628   (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8629     x,y,&mask);
8630 }
8631 \f
8632 /*
8633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8634 %                                                                             %
8635 %                                                                             %
8636 %                                                                             %
8637 %   X R e f r e s h W i n d o w                                               %
8638 %                                                                             %
8639 %                                                                             %
8640 %                                                                             %
8641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8642 %
8643 %  XRefreshWindow() refreshes an image in a X window.
8644 %
8645 %  The format of the XRefreshWindow method is:
8646 %
8647 %      void XRefreshWindow(Display *display,const XWindowInfo *window,
8648 %        const XEvent *event)
8649 %
8650 %  A description of each parameter follows:
8651 %
8652 %    o display: Specifies a connection to an X server;  returned from
8653 %      XOpenDisplay.
8654 %
8655 %    o window: Specifies a pointer to a XWindowInfo structure.
8656 %
8657 %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
8658 %      the entire image is refreshed.
8659 %
8660 */
8661 MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8662   const XEvent *event)
8663 {
8664   int
8665     x,
8666     y;
8667
8668   unsigned int
8669     height,
8670     width;
8671
8672   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8673   assert(display != (Display *) NULL);
8674   assert(window != (XWindowInfo *) NULL);
8675   if (window->ximage == (XImage *) NULL)
8676     return;
8677   if (event != (XEvent *) NULL)
8678     {
8679       /*
8680         Determine geometry from expose event.
8681       */
8682       x=event->xexpose.x;
8683       y=event->xexpose.y;
8684       width=(unsigned int) event->xexpose.width;
8685       height=(unsigned int) event->xexpose.height;
8686     }
8687   else
8688     {
8689       XEvent
8690         sans_event;
8691
8692       /*
8693         Refresh entire window; discard outstanding expose events.
8694       */
8695       x=0;
8696       y=0;
8697       width=window->width;
8698       height=window->height;
8699       while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8700     }
8701   /*
8702     Check boundary conditions.
8703   */
8704   if ((window->ximage->width-(x+window->x)) < (int) width)
8705     width=(unsigned int) (window->ximage->width-(x+window->x));
8706   if ((window->ximage->height-(y+window->y)) < (int) height)
8707     height=(unsigned int) (window->ximage->height-(y+window->y));
8708   /*
8709     Refresh image.
8710   */
8711   if (window->matte_pixmap != (Pixmap) NULL)
8712     {
8713 #if defined(MAGICKCORE_HAVE_SHAPE)
8714       if (window->shape != MagickFalse)
8715         XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8716           window->matte_pixmap,ShapeSet);
8717 #endif
8718       (void) XSetClipMask(display,window->annotate_context,
8719         window->matte_pixmap);
8720     }
8721   if (window->pixmap != (Pixmap) NULL)
8722     {
8723       if (window->depth > 1)
8724         (void) XCopyArea(display,window->pixmap,window->id,
8725           window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8726       else
8727         (void) XCopyPlane(display,window->pixmap,window->id,
8728           window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8729           1L);
8730     }
8731   else
8732     {
8733 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8734       if (window->shared_memory)
8735         (void) XShmPutImage(display,window->id,window->annotate_context,
8736           window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8737 #endif
8738       if (window->shared_memory == MagickFalse)
8739         (void) XPutImage(display,window->id,window->annotate_context,
8740           window->ximage,x+window->x,y+window->y,x,y,width,height);
8741     }
8742   if (window->matte_pixmap != (Pixmap) NULL)
8743     (void) XSetClipMask(display,window->annotate_context,None);
8744   (void) XFlush(display);
8745 }
8746 \f
8747 /*
8748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8749 %                                                                             %
8750 %                                                                             %
8751 %                                                                             %
8752 %   X R e m o t e C o m m a n d                                               %
8753 %                                                                             %
8754 %                                                                             %
8755 %                                                                             %
8756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8757 %
8758 %  XRemoteCommand() forces a remote display(1) to display the specified
8759 %  image filename.
8760 %
8761 %  The format of the XRemoteCommand method is:
8762 %
8763 %      MagickBooleanType XRemoteCommand(Display *display,const char *window,
8764 %        const char *filename)
8765 %
8766 %  A description of each parameter follows:
8767 %
8768 %    o display: Specifies a connection to an X server; returned from
8769 %      XOpenDisplay.
8770 %
8771 %    o window: Specifies the name or id of an X window.
8772 %
8773 %    o filename: the name of the image filename to display.
8774 %
8775 */
8776 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8777   const char *window,const char *filename)
8778 {
8779   Atom
8780     remote_atom;
8781
8782   Window
8783     remote_window,
8784     root_window;
8785
8786   assert(filename != (char *) NULL);
8787   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8788   if (display == (Display *) NULL)
8789     display=XOpenDisplay((char *) NULL);
8790   if (display == (Display *) NULL)
8791     {
8792       ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8793       return(MagickFalse);
8794     }
8795   remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8796   remote_window=(Window) NULL;
8797   root_window=XRootWindow(display,XDefaultScreen(display));
8798   if (window != (char *) NULL)
8799     {
8800       /*
8801         Search window hierarchy and identify any clients by name or ID.
8802       */
8803       if (isdigit((unsigned char) *window) != 0)
8804         remote_window=XWindowByID(display,root_window,(Window)
8805           strtol((char *) window,(char **) NULL,0));
8806       if (remote_window == (Window) NULL)
8807         remote_window=XWindowByName(display,root_window,window);
8808     }
8809   if (remote_window == (Window) NULL)
8810     remote_window=XWindowByProperty(display,root_window,remote_atom);
8811   if (remote_window == (Window) NULL)
8812     {
8813       ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8814         filename);
8815       return(MagickFalse);
8816     }
8817   /*
8818     Send remote command.
8819   */
8820   remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8821   (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8822     PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8823   (void) XSync(display,MagickFalse);
8824   return(MagickTrue);
8825 }
8826 \f
8827 /*
8828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8829 %                                                                             %
8830 %                                                                             %
8831 %                                                                             %
8832 %   X R e t a i n W i n d o w C o l o r s                                     %
8833 %                                                                             %
8834 %                                                                             %
8835 %                                                                             %
8836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8837 %
8838 %  XRetainWindowColors() sets X11 color resources on a window.  This preserves
8839 %  the colors associated with an image displayed on the window.
8840 %
8841 %  The format of the XRetainWindowColors method is:
8842 %
8843 %      void XRetainWindowColors(Display *display,const Window window)
8844 %
8845 %  A description of each parameter follows:
8846 %
8847 %    o display: Specifies a connection to an X server; returned from
8848 %      XOpenDisplay.
8849 %
8850 %    o window: Specifies a pointer to a XWindowInfo structure.
8851 %
8852 */
8853 MagickExport void XRetainWindowColors(Display *display,const Window window)
8854 {
8855   Atom
8856     property;
8857
8858   Pixmap
8859     pixmap;
8860
8861   /*
8862     Put property on the window.
8863   */
8864   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8865   assert(display != (Display *) NULL);
8866   assert(window != (Window) NULL);
8867   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8868   if (property == (Atom) NULL)
8869     {
8870       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8871         "_XSETROOT_ID");
8872       return;
8873     }
8874   pixmap=XCreatePixmap(display,window,1,1,1);
8875   if (pixmap == (Pixmap) NULL)
8876     {
8877       ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8878       return;
8879     }
8880   (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8881     (unsigned char *) &pixmap,1);
8882   (void) XSetCloseDownMode(display,RetainPermanent);
8883 }
8884 \f
8885 /*
8886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8887 %                                                                             %
8888 %                                                                             %
8889 %                                                                             %
8890 %   X S e l e c t W i n d o w                                                 %
8891 %                                                                             %
8892 %                                                                             %
8893 %                                                                             %
8894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8895 %
8896 %  XSelectWindow() allows a user to select a window using the mouse.  If the
8897 %  mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8898 %  is returned in the crop_info structure.
8899 %
8900 %  The format of the XSelectWindow function is:
8901 %
8902 %      target_window=XSelectWindow(display,crop_info)
8903 %
8904 %  A description of each parameter follows:
8905 %
8906 %    o window: XSelectWindow returns the window id.
8907 %
8908 %    o display: Specifies a pointer to the Display structure;  returned from
8909 %      XOpenDisplay.
8910 %
8911 %    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
8912 %      contains the extents of any cropping rectangle.
8913 %
8914 %
8915 */
8916 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8917 {
8918 #define MinimumCropArea  (unsigned int) 9
8919
8920   Cursor
8921     target_cursor;
8922
8923   GC
8924     annotate_context;
8925
8926   int
8927     presses,
8928     x_offset,
8929     y_offset;
8930
8931   Status
8932     status;
8933
8934   Window
8935     root_window,
8936     target_window;
8937
8938   XEvent
8939     event;
8940
8941   XGCValues
8942     context_values;
8943
8944   /*
8945     Initialize graphic context.
8946   */
8947   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8948   assert(display != (Display *) NULL);
8949   assert(crop_info != (RectangleInfo *) NULL);
8950   root_window=XRootWindow(display,XDefaultScreen(display));
8951   context_values.background=XBlackPixel(display,XDefaultScreen(display));
8952   context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
8953   context_values.function=GXinvert;
8954   context_values.plane_mask=
8955     context_values.background ^ context_values.foreground;
8956   context_values.subwindow_mode=IncludeInferiors;
8957   annotate_context=XCreateGC(display,root_window,(unsigned long) (GCBackground |
8958     GCForeground | GCFunction | GCSubwindowMode),&context_values);
8959   if (annotate_context == (GC) NULL)
8960     return(MagickFalse);
8961   /*
8962     Grab the pointer using target cursor.
8963   */
8964   target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
8965     XDefaultScreen(display)),(char * ) "white",(char * ) "black");
8966   status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
8967     (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
8968     GrabModeAsync,root_window,target_cursor,CurrentTime);
8969   if (status != GrabSuccess)
8970     {
8971       ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
8972       return((Window) NULL);
8973     }
8974   /*
8975     Select a window.
8976   */
8977   crop_info->width=0;
8978   crop_info->height=0;
8979   presses=0;
8980   target_window=(Window) NULL;
8981   x_offset=0;
8982   y_offset=0;
8983   do
8984   {
8985     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
8986       (void) XDrawRectangle(display,root_window,annotate_context,
8987         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
8988         (unsigned int) crop_info->height-1);
8989     /*
8990       Allow another event.
8991     */
8992     (void) XAllowEvents(display,SyncPointer,CurrentTime);
8993     (void) XWindowEvent(display,root_window,ButtonPressMask |
8994       ButtonReleaseMask | ButtonMotionMask,&event);
8995     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
8996       (void) XDrawRectangle(display,root_window,annotate_context,
8997         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
8998         (unsigned int) crop_info->height-1);
8999     switch (event.type)
9000     {
9001       case ButtonPress:
9002       {
9003         target_window=XGetSubwindow(display,event.xbutton.subwindow,
9004           event.xbutton.x,event.xbutton.y);
9005         if (target_window == (Window) NULL)
9006           target_window=root_window;
9007         x_offset=event.xbutton.x_root;
9008         y_offset=event.xbutton.y_root;
9009         crop_info->x=x_offset;
9010         crop_info->y=y_offset;
9011         crop_info->width=0;
9012         crop_info->height=0;
9013         presses++;
9014         break;
9015       }
9016       case ButtonRelease:
9017       {
9018         presses--;
9019         break;
9020       }
9021       case MotionNotify:
9022       {
9023         /*
9024           Discard pending button motion events.
9025         */
9026         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9027         crop_info->x=event.xmotion.x;
9028         crop_info->y=event.xmotion.y;
9029         /*
9030           Check boundary conditions.
9031         */
9032         if ((int) crop_info->x < x_offset)
9033           crop_info->width=(unsigned int) (x_offset-crop_info->x);
9034         else
9035           {
9036             crop_info->width=(unsigned int) (crop_info->x-x_offset);
9037             crop_info->x=x_offset;
9038           }
9039         if ((int) crop_info->y < y_offset)
9040           crop_info->height=(unsigned int) (y_offset-crop_info->y);
9041         else
9042           {
9043             crop_info->height=(unsigned int) (crop_info->y-y_offset);
9044             crop_info->y=y_offset;
9045           }
9046       }
9047       default:
9048         break;
9049     }
9050   } while ((target_window == (Window) NULL) || (presses > 0));
9051   (void) XUngrabPointer(display,CurrentTime);
9052   (void) XFreeCursor(display,target_cursor);
9053   (void) XFreeGC(display,annotate_context);
9054   if ((crop_info->width*crop_info->height) < MinimumCropArea)
9055     {
9056       crop_info->width=0;
9057       crop_info->height=0;
9058     }
9059   if ((crop_info->width != 0) && (crop_info->height != 0))
9060     target_window=root_window;
9061   return(target_window);
9062 }
9063 \f
9064 /*
9065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9066 %                                                                             %
9067 %                                                                             %
9068 %                                                                             %
9069 %   X S e t C u r s o r S t a t e                                             %
9070 %                                                                             %
9071 %                                                                             %
9072 %                                                                             %
9073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9074 %
9075 %  XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9076 %  reset to their default.
9077 %
9078 %  The format of the XXSetCursorState method is:
9079 %
9080 %      XSetCursorState(display,windows,const MagickStatusType state)
9081 %
9082 %  A description of each parameter follows:
9083 %
9084 %    o display: Specifies a connection to an X server;  returned from
9085 %      XOpenDisplay.
9086 %
9087 %    o windows: Specifies a pointer to a XWindows structure.
9088 %
9089 %    o state: An unsigned integer greater than 0 sets the cursor state
9090 %      to busy, otherwise the cursor are reset to their default.
9091 %
9092 */
9093 MagickExport void XSetCursorState(Display *display,XWindows *windows,
9094   const MagickStatusType state)
9095 {
9096   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9097   assert(display != (Display *) NULL);
9098   assert(windows != (XWindows *) NULL);
9099   if (state)
9100     {
9101       (void) XCheckDefineCursor(display,windows->image.id,
9102         windows->image.busy_cursor);
9103       (void) XCheckDefineCursor(display,windows->pan.id,
9104         windows->pan.busy_cursor);
9105       (void) XCheckDefineCursor(display,windows->magnify.id,
9106         windows->magnify.busy_cursor);
9107       (void) XCheckDefineCursor(display,windows->command.id,
9108         windows->command.busy_cursor);
9109     }
9110   else
9111     {
9112       (void) XCheckDefineCursor(display,windows->image.id,
9113         windows->image.cursor);
9114       (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9115       (void) XCheckDefineCursor(display,windows->magnify.id,
9116         windows->magnify.cursor);
9117       (void) XCheckDefineCursor(display,windows->command.id,
9118         windows->command.cursor);
9119       (void) XCheckDefineCursor(display,windows->command.id,
9120         windows->widget.cursor);
9121       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9122     }
9123   windows->info.mapped=MagickFalse;
9124 }
9125 \f
9126 /*
9127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9128 %                                                                             %
9129 %                                                                             %
9130 %                                                                             %
9131 %   X S e t W i n d o w s                                                     %
9132 %                                                                             %
9133 %                                                                             %
9134 %                                                                             %
9135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9136 %
9137 %  XSetWindows() sets the X windows structure if the windows info is specified.
9138 %  Otherwise the current windows structure is returned.
9139 %
9140 %  The format of the XSetWindows method is:
9141 %
9142 %      XWindows *XSetWindows(XWindows *windows_info)
9143 %
9144 %  A description of each parameter follows:
9145 %
9146 %    o windows_info: Initialize the Windows structure with this information.
9147 %
9148 */
9149 MagickExport XWindows *XSetWindows(XWindows *windows_info)
9150 {
9151   static XWindows
9152     *windows = (XWindows *) NULL;
9153
9154   if (windows_info != (XWindows *) ~0)
9155     {
9156       windows=(XWindows *) RelinquishMagickMemory(windows);
9157       windows=windows_info;
9158     }
9159   return(windows);
9160 }
9161 /*
9162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9163 %                                                                             %
9164 %                                                                             %
9165 %                                                                             %
9166 %   X U s e r P r e f e r e n c e s                                           %
9167 %                                                                             %
9168 %                                                                             %
9169 %                                                                             %
9170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9171 %
9172 %  XUserPreferences() saves the preferences in a configuration file in the
9173 %  users' home directory.
9174 %
9175 %  The format of the XUserPreferences method is:
9176 %
9177 %      void XUserPreferences(XResourceInfo *resource_info)
9178 %
9179 %  A description of each parameter follows:
9180 %
9181 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9182 %
9183 */
9184 MagickExport void XUserPreferences(XResourceInfo *resource_info)
9185 {
9186 #if defined(X11_PREFERENCES_PATH)
9187   char
9188     cache[MaxTextExtent],
9189     filename[MaxTextExtent],
9190     specifier[MaxTextExtent];
9191
9192   const char
9193     *value;
9194
9195   XrmDatabase
9196     preferences_database;
9197
9198   /*
9199     Save user preferences to the client configuration file.
9200   */
9201   assert(resource_info != (XResourceInfo *) NULL);
9202   preferences_database=XrmGetStringDatabase("");
9203   (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",
9204     GetClientName());
9205   value=resource_info->backdrop ? "True" : "False";
9206   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9207   (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",
9208     GetClientName());
9209   value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9210   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9211   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
9212     GetClientName());
9213   value=resource_info->confirm_exit ? "True" : "False";
9214   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9215   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
9216     GetClientName());
9217   value=resource_info->confirm_edit ? "True" : "False";
9218   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9219   (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
9220     GetClientName());
9221   value=resource_info->display_warnings ? "True" : "False";
9222   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9223   (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",
9224     GetClientName());
9225   value=resource_info->quantize_info->dither ? "True" : "False";
9226   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9227   (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
9228     GetClientName());
9229   value=resource_info->gamma_correct ? "True" : "False";
9230   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9231   (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",
9232     GetClientName());
9233   (void) FormatMagickString(cache,MaxTextExtent,"%lu",
9234     resource_info->undo_cache);
9235   XrmPutStringResource(&preferences_database,specifier,cache);
9236   (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",
9237     GetClientName());
9238   value=resource_info->use_pixmap ? "True" : "False";
9239   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9240   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
9241     X11_PREFERENCES_PATH,GetClientName());
9242   ExpandFilename(filename);
9243   XrmPutFileDatabase(preferences_database,filename);
9244 #endif
9245 }
9246 \f
9247 /*
9248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9249 %                                                                             %
9250 %                                                                             %
9251 %                                                                             %
9252 %   X V i s u a l C l a s s N a m e                                           %
9253 %                                                                             %
9254 %                                                                             %
9255 %                                                                             %
9256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9257 %
9258 %  XVisualClassName() returns the visual class name as a character string.
9259 %
9260 %  The format of the XVisualClassName method is:
9261 %
9262 %      char *XVisualClassName(const int visual_class)
9263 %
9264 %  A description of each parameter follows:
9265 %
9266 %    o visual_type: XVisualClassName returns the visual class as a character
9267 %      string.
9268 %
9269 %    o class: Specifies the visual class.
9270 %
9271 %
9272 */
9273 static const char *XVisualClassName(const int visual_class)
9274 {
9275   switch (visual_class)
9276   {
9277     case StaticGray: return("StaticGray");
9278     case GrayScale: return("GrayScale");
9279     case StaticColor: return("StaticColor");
9280     case PseudoColor: return("PseudoColor");
9281     case TrueColor: return("TrueColor");
9282     case DirectColor: return("DirectColor");
9283   }
9284   return("unknown visual class");
9285 }
9286 \f
9287 /*
9288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9289 %                                                                             %
9290 %                                                                             %
9291 %                                                                             %
9292 %   X W a r n i n g                                                           %
9293 %                                                                             %
9294 %                                                                             %
9295 %                                                                             %
9296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9297 %
9298 %  XWarning() displays a warning reason in a Notice widget.
9299 %
9300 %  The format of the XWarning method is:
9301 %
9302 %      void XWarning(const unsigned int warning,const char *reason,
9303 %        const char *description)
9304 %
9305 %  A description of each parameter follows:
9306 %
9307 %    o warning: Specifies the numeric warning category.
9308 %
9309 %    o reason: Specifies the reason to display before terminating the
9310 %      program.
9311 %
9312 %    o description: Specifies any description to the reason.
9313 %
9314 */
9315 MagickExport void XWarning(const ExceptionType magick_unused(warning),
9316   const char *reason,const char *description)
9317 {
9318   char
9319     text[MaxTextExtent];
9320
9321   XWindows
9322     *windows;
9323
9324   if (reason == (char *) NULL)
9325     return;
9326   (void) CopyMagickString(text,reason,MaxTextExtent);
9327   (void) ConcatenateMagickString(text,":",MaxTextExtent);
9328   windows=XSetWindows((XWindows *) ~0);
9329   XNoticeWidget(windows->display,windows,text,(char *) description);
9330 }
9331 \f
9332 /*
9333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9334 %                                                                             %
9335 %                                                                             %
9336 %                                                                             %
9337 %   X W i n d o w B y I D                                                     %
9338 %                                                                             %
9339 %                                                                             %
9340 %                                                                             %
9341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9342 %
9343 %  XWindowByID() locates a child window with a given ID.  If not window with
9344 %  the given name is found, 0 is returned.   Only the window specified and its
9345 %  subwindows are searched.
9346 %
9347 %  The format of the XWindowByID function is:
9348 %
9349 %      child=XWindowByID(display,window,id)
9350 %
9351 %  A description of each parameter follows:
9352 %
9353 %    o child: XWindowByID returns the window with the specified
9354 %      id.  If no windows are found, XWindowByID returns 0.
9355 %
9356 %    o display: Specifies a pointer to the Display structure;  returned from
9357 %      XOpenDisplay.
9358 %
9359 %    o id: Specifies the id of the window to locate.
9360 %
9361 */
9362 MagickExport Window XWindowByID(Display *display,const Window root_window,
9363   const unsigned long id)
9364 {
9365   RectangleInfo
9366     rectangle_info;
9367
9368   register int
9369     i;
9370
9371   Status
9372     status;
9373
9374   unsigned int
9375     number_children;
9376
9377   Window
9378     child,
9379     *children,
9380     window;
9381
9382   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9383   assert(display != (Display *) NULL);
9384   assert(root_window != (Window) NULL);
9385   if (id == 0)
9386     return(XSelectWindow(display,&rectangle_info));
9387   if (root_window == id)
9388     return(id);
9389   status=XQueryTree(display,root_window,&child,&child,&children,
9390     &number_children);
9391   if (status == False)
9392     return((Window) NULL);
9393   window=(Window) NULL;
9394   for (i=0; i < (int) number_children; i++)
9395   {
9396     /*
9397       Search each child and their children.
9398     */
9399     window=XWindowByID(display,children[i],id);
9400     if (window != (Window) NULL)
9401       break;
9402   }
9403   if (children != (Window *) NULL)
9404     (void) XFree((void *) children);
9405   return(window);
9406 }
9407 \f
9408 /*
9409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9410 %                                                                             %
9411 %                                                                             %
9412 %                                                                             %
9413 %   X W i n d o w B y N a m e                                                 %
9414 %                                                                             %
9415 %                                                                             %
9416 %                                                                             %
9417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9418 %
9419 %  XWindowByName() locates a window with a given name on a display.  If no
9420 %  window with the given name is found, 0 is returned. If more than one window
9421 %  has the given name, the first one is returned.  Only root and its children
9422 %  are searched.
9423 %
9424 %  The format of the XWindowByName function is:
9425 %
9426 %      window=XWindowByName(display,root_window,name)
9427 %
9428 %  A description of each parameter follows:
9429 %
9430 %    o window: XWindowByName returns the window id.
9431 %
9432 %    o display: Specifies a pointer to the Display structure;  returned from
9433 %      XOpenDisplay.
9434 %
9435 %    o root_window: Specifies the id of the root window.
9436 %
9437 %    o name: Specifies the name of the window to locate.
9438 %
9439 */
9440 MagickExport Window XWindowByName(Display *display,const Window root_window,
9441   const char *name)
9442 {
9443   register int
9444     i;
9445
9446   Status
9447     status;
9448
9449   unsigned int
9450     number_children;
9451
9452   Window
9453     *children,
9454     child,
9455     window;
9456
9457   XTextProperty
9458     window_name;
9459
9460   assert(display != (Display *) NULL);
9461   assert(root_window != (Window) NULL);
9462   assert(name != (char *) NULL);
9463   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9464   if (XGetWMName(display,root_window,&window_name) != 0)
9465     if (LocaleCompare((char *) window_name.value,name) == 0)
9466       return(root_window);
9467   status=XQueryTree(display,root_window,&child,&child,&children,
9468     &number_children);
9469   if (status == False)
9470     return((Window) NULL);
9471   window=(Window) NULL;
9472   for (i=0; i < (int) number_children; i++)
9473   {
9474     /*
9475       Search each child and their children.
9476     */
9477     window=XWindowByName(display,children[i],name);
9478     if (window != (Window) NULL)
9479       break;
9480   }
9481   if (children != (Window *) NULL)
9482     (void) XFree((void *) children);
9483   return(window);
9484 }
9485 \f
9486 /*
9487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9488 %                                                                             %
9489 %                                                                             %
9490 %                                                                             %
9491 %   X W i n d o w B y P r o p e r y                                           %
9492 %                                                                             %
9493 %                                                                             %
9494 %                                                                             %
9495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9496 %
9497 %  XWindowByProperty() locates a child window with a given property. If not
9498 %  window with the given name is found, 0 is returned.  If more than one window
9499 %  has the given property, the first one is returned.  Only the window
9500 %  specified and its subwindows are searched.
9501 %
9502 %  The format of the XWindowByProperty function is:
9503 %
9504 %      child=XWindowByProperty(display,window,property)
9505 %
9506 %  A description of each parameter follows:
9507 %
9508 %    o child: XWindowByProperty returns the window id with the specified
9509 %      property.  If no windows are found, XWindowByProperty returns 0.
9510 %
9511 %    o display: Specifies a pointer to the Display structure;  returned from
9512 %      XOpenDisplay.
9513 %
9514 %    o property: Specifies the property of the window to locate.
9515 %
9516 */
9517 MagickExport Window XWindowByProperty(Display *display,const Window window,
9518   const Atom property)
9519 {
9520   Atom
9521     type;
9522
9523   int
9524     format;
9525
9526   Status
9527     status;
9528
9529   unsigned char
9530     *data;
9531
9532   unsigned int
9533     i,
9534     number_children;
9535
9536   unsigned long
9537     after,
9538     number_items;
9539
9540   Window
9541     child,
9542     *children,
9543     parent,
9544     root;
9545
9546   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9547   assert(display != (Display *) NULL);
9548   assert(window != (Window) NULL);
9549   assert(property != (Atom) NULL);
9550   status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9551   if (status == False)
9552     return((Window) NULL);
9553   type=(Atom) NULL;
9554   child=(Window) NULL;
9555   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9556   {
9557     status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9558       (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9559     if (data != NULL)
9560       (void) XFree((void *) data);
9561     if ((status == Success) && (type != (Atom) NULL))
9562       child=children[i];
9563   }
9564   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9565     child=XWindowByProperty(display,children[i],property);
9566   if (children != (Window *) NULL)
9567     (void) XFree((void *) children);
9568   return(child);
9569 }
9570 #else
9571 \f
9572 /*
9573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9574 %                                                                             %
9575 %                                                                             %
9576 %                                                                             %
9577 %   X I m p o r t I m a g e                                                   %
9578 %                                                                             %
9579 %                                                                             %
9580 %                                                                             %
9581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9582 %
9583 %  XImportImage() reads an image from an X window.
9584 %
9585 %  The format of the XImportImage method is:
9586 %
9587 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9588 %
9589 %  A description of each parameter follows:
9590 %
9591 %    o image_info: the image info..
9592 %
9593 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
9594 %
9595 */
9596 MagickExport Image *XImportImage(const ImageInfo *image_info,
9597   XImportInfo *ximage_info)
9598 {
9599   assert(image_info != (const ImageInfo *) NULL);
9600   assert(image_info->signature == MagickSignature);
9601   if (image_info->debug != MagickFalse)
9602     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9603       image_info->filename);
9604   assert(ximage_info != (XImportInfo *) NULL);
9605   return((Image *) NULL);
9606 }
9607 #endif
9608 \f
9609 /*
9610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9611 %                                                                             %
9612 %                                                                             %
9613 %                                                                             %
9614 %   X G e t I m p o r t I n f o                                               %
9615 %                                                                             %
9616 %                                                                             %
9617 %                                                                             %
9618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9619 %
9620 %  XGetImportInfo() initializes the XImportInfo structure.
9621 %
9622 %  The format of the XGetImportInfo method is:
9623 %
9624 %      void XGetImportInfo(XImportInfo *ximage_info)
9625 %
9626 %  A description of each parameter follows:
9627 %
9628 %    o ximage_info: Specifies a pointer to an ImageInfo structure.
9629 %
9630 */
9631 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9632 {
9633   assert(ximage_info != (XImportInfo *) NULL);
9634   ximage_info->frame=MagickFalse;
9635   ximage_info->borders=MagickFalse;
9636   ximage_info->screen=MagickFalse;
9637   ximage_info->descend=MagickTrue;
9638   ximage_info->silent=MagickFalse;
9639 }