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