]> 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       height=(unsigned int) window->image->rows;
5457     }
5458   /*
5459     Create X image.
5460   */
5461   ximage=(XImage *) NULL;
5462   format=(depth == 1) ? XYBitmap : ZPixmap;
5463 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5464   if (window->shared_memory != MagickFalse)
5465     {
5466       XShmSegmentInfo
5467         *segment_info;
5468
5469       segment_info=(XShmSegmentInfo *) window->segment_info;
5470       segment_info[1].shmid=(-1);
5471       segment_info[1].shmaddr=(char *) NULL;
5472       ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5473         (char *) NULL,&segment_info[1],width,height);
5474       if (ximage == (XImage *) NULL)
5475         window->shared_memory=MagickFalse;
5476       length=(size_t) ximage->bytes_per_line*ximage->height;
5477       if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5478         window->shared_memory=MagickFalse;
5479       if (window->shared_memory != MagickFalse)
5480         segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5481       if (window->shared_memory != MagickFalse)
5482         segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5483       if (segment_info[1].shmid < 0)
5484         window->shared_memory=MagickFalse;
5485       if (window->shared_memory != MagickFalse)
5486         (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5487       else
5488         {
5489           if (ximage != (XImage *) NULL)
5490             XDestroyImage(ximage);
5491           ximage=(XImage *) NULL;
5492           if (segment_info[1].shmaddr)
5493             {
5494               (void) shmdt(segment_info[1].shmaddr);
5495               segment_info[1].shmaddr=(char *) NULL;
5496             }
5497           if (segment_info[1].shmid >= 0)
5498             {
5499               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5500               segment_info[1].shmid=(-1);
5501             }
5502         }
5503     }
5504 #endif
5505   /*
5506     Allocate X image pixel data.
5507   */
5508 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5509   if (window->shared_memory)
5510     {
5511       Status
5512         status;
5513
5514       XShmSegmentInfo
5515         *segment_info;
5516
5517       (void) XSync(display,MagickFalse);
5518       xerror_alert=MagickFalse;
5519       segment_info=(XShmSegmentInfo *) window->segment_info;
5520       ximage->data=segment_info[1].shmaddr;
5521       segment_info[1].readOnly=MagickFalse;
5522       status=XShmAttach(display,&segment_info[1]);
5523       if (status != False)
5524         (void) XSync(display,MagickFalse);
5525       if ((status == False) || (xerror_alert != MagickFalse))
5526         {
5527           window->shared_memory=MagickFalse;
5528           if (status != False)
5529             XShmDetach(display,&segment_info[1]);
5530           if (ximage != (XImage *) NULL)
5531             {
5532               ximage->data=NULL;
5533               XDestroyImage(ximage);
5534               ximage=(XImage *) NULL;
5535             }
5536           if (segment_info[1].shmid >= 0)
5537             {
5538               if (segment_info[1].shmaddr != NULL)
5539                 (void) shmdt(segment_info[1].shmaddr);
5540               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5541               segment_info[1].shmid=(-1);
5542               segment_info[1].shmaddr=(char *) NULL;
5543             }
5544         }
5545     }
5546 #endif
5547   if (window->shared_memory == MagickFalse)
5548     ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5549       (char *) NULL,width,height,XBitmapPad(display),0);
5550   if (ximage == (XImage *) NULL)
5551     {
5552       /*
5553         Unable to create X image.
5554       */
5555       (void) XCheckDefineCursor(display,window->id,window->cursor);
5556       return(MagickFalse);
5557     }
5558   length=(size_t) ximage->bytes_per_line*ximage->height;
5559   if (IsEventLogging())
5560     {
5561       (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5562       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %dx%d",
5563         ximage->width,ximage->height);
5564       (void) LogMagickEvent(X11Event,GetMagickModule(),"  format: %d",
5565         ximage->format);
5566       (void) LogMagickEvent(X11Event,GetMagickModule(),"  byte order: %d",
5567         ximage->byte_order);
5568       (void) LogMagickEvent(X11Event,GetMagickModule(),
5569         "  bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5570         ximage->bitmap_bit_order,ximage->bitmap_pad);
5571       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d",
5572         ximage->depth);
5573       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bytes per line: %d",
5574         ximage->bytes_per_line);
5575       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bits per pixel: %d",
5576         ximage->bits_per_pixel);
5577       (void) LogMagickEvent(X11Event,GetMagickModule(),
5578         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5579         ximage->green_mask,ximage->blue_mask);
5580     }
5581   if (window->shared_memory == MagickFalse)
5582     {
5583       if (ximage->format != XYBitmap)
5584         ximage->data=(char *) AcquireQuantumMemory((size_t)
5585           ximage->bytes_per_line,(size_t) ximage->height);
5586       else
5587         ximage->data=(char *) AcquireQuantumMemory((size_t)
5588           ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5589     }
5590   if (ximage->data == (char *) NULL)
5591     {
5592       /*
5593         Unable to allocate pixel data.
5594       */
5595       XDestroyImage(ximage);
5596       ximage=(XImage *) NULL;
5597       (void) XCheckDefineCursor(display,window->id,window->cursor);
5598       return(MagickFalse);
5599     }
5600   if (window->ximage != (XImage *) NULL)
5601     {
5602       /*
5603         Destroy previous X image.
5604       */
5605       length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5606 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5607       if (window->segment_info != (XShmSegmentInfo *) NULL)
5608         {
5609           XShmSegmentInfo
5610             *segment_info;
5611
5612           segment_info=(XShmSegmentInfo *) window->segment_info;
5613           if (segment_info[0].shmid >= 0)
5614             {
5615               (void) XSync(display,MagickFalse);
5616               (void) XShmDetach(display,&segment_info[0]);
5617               (void) XSync(display,MagickFalse);
5618               if (segment_info[0].shmaddr != (char *) NULL)
5619                 (void) shmdt(segment_info[0].shmaddr);
5620               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5621               segment_info[0].shmid=(-1);
5622               segment_info[0].shmaddr=(char *) NULL;
5623               window->ximage->data=(char *) NULL;
5624           }
5625         }
5626 #endif
5627       if (window->ximage->data != (char *) NULL)
5628         free(window->ximage->data);
5629       window->ximage->data=(char *) NULL;
5630       XDestroyImage(window->ximage);
5631       window->ximage=(XImage *) NULL;
5632     }
5633 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5634   if (window->segment_info != (XShmSegmentInfo *) NULL)
5635     {
5636       XShmSegmentInfo
5637         *segment_info;
5638
5639       segment_info=(XShmSegmentInfo *) window->segment_info;
5640       segment_info[0]=segment_info[1];
5641     }
5642 #endif
5643   window->ximage=ximage;
5644   matte_image=(XImage *) NULL;
5645   if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5646     if ((window->image->matte != MagickFalse) &&
5647         ((long) width <= XDisplayWidth(display,window->screen)) &&
5648         ((long) height <= XDisplayHeight(display,window->screen)))
5649       {
5650         /*
5651           Create matte image.
5652         */
5653         matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5654           (char *) NULL,width,height,XBitmapPad(display),0);
5655         if (IsEventLogging())
5656           {
5657             (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5658             (void) LogMagickEvent(X11Event,GetMagickModule(),
5659               "  width, height: %dx%d",matte_image->width,matte_image->height);
5660           }
5661         if (matte_image != (XImage *) NULL)
5662           {
5663             /*
5664               Allocate matte image pixel data.
5665             */
5666             matte_image->data=(char *) AcquireQuantumMemory((size_t)
5667               matte_image->bytes_per_line*matte_image->depth,
5668               (size_t) matte_image->height);
5669             if (matte_image->data == (char *) NULL)
5670               {
5671                 XDestroyImage(matte_image);
5672                 matte_image=(XImage *) NULL;
5673               }
5674           }
5675       }
5676   if (window->matte_image != (XImage *) NULL)
5677     {
5678       /*
5679         Free matte image.
5680       */
5681       if (window->matte_image->data != (char *) NULL)
5682         free(window->matte_image->data);
5683       window->matte_image->data=(char *) NULL;
5684       XDestroyImage(window->matte_image);
5685       window->matte_image=(XImage *) NULL;
5686     }
5687   window->matte_image=matte_image;
5688   if (window->matte_pixmap != (Pixmap) NULL)
5689     {
5690       (void) XFreePixmap(display,window->matte_pixmap);
5691       window->matte_pixmap=(Pixmap) NULL;
5692 #if defined(MAGICKCORE_HAVE_SHAPE)
5693       if (window->shape != MagickFalse)
5694         XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5695 #endif
5696     }
5697   window->stasis=MagickFalse;
5698   /*
5699     Convert pixels to X image data.
5700   */
5701   if (window->image != (Image *) NULL)
5702     {
5703       if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5704           (ximage->bitmap_bit_order == LSBFirst)))
5705         XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5706           matte_image);
5707       else
5708         XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5709           matte_image);
5710     }
5711   if (window->matte_image != (XImage *) NULL)
5712     {
5713       /*
5714         Create matte pixmap.
5715       */
5716       window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5717       if (window->matte_pixmap != (Pixmap) NULL)
5718         {
5719           GC
5720             graphics_context;
5721
5722           XGCValues
5723             context_values;
5724
5725           /*
5726             Copy matte image to matte pixmap.
5727           */
5728           context_values.background=1;
5729           context_values.foreground=0;
5730           graphics_context=XCreateGC(display,window->matte_pixmap,
5731             (unsigned long) (GCBackground | GCForeground),&context_values);
5732           (void) XPutImage(display,window->matte_pixmap,graphics_context,
5733             window->matte_image,0,0,0,0,width,height);
5734           (void) XFreeGC(display,graphics_context);
5735 #if defined(MAGICKCORE_HAVE_SHAPE)
5736           if (window->shape != MagickFalse)
5737             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5738               window->matte_pixmap,ShapeSet);
5739 #endif
5740         }
5741       }
5742   (void) XMakePixmap(display,resource_info,window);
5743   /*
5744     Restore cursor.
5745   */
5746   (void) XCheckDefineCursor(display,window->id,window->cursor);
5747   return(MagickTrue);
5748 }
5749 \f
5750 /*
5751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5752 %                                                                             %
5753 %                                                                             %
5754 %                                                                             %
5755 +   X M a k e I m a g e L S B F i r s t                                       %
5756 %                                                                             %
5757 %                                                                             %
5758 %                                                                             %
5759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5760 %
5761 %  XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5762 %  pixels are copied in least-significant bit and byte first order.  The
5763 %  server's scanline pad is respected.  Rather than using one or two general
5764 %  cases, many special cases are found here to help speed up the image
5765 %  conversion.
5766 %
5767 %  The format of the XMakeImageLSBFirst method is:
5768 %
5769 %      void XMakeImageLSBFirst(Display *display,XWindows *windows)
5770 %
5771 %  A description of each parameter follows:
5772 %
5773 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5774 %
5775 %    o window: Specifies a pointer to a XWindowInfo structure.
5776 %
5777 %    o image: the image.
5778 %
5779 %    o ximage: Specifies a pointer to a XImage structure;  returned from
5780 %      XCreateImage.
5781 %
5782 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
5783 %      XCreateImage.
5784 %
5785 */
5786 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5787   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5788 {
5789   Image
5790     *canvas;
5791
5792   int
5793     y;
5794
5795   register const IndexPacket
5796     *indexes;
5797
5798   register const PixelPacket
5799     *p;
5800
5801   register int
5802     x;
5803
5804   register unsigned char
5805     *q;
5806
5807   unsigned char
5808     bit,
5809     byte;
5810
5811   unsigned int
5812     scanline_pad;
5813
5814   unsigned long
5815     pixel,
5816     *pixels;
5817
5818   XStandardColormap
5819     *map_info;
5820
5821   assert(resource_info != (XResourceInfo *) NULL);
5822   assert(window != (XWindowInfo *) NULL);
5823   assert(image != (Image *) NULL);
5824   if (image->debug != MagickFalse)
5825     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5826   canvas=image;
5827   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
5828     {
5829       char
5830         size[MaxTextExtent];
5831
5832       Image
5833         *pattern;
5834
5835       ImageInfo
5836         *image_info;
5837
5838       image_info=AcquireImageInfo();
5839       (void) CopyMagickString(image_info->filename,
5840         resource_info->image_info->texture != (char *) NULL ?
5841         resource_info->image_info->texture : "pattern:checkerboard",
5842         MaxTextExtent);
5843       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
5844         image->rows);
5845       image_info->size=ConstantString(size);
5846       pattern=ReadImage(image_info,&image->exception);
5847       image_info=DestroyImageInfo(image_info);
5848       if (pattern != (Image *) NULL)
5849         {
5850           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5851           if (canvas != (Image *) NULL)
5852             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5853           pattern=DestroyImage(pattern);
5854         }
5855     }
5856   scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5857     ximage->bits_per_pixel) >> 3));
5858   map_info=window->map_info;
5859   pixels=window->pixel_info->pixels;
5860   q=(unsigned char *) ximage->data;
5861   x=0;
5862   if (ximage->format == XYBitmap)
5863     {
5864       register unsigned short
5865         polarity;
5866
5867       unsigned char
5868         background,
5869         foreground;
5870
5871       /*
5872         Convert canvas to big-endian bitmap.
5873       */
5874       background=(unsigned char)
5875         (XPixelIntensity(&window->pixel_info->foreground_color) <
5876          XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5877       foreground=(unsigned char)
5878         (XPixelIntensity(&window->pixel_info->background_color) <
5879          XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5880       polarity=(unsigned short) ((PixelIntensityToQuantum(
5881         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5882       if (canvas->colors == 2)
5883         polarity=PixelIntensity(&canvas->colormap[0]) <
5884           PixelIntensity(&canvas->colormap[1]);
5885       for (y=0; y < (int) canvas->rows; y++)
5886       {
5887         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5888         if (p == (const PixelPacket *) NULL)
5889           break;
5890         indexes=GetVirtualIndexQueue(canvas);
5891         bit=0;
5892         byte=0;
5893         for (x=0; x < (int) canvas->columns; x++)
5894         {
5895           byte>>=1;
5896           if (indexes[x] == (IndexPacket) polarity)
5897             byte|=foreground;
5898           else
5899             byte|=background;
5900           bit++;
5901           if (bit == 8)
5902             {
5903               *q++=byte;
5904               bit=0;
5905               byte=0;
5906             }
5907         }
5908         if (bit != 0)
5909           *q=byte >> (8-bit);
5910         q+=scanline_pad;
5911       }
5912     }
5913   else
5914     if (window->pixel_info->colors != 0)
5915       switch (ximage->bits_per_pixel)
5916       {
5917         case 2:
5918         {
5919           register unsigned int
5920             nibble;
5921
5922           /*
5923             Convert to 2 bit color-mapped X canvas.
5924           */
5925           for (y=0; y < (int) canvas->rows; y++)
5926           {
5927             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5928             if (p == (const PixelPacket *) NULL)
5929               break;
5930             indexes=GetVirtualIndexQueue(canvas);
5931             nibble=0;
5932             for (x=0; x < (int) canvas->columns; x++)
5933             {
5934               pixel=pixels[(long) indexes[x]] & 0x0f;
5935               switch (nibble)
5936               {
5937                 case 0:
5938                 {
5939                   *q=(unsigned char) pixel;
5940                   nibble++;
5941                   break;
5942                 }
5943                 case 1:
5944                 {
5945                   *q|=(unsigned char) (pixel << 2);
5946                   nibble++;
5947                   break;
5948                 }
5949                 case 2:
5950                 {
5951                   *q|=(unsigned char) (pixel << 4);
5952                   nibble++;
5953                   break;
5954                 }
5955                 case 3:
5956                 {
5957                   *q|=(unsigned char) (pixel << 6);
5958                   q++;
5959                   nibble=0;
5960                   break;
5961                 }
5962               }
5963             }
5964             q+=scanline_pad;
5965           }
5966           break;
5967         }
5968         case 4:
5969         {
5970           register unsigned int
5971             nibble;
5972
5973           /*
5974             Convert to 4 bit color-mapped X canvas.
5975           */
5976           for (y=0; y < (int) canvas->rows; y++)
5977           {
5978             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
5979             if (p == (const PixelPacket *) NULL)
5980               break;
5981             indexes=GetVirtualIndexQueue(canvas);
5982             nibble=0;
5983             for (x=0; x < (int) canvas->columns; x++)
5984             {
5985               pixel=pixels[(long) indexes[x]] & 0xf;
5986               switch (nibble)
5987               {
5988                 case 0:
5989                 {
5990                   *q=(unsigned char) pixel;
5991                   nibble++;
5992                   break;
5993                 }
5994                 case 1:
5995                 {
5996                   *q|=(unsigned char) (pixel << 4);
5997                   q++;
5998                   nibble=0;
5999                   break;
6000                 }
6001               }
6002             }
6003             q+=scanline_pad;
6004           }
6005           break;
6006         }
6007         case 6:
6008         case 8:
6009         {
6010           /*
6011             Convert to 8 bit color-mapped X canvas.
6012           */
6013           if (resource_info->color_recovery &&
6014               resource_info->quantize_info->dither)
6015             {
6016               XDitherImage(canvas,ximage);
6017               break;
6018             }
6019           for (y=0; y < (int) canvas->rows; y++)
6020           {
6021             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6022             if (p == (const PixelPacket *) NULL)
6023               break;
6024             indexes=GetVirtualIndexQueue(canvas);
6025             for (x=0; x < (int) canvas->columns; x++)
6026             {
6027               pixel=pixels[(long) indexes[x]];
6028               *q++=(unsigned char) pixel;
6029             }
6030             q+=scanline_pad;
6031           }
6032           break;
6033         }
6034         default:
6035         {
6036           register int
6037             k;
6038
6039           register unsigned int
6040             bytes_per_pixel;
6041
6042           unsigned char
6043             channel[sizeof(unsigned long)];
6044
6045           /*
6046             Convert to multi-byte color-mapped X canvas.
6047           */
6048           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6049           for (y=0; y < (int) canvas->rows; y++)
6050           {
6051             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6052             if (p == (const PixelPacket *) NULL)
6053               break;
6054             indexes=GetVirtualIndexQueue(canvas);
6055             for (x=0; x < (int) canvas->columns; x++)
6056             {
6057               pixel=pixels[(long) indexes[x]];
6058               for (k=0; k < (int) bytes_per_pixel; k++)
6059               {
6060                 channel[k]=(unsigned char) pixel;
6061                 pixel>>=8;
6062               }
6063               for (k=0; k < (int) bytes_per_pixel; k++)
6064                 *q++=channel[k];
6065             }
6066             q+=scanline_pad;
6067           }
6068           break;
6069         }
6070       }
6071     else
6072       switch (ximage->bits_per_pixel)
6073       {
6074         case 2:
6075         {
6076           register unsigned int
6077             nibble;
6078
6079           /*
6080             Convert to contiguous 2 bit continuous-tone X canvas.
6081           */
6082           for (y=0; y < (int) canvas->rows; y++)
6083           {
6084             nibble=0;
6085             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6086             if (p == (const PixelPacket *) NULL)
6087               break;
6088             for (x=0; x < (int) canvas->columns; x++)
6089             {
6090               pixel=XGammaPixel(map_info,p);
6091               pixel&=0xf;
6092               switch (nibble)
6093               {
6094                 case 0:
6095                 {
6096                   *q=(unsigned char) pixel;
6097                   nibble++;
6098                   break;
6099                 }
6100                 case 1:
6101                 {
6102                   *q|=(unsigned char) (pixel << 2);
6103                   nibble++;
6104                   break;
6105                 }
6106                 case 2:
6107                 {
6108                   *q|=(unsigned char) (pixel << 4);
6109                   nibble++;
6110                   break;
6111                 }
6112                 case 3:
6113                 {
6114                   *q|=(unsigned char) (pixel << 6);
6115                   q++;
6116                   nibble=0;
6117                   break;
6118                 }
6119               }
6120               p++;
6121             }
6122             q+=scanline_pad;
6123           }
6124           break;
6125         }
6126         case 4:
6127         {
6128           register unsigned int
6129             nibble;
6130
6131           /*
6132             Convert to contiguous 4 bit continuous-tone X canvas.
6133           */
6134           for (y=0; y < (int) canvas->rows; y++)
6135           {
6136             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6137             if (p == (const PixelPacket *) NULL)
6138               break;
6139             nibble=0;
6140             for (x=0; x < (int) canvas->columns; x++)
6141             {
6142               pixel=XGammaPixel(map_info,p);
6143               pixel&=0xf;
6144               switch (nibble)
6145               {
6146                 case 0:
6147                 {
6148                   *q=(unsigned char) pixel;
6149                   nibble++;
6150                   break;
6151                 }
6152                 case 1:
6153                 {
6154                   *q|=(unsigned char) (pixel << 4);
6155                   q++;
6156                   nibble=0;
6157                   break;
6158                 }
6159               }
6160               p++;
6161             }
6162             q+=scanline_pad;
6163           }
6164           break;
6165         }
6166         case 6:
6167         case 8:
6168         {
6169           /*
6170             Convert to contiguous 8 bit continuous-tone X canvas.
6171           */
6172           if (resource_info->color_recovery &&
6173               resource_info->quantize_info->dither)
6174             {
6175               XDitherImage(canvas,ximage);
6176               break;
6177             }
6178           for (y=0; y < (int) canvas->rows; y++)
6179           {
6180             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6181             if (p == (const PixelPacket *) NULL)
6182               break;
6183             for (x=0; x < (int) canvas->columns; x++)
6184             {
6185               pixel=XGammaPixel(map_info,p);
6186               *q++=(unsigned char) pixel;
6187               p++;
6188             }
6189             q+=scanline_pad;
6190           }
6191           break;
6192         }
6193         default:
6194         {
6195           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6196               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6197               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6198               (map_info->blue_mult == 1))
6199             {
6200               /*
6201                 Convert to 32 bit continuous-tone X canvas.
6202               */
6203               for (y=0; y < (int) canvas->rows; y++)
6204               {
6205                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6206                   &canvas->exception);
6207                 if (p == (const PixelPacket *) NULL)
6208                   break;
6209                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6210                     (blue_gamma != 1.0))
6211                   {
6212                     /*
6213                       Gamma correct canvas.
6214                     */
6215                     for (x=(int) canvas->columns-1; x >= 0; x--)
6216                     {
6217                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6218                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6219                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
6220                       *q++=0;
6221                       p++;
6222                     }
6223                     continue;
6224                   }
6225                 for (x=(int) canvas->columns-1; x >= 0; x--)
6226                 {
6227                   *q++=ScaleQuantumToChar((Quantum) p->blue);
6228                   *q++=ScaleQuantumToChar((Quantum) p->green);
6229                   *q++=ScaleQuantumToChar((Quantum) p->red);
6230                   *q++=0;
6231                   p++;
6232                 }
6233               }
6234             }
6235           else
6236             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6237                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6238                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6239                 (map_info->blue_mult == 65536L))
6240               {
6241                 /*
6242                   Convert to 32 bit continuous-tone X canvas.
6243                 */
6244                 for (y=0; y < (int) canvas->rows; y++)
6245                 {
6246                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6247                     &canvas->exception);
6248                   if (p == (const PixelPacket *) NULL)
6249                     break;
6250                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6251                       (blue_gamma != 1.0))
6252                     {
6253                       /*
6254                         Gamma correct canvas.
6255                       */
6256                       for (x=(int) canvas->columns-1; x >= 0; x--)
6257                       {
6258                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
6259                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6260                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6261                         *q++=0;
6262                         p++;
6263                       }
6264                       continue;
6265                     }
6266                   for (x=(int) canvas->columns-1; x >= 0; x--)
6267                   {
6268                     *q++=ScaleQuantumToChar((Quantum) p->red);
6269                     *q++=ScaleQuantumToChar((Quantum) p->green);
6270                     *q++=ScaleQuantumToChar((Quantum) p->blue);
6271                     *q++=0;
6272                     p++;
6273                   }
6274                 }
6275               }
6276             else
6277               {
6278                 register int
6279                   k;
6280
6281                 register unsigned int
6282                   bytes_per_pixel;
6283
6284                 unsigned char
6285                   channel[sizeof(unsigned long)];
6286
6287                 /*
6288                   Convert to multi-byte continuous-tone X canvas.
6289                 */
6290                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6291                 for (y=0; y < (int) canvas->rows; y++)
6292                 {
6293                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6294                     &canvas->exception);
6295                   if (p == (PixelPacket *) NULL)
6296                     break;
6297                   for (x=0; x < (long) canvas->columns; x++)
6298                   {
6299                     pixel=XGammaPixel(map_info,p);
6300                     for (k=0; k < (int) bytes_per_pixel; k++)
6301                     {
6302                       channel[k]=(unsigned char) pixel;
6303                       pixel>>=8;
6304                     }
6305                     for (k=0; k < (int) bytes_per_pixel; k++)
6306                       *q++=channel[k];
6307                     p++;
6308                   }
6309                   q+=scanline_pad;
6310                 }
6311               }
6312           break;
6313         }
6314       }
6315   if (matte_image != (XImage *) NULL)
6316     {
6317       /*
6318         Initialize matte canvas.
6319       */
6320       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6321         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6322       q=(unsigned char *) matte_image->data;
6323       for (y=0; y < (int) canvas->rows; y++)
6324       {
6325         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6326         if (p == (const PixelPacket *) NULL)
6327           break;
6328         bit=0;
6329         byte=0;
6330         for (x=(int) canvas->columns-1; x >= 0; x--)
6331         {
6332           byte>>=1;
6333           if (p->opacity > (long) (QuantumRange/2))
6334             byte|=0x80;
6335           bit++;
6336           if (bit == 8)
6337             {
6338               *q++=byte;
6339               bit=0;
6340               byte=0;
6341             }
6342           p++;
6343         }
6344         if (bit != 0)
6345           *q=byte >> (8-bit);
6346         q+=scanline_pad;
6347       }
6348     }
6349   if (canvas != image)
6350     canvas=DestroyImage(canvas);
6351 }
6352 \f
6353 /*
6354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6355 %                                                                             %
6356 %                                                                             %
6357 %                                                                             %
6358 +   X M a k e I m a g e M S B F i r s t                                       %
6359 %                                                                             %
6360 %                                                                             %
6361 %                                                                             %
6362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6363 %
6364 %  XMakeImageMSBFirst() initializes the pixel data of an X11 Image.  The X
6365 %  image pixels are copied in most-significant bit and byte first order.  The
6366 %  server's scanline pad is also respected. Rather than using one or two
6367 %  general cases, many special cases are found here to help speed up the image
6368 %  conversion.
6369 %
6370 %  The format of the XMakeImageMSBFirst method is:
6371 %
6372 %      XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6373 %
6374 %  A description of each parameter follows:
6375 %
6376 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6377 %
6378 %    o window: Specifies a pointer to a XWindowInfo structure.
6379 %
6380 %    o image: the image.
6381 %
6382 %    o ximage: Specifies a pointer to a XImage structure;  returned from
6383 %      XCreateImage.
6384 %
6385 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
6386 %      XCreateImage.
6387 %
6388 %
6389 */
6390 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6391   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6392 {
6393   Image
6394     *canvas;
6395
6396   int
6397     y;
6398
6399   register int
6400     x;
6401
6402   register const IndexPacket
6403     *indexes;
6404
6405   register const PixelPacket
6406     *p;
6407
6408   register unsigned char
6409     *q;
6410
6411   unsigned char
6412     bit,
6413     byte;
6414
6415   unsigned int
6416     scanline_pad;
6417
6418   unsigned long
6419     pixel,
6420     *pixels;
6421
6422   XStandardColormap
6423     *map_info;
6424
6425   assert(resource_info != (XResourceInfo *) NULL);
6426   assert(window != (XWindowInfo *) NULL);
6427   assert(image != (Image *) NULL);
6428   if (image->debug != MagickFalse)
6429     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6430   canvas=image;
6431   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
6432     {
6433       char
6434         size[MaxTextExtent];
6435
6436       Image
6437         *pattern;
6438
6439       ImageInfo
6440         *image_info;
6441
6442       image_info=AcquireImageInfo();
6443       (void) CopyMagickString(image_info->filename,
6444         resource_info->image_info->texture != (char *) NULL ?
6445         resource_info->image_info->texture : "pattern:checkerboard",
6446         MaxTextExtent);
6447       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
6448         image->rows);
6449       image_info->size=ConstantString(size);
6450       pattern=ReadImage(image_info,&image->exception);
6451       image_info=DestroyImageInfo(image_info);
6452       if (pattern != (Image *) NULL)
6453         {
6454           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6455           if (canvas != (Image *) NULL)
6456             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6457           pattern=DestroyImage(pattern);
6458         }
6459     }
6460   scanline_pad=(unsigned int) (ximage->bytes_per_line-
6461     ((ximage->width*ximage->bits_per_pixel) >> 3));
6462   map_info=window->map_info;
6463   pixels=window->pixel_info->pixels;
6464   q=(unsigned char *) ximage->data;
6465   x=0;
6466   if (ximage->format == XYBitmap)
6467     {
6468       register unsigned short
6469         polarity;
6470
6471       unsigned char
6472         background,
6473         foreground;
6474
6475       /*
6476         Convert canvas to big-endian bitmap.
6477       */
6478       background=(unsigned char)
6479         (XPixelIntensity(&window->pixel_info->foreground_color) <
6480          XPixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
6481       foreground=(unsigned char)
6482         (XPixelIntensity(&window->pixel_info->background_color) <
6483          XPixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
6484       polarity=(unsigned short) ((PixelIntensityToQuantum(
6485         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6486       if (canvas->colors == 2)
6487         polarity=PixelIntensity(&canvas->colormap[0]) <
6488           PixelIntensity(&canvas->colormap[1]);
6489       for (y=0; y < (int) canvas->rows; y++)
6490       {
6491         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6492         if (p == (const PixelPacket *) NULL)
6493           break;
6494         indexes=GetVirtualIndexQueue(canvas);
6495         bit=0;
6496         byte=0;
6497         for (x=(int) canvas->columns-1; x >= 0; x--)
6498         {
6499           byte<<=1;
6500           if (indexes[x] == (IndexPacket) polarity)
6501             byte|=foreground;
6502           else
6503             byte|=background;
6504           bit++;
6505           if (bit == 8)
6506             {
6507               *q++=byte;
6508               bit=0;
6509               byte=0;
6510             }
6511         }
6512         if (bit != 0)
6513           *q=byte << (8-bit);
6514         q+=scanline_pad;
6515       }
6516     }
6517   else
6518     if (window->pixel_info->colors != 0)
6519       switch (ximage->bits_per_pixel)
6520       {
6521         case 2:
6522         {
6523           register unsigned int
6524             nibble;
6525
6526           /*
6527             Convert to 2 bit color-mapped X canvas.
6528           */
6529           for (y=0; y < (int) canvas->rows; y++)
6530           {
6531             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6532             if (p == (const PixelPacket *) NULL)
6533               break;
6534             indexes=GetVirtualIndexQueue(canvas);
6535             nibble=0;
6536             for (x=0; x < (int) canvas->columns; x++)
6537             {
6538               pixel=pixels[(long) indexes[x]] & 0xf;
6539               switch (nibble)
6540               {
6541                 case 0:
6542                 {
6543                   *q=(unsigned char) (pixel << 6);
6544                   nibble++;
6545                   break;
6546                 }
6547                 case 1:
6548                 {
6549                   *q|=(unsigned char) (pixel << 4);
6550                   nibble++;
6551                   break;
6552                 }
6553                 case 2:
6554                 {
6555                   *q|=(unsigned char) (pixel << 2);
6556                   nibble++;
6557                   break;
6558                 }
6559                 case 3:
6560                 {
6561                   *q|=(unsigned char) pixel;
6562                   q++;
6563                   nibble=0;
6564                   break;
6565                 }
6566               }
6567             }
6568             q+=scanline_pad;
6569           }
6570           break;
6571         }
6572         case 4:
6573         {
6574           register unsigned int
6575             nibble;
6576
6577           /*
6578             Convert to 4 bit color-mapped X canvas.
6579           */
6580           for (y=0; y < (int) canvas->rows; y++)
6581           {
6582             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6583             if (p == (const PixelPacket *) NULL)
6584               break;
6585             indexes=GetVirtualIndexQueue(canvas);
6586             nibble=0;
6587             for (x=0; x < (int) canvas->columns; x++)
6588             {
6589               pixel=pixels[(long) indexes[x]] & 0xf;
6590               switch (nibble)
6591               {
6592                 case 0:
6593                 {
6594                   *q=(unsigned char) (pixel << 4);
6595                   nibble++;
6596                   break;
6597                 }
6598                 case 1:
6599                 {
6600                   *q|=(unsigned char) pixel;
6601                   q++;
6602                   nibble=0;
6603                   break;
6604                 }
6605               }
6606             }
6607             q+=scanline_pad;
6608           }
6609           break;
6610         }
6611         case 6:
6612         case 8:
6613         {
6614           /*
6615             Convert to 8 bit color-mapped X canvas.
6616           */
6617           if (resource_info->color_recovery &&
6618               resource_info->quantize_info->dither)
6619             {
6620               XDitherImage(canvas,ximage);
6621               break;
6622             }
6623           for (y=0; y < (int) canvas->rows; y++)
6624           {
6625             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6626             if (p == (const PixelPacket *) NULL)
6627               break;
6628             indexes=GetVirtualIndexQueue(canvas);
6629             for (x=0; x < (int) canvas->columns; x++)
6630             {
6631               pixel=pixels[(long) indexes[x]];
6632               *q++=(unsigned char) pixel;
6633             }
6634             q+=scanline_pad;
6635           }
6636           break;
6637         }
6638         default:
6639         {
6640           register int
6641             k;
6642
6643           register unsigned int
6644             bytes_per_pixel;
6645
6646           unsigned char
6647             channel[sizeof(unsigned long)];
6648
6649           /*
6650             Convert to 8 bit color-mapped X canvas.
6651           */
6652           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6653           for (y=0; y < (int) canvas->rows; y++)
6654           {
6655             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6656             if (p == (const PixelPacket *) NULL)
6657               break;
6658             indexes=GetVirtualIndexQueue(canvas);
6659             for (x=0; x < (int) canvas->columns; x++)
6660             {
6661               pixel=pixels[(long) indexes[x]];
6662               for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6663               {
6664                 channel[k]=(unsigned char) pixel;
6665                 pixel>>=8;
6666               }
6667               for (k=0; k < (int) bytes_per_pixel; k++)
6668                 *q++=channel[k];
6669             }
6670             q+=scanline_pad;
6671           }
6672           break;
6673         }
6674       }
6675     else
6676       switch (ximage->bits_per_pixel)
6677       {
6678         case 2:
6679         {
6680           register unsigned int
6681             nibble;
6682
6683           /*
6684             Convert to 4 bit continuous-tone X canvas.
6685           */
6686           for (y=0; y < (int) canvas->rows; y++)
6687           {
6688             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6689             if (p == (const PixelPacket *) NULL)
6690               break;
6691             nibble=0;
6692             for (x=(int) canvas->columns-1; x >= 0; x--)
6693             {
6694               pixel=XGammaPixel(map_info,p);
6695               pixel&=0xf;
6696               switch (nibble)
6697               {
6698                 case 0:
6699                 {
6700                   *q=(unsigned char) (pixel << 6);
6701                   nibble++;
6702                   break;
6703                 }
6704                 case 1:
6705                 {
6706                   *q|=(unsigned char) (pixel << 4);
6707                   nibble++;
6708                   break;
6709                 }
6710                 case 2:
6711                 {
6712                   *q|=(unsigned char) (pixel << 2);
6713                   nibble++;
6714                   break;
6715                 }
6716                 case 3:
6717                 {
6718                   *q|=(unsigned char) pixel;
6719                   q++;
6720                   nibble=0;
6721                   break;
6722                 }
6723               }
6724               p++;
6725             }
6726             q+=scanline_pad;
6727           }
6728           break;
6729         }
6730         case 4:
6731         {
6732           register unsigned int
6733             nibble;
6734
6735           /*
6736             Convert to 4 bit continuous-tone X canvas.
6737           */
6738           for (y=0; y < (int) canvas->rows; y++)
6739           {
6740             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6741             if (p == (const PixelPacket *) NULL)
6742               break;
6743             nibble=0;
6744             for (x=(int) canvas->columns-1; x >= 0; x--)
6745             {
6746               pixel=XGammaPixel(map_info,p);
6747               pixel&=0xf;
6748               switch (nibble)
6749               {
6750                 case 0:
6751                 {
6752                   *q=(unsigned char) (pixel << 4);
6753                   nibble++;
6754                   break;
6755                 }
6756                 case 1:
6757                 {
6758                   *q|=(unsigned char) pixel;
6759                   q++;
6760                   nibble=0;
6761                   break;
6762                 }
6763               }
6764               p++;
6765             }
6766             q+=scanline_pad;
6767           }
6768           break;
6769         }
6770         case 6:
6771         case 8:
6772         {
6773           /*
6774             Convert to 8 bit continuous-tone X canvas.
6775           */
6776           if (resource_info->color_recovery &&
6777               resource_info->quantize_info->dither)
6778             {
6779               XDitherImage(canvas,ximage);
6780               break;
6781             }
6782           for (y=0; y < (int) canvas->rows; y++)
6783           {
6784             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6785             if (p == (const PixelPacket *) NULL)
6786               break;
6787             for (x=(int) canvas->columns-1; x >= 0; x--)
6788             {
6789               pixel=XGammaPixel(map_info,p);
6790               *q++=(unsigned char) pixel;
6791               p++;
6792             }
6793             q+=scanline_pad;
6794           }
6795           break;
6796         }
6797         default:
6798         {
6799           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6800               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6801               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6802               (map_info->blue_mult == 1))
6803             {
6804               /*
6805                 Convert to 32 bit continuous-tone X canvas.
6806               */
6807               for (y=0; y < (int) canvas->rows; y++)
6808               {
6809                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6810                   &canvas->exception);
6811                 if (p == (const PixelPacket *) NULL)
6812                   break;
6813                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6814                     (blue_gamma != 1.0))
6815                   {
6816                     /*
6817                       Gamma correct canvas.
6818                     */
6819                     for (x=(int) canvas->columns-1; x >= 0; x--)
6820                     {
6821                       *q++=0;
6822                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
6823                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6824                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6825                       p++;
6826                     }
6827                     continue;
6828                   }
6829                 for (x=(int) canvas->columns-1; x >= 0; x--)
6830                 {
6831                   *q++=0;
6832                   *q++=ScaleQuantumToChar((Quantum) p->red);
6833                   *q++=ScaleQuantumToChar((Quantum) p->green);
6834                   *q++=ScaleQuantumToChar((Quantum) p->blue);
6835                   p++;
6836                 }
6837               }
6838             }
6839           else
6840             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6841                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6842                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6843                 (map_info->blue_mult == 65536L))
6844               {
6845                 /*
6846                   Convert to 32 bit continuous-tone X canvas.
6847                 */
6848                 for (y=0; y < (int) canvas->rows; y++)
6849                 {
6850                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6851                     &canvas->exception);
6852                   if (p == (const PixelPacket *) NULL)
6853                     break;
6854                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6855                       (blue_gamma != 1.0))
6856                     {
6857                       /*
6858                         Gamma correct canvas.
6859                       */
6860                       for (x=(int) canvas->columns-1; x >= 0; x--)
6861                       {
6862                         *q++=0;
6863                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
6864                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
6865                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
6866                         p++;
6867                       }
6868                       continue;
6869                     }
6870                   for (x=(int) canvas->columns-1; x >= 0; x--)
6871                   {
6872                     *q++=0;
6873                     *q++=ScaleQuantumToChar((Quantum) p->blue);
6874                     *q++=ScaleQuantumToChar((Quantum) p->green);
6875                     *q++=ScaleQuantumToChar((Quantum) p->red);
6876                     p++;
6877                   }
6878                 }
6879               }
6880             else
6881               {
6882                 register int
6883                   k;
6884
6885                 register unsigned int
6886                   bytes_per_pixel;
6887
6888                 unsigned char
6889                   channel[sizeof(unsigned long)];
6890
6891                 /*
6892                   Convert to multi-byte continuous-tone X canvas.
6893                 */
6894                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6895                 for (y=0; y < (int) canvas->rows; y++)
6896                 {
6897                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
6898                     &canvas->exception);
6899                   if (p == (const PixelPacket *) NULL)
6900                     break;
6901                   for (x=(int) canvas->columns-1; x >= 0; x--)
6902                   {
6903                     pixel=XGammaPixel(map_info,p);
6904                     for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6905                     {
6906                       channel[k]=(unsigned char) pixel;
6907                       pixel>>=8;
6908                     }
6909                     for (k=0; k < (int) bytes_per_pixel; k++)
6910                       *q++=channel[k];
6911                     p++;
6912                   }
6913                   q+=scanline_pad;
6914                 }
6915               }
6916           break;
6917         }
6918       }
6919   if (matte_image != (XImage *) NULL)
6920     {
6921       /*
6922         Initialize matte canvas.
6923       */
6924       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6925         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6926       q=(unsigned char *) matte_image->data;
6927       for (y=0; y < (int) canvas->rows; y++)
6928       {
6929         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
6930         if (p == (const PixelPacket *) NULL)
6931           break;
6932         bit=0;
6933         byte=0;
6934         for (x=(int) canvas->columns-1; x >= 0; x--)
6935         {
6936           byte<<=1;
6937           if (p->opacity > (long) (QuantumRange/2))
6938             byte|=0x01;
6939           bit++;
6940           if (bit == 8)
6941             {
6942               *q++=byte;
6943               bit=0;
6944               byte=0;
6945             }
6946           p++;
6947         }
6948         if (bit != 0)
6949           *q=byte << (8-bit);
6950         q+=scanline_pad;
6951       }
6952     }
6953   if (canvas != image)
6954     canvas=DestroyImage(canvas);
6955 }
6956 \f
6957 /*
6958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6959 %                                                                             %
6960 %                                                                             %
6961 %                                                                             %
6962 %   X M a k e M a g n i f y I m a g e                                         %
6963 %                                                                             %
6964 %                                                                             %
6965 %                                                                             %
6966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6967 %
6968 %  XMakeMagnifyImage() magnifies a region of an X image and displays it.
6969 %
6970 %  The format of the XMakeMagnifyImage method is:
6971 %
6972 %      void XMakeMagnifyImage(display,windows)
6973 %
6974 %  A description of each parameter follows:
6975 %
6976 %    o display: Specifies a connection to an X server;  returned from
6977 %      XOpenDisplay.
6978 %
6979 %    o windows: Specifies a pointer to a XWindows structure.
6980 %
6981 */
6982 MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
6983 {
6984   char
6985     tuple[MaxTextExtent];
6986
6987   int
6988     y;
6989
6990   long
6991     n;
6992
6993   MagickPixelPacket
6994     pixel;
6995
6996   register int
6997     x;
6998
6999   register long
7000     i;
7001
7002   register unsigned char
7003     *p,
7004     *q;
7005
7006   static unsigned int
7007     previous_magnify = 0;
7008
7009   static XWindowInfo
7010     magnify_window;
7011
7012   unsigned int
7013     height,
7014     j,
7015     k,
7016     l,
7017     magnify,
7018     scanline_pad,
7019     width;
7020
7021   XImage
7022     *ximage;
7023
7024   /*
7025     Check boundary conditions.
7026   */
7027   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7028   assert(display != (Display *) NULL);
7029   assert(windows != (XWindows *) NULL);
7030   magnify=1;
7031   for (n=1; n < (long) windows->magnify.data; n++)
7032     magnify<<=1;
7033   while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7034     magnify<<=1;
7035   while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7036     magnify<<=1;
7037   while (magnify > windows->magnify.width)
7038     magnify>>=1;
7039   while (magnify > windows->magnify.height)
7040     magnify>>=1;
7041   if (magnify != previous_magnify)
7042     {
7043       Status
7044         status;
7045
7046       XTextProperty
7047         window_name;
7048
7049       /*
7050         New magnify factor:  update magnify window name.
7051       */
7052       i=0;
7053       while ((1 << i) <= (int) magnify)
7054         i++;
7055       (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
7056         "Magnify %luX",i);
7057       status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7058       if (status != False)
7059         {
7060           XSetWMName(display,windows->magnify.id,&window_name);
7061           XSetWMIconName(display,windows->magnify.id,&window_name);
7062           (void) XFree((void *) window_name.value);
7063         }
7064     }
7065   previous_magnify=magnify;
7066   ximage=windows->image.ximage;
7067   width=(unsigned int) windows->magnify.ximage->width;
7068   height=(unsigned int) windows->magnify.ximage->height;
7069   if ((windows->magnify.x < 0) ||
7070       (windows->magnify.x >= windows->image.ximage->width))
7071     windows->magnify.x=windows->image.ximage->width >> 1;
7072   x=windows->magnify.x-((width/magnify) >> 1);
7073   if (x < 0)
7074     x=0;
7075   else
7076     if (x > (int) (ximage->width-(width/magnify)))
7077       x=ximage->width-width/magnify;
7078   if ((windows->magnify.y < 0) ||
7079       (windows->magnify.y >= windows->image.ximage->height))
7080     windows->magnify.y=windows->image.ximage->height >> 1;
7081   y=windows->magnify.y-((height/magnify) >> 1);
7082   if (y < 0)
7083     y=0;
7084   else
7085     if (y > (int) (ximage->height-(height/magnify)))
7086       y=ximage->height-height/magnify;
7087   q=(unsigned char *) windows->magnify.ximage->data;
7088   scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7089     ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7090   if (ximage->bits_per_pixel < 8)
7091     {
7092       register unsigned char
7093         background,
7094         byte,
7095         foreground,
7096         p_bit,
7097         q_bit;
7098
7099       register unsigned int
7100         plane;
7101
7102       XPixelInfo
7103         *pixel_info;
7104
7105       pixel_info=windows->magnify.pixel_info;
7106       switch (ximage->bitmap_bit_order)
7107       {
7108         case LSBFirst:
7109         {
7110           /*
7111             Magnify little-endian bitmap.
7112           */
7113           background=0x00;
7114           foreground=0x80;
7115           if (ximage->format == XYBitmap)
7116             {
7117               background=(unsigned char)
7118                 (XPixelIntensity(&pixel_info->foreground_color) <
7119                  XPixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
7120               foreground=(unsigned char)
7121                 (XPixelIntensity(&pixel_info->background_color) <
7122                  XPixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
7123               if (windows->magnify.depth > 1)
7124                 Swap(background,foreground);
7125             }
7126           for (i=0; i < (long) height; i+=magnify)
7127           {
7128             /*
7129               Propogate pixel magnify rows.
7130             */
7131             for (j=0; j < magnify; j++)
7132             {
7133               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7134                 ((x*ximage->bits_per_pixel) >> 3);
7135               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7136               q_bit=0;
7137               byte=0;
7138               for (k=0; k < width; k+=magnify)
7139               {
7140                 /*
7141                   Propogate pixel magnify columns.
7142                 */
7143                 for (l=0; l < magnify; l++)
7144                 {
7145                   /*
7146                     Propogate each bit plane.
7147                   */
7148                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7149                   {
7150                     byte>>=1;
7151                     if (*p & (0x01 << (p_bit+plane)))
7152                       byte|=foreground;
7153                     else
7154                       byte|=background;
7155                     q_bit++;
7156                     if (q_bit == 8)
7157                       {
7158                         *q++=byte;
7159                         q_bit=0;
7160                         byte=0;
7161                       }
7162                   }
7163                 }
7164                 p_bit+=ximage->bits_per_pixel;
7165                 if (p_bit == 8)
7166                   {
7167                     p++;
7168                     p_bit=0;
7169                   }
7170                 if (q_bit != 0)
7171                   *q=byte >> (8-q_bit);
7172                 q+=scanline_pad;
7173               }
7174             }
7175             y++;
7176           }
7177           break;
7178         }
7179         case MSBFirst:
7180         default:
7181         {
7182           /*
7183             Magnify big-endian bitmap.
7184           */
7185           background=0x00;
7186           foreground=0x01;
7187           if (ximage->format == XYBitmap)
7188             {
7189               background=(unsigned char)
7190                 (XPixelIntensity(&pixel_info->foreground_color) <
7191                  XPixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
7192               foreground=(unsigned char)
7193                 (XPixelIntensity(&pixel_info->background_color) <
7194                  XPixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
7195               if (windows->magnify.depth > 1)
7196                 Swap(background,foreground);
7197             }
7198           for (i=0; i < (long) height; i+=magnify)
7199           {
7200             /*
7201               Propogate pixel magnify rows.
7202             */
7203             for (j=0; j < magnify; j++)
7204             {
7205               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7206                 ((x*ximage->bits_per_pixel) >> 3);
7207               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7208               q_bit=0;
7209               byte=0;
7210               for (k=0; k < width; k+=magnify)
7211               {
7212                 /*
7213                   Propogate pixel magnify columns.
7214                 */
7215                 for (l=0; l < magnify; l++)
7216                 {
7217                   /*
7218                     Propogate each bit plane.
7219                   */
7220                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7221                   {
7222                     byte<<=1;
7223                     if (*p & (0x80 >> (p_bit+plane)))
7224                       byte|=foreground;
7225                     else
7226                       byte|=background;
7227                     q_bit++;
7228                     if (q_bit == 8)
7229                       {
7230                         *q++=byte;
7231                         q_bit=0;
7232                         byte=0;
7233                       }
7234                   }
7235                 }
7236                 p_bit+=ximage->bits_per_pixel;
7237                 if (p_bit == 8)
7238                   {
7239                     p++;
7240                     p_bit=0;
7241                   }
7242                 if (q_bit != 0)
7243                   *q=byte << (8-q_bit);
7244                 q+=scanline_pad;
7245               }
7246             }
7247             y++;
7248           }
7249           break;
7250         }
7251       }
7252     }
7253   else
7254     switch (ximage->bits_per_pixel)
7255     {
7256       case 6:
7257       case 8:
7258       {
7259         /*
7260           Magnify 8 bit X image.
7261         */
7262         for (i=0; i < (long) height; i+=magnify)
7263         {
7264           /*
7265             Propogate pixel magnify rows.
7266           */
7267           for (j=0; j < magnify; j++)
7268           {
7269             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7270               ((x*ximage->bits_per_pixel) >> 3);
7271             for (k=0; k < width; k+=magnify)
7272             {
7273               /*
7274                 Propogate pixel magnify columns.
7275               */
7276               for (l=0; l < magnify; l++)
7277                 *q++=(*p);
7278               p++;
7279             }
7280             q+=scanline_pad;
7281           }
7282           y++;
7283         }
7284         break;
7285       }
7286       default:
7287       {
7288         register unsigned int
7289           bytes_per_pixel,
7290           m;
7291
7292         /*
7293           Magnify multi-byte X image.
7294         */
7295         bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
7296         for (i=0; i < (long) height; i+=magnify)
7297         {
7298           /*
7299             Propogate pixel magnify rows.
7300           */
7301           for (j=0; j < magnify; j++)
7302           {
7303             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7304               ((x*ximage->bits_per_pixel) >> 3);
7305             for (k=0; k < width; k+=magnify)
7306             {
7307               /*
7308                 Propogate pixel magnify columns.
7309               */
7310               for (l=0; l < magnify; l++)
7311                 for (m=0; m < bytes_per_pixel; m++)
7312                   *q++=(*(p+m));
7313               p+=bytes_per_pixel;
7314             }
7315             q+=scanline_pad;
7316           }
7317           y++;
7318         }
7319         break;
7320       }
7321     }
7322   /*
7323     Copy X image to magnify pixmap.
7324   */
7325   x=windows->magnify.x-((width/magnify) >> 1);
7326   if (x < 0)
7327     x=(int) ((width >> 1)-windows->magnify.x*magnify);
7328   else
7329     if (x > (int) (ximage->width-(width/magnify)))
7330       x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7331     else
7332       x=0;
7333   y=windows->magnify.y-((height/magnify) >> 1);
7334   if (y < 0)
7335     y=(int) ((height >> 1)-windows->magnify.y*magnify);
7336   else
7337     if (y > (int) (ximage->height-(height/magnify)))
7338       y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7339     else
7340       y=0;
7341   if ((x != 0) || (y != 0))
7342     (void) XFillRectangle(display,windows->magnify.pixmap,
7343       windows->magnify.annotate_context,0,0,width,height);
7344   (void) XPutImage(display,windows->magnify.pixmap,
7345     windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7346     height-y);
7347   if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7348       (magnify <= (height >> 1))))
7349     {
7350       RectangleInfo
7351         highlight_info;
7352
7353       /*
7354         Highlight center pixel.
7355       */
7356       highlight_info.x=(long) windows->magnify.width >> 1;
7357       highlight_info.y=(long) windows->magnify.height >> 1;
7358       highlight_info.width=magnify;
7359       highlight_info.height=magnify;
7360       (void) XDrawRectangle(display,windows->magnify.pixmap,
7361         windows->magnify.highlight_context,(int) highlight_info.x,
7362         (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7363         (unsigned int) highlight_info.height-1);
7364       if (magnify > 2)
7365         (void) XDrawRectangle(display,windows->magnify.pixmap,
7366           windows->magnify.annotate_context,(int) highlight_info.x+1,
7367           (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7368           (unsigned int) highlight_info.height-3);
7369     }
7370   /*
7371     Show center pixel color.
7372   */
7373   (void) GetOneVirtualMagickPixel(windows->image.image,windows->magnify.x,
7374     windows->magnify.y,&pixel,&windows->image.image->exception);
7375   (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7376     windows->magnify.x,windows->magnify.y);
7377   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7378   ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7379   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7380   ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7381   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7382   ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7383   if (pixel.colorspace == CMYKColorspace)
7384     {
7385       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7386       ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7387     }
7388   if (pixel.matte != MagickFalse)
7389     {
7390       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7391       ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7392     }
7393   (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7394   height=(unsigned int) windows->magnify.font_info->ascent+
7395     windows->magnify.font_info->descent;
7396   x=windows->magnify.font_info->max_bounds.width >> 1;
7397   y=windows->magnify.font_info->ascent+(height >> 2);
7398   (void) XDrawImageString(display,windows->magnify.pixmap,
7399     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7400   GetColorTuple(&pixel,MagickTrue,tuple);
7401   y+=height;
7402   (void) XDrawImageString(display,windows->magnify.pixmap,
7403     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7404   (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7405      &windows->image.image->exception);
7406   y+=height;
7407   (void) XDrawImageString(display,windows->magnify.pixmap,
7408     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7409   /*
7410     Refresh magnify window.
7411   */
7412   magnify_window=windows->magnify;
7413   magnify_window.x=0;
7414   magnify_window.y=0;
7415   XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7416 }
7417 \f
7418 /*
7419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7420 %                                                                             %
7421 %                                                                             %
7422 %                                                                             %
7423 %   X M a k e P i x m a p                                                     %
7424 %                                                                             %
7425 %                                                                             %
7426 %                                                                             %
7427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7428 %
7429 %  XMakePixmap() creates an X11 pixmap.
7430 %
7431 %  The format of the XMakePixmap method is:
7432 %
7433 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7434 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7435 %        XPixelInfo *pixel)
7436 %
7437 %  A description of each parameter follows:
7438 %
7439 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7440 %
7441 %    o display: Specifies a connection to an X server; returned from
7442 %      XOpenDisplay.
7443 %
7444 %    o window: Specifies a pointer to a XWindowInfo structure.
7445 %
7446 %
7447 */
7448 static MagickBooleanType XMakePixmap(Display *display,
7449   const XResourceInfo *resource_info,XWindowInfo *window)
7450 {
7451   unsigned int
7452     height,
7453     width;
7454
7455   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7456   assert(display != (Display *) NULL);
7457   assert(resource_info != (XResourceInfo *) NULL);
7458   assert(window != (XWindowInfo  *) NULL);
7459   if (window->pixmap != (Pixmap) NULL)
7460     {
7461       /*
7462         Destroy previous X pixmap.
7463       */
7464       (void) XFreePixmap(display,window->pixmap);
7465       window->pixmap=(Pixmap) NULL;
7466     }
7467   if (window->use_pixmap == MagickFalse)
7468     return(MagickFalse);
7469   if (window->ximage == (XImage *) NULL)
7470     return(MagickFalse);
7471   /*
7472     Display busy cursor.
7473   */
7474   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7475   (void) XFlush(display);
7476   /*
7477     Create pixmap.
7478   */
7479   width=(unsigned int) window->ximage->width;
7480   height=(unsigned int) window->ximage->height;
7481   window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7482   if (window->pixmap == (Pixmap) NULL)
7483     {
7484       /*
7485         Unable to allocate pixmap.
7486       */
7487       (void) XCheckDefineCursor(display,window->id,window->cursor);
7488       return(MagickFalse);
7489     }
7490   /*
7491     Copy X image to pixmap.
7492   */
7493 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7494   if (window->shared_memory)
7495     (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7496       window->ximage,0,0,0,0,width,height,MagickTrue);
7497 #endif
7498   if (window->shared_memory == MagickFalse)
7499     (void) XPutImage(display,window->pixmap,window->annotate_context,
7500       window->ximage,0,0,0,0,width,height);
7501   if (IsEventLogging())
7502     {
7503       (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7504       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
7505         width,height);
7506     }
7507   /*
7508     Restore cursor.
7509   */
7510   (void) XCheckDefineCursor(display,window->id,window->cursor);
7511   return(MagickTrue);
7512 }
7513 \f
7514 /*
7515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7516 %                                                                             %
7517 %                                                                             %
7518 %                                                                             %
7519 %   X M a k e S t a n d a r d C o l o r m a p                                 %
7520 %                                                                             %
7521 %                                                                             %
7522 %                                                                             %
7523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7524 %
7525 %  XMakeStandardColormap() creates an X11 Standard Colormap.
7526 %
7527 %  The format of the XMakeStandardColormap method is:
7528 %
7529 %      XMakeStandardColormap(display,visual_info,resource_info,image,
7530 %        map_info,pixel)
7531 %
7532 %  A description of each parameter follows:
7533 %
7534 %    o display: Specifies a connection to an X server; returned from
7535 %      XOpenDisplay.
7536 %
7537 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7538 %      returned from XGetVisualInfo.
7539 %
7540 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7541 %
7542 %    o image: the image.
7543 %
7544 %    o map_info: If a Standard Colormap type is specified, this structure is
7545 %      initialized with info from the Standard Colormap.
7546 %
7547 %    o pixel: Specifies a pointer to a XPixelInfo structure.
7548 %
7549 %
7550 */
7551
7552 #if defined(__cplusplus) || defined(c_plusplus)
7553 extern "C" {
7554 #endif
7555
7556 static inline MagickRealType DiversityPixelIntensity(
7557   const DiversityPacket *pixel)
7558 {
7559   MagickRealType
7560     intensity;
7561
7562   intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7563   return(intensity);
7564 }
7565
7566 static int IntensityCompare(const void *x,const void *y)
7567 {
7568   DiversityPacket
7569     *color_1,
7570     *color_2;
7571
7572   int
7573     diversity;
7574
7575   color_1=(DiversityPacket *) x;
7576   color_2=(DiversityPacket *) y;
7577   diversity=(int) (DiversityPixelIntensity(color_2)-
7578     DiversityPixelIntensity(color_1));
7579   return(diversity);
7580 }
7581
7582 static int PopularityCompare(const void *x,const void *y)
7583 {
7584   DiversityPacket
7585     *color_1,
7586     *color_2;
7587
7588   color_1=(DiversityPacket *) x;
7589   color_2=(DiversityPacket *) y;
7590   return((int) color_2->count-(int) color_1->count);
7591 }
7592
7593 #if defined(__cplusplus) || defined(c_plusplus)
7594 }
7595 #endif
7596
7597 static inline Quantum ScaleXToQuantum(const unsigned long x,
7598   const unsigned long scale)
7599 {
7600   return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7601 }
7602
7603 MagickExport void XMakeStandardColormap(Display *display,
7604   XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7605   XStandardColormap *map_info,XPixelInfo *pixel)
7606 {
7607   Colormap
7608     colormap;
7609
7610   ExceptionInfo
7611     *exception;
7612
7613   register IndexPacket
7614     *indexes;
7615
7616   register long
7617     i;
7618
7619   Status
7620     status;
7621
7622   unsigned long
7623     number_colors,
7624     retain_colors;
7625
7626   unsigned short
7627     gray_value;
7628
7629   XColor
7630     color,
7631     *colors,
7632     *p;
7633
7634   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7635   assert(display != (Display *) NULL);
7636   assert(visual_info != (XVisualInfo *) NULL);
7637   assert(map_info != (XStandardColormap *) NULL);
7638   assert(resource_info != (XResourceInfo *) NULL);
7639   assert(pixel != (XPixelInfo *) NULL);
7640   exception=(&image->exception);
7641   if (resource_info->map_type != (char *) NULL)
7642     {
7643       /*
7644         Standard Colormap is already defined (i.e. xstdcmap).
7645       */
7646       XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7647         pixel);
7648       number_colors=(unsigned int) (map_info->base_pixel+
7649         (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7650       if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7651         if ((image->matte == MagickFalse) &&
7652             (resource_info->color_recovery == MagickFalse) &&
7653             resource_info->quantize_info->dither &&
7654             (number_colors < MaxColormapSize))
7655           {
7656             Image
7657               *affinity_image;
7658
7659             register PixelPacket
7660               *__restrict q;
7661
7662             /*
7663               Improve image appearance with error diffusion.
7664             */
7665             affinity_image=AcquireImage((ImageInfo *) NULL);
7666             if (affinity_image == (Image *) NULL)
7667               ThrowXWindowFatalException(ResourceLimitFatalError,
7668                 "UnableToDitherImage",image->filename);
7669             affinity_image->columns=number_colors;
7670             affinity_image->rows=1;
7671             /*
7672               Initialize colormap image.
7673             */
7674             q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7675               1,exception);
7676             if (q != (PixelPacket *) NULL)
7677               {
7678                 for (i=0; i < (long) number_colors; i++)
7679                 {
7680                   q->red=(Quantum) 0;
7681                   if (map_info->red_max != 0)
7682                     q->red=ScaleXToQuantum((unsigned long) (i/
7683                       map_info->red_mult),map_info->red_max);
7684                   q->green=(Quantum) 0;
7685                   if (map_info->green_max != 0)
7686                     q->green=ScaleXToQuantum((unsigned long) ((i/
7687                       map_info->green_mult) % (map_info->green_max+1)),
7688                       map_info->green_max);
7689                   q->blue=(Quantum) 0;
7690                   if (map_info->blue_max != 0)
7691                     q->blue=ScaleXToQuantum((unsigned long) (i %
7692                       map_info->green_mult),map_info->blue_max);
7693                   q->opacity=(Quantum) TransparentOpacity;
7694                   q++;
7695                 }
7696                 (void) SyncAuthenticPixels(affinity_image,exception);
7697                 (void) RemapImage(resource_info->quantize_info,image,
7698                   affinity_image);
7699               }
7700             XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7701               pixel);
7702             (void) SetImageStorageClass(image,DirectClass);
7703             affinity_image=DestroyImage(affinity_image);
7704           }
7705       if (IsEventLogging())
7706         {
7707           (void) LogMagickEvent(X11Event,GetMagickModule(),
7708             "Standard Colormap:");
7709           (void) LogMagickEvent(X11Event,GetMagickModule(),
7710             "  colormap id: 0x%lx",map_info->colormap);
7711           (void) LogMagickEvent(X11Event,GetMagickModule(),
7712             "  red, green, blue max: %lu %lu %lu",map_info->red_max,
7713             map_info->green_max,map_info->blue_max);
7714           (void) LogMagickEvent(X11Event,GetMagickModule(),
7715             "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7716             map_info->green_mult,map_info->blue_mult);
7717         }
7718       return;
7719     }
7720   if ((visual_info->klass != DirectColor) &&
7721       (visual_info->klass != TrueColor))
7722     if ((image->storage_class == DirectClass) ||
7723         ((int) image->colors > visual_info->colormap_size))
7724       {
7725         QuantizeInfo
7726           quantize_info;
7727
7728         /*
7729           Image has more colors than the visual supports.
7730         */
7731         quantize_info=(*resource_info->quantize_info);
7732         quantize_info.number_colors=(unsigned long) visual_info->colormap_size;
7733         (void) QuantizeImage(&quantize_info,image);
7734       }
7735   /*
7736     Free previous and create new colormap.
7737   */
7738   (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7739   colormap=XDefaultColormap(display,visual_info->screen);
7740   if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7741     colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7742       visual_info->visual,visual_info->klass == DirectColor ?
7743       AllocAll : AllocNone);
7744   if (colormap == (Colormap) NULL)
7745     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7746       image->filename);
7747   /*
7748     Initialize the map and pixel info structures.
7749   */
7750   XGetMapInfo(visual_info,colormap,map_info);
7751   XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7752   /*
7753     Allocating colors in server colormap is based on visual class.
7754   */
7755   switch (visual_info->klass)
7756   {
7757     case StaticGray:
7758     case StaticColor:
7759     {
7760       /*
7761         Define Standard Colormap for StaticGray or StaticColor visual.
7762       */
7763       number_colors=image->colors;
7764       colors=(XColor *) AcquireQuantumMemory((size_t)
7765         visual_info->colormap_size,sizeof(*colors));
7766       if (colors == (XColor *) NULL)
7767         ThrowXWindowFatalException(ResourceLimitFatalError,
7768           "UnableToCreateColormap",image->filename);
7769       p=colors;
7770       color.flags=(char) (DoRed | DoGreen | DoBlue);
7771       for (i=0; i < (long) image->colors; i++)
7772       {
7773         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7774         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7775         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7776         if (visual_info->klass != StaticColor)
7777           {
7778             gray_value=(unsigned short) XPixelIntensity(&color);
7779             color.red=gray_value;
7780             color.green=gray_value;
7781             color.blue=gray_value;
7782           }
7783         status=XAllocColor(display,colormap,&color);
7784         if (status == False)
7785           {
7786             colormap=XCopyColormapAndFree(display,colormap);
7787             (void) XAllocColor(display,colormap,&color);
7788           }
7789         pixel->pixels[i]=color.pixel;
7790         *p++=color;
7791       }
7792       break;
7793     }
7794     case GrayScale:
7795     case PseudoColor:
7796     {
7797       unsigned int
7798         colormap_type;
7799
7800       /*
7801         Define Standard Colormap for GrayScale or PseudoColor visual.
7802       */
7803       number_colors=image->colors;
7804       colors=(XColor *) AcquireQuantumMemory((size_t)
7805         visual_info->colormap_size,sizeof(*colors));
7806       if (colors == (XColor *) NULL)
7807         ThrowXWindowFatalException(ResourceLimitFatalError,
7808           "UnableToCreateColormap",image->filename);
7809       /*
7810         Preallocate our GUI colors.
7811       */
7812       (void) XAllocColor(display,colormap,&pixel->foreground_color);
7813       (void) XAllocColor(display,colormap,&pixel->background_color);
7814       (void) XAllocColor(display,colormap,&pixel->border_color);
7815       (void) XAllocColor(display,colormap,&pixel->matte_color);
7816       (void) XAllocColor(display,colormap,&pixel->highlight_color);
7817       (void) XAllocColor(display,colormap,&pixel->shadow_color);
7818       (void) XAllocColor(display,colormap,&pixel->depth_color);
7819       (void) XAllocColor(display,colormap,&pixel->trough_color);
7820       for (i=0; i < MaxNumberPens; i++)
7821         (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7822       /*
7823         Determine if image colors will "fit" into X server colormap.
7824       */
7825       colormap_type=resource_info->colormap;
7826       status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
7827         NULL,0,pixel->pixels,(unsigned int) image->colors);
7828       if (status != False)
7829         colormap_type=PrivateColormap;
7830       if (colormap_type == SharedColormap)
7831         {
7832           DiversityPacket
7833             *diversity;
7834
7835           int
7836             y;
7837
7838           register int
7839             x;
7840
7841           unsigned short
7842             index;
7843
7844           XColor
7845             *server_colors;
7846
7847           /*
7848             Define Standard colormap for shared GrayScale or PseudoColor visual.
7849           */
7850           diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7851             sizeof(*diversity));
7852           if (diversity == (DiversityPacket *) NULL)
7853             ThrowXWindowFatalException(ResourceLimitFatalError,
7854               "UnableToCreateColormap",image->filename);
7855           for (i=0; i < (long) image->colors; i++)
7856           {
7857             diversity[i].red=image->colormap[i].red;
7858             diversity[i].green=image->colormap[i].green;
7859             diversity[i].blue=image->colormap[i].blue;
7860             diversity[i].index=(unsigned short) i;
7861             diversity[i].count=0;
7862           }
7863           for (y=0; y < (int) image->rows; y++)
7864           {
7865             register long
7866               x;
7867
7868             register PixelPacket
7869               *__restrict q;
7870
7871             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
7872             if (q == (PixelPacket *) NULL)
7873               break;
7874             indexes=GetAuthenticIndexQueue(image);
7875             for (x=(long) image->columns-1; x >= 0; x--)
7876               diversity[(long) indexes[x]].count++;
7877           }
7878           /*
7879             Sort colors by decreasing intensity.
7880           */
7881           qsort((void *) diversity,image->colors,sizeof(*diversity),
7882             IntensityCompare);
7883           for (i=0; i < (long) image->colors; )
7884           {
7885             diversity[i].count<<=4;  /* increase this colors popularity */
7886             i+=MagickMax((long) (image->colors >> 4),2);
7887           }
7888           diversity[image->colors-1].count<<=4;
7889           qsort((void *) diversity,image->colors,sizeof(*diversity),
7890             PopularityCompare);
7891           /*
7892             Allocate colors.
7893           */
7894           p=colors;
7895           color.flags=(char) (DoRed | DoGreen | DoBlue);
7896           for (i=0; i < (long) image->colors; i++)
7897           {
7898             index=diversity[i].index;
7899             color.red=
7900               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7901             color.green=
7902               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7903             color.blue=
7904               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7905             if (visual_info->klass != PseudoColor)
7906               {
7907                 gray_value=(unsigned short) XPixelIntensity(&color);
7908                 color.red=gray_value;
7909                 color.green=gray_value;
7910                 color.blue=gray_value;
7911               }
7912             status=XAllocColor(display,colormap,&color);
7913             if (status == False)
7914               break;
7915             pixel->pixels[index]=color.pixel;
7916             *p++=color;
7917           }
7918           /*
7919             Read X server colormap.
7920           */
7921           server_colors=(XColor *) AcquireQuantumMemory((size_t)
7922             visual_info->colormap_size,sizeof(*server_colors));
7923           if (server_colors == (XColor *) NULL)
7924             ThrowXWindowFatalException(ResourceLimitFatalError,
7925               "UnableToCreateColormap",image->filename);
7926           for (x=visual_info->colormap_size-1; x >= 0; x--)
7927             server_colors[x].pixel=(unsigned long) x;
7928           (void) XQueryColors(display,colormap,server_colors,
7929             (int) MagickMin((unsigned int) visual_info->colormap_size,256));
7930           /*
7931             Select remaining colors from X server colormap.
7932           */
7933           for (; i < (long) image->colors; i++)
7934           {
7935             index=diversity[i].index;
7936             color.red=
7937               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7938             color.green=
7939               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7940             color.blue=
7941               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7942             if (visual_info->klass != PseudoColor)
7943               {
7944                 gray_value=(unsigned short) XPixelIntensity(&color);
7945                 color.red=gray_value;
7946                 color.green=gray_value;
7947                 color.blue=gray_value;
7948               }
7949             XBestPixel(display,colormap,server_colors,(unsigned int)
7950               visual_info->colormap_size,&color);
7951             pixel->pixels[index]=color.pixel;
7952             *p++=color;
7953           }
7954           if ((int) image->colors < visual_info->colormap_size)
7955             {
7956               /*
7957                 Fill up colors array-- more choices for pen colors.
7958               */
7959               retain_colors=MagickMin((unsigned int)
7960                (visual_info->colormap_size-image->colors),256);
7961               for (i=0; i < (long) retain_colors; i++)
7962                 *p++=server_colors[i];
7963               number_colors+=retain_colors;
7964             }
7965           server_colors=(XColor *) RelinquishMagickMemory(server_colors);
7966           diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
7967           break;
7968         }
7969       /*
7970         Define Standard colormap for private GrayScale or PseudoColor visual.
7971       */
7972       if (status == False)
7973         {
7974           /*
7975             Not enough colormap entries in the colormap-- Create a new colormap.
7976           */
7977           colormap=XCreateColormap(display,
7978             XRootWindow(display,visual_info->screen),visual_info->visual,
7979             AllocNone);
7980           if (colormap == (Colormap) NULL)
7981             ThrowXWindowFatalException(ResourceLimitFatalError,
7982               "UnableToCreateColormap",image->filename);
7983           map_info->colormap=colormap;
7984           if ((int) image->colors < visual_info->colormap_size)
7985             {
7986               /*
7987                 Retain colors from the default colormap to help lessens the
7988                 effects of colormap flashing.
7989               */
7990               retain_colors=MagickMin((unsigned int)
7991                 (visual_info->colormap_size-image->colors),256);
7992               p=colors+image->colors;
7993               for (i=0; i < (long) retain_colors; i++)
7994               {
7995                 p->pixel=(unsigned long) i;
7996                 p++;
7997               }
7998               (void) XQueryColors(display,
7999                 XDefaultColormap(display,visual_info->screen),
8000                 colors+image->colors,(int) retain_colors);
8001               /*
8002                 Transfer colors from default to private colormap.
8003               */
8004               (void) XAllocColorCells(display,colormap,MagickFalse,
8005                 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8006                 retain_colors);
8007               p=colors+image->colors;
8008               for (i=0; i < (long) retain_colors; i++)
8009               {
8010                 p->pixel=pixel->pixels[i];
8011                 p++;
8012               }
8013               (void) XStoreColors(display,colormap,colors+image->colors,
8014                 (int) retain_colors);
8015               number_colors+=retain_colors;
8016             }
8017           (void) XAllocColorCells(display,colormap,MagickFalse,
8018             (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
8019             image->colors);
8020         }
8021       /*
8022         Store the image colormap.
8023       */
8024       p=colors;
8025       color.flags=(char) (DoRed | DoGreen | DoBlue);
8026       for (i=0; i < (long) image->colors; i++)
8027       {
8028         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8029         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8030         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8031         if (visual_info->klass != PseudoColor)
8032           {
8033             gray_value=(unsigned short) XPixelIntensity(&color);
8034             color.red=gray_value;
8035             color.green=gray_value;
8036             color.blue=gray_value;
8037           }
8038         color.pixel=pixel->pixels[i];
8039         *p++=color;
8040       }
8041       (void) XStoreColors(display,colormap,colors,(int) image->colors);
8042       break;
8043     }
8044     case TrueColor:
8045     case DirectColor:
8046     default:
8047     {
8048       MagickBooleanType
8049         linear_colormap;
8050
8051       /*
8052         Define Standard Colormap for TrueColor or DirectColor visual.
8053       */
8054       number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8055         (map_info->green_max*map_info->green_mult)+
8056         (map_info->blue_max*map_info->blue_mult)+1);
8057       linear_colormap=(number_colors > 4096) ||
8058         (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8059          ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8060          ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8061          MagickTrue : MagickFalse;
8062       if (linear_colormap != MagickFalse)
8063         number_colors=(unsigned long) visual_info->colormap_size;
8064       /*
8065         Allocate color array.
8066       */
8067       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8068       if (colors == (XColor *) NULL)
8069         ThrowXWindowFatalException(ResourceLimitFatalError,
8070           "UnableToCreateColormap",image->filename);
8071       /*
8072         Initialize linear color ramp.
8073       */
8074       p=colors;
8075       color.flags=(char) (DoRed | DoGreen | DoBlue);
8076       if (linear_colormap != MagickFalse)
8077         for (i=0; i < (long) number_colors; i++)
8078         {
8079           color.blue=(unsigned short) 0;
8080           if (map_info->blue_max != 0)
8081             color.blue=(unsigned short) ((unsigned long)
8082               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8083           color.green=color.blue;
8084           color.red=color.blue;
8085           color.pixel=XStandardPixel(map_info,&color);
8086           *p++=color;
8087         }
8088       else
8089         for (i=0; i < (long) number_colors; i++)
8090         {
8091           color.red=(unsigned short) 0;
8092           if (map_info->red_max != 0)
8093             color.red=(unsigned short) ((unsigned long)
8094               ((65535L*(i/map_info->red_mult))/map_info->red_max));
8095           color.green=(unsigned int) 0;
8096           if (map_info->green_max != 0)
8097             color.green=(unsigned short) ((unsigned long)
8098               ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8099                 map_info->green_max));
8100           color.blue=(unsigned short) 0;
8101           if (map_info->blue_max != 0)
8102             color.blue=(unsigned short) ((unsigned long)
8103               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8104           color.pixel=XStandardPixel(map_info,&color);
8105           *p++=color;
8106         }
8107       if ((visual_info->klass == DirectColor) &&
8108           (colormap != XDefaultColormap(display,visual_info->screen)))
8109         (void) XStoreColors(display,colormap,colors,(int) number_colors);
8110       else
8111         for (i=0; i < (long) number_colors; i++)
8112           (void) XAllocColor(display,colormap,&colors[i]);
8113       break;
8114     }
8115   }
8116   if ((visual_info->klass != DirectColor) &&
8117       (visual_info->klass != TrueColor))
8118     {
8119       /*
8120         Set foreground, background, border, etc. pixels.
8121       */
8122       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8123         &pixel->foreground_color);
8124       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8125         &pixel->background_color);
8126       if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8127         {
8128           /*
8129             Foreground and background colors must differ.
8130           */
8131           pixel->background_color.red=(~pixel->foreground_color.red);
8132           pixel->background_color.green=
8133             (~pixel->foreground_color.green);
8134           pixel->background_color.blue=
8135             (~pixel->foreground_color.blue);
8136           XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8137             &pixel->background_color);
8138         }
8139       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8140         &pixel->border_color);
8141       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8142         &pixel->matte_color);
8143       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8144         &pixel->highlight_color);
8145       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8146         &pixel->shadow_color);
8147       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8148         &pixel->depth_color);
8149       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8150         &pixel->trough_color);
8151       for (i=0; i < MaxNumberPens; i++)
8152       {
8153         XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8154           &pixel->pen_colors[i]);
8155         pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8156       }
8157       pixel->colors=image->colors+MaxNumberPens;
8158     }
8159   colors=(XColor *) RelinquishMagickMemory(colors);
8160   if (IsEventLogging())
8161     {
8162       (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8163       (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
8164         map_info->colormap);
8165       (void) LogMagickEvent(X11Event,GetMagickModule(),
8166         "  red, green, blue max: %lu %lu %lu",map_info->red_max,
8167         map_info->green_max,map_info->blue_max);
8168       (void) LogMagickEvent(X11Event,GetMagickModule(),
8169         "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8170         map_info->green_mult,map_info->blue_mult);
8171     }
8172 }
8173 \f
8174 /*
8175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8176 %                                                                             %
8177 %                                                                             %
8178 %                                                                             %
8179 %   X M a k e W i n d o w                                                     %
8180 %                                                                             %
8181 %                                                                             %
8182 %                                                                             %
8183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8184 %
8185 %  XMakeWindow() creates an X11 window.
8186 %
8187 %  The format of the XMakeWindow method is:
8188 %
8189 %      void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8190 %        XClassHint *class_hint,XWMHints *manager_hints,
8191 %        XWindowInfo *window_info)
8192 %
8193 %  A description of each parameter follows:
8194 %
8195 %    o display: Specifies a connection to an X server; returned from
8196 %      XOpenDisplay.
8197 %
8198 %    o parent: Specifies the parent window_info.
8199 %
8200 %    o argv: Specifies the application's argument list.
8201 %
8202 %    o argc: Specifies the number of arguments.
8203 %
8204 %    o class_hint: Specifies a pointer to a X11 XClassHint structure.
8205 %
8206 %    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8207 %
8208 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8209 %
8210 */
8211 MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8212   int argc,XClassHint *class_hint,XWMHints *manager_hints,
8213   XWindowInfo *window_info)
8214 {
8215 #define MinWindowSize  64
8216
8217   Atom
8218     atom_list[2];
8219
8220   int
8221     gravity;
8222
8223   static XTextProperty
8224     icon_name,
8225     window_name;
8226
8227   Status
8228     status;
8229
8230   XSizeHints
8231     *size_hints;
8232
8233   /*
8234     Set window info hints.
8235   */
8236   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8237   assert(display != (Display *) NULL);
8238   assert(window_info != (XWindowInfo *) NULL);
8239   size_hints=XAllocSizeHints();
8240   if (size_hints == (XSizeHints *) NULL)
8241     ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
8242   size_hints->flags=(long) window_info->flags;
8243   size_hints->x=window_info->x;
8244   size_hints->y=window_info->y;
8245   size_hints->width=(int) window_info->width;
8246   size_hints->height=(int) window_info->height;
8247   if (window_info->immutable != MagickFalse)
8248     {
8249       /*
8250         Window size cannot be changed.
8251       */
8252       size_hints->min_width=size_hints->width;
8253       size_hints->min_height=size_hints->height;
8254       size_hints->max_width=size_hints->width;
8255       size_hints->max_height=size_hints->height;
8256       size_hints->flags|=PMinSize;
8257       size_hints->flags|=PMaxSize;
8258     }
8259   else
8260     {
8261       /*
8262         Window size can be changed.
8263       */
8264       size_hints->min_width=(int) window_info->min_width;
8265       size_hints->min_height=(int) window_info->min_height;
8266       size_hints->flags|=PResizeInc;
8267       size_hints->width_inc=(int) window_info->width_inc;
8268       size_hints->height_inc=(int) window_info->height_inc;
8269 #if !defined(PRE_R4_ICCCM)
8270       size_hints->flags|=PBaseSize;
8271       size_hints->base_width=size_hints->width_inc;
8272       size_hints->base_height=size_hints->height_inc;
8273 #endif
8274     }
8275   gravity=NorthWestGravity;
8276   if (window_info->geometry != (char *) NULL)
8277     {
8278       char
8279         default_geometry[MaxTextExtent],
8280         geometry[MaxTextExtent];
8281
8282       int
8283         flags;
8284
8285       register char
8286         *p;
8287
8288       /*
8289         User specified geometry.
8290       */
8291       (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8292         size_hints->width,size_hints->height);
8293       (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8294       p=geometry;
8295       while (strlen(p) != 0)
8296       {
8297         if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8298           p++;
8299         else
8300           (void) CopyMagickString(p,p+1,MaxTextExtent);
8301       }
8302       flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8303         window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8304         &size_hints->width,&size_hints->height,&gravity);
8305       if ((flags & WidthValue) && (flags & HeightValue))
8306         size_hints->flags|=USSize;
8307       if ((flags & XValue) && (flags & YValue))
8308         {
8309           size_hints->flags|=USPosition;
8310           window_info->x=size_hints->x;
8311           window_info->y=size_hints->y;
8312         }
8313     }
8314 #if !defined(PRE_R4_ICCCM)
8315   size_hints->win_gravity=gravity;
8316   size_hints->flags|=PWinGravity;
8317 #endif
8318   if (window_info->id == (Window) NULL)
8319     window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8320       (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8321       window_info->border_width,(int) window_info->depth,InputOutput,
8322       window_info->visual,window_info->mask,&window_info->attributes);
8323   else
8324     {
8325       MagickStatusType
8326         mask;
8327
8328       XEvent
8329         sans_event;
8330
8331       XWindowChanges
8332         window_changes;
8333
8334       /*
8335         Window already exists;  change relevant attributes.
8336       */
8337       (void) XChangeWindowAttributes(display,window_info->id,window_info->mask,
8338         &window_info->attributes);
8339       mask=ConfigureNotify;
8340       while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8341       window_changes.x=window_info->x;
8342       window_changes.y=window_info->y;
8343       window_changes.width=(int) window_info->width;
8344       window_changes.height=(int) window_info->height;
8345       mask=(MagickStatusType) (CWWidth | CWHeight);
8346       if (window_info->flags & USPosition)
8347         mask|=CWX | CWY;
8348       (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8349         mask,&window_changes);
8350     }
8351   if (window_info->id == (Window) NULL)
8352     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8353       window_info->name);
8354   status=XStringListToTextProperty(&window_info->name,1,&window_name);
8355   if (status == False)
8356     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8357       window_info->name);
8358   status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8359   if (status == False)
8360     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8361       window_info->icon_name);
8362   if (window_info->icon_geometry != (char *) NULL)
8363     {
8364       int
8365         flags,
8366         height,
8367         width;
8368
8369       /*
8370         User specified icon geometry.
8371       */
8372       size_hints->flags|=USPosition;
8373       flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8374         (char *) NULL,0,size_hints,&manager_hints->icon_x,
8375         &manager_hints->icon_y,&width,&height,&gravity);
8376       if ((flags & XValue) && (flags & YValue))
8377         manager_hints->flags|=IconPositionHint;
8378     }
8379   XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8380     size_hints,manager_hints,class_hint);
8381   if (window_name.value != (void *) NULL)
8382     {
8383       (void) XFree((void *) window_name.value);
8384       window_name.value=(unsigned char *) NULL;
8385       window_name.nitems=0;
8386     }
8387   if (icon_name.value != (void *) NULL)
8388     {
8389       (void) XFree((void *) icon_name.value);
8390       icon_name.value=(unsigned char *) NULL;
8391       icon_name.nitems=0;
8392     }
8393   atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8394   atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8395   (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8396   (void) XFree((void *) size_hints);
8397   if (window_info->shape != MagickFalse)
8398     {
8399 #if defined(MAGICKCORE_HAVE_SHAPE)
8400       int
8401         error_base,
8402         event_base;
8403
8404       /*
8405         Can we apply a non-rectangular shaping mask?
8406       */
8407       error_base=0;
8408       event_base=0;
8409       if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8410         window_info->shape=MagickFalse;
8411 #else
8412       window_info->shape=MagickFalse;
8413 #endif
8414     }
8415   if (window_info->shared_memory)
8416     {
8417 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8418       /*
8419         Can we use shared memory with this window?
8420       */
8421       if (XShmQueryExtension(display) == 0)
8422         window_info->shared_memory=MagickFalse;
8423 #else
8424       window_info->shared_memory=MagickFalse;
8425 #endif
8426     }
8427   window_info->image=NewImageList();
8428   window_info->destroy=MagickFalse;
8429 }
8430 \f
8431 /*
8432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8433 %                                                                             %
8434 %                                                                             %
8435 %                                                                             %
8436 %   X M a g i c k P r o g r e s s M o n i t o r                               %
8437 %                                                                             %
8438 %                                                                             %
8439 %                                                                             %
8440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8441 %
8442 %  XMagickProgressMonitor() displays the progress a task is making in
8443 %  completing a task.
8444 %
8445 %  The format of the XMagickProgressMonitor method is:
8446 %
8447 %      void XMagickProgressMonitor(const char *task,
8448 %        const MagickOffsetType quantum,const MagickSizeType span,
8449 %        void *client_data)
8450 %
8451 %  A description of each parameter follows:
8452 %
8453 %    o task: Identifies the task in progress.
8454 %
8455 %    o quantum: Specifies the quantum position within the span which represents
8456 %      how much progress has been made in completing a task.
8457 %
8458 %    o span: Specifies the span relative to completing a task.
8459 %
8460 %    o client_data: Pointer to any client data.
8461 %
8462 */
8463
8464 static const char *GetLocaleMonitorMessage(const char *text)
8465 {
8466   char
8467     message[MaxTextExtent],
8468     tag[MaxTextExtent];
8469
8470   const char
8471     *locale_message;
8472
8473   register char
8474     *p;
8475
8476   (void) CopyMagickMemory(tag,text,MaxTextExtent);
8477   p=strrchr(tag,'/');
8478   if (p != (char *) NULL)
8479     *p='\0';
8480   (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8481   locale_message=GetLocaleMessage(message);
8482   if (locale_message == message)
8483     return(text);
8484   return(locale_message);
8485 }
8486
8487 MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8488   const MagickOffsetType quantum,const MagickSizeType span,
8489   void *magick_unused(client_data))
8490 {
8491   XWindows
8492     *windows;
8493
8494   windows=XSetWindows((XWindows *) ~0);
8495   if (windows == (XWindows *) NULL)
8496     return(MagickTrue);
8497   if (windows->info.mapped != MagickFalse)
8498     XProgressMonitorWidget(windows->display,windows,
8499       GetLocaleMonitorMessage(tag),quantum,span);
8500   return(MagickTrue);
8501 }
8502 \f
8503 /*
8504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8505 %                                                                             %
8506 %                                                                             %
8507 %                                                                             %
8508 %   X Q u e r y C o l o r D a t a b a s e                                     %
8509 %                                                                             %
8510 %                                                                             %
8511 %                                                                             %
8512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8513 %
8514 %  XQueryColorDatabase() looks up a RGB values for a color given in the target
8515 %  string.
8516 %
8517 %  The format of the XQueryColorDatabase method is:
8518 %
8519 %      MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8520 %
8521 %  A description of each parameter follows:
8522 %
8523 %    o target: Specifies the color to lookup in the X color database.
8524 %
8525 %    o color: A pointer to an PixelPacket structure.  The RGB value of the target
8526 %      color is returned as this value.
8527 %
8528 */
8529 MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8530   XColor *color)
8531 {
8532   Colormap
8533     colormap;
8534
8535   static Display
8536     *display = (Display *) NULL;
8537
8538   Status
8539     status;
8540
8541   XColor
8542     xcolor;
8543
8544   /*
8545     Initialize color return value.
8546   */
8547   assert(color != (XColor *) NULL);
8548   color->red=0;
8549   color->green=0;
8550   color->blue=0;
8551   color->flags=(char) (DoRed | DoGreen | DoBlue);
8552   if ((target == (char *) NULL) || (*target == '\0'))
8553     target="#ffffffffffff";
8554   /*
8555     Let the X server define the color for us.
8556   */
8557   if (display == (Display *) NULL)
8558     display=XOpenDisplay((char *) NULL);
8559   if (display == (Display *) NULL)
8560     {
8561       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8562       return(MagickFalse);
8563     }
8564   colormap=XDefaultColormap(display,XDefaultScreen(display));
8565   status=XParseColor(display,colormap,(char *) target,&xcolor);
8566   if (status == False)
8567     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8568   else
8569     {
8570       color->red=xcolor.red;
8571       color->green=xcolor.green;
8572       color->blue=xcolor.blue;
8573       color->flags=xcolor.flags;
8574     }
8575   return(status != False ? MagickTrue : MagickFalse);
8576 }
8577 \f
8578 /*
8579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8580 %                                                                             %
8581 %                                                                             %
8582 %                                                                             %
8583 %   X Q u e r y P o s i t i o n                                               %
8584 %                                                                             %
8585 %                                                                             %
8586 %                                                                             %
8587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8588 %
8589 %  XQueryPosition() gets the pointer coordinates relative to a window.
8590 %
8591 %  The format of the XQueryPosition method is:
8592 %
8593 %      void XQueryPosition(Display *display,const Window window,int *x,int *y)
8594 %
8595 %  A description of each parameter follows:
8596 %
8597 %    o display: Specifies a connection to an X server;  returned from
8598 %      XOpenDisplay.
8599 %
8600 %    o window: Specifies a pointer to a Window.
8601 %
8602 %    o x: Return the x coordinate of the pointer relative to the origin of the
8603 %      window.
8604 %
8605 %    o y: Return the y coordinate of the pointer relative to the origin of the
8606 %      window.
8607 %
8608 */
8609 MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8610 {
8611   int
8612     x_root,
8613     y_root;
8614
8615   unsigned int
8616     mask;
8617
8618   Window
8619     root_window;
8620
8621   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8622   assert(display != (Display *) NULL);
8623   assert(window != (Window) NULL);
8624   assert(x != (int *) NULL);
8625   assert(y != (int *) NULL);
8626   (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8627     x,y,&mask);
8628 }
8629 \f
8630 /*
8631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8632 %                                                                             %
8633 %                                                                             %
8634 %                                                                             %
8635 %   X R e f r e s h W i n d o w                                               %
8636 %                                                                             %
8637 %                                                                             %
8638 %                                                                             %
8639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8640 %
8641 %  XRefreshWindow() refreshes an image in a X window.
8642 %
8643 %  The format of the XRefreshWindow method is:
8644 %
8645 %      void XRefreshWindow(Display *display,const XWindowInfo *window,
8646 %        const XEvent *event)
8647 %
8648 %  A description of each parameter follows:
8649 %
8650 %    o display: Specifies a connection to an X server;  returned from
8651 %      XOpenDisplay.
8652 %
8653 %    o window: Specifies a pointer to a XWindowInfo structure.
8654 %
8655 %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
8656 %      the entire image is refreshed.
8657 %
8658 */
8659 MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8660   const XEvent *event)
8661 {
8662   int
8663     x,
8664     y;
8665
8666   unsigned int
8667     height,
8668     width;
8669
8670   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8671   assert(display != (Display *) NULL);
8672   assert(window != (XWindowInfo *) NULL);
8673   if (window->ximage == (XImage *) NULL)
8674     return;
8675   if (event != (XEvent *) NULL)
8676     {
8677       /*
8678         Determine geometry from expose event.
8679       */
8680       x=event->xexpose.x;
8681       y=event->xexpose.y;
8682       width=(unsigned int) event->xexpose.width;
8683       height=(unsigned int) event->xexpose.height;
8684     }
8685   else
8686     {
8687       XEvent
8688         sans_event;
8689
8690       /*
8691         Refresh entire window; discard outstanding expose events.
8692       */
8693       x=0;
8694       y=0;
8695       width=window->width;
8696       height=window->height;
8697       while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
8698     }
8699   /*
8700     Check boundary conditions.
8701   */
8702   if ((window->ximage->width-(x+window->x)) < (int) width)
8703     width=(unsigned int) (window->ximage->width-(x+window->x));
8704   if ((window->ximage->height-(y+window->y)) < (int) height)
8705     height=(unsigned int) (window->ximage->height-(y+window->y));
8706   /*
8707     Refresh image.
8708   */
8709   if (window->matte_pixmap != (Pixmap) NULL)
8710     {
8711 #if defined(MAGICKCORE_HAVE_SHAPE)
8712       if (window->shape != MagickFalse)
8713         XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8714           window->matte_pixmap,ShapeSet);
8715 #endif
8716       (void) XSetClipMask(display,window->annotate_context,
8717         window->matte_pixmap);
8718     }
8719   if (window->pixmap != (Pixmap) NULL)
8720     {
8721       if (window->depth > 1)
8722         (void) XCopyArea(display,window->pixmap,window->id,
8723           window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8724       else
8725         (void) XCopyPlane(display,window->pixmap,window->id,
8726           window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8727           1L);
8728     }
8729   else
8730     {
8731 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8732       if (window->shared_memory)
8733         (void) XShmPutImage(display,window->id,window->annotate_context,
8734           window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8735 #endif
8736       if (window->shared_memory == MagickFalse)
8737         (void) XPutImage(display,window->id,window->annotate_context,
8738           window->ximage,x+window->x,y+window->y,x,y,width,height);
8739     }
8740   if (window->matte_pixmap != (Pixmap) NULL)
8741     (void) XSetClipMask(display,window->annotate_context,None);
8742   (void) XFlush(display);
8743 }
8744 \f
8745 /*
8746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8747 %                                                                             %
8748 %                                                                             %
8749 %                                                                             %
8750 %   X R e m o t e C o m m a n d                                               %
8751 %                                                                             %
8752 %                                                                             %
8753 %                                                                             %
8754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8755 %
8756 %  XRemoteCommand() forces a remote display(1) to display the specified
8757 %  image filename.
8758 %
8759 %  The format of the XRemoteCommand method is:
8760 %
8761 %      MagickBooleanType XRemoteCommand(Display *display,const char *window,
8762 %        const char *filename)
8763 %
8764 %  A description of each parameter follows:
8765 %
8766 %    o display: Specifies a connection to an X server; returned from
8767 %      XOpenDisplay.
8768 %
8769 %    o window: Specifies the name or id of an X window.
8770 %
8771 %    o filename: the name of the image filename to display.
8772 %
8773 */
8774 MagickExport MagickBooleanType XRemoteCommand(Display *display,
8775   const char *window,const char *filename)
8776 {
8777   Atom
8778     remote_atom;
8779
8780   Window
8781     remote_window,
8782     root_window;
8783
8784   assert(filename != (char *) NULL);
8785   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8786   if (display == (Display *) NULL)
8787     display=XOpenDisplay((char *) NULL);
8788   if (display == (Display *) NULL)
8789     {
8790       ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8791       return(MagickFalse);
8792     }
8793   remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8794   remote_window=(Window) NULL;
8795   root_window=XRootWindow(display,XDefaultScreen(display));
8796   if (window != (char *) NULL)
8797     {
8798       /*
8799         Search window hierarchy and identify any clients by name or ID.
8800       */
8801       if (isdigit((unsigned char) *window) != 0)
8802         remote_window=XWindowByID(display,root_window,(Window)
8803           strtol((char *) window,(char **) NULL,0));
8804       if (remote_window == (Window) NULL)
8805         remote_window=XWindowByName(display,root_window,window);
8806     }
8807   if (remote_window == (Window) NULL)
8808     remote_window=XWindowByProperty(display,root_window,remote_atom);
8809   if (remote_window == (Window) NULL)
8810     {
8811       ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8812         filename);
8813       return(MagickFalse);
8814     }
8815   /*
8816     Send remote command.
8817   */
8818   remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8819   (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8820     PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8821   (void) XSync(display,MagickFalse);
8822   return(MagickTrue);
8823 }
8824 \f
8825 /*
8826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8827 %                                                                             %
8828 %                                                                             %
8829 %                                                                             %
8830 %   X R e t a i n W i n d o w C o l o r s                                     %
8831 %                                                                             %
8832 %                                                                             %
8833 %                                                                             %
8834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8835 %
8836 %  XRetainWindowColors() sets X11 color resources on a window.  This preserves
8837 %  the colors associated with an image displayed on the window.
8838 %
8839 %  The format of the XRetainWindowColors method is:
8840 %
8841 %      void XRetainWindowColors(Display *display,const Window window)
8842 %
8843 %  A description of each parameter follows:
8844 %
8845 %    o display: Specifies a connection to an X server; returned from
8846 %      XOpenDisplay.
8847 %
8848 %    o window: Specifies a pointer to a XWindowInfo structure.
8849 %
8850 */
8851 MagickExport void XRetainWindowColors(Display *display,const Window window)
8852 {
8853   Atom
8854     property;
8855
8856   Pixmap
8857     pixmap;
8858
8859   /*
8860     Put property on the window.
8861   */
8862   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8863   assert(display != (Display *) NULL);
8864   assert(window != (Window) NULL);
8865   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8866   if (property == (Atom) NULL)
8867     {
8868       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8869         "_XSETROOT_ID");
8870       return;
8871     }
8872   pixmap=XCreatePixmap(display,window,1,1,1);
8873   if (pixmap == (Pixmap) NULL)
8874     {
8875       ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8876       return;
8877     }
8878   (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8879     (unsigned char *) &pixmap,1);
8880   (void) XSetCloseDownMode(display,RetainPermanent);
8881 }
8882 \f
8883 /*
8884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8885 %                                                                             %
8886 %                                                                             %
8887 %                                                                             %
8888 %   X S e l e c t W i n d o w                                                 %
8889 %                                                                             %
8890 %                                                                             %
8891 %                                                                             %
8892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8893 %
8894 %  XSelectWindow() allows a user to select a window using the mouse.  If the
8895 %  mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8896 %  is returned in the crop_info structure.
8897 %
8898 %  The format of the XSelectWindow function is:
8899 %
8900 %      target_window=XSelectWindow(display,crop_info)
8901 %
8902 %  A description of each parameter follows:
8903 %
8904 %    o window: XSelectWindow returns the window id.
8905 %
8906 %    o display: Specifies a pointer to the Display structure;  returned from
8907 %      XOpenDisplay.
8908 %
8909 %    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
8910 %      contains the extents of any cropping rectangle.
8911 %
8912 %
8913 */
8914 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8915 {
8916 #define MinimumCropArea  (unsigned int) 9
8917
8918   Cursor
8919     target_cursor;
8920
8921   GC
8922     annotate_context;
8923
8924   int
8925     presses,
8926     x_offset,
8927     y_offset;
8928
8929   Status
8930     status;
8931
8932   Window
8933     root_window,
8934     target_window;
8935
8936   XEvent
8937     event;
8938
8939   XGCValues
8940     context_values;
8941
8942   /*
8943     Initialize graphic context.
8944   */
8945   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8946   assert(display != (Display *) NULL);
8947   assert(crop_info != (RectangleInfo *) NULL);
8948   root_window=XRootWindow(display,XDefaultScreen(display));
8949   context_values.background=XBlackPixel(display,XDefaultScreen(display));
8950   context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
8951   context_values.function=GXinvert;
8952   context_values.plane_mask=
8953     context_values.background ^ context_values.foreground;
8954   context_values.subwindow_mode=IncludeInferiors;
8955   annotate_context=XCreateGC(display,root_window,(unsigned long) (GCBackground |
8956     GCForeground | GCFunction | GCSubwindowMode),&context_values);
8957   if (annotate_context == (GC) NULL)
8958     return(MagickFalse);
8959   /*
8960     Grab the pointer using target cursor.
8961   */
8962   target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
8963     XDefaultScreen(display)),(char * ) "white",(char * ) "black");
8964   status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
8965     (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
8966     GrabModeAsync,root_window,target_cursor,CurrentTime);
8967   if (status != GrabSuccess)
8968     {
8969       ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
8970       return((Window) NULL);
8971     }
8972   /*
8973     Select a window.
8974   */
8975   crop_info->width=0;
8976   crop_info->height=0;
8977   presses=0;
8978   target_window=(Window) NULL;
8979   x_offset=0;
8980   y_offset=0;
8981   do
8982   {
8983     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
8984       (void) XDrawRectangle(display,root_window,annotate_context,
8985         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
8986         (unsigned int) crop_info->height-1);
8987     /*
8988       Allow another event.
8989     */
8990     (void) XAllowEvents(display,SyncPointer,CurrentTime);
8991     (void) XWindowEvent(display,root_window,ButtonPressMask |
8992       ButtonReleaseMask | ButtonMotionMask,&event);
8993     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
8994       (void) XDrawRectangle(display,root_window,annotate_context,
8995         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
8996         (unsigned int) crop_info->height-1);
8997     switch (event.type)
8998     {
8999       case ButtonPress:
9000       {
9001         target_window=XGetSubwindow(display,event.xbutton.subwindow,
9002           event.xbutton.x,event.xbutton.y);
9003         if (target_window == (Window) NULL)
9004           target_window=root_window;
9005         x_offset=event.xbutton.x_root;
9006         y_offset=event.xbutton.y_root;
9007         crop_info->x=x_offset;
9008         crop_info->y=y_offset;
9009         crop_info->width=0;
9010         crop_info->height=0;
9011         presses++;
9012         break;
9013       }
9014       case ButtonRelease:
9015       {
9016         presses--;
9017         break;
9018       }
9019       case MotionNotify:
9020       {
9021         /*
9022           Discard pending button motion events.
9023         */
9024         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
9025         crop_info->x=event.xmotion.x;
9026         crop_info->y=event.xmotion.y;
9027         /*
9028           Check boundary conditions.
9029         */
9030         if ((int) crop_info->x < x_offset)
9031           crop_info->width=(unsigned int) (x_offset-crop_info->x);
9032         else
9033           {
9034             crop_info->width=(unsigned int) (crop_info->x-x_offset);
9035             crop_info->x=x_offset;
9036           }
9037         if ((int) crop_info->y < y_offset)
9038           crop_info->height=(unsigned int) (y_offset-crop_info->y);
9039         else
9040           {
9041             crop_info->height=(unsigned int) (crop_info->y-y_offset);
9042             crop_info->y=y_offset;
9043           }
9044       }
9045       default:
9046         break;
9047     }
9048   } while ((target_window == (Window) NULL) || (presses > 0));
9049   (void) XUngrabPointer(display,CurrentTime);
9050   (void) XFreeCursor(display,target_cursor);
9051   (void) XFreeGC(display,annotate_context);
9052   if ((crop_info->width*crop_info->height) < MinimumCropArea)
9053     {
9054       crop_info->width=0;
9055       crop_info->height=0;
9056     }
9057   if ((crop_info->width != 0) && (crop_info->height != 0))
9058     target_window=root_window;
9059   return(target_window);
9060 }
9061 \f
9062 /*
9063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9064 %                                                                             %
9065 %                                                                             %
9066 %                                                                             %
9067 %   X S e t C u r s o r S t a t e                                             %
9068 %                                                                             %
9069 %                                                                             %
9070 %                                                                             %
9071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9072 %
9073 %  XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9074 %  reset to their default.
9075 %
9076 %  The format of the XXSetCursorState method is:
9077 %
9078 %      XSetCursorState(display,windows,const MagickStatusType state)
9079 %
9080 %  A description of each parameter follows:
9081 %
9082 %    o display: Specifies a connection to an X server;  returned from
9083 %      XOpenDisplay.
9084 %
9085 %    o windows: Specifies a pointer to a XWindows structure.
9086 %
9087 %    o state: An unsigned integer greater than 0 sets the cursor state
9088 %      to busy, otherwise the cursor are reset to their default.
9089 %
9090 */
9091 MagickExport void XSetCursorState(Display *display,XWindows *windows,
9092   const MagickStatusType state)
9093 {
9094   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9095   assert(display != (Display *) NULL);
9096   assert(windows != (XWindows *) NULL);
9097   if (state)
9098     {
9099       (void) XCheckDefineCursor(display,windows->image.id,
9100         windows->image.busy_cursor);
9101       (void) XCheckDefineCursor(display,windows->pan.id,
9102         windows->pan.busy_cursor);
9103       (void) XCheckDefineCursor(display,windows->magnify.id,
9104         windows->magnify.busy_cursor);
9105       (void) XCheckDefineCursor(display,windows->command.id,
9106         windows->command.busy_cursor);
9107     }
9108   else
9109     {
9110       (void) XCheckDefineCursor(display,windows->image.id,
9111         windows->image.cursor);
9112       (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9113       (void) XCheckDefineCursor(display,windows->magnify.id,
9114         windows->magnify.cursor);
9115       (void) XCheckDefineCursor(display,windows->command.id,
9116         windows->command.cursor);
9117       (void) XCheckDefineCursor(display,windows->command.id,
9118         windows->widget.cursor);
9119       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9120     }
9121   windows->info.mapped=MagickFalse;
9122 }
9123 \f
9124 /*
9125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9126 %                                                                             %
9127 %                                                                             %
9128 %                                                                             %
9129 %   X S e t W i n d o w s                                                     %
9130 %                                                                             %
9131 %                                                                             %
9132 %                                                                             %
9133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9134 %
9135 %  XSetWindows() sets the X windows structure if the windows info is specified.
9136 %  Otherwise the current windows structure is returned.
9137 %
9138 %  The format of the XSetWindows method is:
9139 %
9140 %      XWindows *XSetWindows(XWindows *windows_info)
9141 %
9142 %  A description of each parameter follows:
9143 %
9144 %    o windows_info: Initialize the Windows structure with this information.
9145 %
9146 */
9147 MagickExport XWindows *XSetWindows(XWindows *windows_info)
9148 {
9149   static XWindows
9150     *windows = (XWindows *) NULL;
9151
9152   if (windows_info != (XWindows *) ~0)
9153     {
9154       windows=(XWindows *) RelinquishMagickMemory(windows);
9155       windows=windows_info;
9156     }
9157   return(windows);
9158 }
9159 /*
9160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9161 %                                                                             %
9162 %                                                                             %
9163 %                                                                             %
9164 %   X U s e r P r e f e r e n c e s                                           %
9165 %                                                                             %
9166 %                                                                             %
9167 %                                                                             %
9168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9169 %
9170 %  XUserPreferences() saves the preferences in a configuration file in the
9171 %  users' home directory.
9172 %
9173 %  The format of the XUserPreferences method is:
9174 %
9175 %      void XUserPreferences(XResourceInfo *resource_info)
9176 %
9177 %  A description of each parameter follows:
9178 %
9179 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9180 %
9181 */
9182 MagickExport void XUserPreferences(XResourceInfo *resource_info)
9183 {
9184 #if defined(X11_PREFERENCES_PATH)
9185   char
9186     cache[MaxTextExtent],
9187     filename[MaxTextExtent],
9188     specifier[MaxTextExtent];
9189
9190   const char
9191     *value;
9192
9193   XrmDatabase
9194     preferences_database;
9195
9196   /*
9197     Save user preferences to the client configuration file.
9198   */
9199   assert(resource_info != (XResourceInfo *) NULL);
9200   preferences_database=XrmGetStringDatabase("");
9201   (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",
9202     GetClientName());
9203   value=resource_info->backdrop ? "True" : "False";
9204   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9205   (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",
9206     GetClientName());
9207   value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9208   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9209   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
9210     GetClientName());
9211   value=resource_info->confirm_exit ? "True" : "False";
9212   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9213   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
9214     GetClientName());
9215   value=resource_info->confirm_edit ? "True" : "False";
9216   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9217   (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
9218     GetClientName());
9219   value=resource_info->display_warnings ? "True" : "False";
9220   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9221   (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",
9222     GetClientName());
9223   value=resource_info->quantize_info->dither ? "True" : "False";
9224   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9225   (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
9226     GetClientName());
9227   value=resource_info->gamma_correct ? "True" : "False";
9228   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9229   (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",
9230     GetClientName());
9231   (void) FormatMagickString(cache,MaxTextExtent,"%lu",
9232     resource_info->undo_cache);
9233   XrmPutStringResource(&preferences_database,specifier,cache);
9234   (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",
9235     GetClientName());
9236   value=resource_info->use_pixmap ? "True" : "False";
9237   XrmPutStringResource(&preferences_database,specifier,(char *) value);
9238   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
9239     X11_PREFERENCES_PATH,GetClientName());
9240   ExpandFilename(filename);
9241   XrmPutFileDatabase(preferences_database,filename);
9242 #endif
9243 }
9244 \f
9245 /*
9246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9247 %                                                                             %
9248 %                                                                             %
9249 %                                                                             %
9250 %   X V i s u a l C l a s s N a m e                                           %
9251 %                                                                             %
9252 %                                                                             %
9253 %                                                                             %
9254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9255 %
9256 %  XVisualClassName() returns the visual class name as a character string.
9257 %
9258 %  The format of the XVisualClassName method is:
9259 %
9260 %      char *XVisualClassName(const int visual_class)
9261 %
9262 %  A description of each parameter follows:
9263 %
9264 %    o visual_type: XVisualClassName returns the visual class as a character
9265 %      string.
9266 %
9267 %    o class: Specifies the visual class.
9268 %
9269 %
9270 */
9271 static const char *XVisualClassName(const int visual_class)
9272 {
9273   switch (visual_class)
9274   {
9275     case StaticGray: return("StaticGray");
9276     case GrayScale: return("GrayScale");
9277     case StaticColor: return("StaticColor");
9278     case PseudoColor: return("PseudoColor");
9279     case TrueColor: return("TrueColor");
9280     case DirectColor: return("DirectColor");
9281   }
9282   return("unknown visual class");
9283 }
9284 \f
9285 /*
9286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9287 %                                                                             %
9288 %                                                                             %
9289 %                                                                             %
9290 %   X W a r n i n g                                                           %
9291 %                                                                             %
9292 %                                                                             %
9293 %                                                                             %
9294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9295 %
9296 %  XWarning() displays a warning reason in a Notice widget.
9297 %
9298 %  The format of the XWarning method is:
9299 %
9300 %      void XWarning(const unsigned int warning,const char *reason,
9301 %        const char *description)
9302 %
9303 %  A description of each parameter follows:
9304 %
9305 %    o warning: Specifies the numeric warning category.
9306 %
9307 %    o reason: Specifies the reason to display before terminating the
9308 %      program.
9309 %
9310 %    o description: Specifies any description to the reason.
9311 %
9312 */
9313 MagickExport void XWarning(const ExceptionType magick_unused(warning),
9314   const char *reason,const char *description)
9315 {
9316   char
9317     text[MaxTextExtent];
9318
9319   XWindows
9320     *windows;
9321
9322   if (reason == (char *) NULL)
9323     return;
9324   (void) CopyMagickString(text,reason,MaxTextExtent);
9325   (void) ConcatenateMagickString(text,":",MaxTextExtent);
9326   windows=XSetWindows((XWindows *) ~0);
9327   XNoticeWidget(windows->display,windows,text,(char *) description);
9328 }
9329 \f
9330 /*
9331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9332 %                                                                             %
9333 %                                                                             %
9334 %                                                                             %
9335 %   X W i n d o w B y I D                                                     %
9336 %                                                                             %
9337 %                                                                             %
9338 %                                                                             %
9339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9340 %
9341 %  XWindowByID() locates a child window with a given ID.  If not window with
9342 %  the given name is found, 0 is returned.   Only the window specified and its
9343 %  subwindows are searched.
9344 %
9345 %  The format of the XWindowByID function is:
9346 %
9347 %      child=XWindowByID(display,window,id)
9348 %
9349 %  A description of each parameter follows:
9350 %
9351 %    o child: XWindowByID returns the window with the specified
9352 %      id.  If no windows are found, XWindowByID returns 0.
9353 %
9354 %    o display: Specifies a pointer to the Display structure;  returned from
9355 %      XOpenDisplay.
9356 %
9357 %    o id: Specifies the id of the window to locate.
9358 %
9359 */
9360 MagickExport Window XWindowByID(Display *display,const Window root_window,
9361   const unsigned long id)
9362 {
9363   RectangleInfo
9364     rectangle_info;
9365
9366   register int
9367     i;
9368
9369   Status
9370     status;
9371
9372   unsigned int
9373     number_children;
9374
9375   Window
9376     child,
9377     *children,
9378     window;
9379
9380   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9381   assert(display != (Display *) NULL);
9382   assert(root_window != (Window) NULL);
9383   if (id == 0)
9384     return(XSelectWindow(display,&rectangle_info));
9385   if (root_window == id)
9386     return(id);
9387   status=XQueryTree(display,root_window,&child,&child,&children,
9388     &number_children);
9389   if (status == False)
9390     return((Window) NULL);
9391   window=(Window) NULL;
9392   for (i=0; i < (int) number_children; i++)
9393   {
9394     /*
9395       Search each child and their children.
9396     */
9397     window=XWindowByID(display,children[i],id);
9398     if (window != (Window) NULL)
9399       break;
9400   }
9401   if (children != (Window *) NULL)
9402     (void) XFree((void *) children);
9403   return(window);
9404 }
9405 \f
9406 /*
9407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9408 %                                                                             %
9409 %                                                                             %
9410 %                                                                             %
9411 %   X W i n d o w B y N a m e                                                 %
9412 %                                                                             %
9413 %                                                                             %
9414 %                                                                             %
9415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9416 %
9417 %  XWindowByName() locates a window with a given name on a display.  If no
9418 %  window with the given name is found, 0 is returned. If more than one window
9419 %  has the given name, the first one is returned.  Only root and its children
9420 %  are searched.
9421 %
9422 %  The format of the XWindowByName function is:
9423 %
9424 %      window=XWindowByName(display,root_window,name)
9425 %
9426 %  A description of each parameter follows:
9427 %
9428 %    o window: XWindowByName returns the window id.
9429 %
9430 %    o display: Specifies a pointer to the Display structure;  returned from
9431 %      XOpenDisplay.
9432 %
9433 %    o root_window: Specifies the id of the root window.
9434 %
9435 %    o name: Specifies the name of the window to locate.
9436 %
9437 */
9438 MagickExport Window XWindowByName(Display *display,const Window root_window,
9439   const char *name)
9440 {
9441   register int
9442     i;
9443
9444   Status
9445     status;
9446
9447   unsigned int
9448     number_children;
9449
9450   Window
9451     *children,
9452     child,
9453     window;
9454
9455   XTextProperty
9456     window_name;
9457
9458   assert(display != (Display *) NULL);
9459   assert(root_window != (Window) NULL);
9460   assert(name != (char *) NULL);
9461   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9462   if (XGetWMName(display,root_window,&window_name) != 0)
9463     if (LocaleCompare((char *) window_name.value,name) == 0)
9464       return(root_window);
9465   status=XQueryTree(display,root_window,&child,&child,&children,
9466     &number_children);
9467   if (status == False)
9468     return((Window) NULL);
9469   window=(Window) NULL;
9470   for (i=0; i < (int) number_children; i++)
9471   {
9472     /*
9473       Search each child and their children.
9474     */
9475     window=XWindowByName(display,children[i],name);
9476     if (window != (Window) NULL)
9477       break;
9478   }
9479   if (children != (Window *) NULL)
9480     (void) XFree((void *) children);
9481   return(window);
9482 }
9483 \f
9484 /*
9485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9486 %                                                                             %
9487 %                                                                             %
9488 %                                                                             %
9489 %   X W i n d o w B y P r o p e r y                                           %
9490 %                                                                             %
9491 %                                                                             %
9492 %                                                                             %
9493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9494 %
9495 %  XWindowByProperty() locates a child window with a given property. If not
9496 %  window with the given name is found, 0 is returned.  If more than one window
9497 %  has the given property, the first one is returned.  Only the window
9498 %  specified and its subwindows are searched.
9499 %
9500 %  The format of the XWindowByProperty function is:
9501 %
9502 %      child=XWindowByProperty(display,window,property)
9503 %
9504 %  A description of each parameter follows:
9505 %
9506 %    o child: XWindowByProperty returns the window id with the specified
9507 %      property.  If no windows are found, XWindowByProperty returns 0.
9508 %
9509 %    o display: Specifies a pointer to the Display structure;  returned from
9510 %      XOpenDisplay.
9511 %
9512 %    o property: Specifies the property of the window to locate.
9513 %
9514 */
9515 MagickExport Window XWindowByProperty(Display *display,const Window window,
9516   const Atom property)
9517 {
9518   Atom
9519     type;
9520
9521   int
9522     format;
9523
9524   Status
9525     status;
9526
9527   unsigned char
9528     *data;
9529
9530   unsigned int
9531     i,
9532     number_children;
9533
9534   unsigned long
9535     after,
9536     number_items;
9537
9538   Window
9539     child,
9540     *children,
9541     parent,
9542     root;
9543
9544   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9545   assert(display != (Display *) NULL);
9546   assert(window != (Window) NULL);
9547   assert(property != (Atom) NULL);
9548   status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9549   if (status == False)
9550     return((Window) NULL);
9551   type=(Atom) NULL;
9552   child=(Window) NULL;
9553   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9554   {
9555     status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9556       (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9557     if (data != NULL)
9558       (void) XFree((void *) data);
9559     if ((status == Success) && (type != (Atom) NULL))
9560       child=children[i];
9561   }
9562   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9563     child=XWindowByProperty(display,children[i],property);
9564   if (children != (Window *) NULL)
9565     (void) XFree((void *) children);
9566   return(child);
9567 }
9568 #else
9569 \f
9570 /*
9571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9572 %                                                                             %
9573 %                                                                             %
9574 %                                                                             %
9575 %   X I m p o r t I m a g e                                                   %
9576 %                                                                             %
9577 %                                                                             %
9578 %                                                                             %
9579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9580 %
9581 %  XImportImage() reads an image from an X window.
9582 %
9583 %  The format of the XImportImage method is:
9584 %
9585 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9586 %
9587 %  A description of each parameter follows:
9588 %
9589 %    o image_info: the image info..
9590 %
9591 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
9592 %
9593 */
9594 MagickExport Image *XImportImage(const ImageInfo *image_info,
9595   XImportInfo *ximage_info)
9596 {
9597   assert(image_info != (const ImageInfo *) NULL);
9598   assert(image_info->signature == MagickSignature);
9599   if (image_info->debug != MagickFalse)
9600     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9601       image_info->filename);
9602   assert(ximage_info != (XImportInfo *) NULL);
9603   return((Image *) NULL);
9604 }
9605 #endif
9606 \f
9607 /*
9608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9609 %                                                                             %
9610 %                                                                             %
9611 %                                                                             %
9612 %   X G e t I m p o r t I n f o                                               %
9613 %                                                                             %
9614 %                                                                             %
9615 %                                                                             %
9616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9617 %
9618 %  XGetImportInfo() initializes the XImportInfo structure.
9619 %
9620 %  The format of the XGetImportInfo method is:
9621 %
9622 %      void XGetImportInfo(XImportInfo *ximage_info)
9623 %
9624 %  A description of each parameter follows:
9625 %
9626 %    o ximage_info: Specifies a pointer to an ImageInfo structure.
9627 %
9628 */
9629 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9630 {
9631   assert(ximage_info != (XImportInfo *) NULL);
9632   ximage_info->frame=MagickFalse;
9633   ximage_info->borders=MagickFalse;
9634   ximage_info->screen=MagickFalse;
9635   ximage_info->descend=MagickTrue;
9636   ximage_info->silent=MagickFalse;
9637 }