/*
% Copyright (C) 2003 - 2022 GraphicsMagick Group
% Copyright (C) 2002 ImageMagick Studio
%
% This program is covered by multiple licenses, which are described in
% Copyright.txt. You should have received a copy of Copyright.txt with this
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%              X   X  W   W  IIIII  N   N  DDDD    OOO   W   W                %
%               X X   W   W    I    NN  N  D   D  O   O  W   W                %
%                X    W   W    I    N N N  D   D  O   O  W   W                %
%               X X   W W W    I    N  NN  D   D  O   O  W W W                %
%              X   X   W W   IIIII  N   N  DDDD    OOO    W W                 %
%                                                                             %
%                                                                             %
%                  X11 Utility Methods for GraphicsMagick                     %
%                                                                             %
%                                                                             %
%                               Software Design                               %
%                                 John Cristy                                 %
%                                  July 1992                                  %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/

/*
  Include declarations.
*/
#include "magick/studio.h"
#include "magick/analyze.h"
#include "magick/blob.h"
#include "magick/color.h"
#include "magick/color_lookup.h"
#include "magick/colormap.h"
#include "magick/composite.h"
#include "magick/constitute.h"
#include "magick/describe.h"
#include "magick/log.h"
#include "magick/magick.h"
#include "magick/monitor.h"
#include "magick/pixel_cache.h"
#include "magick/resize.h"
#include "magick/shear.h"
#include "magick/tempfile.h"
#include "magick/texture.h"
#include "magick/transform.h"
#include "magick/utility.h"
#include "magick/version.h"
#if defined(HasSharedMemory)
# if defined(HAVE_MACHINE_PARAM_H)
   /* Need by some *BSD systems in order to use shmget */
#  include <machine/param.h>
# endif /* defined(HAVE_MACHINE_PARAM_H */
# if defined(__FreeBSD__)
#  if __FreeBSD__ >= 5 && defined(_POSIX_C_SOURCE)
   typedef unsigned short ushort; /* needed for sys/ipc.h at the moment */
#  endif
# endif
# include <sys/ipc.h>
# include <sys/shm.h>
#endif
#include "magick/xwindow.h"
#if defined(HasX11)
# if defined(HasShape)
#  include <X11/extensions/shape.h>
# endif
#if defined(HasSharedMemory)
# include <X11/extensions/XShm.h>
#endif

/*
  X defines.
*/
#define MagickXBlueGamma(color) ((Quantum) (blue_gamma == 1.0 ? (color) : \
  ((pow((double) (color)/MaxRGB,1.0/blue_gamma)*MaxRGB)+0.5)))
#define MagickXGammaPixel(map,color)  (unsigned long) (map->base_pixel+ \
  ((ScaleQuantumToShort(MagickXRedGamma((color)->red))*map->red_max/65535L)* \
    map->red_mult)+ \
  ((ScaleQuantumToShort(MagickXGreenGamma((color)->green))*map->green_max/65535L)* \
    map->green_mult)+ \
  ((ScaleQuantumToShort(MagickXBlueGamma((color)->blue))*map->blue_max/65535L)* \
    map->blue_mult))
#define MagickXGreenGamma(color) ((Quantum) (green_gamma == 1.0 ? (color) : \
  ((pow((double) (color)/MaxRGB,1.0/green_gamma)*MaxRGB)+0.5)))
#define MagickXRedGamma(color) ((Quantum) (red_gamma == 1.0 ? (color) : \
  ((pow((double) (color)/MaxRGB,1.0/red_gamma)*MaxRGB)+0.5)))
#define MagickXStandardPixel(map,color)  (unsigned long) (map->base_pixel+ \
  (((color)->red*map->red_max/65535L)*map->red_mult)+ \
  (((color)->green*map->green_max/65535L)*map->green_mult)+ \
  (((color)->blue*map->blue_max/65535L)*map->blue_mult))

/*
  Constant declaractions.
*/
static unsigned int
  xerror_alert = False;

/*
  Method prototypes.
*/
static char
  *MagickXVisualClassName(const int);

static double
  blue_gamma = 1.0,
  green_gamma = 1.0,
  red_gamma = 1.0;

static unsigned int
  MagickXMakePixmap(Display *,const MagickXResourceInfo *,MagickXWindowInfo *);

static void
  MagickXMakeImageLSBFirst(const MagickXResourceInfo *,const MagickXWindowInfo *,Image *,
    XImage *,XImage *),
  MagickXMakeImageMSBFirst(const MagickXResourceInfo *,const MagickXWindowInfo *,Image *,
    XImage *,XImage *);

static Window
  MagickXSelectWindow(Display *,RectangleInfo *);

#if defined(HasSharedMemory)
/*
  Attach to shared memory.
*/
static void *
MagickShmAt(int shmid, void *shmaddr, int shmflg)
{
  void *
    address;

  if ((address=shmat(shmid,shmaddr,shmflg)) == (void *) -1)
    {
      if (shmaddr)
        (void) LogMagickEvent(X11Event,GetMagickModule(),
           "shm attach to id %d failed (%s)", shmid, strerror(errno));
      else
        (void) LogMagickEvent(X11Event,GetMagickModule(),
           "shm attach to id %d at address 0x%p failed (%s)", shmid, shmaddr,
             strerror(errno));
    }
  else
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),
         "shm attach to id %d at address 0x%p", shmid, address);
    }


  (void) LogMagickEvent(X11Event,GetMagickModule(),
    "shm attach to id %d at address 0x%p, errno=%d", shmid, address, errno);
  return (address);
}
/*
  Shared memory control operations.
*/
static int
MagickShmCtl(int shmid, int cmd, struct shmid_ds *buf)
{
  int status;
  if ((status=shmctl(shmid, cmd, buf)) == -1)
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"shm control id=%d cmd=%s failed (%s)",
                            shmid, ((cmd == IPC_STAT) ? "IPC_STAT" :
                                    (cmd == IPC_SET) ? "IPC_SET" :
                                    (cmd == IPC_RMID) ? "IPC_RMID" : "Unknown"),
                            strerror(errno));
    }
  else
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"shm control id=%d cmd=%s",
                            shmid, ((cmd == IPC_STAT) ? "IPC_STAT" :
                                    (cmd == IPC_SET) ? "IPC_SET" :
                                    (cmd == IPC_RMID) ? "IPC_RMID" : "Unknown"));
    }
  return status;
}
/*
  Detatch from shared memory.
*/
static int
MagickShmDt(void *shmaddr)
{
  int result;
  if ((result=shmdt(shmaddr)) == -1)
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),
                            "shm detatch at address 0x%p failed (%s)",
                            shmaddr,
                            strerror(errno));
    }
  else
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),
                            "shm detatch at address 0x%p",
                            shmaddr);
    }
  return (result);
}
#endif

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y X 1 1 R e s o u r c e s                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyX11Resources() destroys all remaining allocations related
%  to X11, and closes the X11 display. It is intended to be invoked by
%  DestroyMagick().
%
%  The format of the MagickXDestroyX11Resources method is:
%
%      void MagickXDestroyX11Resources(void)
%
%  A description of each parameter follows:
%
%
*/
MagickExport void
MagickXDestroyX11Resources(void)
{
  MagickXWindows *windows = MagickXSetWindows((MagickXWindows *) ~0);
  if (windows != (MagickXWindows *) NULL)
    {
      MagickXDestroyXWindows(windows);
      (void) MagickXSetWindows((MagickXWindows *) NULL);
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y X W i n d o w s                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyXWindows() destroys existing allocations in an MagickXWindows
%  structure.
%
%  The format of the MagickXDestroyXWindows method is:
%
%      void MagickXDestroyXWindows(MagickXWindows *windows)
%
%  A description of each parameter follows:
%
%
*/
MagickExport void
MagickXDestroyXWindows(MagickXWindows *windows)
{
  if (windows == (MagickXWindows *) NULL ||
      (windows->display == (Display *) NULL))
    return;
  MagickFreeMemory(windows->icon_resources);

  if (windows->icon_pixel)
    {
      MagickFreeMemory(windows->icon_pixel->pixels);
      if (windows->icon_pixel->annotate_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->icon_pixel->annotate_context); /* Allocated by XCreateGC */
      if (windows->icon_pixel->widget_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->icon_pixel->widget_context); /* Allocated by XCreateGC */
      if (windows->icon_pixel->highlight_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->icon_pixel->highlight_context); /* Allocated by XCreateGC */
      MagickFreeMemory(windows->icon_pixel);
    }

  if (windows->pixel_info)
    {
      MagickFreeMemory(windows->pixel_info->pixels);
      if (windows->pixel_info->annotate_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->pixel_info->annotate_context); /* Allocated by XCreateGC */
      if (windows->pixel_info->widget_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->pixel_info->widget_context); /* Allocated by XCreateGC */
      if (windows->pixel_info->highlight_context != (GC) NULL)
        (void) XFreeGC(windows->display,windows->pixel_info->highlight_context); /* Allocated by XCreateGC */
      MagickFreeMemory(windows->pixel_info);
    }

  if (windows->font_info != (XFontStruct *) NULL)
    {
      (void) XFreeFont(windows->display,windows->font_info); /* Allocated by XLoadQueryFont */
      windows->font_info=(XFontStruct *) NULL;
    }

  if (windows->class_hints != (XClassHint *) NULL)
    {
      (void) XFree(windows->class_hints); /* Allocated by XAllocClassHint */
      windows->class_hints=(XClassHint *) NULL;
    }

  if (windows->manager_hints != (XWMHints *) NULL)
    {
      (void) XFree(windows->manager_hints); /* Allocated by XAllocWMHints */
      windows->manager_hints=(XWMHints *) NULL;
    }

  if (windows->map_info != (XStandardColormap *) NULL)
    {
      (void) XFree(windows->map_info); /* Allocated by XAllocStandardColormap */
      windows->map_info=(XStandardColormap *) NULL;
    }

  if(windows->icon_map != (XStandardColormap *) NULL)
    {
      (void) XFree(windows->icon_map); /* Allocated by XAllocStandardColormap */
      windows->icon_map=(XStandardColormap *) NULL;
    }

  if (windows->visual_info != (XVisualInfo *) NULL)
    {
      (void) XFree(windows->visual_info); /* Allocated by XGetVisualInfo */
      windows->visual_info=(XVisualInfo *) NULL;
    }

  if (windows->icon_visual != (XVisualInfo *) NULL)
    {
      (void) XFree(windows->icon_visual); /* Allocated by XGetVisualInfo */
      windows->icon_visual=(XVisualInfo *) NULL;
    }

  MagickXDestroyXWindowInfo(windows->display,&windows->context);
  MagickXDestroyXWindowInfo(windows->display,&windows->backdrop);
  MagickXDestroyXWindowInfo(windows->display,&windows->icon);
  MagickXDestroyXWindowInfo(windows->display,&windows->image);
  MagickXDestroyXWindowInfo(windows->display,&windows->info);
  MagickXDestroyXWindowInfo(windows->display,&windows->magnify);
  MagickXDestroyXWindowInfo(windows->display,&windows->pan);
  MagickXDestroyXWindowInfo(windows->display,&windows->command);
  MagickXDestroyXWindowInfo(windows->display,&windows->widget);
  MagickXDestroyXWindowInfo(windows->display,&windows->popup);
  MagickXDestroyXWindowInfo(windows->display,&windows->group_leader);
  windows->display=(Display *) NULL;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y X W i n d o w I n f o                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyXWindowInfo() destroys existing allocations in an
%  MagickXWindowInfo structure. The MagickXWindowInfo structure itself is
%  not freed.
%
%  The format of the MagickXDestroyXWindowInfo method is:
%
%      void MagickXDestroyXWindowInfo(Display *display,
%                                     MagickXWindowInfo *window)
%
%  A description of each parameter follows:
%
%    o display: Pointer to an X11 Display structure
%
%    o window: Pointer to MagickXWindowInfo structure to destroy.
*/
MagickExport void
MagickXDestroyXWindowInfo(Display *display,MagickXWindowInfo *window)
{
  if (window->mapped != False)
    {
      (void) XWithdrawWindow(display,window->id,
                             window->screen);
      (void) XSync(display,False);
      window->mapped=False;
    }

  MagickFreeMemory(window->name);

  MagickFreeMemory(window->icon_name);

  if (window->cursor != (Cursor) NULL)
    {
      (void) XFreeCursor(display,window->cursor);
      window->cursor=(Cursor) NULL;
    }

  if (window->highlight_stipple != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->highlight_stipple);
      window->highlight_stipple=(Pixmap) NULL;
    }

  if (window->shadow_stipple != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->shadow_stipple);
      window->shadow_stipple=(Pixmap) NULL;
   }

  if (window->ximage != (XImage *) NULL)
    {
      XDestroyImage(window->ximage);
      window->ximage=(XImage *) NULL;
    }

  if (window->matte_image != (XImage *) NULL)
    {
      /* MagickFreeMemory(window->matte_image->data); ???? */
      XDestroyImage(window->matte_image);
      window->matte_image=(XImage *) NULL;
    }

  if (window->pixmap != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->pixmap);
      window->pixmap=(Pixmap) NULL;
    }

  if (window->id != (Window) NULL)
    {
      (void) XDestroyWindow(display,window->id);
      window->id=(Window) NULL;
    }

  if (window->destroy)
    {
      if (window->image != (Image *) NULL)
        {
          DestroyImage(window->image);
          window->image=(Image *) NULL;
        }
    }

  if (window->segment_info != (void *) NULL)
    {
#if defined(HasSharedMemory)
      XShmSegmentInfo
        *segment_info;

      segment_info=(XShmSegmentInfo *) window->segment_info;
      if (segment_info != (XShmSegmentInfo *) NULL)
        {
          if (segment_info[0].shmid >= 0)
            {
              if (segment_info[0].shmaddr != NULL)
                (void) MagickShmDt(segment_info[0].shmaddr);
              (void) MagickShmCtl(segment_info[0].shmid,IPC_RMID,0);
              segment_info[0].shmaddr=NULL;
              segment_info[0].shmid=(-1);
            }
        }
#endif

      MagickFreeMemory(window->segment_info);
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k I s T r u e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickIsTrue returns True if the reason is "true", "on", "yes"
%  or "1".
%
%  The format of the MagickIsTrue method is:
%
%      unsigned int MagickIsTrue(const char *reason)
%
%  A description of each parameter follows:
%
%    o option: either True or False depending on the reason parameter.
%
%    o reason: Specifies a pointer to a character array.
%
%
*/
MagickExport unsigned int
MagickIsTrue(const char *reason)
{
  if (reason == (char *) NULL)
    return(False);
  if (LocaleCompare(reason,"true") == 0)
    return(True);
  if (LocaleCompare(reason,"on") == 0)
    return(True);
  if (LocaleCompare(reason,"yes") == 0)
    return(True);
  if (LocaleCompare(reason,"1") == 0)
    return(True);
  return(False);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X A n n o t a t e I m a g e                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXAnnotateImage annotates the image with text.
%
%  The format of the MagickXAnnotateImage method is:
%
%      unsigned int MagickXAnnotateImage(Display *display,
%        const MagickXPixelInfo *pixel,MagickXAnnotateInfo *annotate_info,
%        Image *image)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXAnnotateImage returns True if the image is
%      successfully annotated with text.  False is returned is there is a
%      memory shortage.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o annotate_info: Specifies a pointer to a MagickXAnnotateInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport unsigned int
MagickXAnnotateImage(Display *display,
                     const MagickXPixelInfo *pixel,
                     MagickXAnnotateInfo *annotate_info,
                     Image *image)
{
  GC
    annotate_context;

  Image
    *annotate_image;

  int
    x,
    y;

  Pixmap
    annotate_pixmap;

  register PixelPacket
    *q;

  unsigned int
    depth,
    height,
    matte,
    width;

  Window
    root_window;

  XGCValues
    context_values;

  XImage
    *annotate_ximage;

  /*
    Initialize annotated image.
  */
  assert(display != (Display *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  assert(annotate_info != (MagickXAnnotateInfo *) NULL);
  assert(image != (Image *) NULL);
  /*
    Initialize annotated pixmap.
  */
  root_window=XRootWindow(display,XDefaultScreen(display));
  depth=XDefaultDepth(display,XDefaultScreen(display));
  annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
    annotate_info->height,(int) depth);
  if (annotate_pixmap == (Pixmap) NULL)
    return(False);
  /*
    Initialize graphics info.
  */
  context_values.background=0;
  context_values.foreground=(unsigned long) (~0);
  context_values.font=annotate_info->font_info->fid;
  annotate_context=XCreateGC(display,root_window,GCBackground | GCFont |
    GCForeground,&context_values);
  if (annotate_context == (GC) NULL)
    return(False);
  /*
    Draw text to pixmap.
  */
  (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
    (int) annotate_info->font_info->ascent,annotate_info->text,
    (int) strlen(annotate_info->text));
  (void) XFreeGC(display,annotate_context);
  /*
    Initialize annotated X image.
  */
  annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
    annotate_info->height,AllPlanes,ZPixmap);
  if (annotate_ximage == (XImage *) NULL)
    return(False);
  (void) XFreePixmap(display,annotate_pixmap);
  /*
    Initialize annotated image.
  */
  annotate_image=AllocateImage((ImageInfo *) NULL);
  if (annotate_image == (Image *) NULL)
    return(False);
  annotate_image->columns=annotate_info->width;
  annotate_image->rows=annotate_info->height;
  /*
    Transfer annotated X image to image.
  */
  width=(unsigned int) image->columns;
  height=(unsigned int) image->rows;
  x=0;
  y=0;
  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
  (void) AcquireOnePixelByReference(image,&annotate_image->background_color,
                                    x,y,&image->exception);
  annotate_image->matte=annotate_info->stencil == ForegroundStencil;
  for (y=0; y < (long) annotate_image->rows; y++)
  {
    q=GetImagePixels(annotate_image,0,y,annotate_image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (long) annotate_image->columns; x++)
    {
      q->opacity=OpaqueOpacity;
      if (XGetPixel(annotate_ximage,x,y) == 0)
        {
          /*
            Set this pixel to the background color.
          */
          q->red=ScaleShortToQuantum(pixel->box_color.red);
          q->green=ScaleShortToQuantum(pixel->box_color.green);
          q->blue=ScaleShortToQuantum(pixel->box_color.blue);
          if ((annotate_info->stencil == ForegroundStencil) ||
              (annotate_info->stencil == OpaqueStencil))
            q->opacity=TransparentOpacity;
        }
      else
        {
          /*
            Set this pixel to the pen color.
          */
          q->red=ScaleShortToQuantum(pixel->pen_color.red);
          q->green=ScaleShortToQuantum(pixel->pen_color.green);
          q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
          if (annotate_info->stencil == BackgroundStencil)
            q->opacity=TransparentOpacity;
        }
      q++;
    }
    if (!SyncImagePixels(annotate_image))
      break;
  }
  XDestroyImage(annotate_ximage);
  annotate_ximage=(XImage *) NULL;
  /*
    Determine annotate geometry.
  */
  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
  if ((width != (unsigned int) annotate_image->columns) ||
      (height != (unsigned int) annotate_image->rows))
    {
      char
        image_geometry[MaxTextExtent];

      /*
        Scale image.
      */
      FormatString(image_geometry,"%ux%u",width,height);
      TransformImage(&annotate_image,(char *) NULL,image_geometry);
    }
  if (annotate_info->degrees != 0.0)
    {
      double
        normalized_degrees;

      Image
        *rotate_image;

      int
        rotations;

      /*
        Rotate image.
      */
      rotate_image=
        RotateImage(annotate_image,annotate_info->degrees,&image->exception);
      if (rotate_image == (Image *) NULL)
        return(False);
      DestroyImage(annotate_image);
      annotate_image=rotate_image;
      /*
        Annotation is relative to the degree of rotation.
      */
      normalized_degrees=annotate_info->degrees;
      while (normalized_degrees < -45.0)
        normalized_degrees+=360.0;
      for (rotations=0; normalized_degrees > 45.0; rotations++)
        normalized_degrees-=90.0;
      switch (rotations % 4)
      {
        default:
        case 0:
          break;
        case 1:
        {
          /*
            Rotate 90 degrees.
          */
          x-=(int) annotate_image->columns/2;
          y+=(int) annotate_image->columns/2;
          break;
        }
        case 2:
        {
          /*
            Rotate 180 degrees.
          */
          x=x-(int) annotate_image->columns;
          break;
        }
        case 3:
        {
          /*
            Rotate 270 degrees.
          */
          x=x-(int) annotate_image->columns/2;
          y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
          break;
        }
      }
    }
  /*
    Composite text onto the image.
  */
  (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
  matte=image->matte;
  (void) CompositeImage(image,annotate_image->matte ? OverCompositeOp :
    CopyCompositeOp,annotate_image,x,y);
  image->matte=matte;
  DestroyImage(annotate_image);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t F o n t                                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestFont returns the "best" font.  "Best" is defined as a font
%  specified in the X resource database or a font such that the text width
%  displayed with the font does not exceed the specified maximum width.
%
%  The format of the MagickXBestFont method is:
%
%      XFontStruct *MagickXBestFont(Display *display,
%        const MagickXResourceInfo *resource_info,const unsigned int text_font)
%
%  A description of each parameter follows:
%
%    o font: MagickXBestFont returns a pointer to a XFontStruct structure.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o text_font:  True is font should be mono-spaced (typewriter style).
%
%
*/
static char **
MagickFontToList(char *font)
{
  char
    **fontlist;

  register char
    *p,
    *q;

  register int
    i;

  unsigned int
    fonts;

  if (font == (char *) NULL)
    return((char **) NULL);
  /*
    Convert string to an ASCII list.
  */
  fonts=1;
  for (p=font; *p != '\0'; p++)
    if ((*p == ':') || (*p == ';') || (*p == ','))
      fonts++;
  fontlist=MagickAllocateArray(char **,(fonts+1),sizeof(char *));
  if (fontlist == (char **) NULL)
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToConvertFont);
      return((char **) NULL);
    }
  p=font;
  for (i=0; i < (int) fonts; i++)
  {
    for (q=p; *q != '\0'; q++)
      if ((*q == ':') || (*q == ';') || (*q == ','))
        break;
    fontlist[i]=MagickAllocateMemory(char *,(size_t) (q-p+1));
    if (fontlist[i] == (char *) NULL)
      {
        MagickError3(ResourceLimitError,MemoryAllocationFailed,
          UnableToConvertFont);
        return((char **) NULL);
      }
    (void) strlcpy(fontlist[i],p,q-p+1);
    p=q+1;
  }
  fontlist[i]=(char *) NULL;
  return(fontlist);
}

MagickExport XFontStruct *
MagickXBestFont(Display *display,
                const MagickXResourceInfo *resource_info,
                const unsigned int text_font)
{
  static const char
    *Fonts[]=
    {
      "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
      "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
      "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
      "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
      "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
      "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
      "variable",
      "fixed",
      (char *) NULL
    },
    *TextFonts[]=
    {
      "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
      "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
      "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
      "fixed",
      (char *) NULL
    };

  char
    *font_name;

  register const char
    **p;

  XFontStruct
    *font_info;

  font_info=(XFontStruct *) NULL;
  font_name=resource_info->font;
  if (text_font)
    font_name=resource_info->text_font;
  if (font_name != (char *) NULL)
    {
      char
        **fontlist;

      register int
        i;

      /*
        Load preferred font specified in the X resource database.
      */
      fontlist=MagickFontToList(font_name);
      if (fontlist != (char **) NULL)
        {
          for (i=0; fontlist[i] != (char *) NULL; i++)
          {
            if (font_info == (XFontStruct *) NULL)
              font_info=XLoadQueryFont(display,fontlist[i]);
            MagickFreeMemory(fontlist[i]);
          }
          MagickFreeMemory(fontlist);
        }
      if (font_info == (XFontStruct *) NULL)
        MagickError(XServerError,UnableToLoadFont,font_name);
    }
  /*
    Load fonts from list of fonts until one is found.
  */
  p=Fonts;
  if (text_font)
    p=TextFonts;
  if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
    p++;
  while (*p != (char *) NULL)
  {
    if (font_info != (XFontStruct *) NULL)
      break;
    font_info=XLoadQueryFont(display,(char *) *p);
    p++;
  }
  return(font_info);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t I c o n S i z e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestIconSize returns the "best" icon size.  "Best" is
%  defined as an icon size that maintains the aspect ratio of the image.
%  If the window manager has preferred icon sizes, one of the preferred
%  sizes is used.
%
%  The format of the MagickXBestIconSize method is:
%
%      void MagickXBestIconSize(Display *display,MagickXWindowInfo *window,
%                               Image *image)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport void
MagickXBestIconSize(Display *display,MagickXWindowInfo *window,
  Image *image)
{
  double
    scale_factor;

  int
    i,
    number_sizes;

  unsigned int
    height,
    icon_height,
    icon_width,
    width;

  Window
    root_window;

  XIconSize
    *icon_size,
    *size_list;

  /*
    Determine if the window manager has specified preferred icon sizes.
  */
  assert(display != (Display *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(image != (Image *) NULL);
  window->width=MaxIconSize;
  window->height=MaxIconSize;
  icon_size=(XIconSize *) NULL;
  number_sizes=0;
  root_window=XRootWindow(display,window->screen);
  if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
    if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
      icon_size=size_list;
  if (icon_size == (XIconSize *) NULL)
    {
      /*
        Window manager does not restrict icon size.
      */
      icon_size=XAllocIconSize();
      if (icon_size == (XIconSize *) NULL)
        {
          MagickError3(ResourceLimitError,MemoryAllocationFailed,
            UnableToGetBestIconSize);
          return;
        }
      icon_size->min_width=1;
      icon_size->max_width=MaxIconSize;
      icon_size->min_height=1;
      icon_size->max_height=MaxIconSize;
      icon_size->width_inc=1;
      icon_size->height_inc=1;
    }
  /*
    Determine aspect ratio of image.
  */
  width=(unsigned int) image->columns;
  height=(unsigned int) image->rows;
  i=0;
  if (window->crop_geometry)
    (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
  /*
    Look for an icon size that maintains the aspect ratio of image.
  */
  scale_factor=(double) icon_size->max_width/width;
  if (scale_factor > ((double) icon_size->max_height/height))
    scale_factor=(double) icon_size->max_height/height;
  icon_width=icon_size->min_width;
  while ((int) icon_width < icon_size->max_width)
  {
    if (icon_width >= (scale_factor*width))
      break;
    icon_width+=icon_size->width_inc;
  }
  icon_height=icon_size->min_height;
  while ((int) icon_height < icon_size->max_height)
  {
    if (icon_height >= (scale_factor*height))
      break;
    icon_height+=icon_size->height_inc;
  }
  (void) XFree((void *) icon_size);
  window->width=icon_width;
  window->height=icon_height;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t P i x e l                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestPixel returns a pixel from an array of pixels that is
%  closest to the requested color.  If the color array is NULL, the colors
%  are obtained from the X server.
%
%  The format of the MagickXBestPixel method is:
%
%      void MagickXBestPixel(Display *display,const Colormap colormap,
%        XColor *colors,unsigned int number_colors,XColor *color)
%
%  A description of each parameter follows:
%
%    o pixel: MagickXBestPixel returns the pixel value closest to the requested
%      color.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o colormap: Specifies the ID of the X server colormap.
%
%    o colors: Specifies an array of XColor structures.
%
%    o number_colors: Specifies the number of XColor structures in the
%      color definition array.
%
%    o color: Specifies the desired RGB value to find in the colors array.
%
%
*/
MagickExport void
MagickXBestPixel(Display *display,const Colormap colormap,
                 XColor *colors,unsigned int number_colors,XColor *color)
{
  double
    min_distance;

  DoublePixelPacket
    pixel;

  int
    query_server,
    status;

  register double
    distance;

  register int
    i,
    j;

  /*
    Find closest representation for the requested RGB color.
  */
  assert(display != (Display *) NULL);
  assert(color != (XColor *) NULL);
  status=XAllocColor(display,colormap,color);
  if (status != 0)
    return;
  query_server=colors == (XColor *) NULL;
  if (query_server)
    {
      /*
        Read X server colormap.
      */
      colors=MagickAllocateArray(XColor *,number_colors,sizeof(XColor));
      if (colors == (XColor *) NULL)
        {
          MagickError3(ResourceLimitError,MemoryAllocationFailed,
            UnableToReadXServerColormap);
          return;
        }
      for (i=0; i < (int) number_colors; i++)
        colors[i].pixel=(unsigned long) i;
      if (number_colors > 256)
        number_colors=256;
      (void) XQueryColors(display,colormap,colors,number_colors);
    }
  min_distance=3.0*((double) MaxRGB+1.0)*((double) MaxRGB+1.0);
  j=0;
  for (i=0; i < (int) number_colors; i++)
  {
    pixel.red=colors[i].red-(double) color->red;
    distance=pixel.red*pixel.red;
    if (distance > min_distance)
      continue;
    pixel.green=colors[i].green-(double) color->green;
    distance+=pixel.green*pixel.green;
    if (distance > min_distance)
      continue;
    pixel.blue=colors[i].blue-(double) color->blue;
    distance+=pixel.blue*pixel.blue;
    if (distance > min_distance)
      continue;
    min_distance=distance;
    color->pixel=colors[i].pixel;
    j=i;
  }
  (void) XAllocColor(display,colormap,&colors[j]);
  if (query_server)
    MagickFreeMemory(colors);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X B e s t V i s u a l I n f o                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXBestVisualInfo returns visual information for a visual that is
%  the "best" the server supports.  "Best" is defined as:
%
%    1. Restrict the visual list to those supported by the default screen.
%
%    2. If a visual type is specified, restrict the visual list to those of
%       that type.
%
%    3. If a map type is specified, choose the visual that matches the id
%       specified by the Standard Colormap.
%
%    4  From the list of visuals, choose one that can display the most
%       simultaneous colors.  If more than one visual can display the same
%       number of simultaneous colors, one is chosen based on a rank.
%
%  The format of the MagickXBestVisualInfo method is:
%
%      XVisualInfo *MagickXBestVisualInfo(Display *display,
%        XStandardColormap *map_info,MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o visual_info: MagickXBestVisualInfo returns a pointer to a X11
%      XVisualInfo structure.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
#define MaxStandardColormaps  7
#define MagickXVisualColormapSize(visual_info) Min( (int) (\
  ((visual_info->class == TrueColor) || (visual_info->class == DirectColor)) ? \
    (int) (visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask) : \
    visual_info->colormap_size),(1L << visual_info->depth))

MagickExport XVisualInfo *
MagickXBestVisualInfo(Display *display,
                      XStandardColormap *map_info,
                      MagickXResourceInfo *resource_info)
{
  char
    *map_type,
    *visual_type;

  long
    visual_mask;

  register int
    i;

  static int
    number_visuals;

  static XVisualInfo
    visual_template;

  XVisualInfo
    *visual_info,
    *visual_list;

  /*
    Restrict visual search by screen number.
  */
  assert(display != (Display *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  map_type=resource_info->map_type;
  visual_type=resource_info->visual_type;
  visual_mask=VisualScreenMask;
  visual_template.screen=XDefaultScreen(display);
  visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
  if (resource_info->immutable && (resource_info->colors != 0))
    if (resource_info->colors <= (1UL << visual_template.depth))
      visual_mask|=VisualDepthMask;
  if (visual_type != (char *) NULL)
    {
      /*
        Restrict visual search by class or visual id.
      */
      if (LocaleCompare("staticgray",visual_type) == 0)
        {
          visual_mask|=VisualClassMask;
          visual_template.class=StaticGray;
        }
      else
        if (LocaleCompare("grayscale",visual_type) == 0)
          {
            visual_mask|=VisualClassMask;
            visual_template.class=GrayScale;
          }
        else
          if (LocaleCompare("staticcolor",visual_type) == 0)
            {
              visual_mask|=VisualClassMask;
              visual_template.class=StaticColor;
            }
          else
            if (LocaleCompare("pseudocolor",visual_type) == 0)
              {
                visual_mask|=VisualClassMask;
                visual_template.class=PseudoColor;
              }
            else
              if (LocaleCompare("truecolor",visual_type) == 0)
                {
                  visual_mask|=VisualClassMask;
                  visual_template.class=TrueColor;
                }
              else
                if (LocaleCompare("directcolor",visual_type) == 0)
                  {
                    visual_mask|=VisualClassMask;
                    visual_template.class=DirectColor;
                  }
                else
                  if (LocaleCompare("default",visual_type) == 0)
                    {
                      visual_mask|=VisualIDMask;
                      visual_template.visualid=XVisualIDFromVisual(
                        XDefaultVisual(display,XDefaultScreen(display)));
                    }
                  else
                    if (isdigit((int) (*visual_type)))
                      {
                        visual_mask|=VisualIDMask;
                        visual_template.visualid=
                          strtol(visual_type,(char **) NULL,0);
                      }
                    else
                      MagickError(XServerError,UnrecognizedVisualSpecifier,
                        visual_type);
    }
  /*
    Get all visuals that meet our criteria so far.
  */
  number_visuals=0;
  visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
    &number_visuals);
  visual_mask=VisualScreenMask | VisualIDMask;
  if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
    {
      /*
        Failed to get visual;  try using the default visual.
      */
      MagickWarning(XServerWarning,UnableToGetVisual,visual_type);
      visual_template.visualid=
        XVisualIDFromVisual(XDefaultVisual(display,XDefaultScreen(display)));
      visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
        &number_visuals);
      if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
        return((XVisualInfo *) NULL);
      MagickWarning(XServerWarning,UsingDefaultVisual,
        MagickXVisualClassName(visual_list->class));
    }
  resource_info->color_recovery=False;
  if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
    {
      Atom
        map_property;

      char
        map_name[MaxTextExtent];

      int
        j,
        number_maps,
        status;

      Window
        root_window;

      XStandardColormap
        *map_list;

      /*
        Choose a visual associated with a standard colormap.
      */
      root_window=XRootWindow(display,XDefaultScreen(display));
      status=0;
      if (LocaleCompare(map_type,"list") != 0)
        {
          /*
            User specified Standard Colormap.
          */
          FormatString((char *) map_name,"RGB_%.1024s_MAP",map_type);
          LocaleUpper(map_name);
          map_property=XInternAtom(display,(char *) map_name,True);
          if (map_property != (Atom) NULL)
            status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
              map_property);
        }
      else
        {
          static const char
            *colormap[MaxStandardColormaps]=
            {
              "_HP_RGB_SMOOTH_MAP_LIST",
              "RGB_BEST_MAP",
              "RGB_DEFAULT_MAP",
              "RGB_GRAY_MAP",
              "RGB_RED_MAP",
              "RGB_GREEN_MAP",
              "RGB_BLUE_MAP",
            };

          /*
            Choose a standard colormap from a list.
          */
          for (i=0; i < MaxStandardColormaps; i++)
          {
            map_property=XInternAtom(display,(char *) colormap[i],True);
            if (map_property == (Atom) NULL)
              continue;
            status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
              map_property);
            if (status != 0)
              break;
          }
          resource_info->color_recovery=(i == 0);  /* _HP_RGB_SMOOTH_MAP_LIST */
        }
      if (status == 0)
        {
          MagickError(XServerError,UnableToGetStandardColormap,map_type);
          return((XVisualInfo *) NULL);
        }
      /*
        Search all Standard Colormaps and visuals for ids that match.
      */
      *map_info=map_list[0];
#if !defined(PRE_R4_ICCCM)
      visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
      for (i=0; i < number_maps; i++)
        for (j=0; j < number_visuals; j++)
          if (map_list[i].visualid ==
              XVisualIDFromVisual(visual_list[j].visual))
            {
              *map_info=map_list[i];
              visual_template.visualid=
                XVisualIDFromVisual(visual_list[j].visual);
              break;
            }
      if (map_info->visualid != visual_template.visualid)
        {
          MagickError(XServerError,UnableToMatchVisualToStandardColormap,
            map_type);
          return((XVisualInfo *) NULL);
        }
#endif
      if (map_info->colormap == (Colormap) NULL)
        {
          MagickError(XServerError,StandardColormapIsNotInitialized,map_type);
          return((XVisualInfo *) NULL);
        }
      (void) XFree((void *) map_list);
    }
  else
    {
      static const unsigned int
        rank[]=
          {
            StaticGray,
            GrayScale,
            StaticColor,
            DirectColor,
            TrueColor,
            PseudoColor
          };

      XVisualInfo
        *p;

      /*
        Pick one visual that displays the most simultaneous colors.
      */
      visual_info=visual_list;
      p=visual_list;
      for (i=1; i < number_visuals; i++)
      {
        p++;
        if (MagickXVisualColormapSize(p) > MagickXVisualColormapSize(visual_info))
          visual_info=p;
        else
          if (MagickXVisualColormapSize(p) == MagickXVisualColormapSize(visual_info))
            if (rank[p->class] > rank[visual_info->class])
              visual_info=p;
      }
      visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
    }
  (void) XFree((void *) visual_list);
  /*
    Retrieve only one visual by its screen & id number.
  */
  visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
    &number_visuals);
  if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
    return((XVisualInfo *) NULL);
  return(visual_info);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C h e c k R e f r e s h W i n d o w s                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXCheckRefreshWindows checks the X server for exposure events
%  for a particular window and updates the area associated with the exposure
%  event.
%
%  The format of the MagickXCheckRefreshWindows method is:
%
%      void MagickXCheckRefreshWindows(Display *display,
%                                      MagickXWindows *windows)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%
*/
MagickExport void
MagickXCheckRefreshWindows(Display *display,MagickXWindows *windows)
{
  XEvent
    event;

  assert(display != (Display *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  MagickXDelay(display,SuspendTime);
  while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
    (void) MagickXCommandWidget(display,windows,(char const **) NULL,&event);
  while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
    MagickXRefreshWindow(display,&windows->image,&event);
  MagickXDelay(display,SuspendTime << 1);
  while (XCheckTypedWindowEvent(display,windows->command.id,Expose,&event))
    (void) MagickXCommandWidget(display,windows,(char const **) NULL,&event);
  while (XCheckTypedWindowEvent(display,windows->image.id,Expose,&event))
    MagickXRefreshWindow(display,&windows->image,&event);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C l i e n t M e s s a g e                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXClientMessage sends a reason to a window with XSendEvent.  The
%  reason is initialized with a particular protocol type and atom.
%
%  The format of the MagickXClientMessage function is:
%
%      MagickXClientMessage(display,window,protocol,reason,timestamp)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o protocol: Specifies an atom value.
%
%    o reason: Specifies an atom value which is the reason to send.
%
%    o timestamp: Specifies a value of type Time.
%
%
*/
MagickExport void
MagickXClientMessage(Display *display,const Window window,
  const Atom protocol,const Atom reason,const Time timestamp)
{
  XClientMessageEvent
    client_event;

  assert(display != (Display *) NULL);
  (void) memset(&client_event,0,sizeof(client_event));
  client_event.type=ClientMessage;
  client_event.window=window;
  client_event.message_type=protocol;
  client_event.format=32;
  client_event.data.l[0]=(long) reason;
  client_event.data.l[1]=(long) timestamp;
  (void) XSendEvent(display,window,False,NoEventMask,(XEvent *) &client_event);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X C l i e n t W i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method XClientWindow finds a window, at or below the specified window,
%  which has a WM_STATE property.  If such a window is found, it is returned,
%  otherwise the argument window is returned.
%
%  The format of the XClientWindow function is:
%
%      client_window=XClientWindow(display,target_window)
%
%  A description of each parameter follows:
%
%    o client_window: XClientWindow returns a window, at or below the specified
%      window, which has a WM_STATE property otherwise the argument
%      target_window is returned.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o target_window: Specifies the window to find a WM_STATE property.
%
%
*/
static Window
MagickXClientWindow(Display *display,Window target_window)
{
  Atom
    state,
    type;

  int
    format,
    status;

  unsigned char
    *data;

  unsigned long
    after,
    number_items;

  Window
    client_window;

  assert(display != (Display *) NULL);
  state=XInternAtom(display,"WM_STATE",True);
  if (state == (Atom) NULL)
    return(target_window);
  type=(Atom) NULL;
  status=XGetWindowProperty(display,target_window,state,0L,0L,False,
    (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
  if ((status == Success) && (type != (Atom) NULL))
    return(target_window);
  client_window=MagickXWindowByProperty(display,target_window,state);
  if (client_window == (Window) NULL)
    return(target_window);
  return(client_window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C o n f i g u r e I m a g e C o l o r m a p                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXConfigureImageColormap creates a new X colormap.
%
%  The format of the MagickXConfigureImageColormap method is:
%
%      void MagickXConfigureImageColormap(Display *display,
%        MagickXResourceInfo *resource_info,MagickXWindows *windows,
%        Image *image)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport void
MagickXConfigureImageColormap(Display *display,
                              MagickXResourceInfo *resource_info,
                              MagickXWindows *windows,Image *image)
{
  Colormap
    colormap;

  /*
    Make standard colormap.
  */
  MagickXSetCursorState(display,windows,True);
  MagickXCheckRefreshWindows(display,windows);
  MagickXMakeStandardColormap(display,windows->visual_info,resource_info,image,
    windows->map_info,windows->pixel_info);
  colormap=windows->map_info->colormap;
  (void) XSetWindowColormap(display,windows->image.id,colormap);
  (void) XSetWindowColormap(display,windows->command.id,colormap);
  (void) XSetWindowColormap(display,windows->widget.id,colormap);
  if (windows->magnify.mapped)
    (void) XSetWindowColormap(display,windows->magnify.id,colormap);
  if (windows->pan.mapped)
    (void) XSetWindowColormap(display,windows->pan.id,colormap);
  MagickXSetCursorState(display,windows,False);
  MagickXClientMessage(display,windows->image.id,windows->im_protocols,
    windows->im_update_colormap,CurrentTime);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X C o n s t r a i n W i n d o w P o s i t i o n               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXConstrainWindowPosition assures a window is positioned
%  within the X server boundaries.
%
%  The format of the MagickXConstrainWindowPosition method is:
%
%      void MagickXConstrainWindowPosition(Display *display,
%                                          MagickXWindowInfo *window_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o window_info: Specifies a pointer to a MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXConstrainWindowPosition(Display *display,
                               MagickXWindowInfo *window_info)
{
  unsigned int
    limit;

  assert(display != (Display *) NULL);
  assert(window_info != (MagickXWindowInfo *) NULL);
  limit=XDisplayWidth(display,window_info->screen)-window_info->width;
  if (window_info->x < 0)
    window_info->x=0;
  else
    if (window_info->x > (int) limit)
      window_info->x=limit;
  limit=XDisplayHeight(display,window_info->screen)-window_info->height;
  if (window_info->y < 0)
    window_info->y=0;
  else
    if (window_info->y > (int) limit)
      window_info->y=limit;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e l a y                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDelay suspends program execution for the number of
%  milliseconds specified.
%
%  The format of the Delay method is:
%
%      void MagickXDelay(Display *display,const unsigned long milliseconds)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o milliseconds: Specifies the number of milliseconds to delay before
%      returning.
%
%
*/
MagickExport void
MagickXDelay(Display *display,const unsigned long milliseconds)
{
  assert(display != (Display *) NULL);
  (void) XFlush(display);
  if (milliseconds == 0)
    return;
#if defined(MSWINDOWS)
  Sleep(milliseconds);
#elif defined(HAVE_SELECT)
  {
    struct timeval
      timer;

    timer.tv_sec=(long) milliseconds/1000;
    timer.tv_usec=(long) (milliseconds % 1000)*1000;
    (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
  }
#elif defined(HAVE_POLL)
  (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
#else
# error "Time delay method not defined."
#endif
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y R e s o u r c e I n f o                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXDestroyResourceInfo() frees memory associated with the
%  MagickXResourceInfo structure.
%
%  The format of the MagickXDestroyResourceInfo method is:
%
%      void MagickXDestroyResourceInfo(MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%
*/
MagickExport void
MagickXDestroyResourceInfo(MagickXResourceInfo *resource_info)
{
  MagickFreeMemory(resource_info->image_geometry);
  if (resource_info->image_info != (ImageInfo *) NULL)
    {
      DestroyImageInfo(resource_info->image_info);
      resource_info->image_info=(ImageInfo *) NULL;
    }
  if (resource_info->quantize_info != (QuantizeInfo *) NULL)
    {
      DestroyQuantizeInfo(resource_info->quantize_info);
      resource_info->quantize_info=(QuantizeInfo *) NULL;
    }
  MagickFreeMemory(resource_info->client_name);
  MagickFreeMemory(resource_info->name);
  (void) memset((void *) resource_info,0,sizeof(MagickXResourceInfo));
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D e s t r o y W i n d o w C o l o r s                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDestroyWindowColors frees X11 color resources previously
%  saved on a window by MagickXRetainWindowColors or programs like xsetroot.
%
%  The format of the MagickXDestroyWindowColors method is:
%
%      void MagickXDestroyWindowColors(Display *display,Window window)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%
*/
MagickExport void
MagickXDestroyWindowColors(Display *display,Window window)
{
  Atom
    property,
    type;

  int
    format,
    status;

  unsigned char
    *data;

  unsigned long
    after,
    length;

  /*
    If there are previous resources on the root window, destroy them.
  */
  assert(display != (Display *) NULL);
  property=XInternAtom(display,"_XSETROOT_ID",False);
  if (property == (Atom) NULL)
    {
      MagickError(XServerError,UnableToCreateProperty,"_XSETROOT_ID");
      return;
    }
  status=XGetWindowProperty(display,window,property,0L,1L,True,
    (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
  if (status != Success)
    return;
  if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
    {
      (void) XKillClient(display,(XID) (*((Pixmap *) data)));
      (void) XDeleteProperty(display,window,property);
    }
  if (type != None)
    (void) XFree((void *) data);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D i s p l a y I m a g e I n f o                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDisplayImageInfo displays information about an X image.
%
%  The format of the MagickXDisplayImageInfo method is:
%
%      void MagickXDisplayImageInfo(Display *display,
%        const MagickXResourceInfo *resource_info,MagickXWindows *windows,
%        Image *undo_image,Image *image)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o undo_image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport void
MagickXDisplayImageInfo(Display *display,
                        const MagickXResourceInfo *resource_info,
                        MagickXWindows *windows,Image *undo_image,
                        Image *image)
{
  char
    filename[MaxTextExtent],
    *text,
    **textlist;

  FILE
    *file;

  long
    bytes;

  register long
    i;

  size_t
    length;

  unsigned int
    levels;

  unsigned long
    number_pixels;

  /*
    Write info about the X server to a file.
  */
  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  assert(image != (Image *) NULL);
  file=AcquireTemporaryFileStream(filename,TextFileIOMode);
  if (file == (FILE *) NULL)
    {
      MagickXNoticeWidget(display,windows,"Unable to create temporary file",
        filename);
      return;
    }
  if (resource_info->gamma_correct)
    if (resource_info->display_gamma != (char *) NULL)
      (void) fprintf(file,"Display\n  gamma: %.1024s\n\n",
        resource_info->display_gamma);
  /*
    Write info about the X image to a file.
  */
  (void) fprintf(file,"X\n  visual: %.1024s\n",
    MagickXVisualClassName(windows->image.storage_class));
  (void) fprintf(file,"  depth: %d\n",windows->image.ximage->depth);
  if (windows->visual_info->colormap_size != 0)
    (void) fprintf(file,"  colormap size: %d\n",
      windows->visual_info->colormap_size);
  if (resource_info->colormap== SharedColormap)
    (void) fprintf(file,"  colormap type: Shared\n");
  else
    (void) fprintf(file,"  colormap type: Private\n");
  (void) fprintf(file,"  geometry: %dx%d\n",windows->image.ximage->width,
    windows->image.ximage->height);
  if (windows->image.crop_geometry != (char *) NULL)
    (void) fprintf(file,"  crop geometry: %.1024s\n",
      windows->image.crop_geometry);
  if (windows->image.pixmap == (Pixmap) NULL)
    (void) fprintf(file,"  type: X Image\n");
  else
    (void) fprintf(file,"  type: Pixmap\n");
  if (windows->image.shape)
    (void) fprintf(file,"  non-rectangular shape: True\n");
  else
    (void) fprintf(file,"  non-rectangular shape: False\n");
  if (windows->image.shared_memory)
    (void) fprintf(file,"  shared memory: True\n");
  else
    (void) fprintf(file,"  shared memory: False\n");
  (void) fprintf(file,"\n");
  if (resource_info->font != (char *) NULL)
    (void) fprintf(file,"Font: %.1024s\n\n",resource_info->font);
  if (resource_info->text_font != (char *) NULL)
    (void) fprintf(file,"Text font: %.1024s\n\n",resource_info->text_font);
  /*
    Write info about the undo cache to a file.
  */
  bytes=0;
  for (levels=0; undo_image != (Image *) NULL; levels++)
  {
    number_pixels=undo_image->list->columns*undo_image->list->rows;
    bytes+=number_pixels*sizeof(PixelPacket);
    undo_image=undo_image->previous;
  }
  (void) fprintf(file,"Undo Edit Cache\n  levels: %u\n",levels);
  (void) fprintf(file,"  bytes: %lumb\n",(bytes+(1 << 19)) >> 20);
  (void) fprintf(file,"  limit: %lumb\n\n",resource_info->undo_cache);
  /*
    Write info about the image to a file.
  */
  (void) DescribeImage(image,file,True);
  (void) fclose(file);
  text=(char *) FileToBlob(filename,&length,&image->exception);
  (void) LiberateTemporaryFile(filename);
  if (text == (char *) NULL)
    {
      MagickXNoticeWidget(display,windows,"MemoryAllocationFailed",
        "UnableToDisplayImageInfo");
      return;
    }
  textlist=StringToList(text);
  if (textlist != (char **) NULL)
    {
      char
        title[MaxTextExtent];

      /*
        Display information about the image in the Text View widget.
      */
      (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
      FormatString(title,"Image Info: %.1024s",image->filename);
      MagickXTextViewWidget(display,resource_info,windows,True,title,
        (char const **) textlist);
      for (i=0; textlist[i] != (char *) NULL; i++)
        MagickFreeMemory(textlist[i]);
      MagickFreeMemory(textlist);
    }
  MagickFreeMemory(text);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+     M a g i c k X D i t h e r I m a g e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method XDitherImage dithers the reference image as required by the HP
%  Color Recovery algorithm
%  (https://www.hpl.hp.com/hpjournal/95apr/apr95a6.pdf).
%  The color values are quantized to 3 bits of red and green, and 2 bits
%  of blue (3/3/2) and can be used as indices into a 8-bit X standard
%  colormap.
%
%  The format of the XDitherImage method is:
%
%      void XDitherImage(Image *image,XImage *ximage)
%
%  A description of each parameter follows:
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o ximage: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%
*/
static void MagickXDitherImage(Image *image,XImage *ximage)
{
  static const short int
    dither_red[2][16]=
    {
      {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
      { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
    },
    dither_green[2][16]=
    {
      { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
      {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
    },
    dither_blue[2][16]=
    {
      { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
      {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
    };

  PixelPacket
    color;

  long
    x,
    y;

  magick_int32_t
    value;

  register char
    *q;

  register const PixelPacket
    *p;

  register int
    i,
    j;

  unsigned int
    scanline_pad;

  register magick_uint32_t
    pixel;

  unsigned char
    *blue_map[2][16],
    *green_map[2][16],
    *red_map[2][16];

  /*
    Allocate and initialize dither maps.
  */
  memset(blue_map,0,sizeof(blue_map));
  memset(green_map,0,sizeof(green_map));
  memset(red_map,0,sizeof(red_map));
  for (i=0; i < 2; i++)
    for (j=0; j < 16; j++)
    {
      red_map[i][j]=MagickAllocateArray(unsigned char *,256,sizeof(unsigned char));
      green_map[i][j]=MagickAllocateArray(unsigned char *,
                                          256,sizeof(unsigned char));
      blue_map[i][j]=MagickAllocateArray(unsigned char *,256,sizeof(unsigned char));
      if ((red_map[i][j] == (unsigned char *) NULL) ||
          (green_map[i][j] == (unsigned char *) NULL) ||
          (blue_map[i][j] == (unsigned char *) NULL))
        {
          MagickError3(ResourceLimitError,MemoryAllocationFailed,
            UnableToDitherImage);
          goto done_xditherimage;
        }
    }
  /*
    Initialize dither tables.
  */
  for (i=0; i < 2; i++)
    for (j=0; j < 16; j++)
      for (x=0; x < 256; x++)
      {
        value=x-16;
        if (x < 48)
          value=x/2+8;
        value+=dither_red[i][j];
        red_map[i][j][x]=(unsigned char)
          ((value < 0) ? 0 : (value > 255) ? 255 : value);
        value=x-16;
        if (x < 48)
          value=x/2+8;
        value+=dither_green[i][j];
        green_map[i][j][x]=(unsigned char)
          ((value < 0) ? 0 : (value > 255) ? 255 : value);
        value=x-32;
        if (x < 112)
          value=x/2+24;
        /* FIXME: Cast to unsigned added below to avoid undefined
           behavior. Not sure if result is what was expected! */
        value+=((magick_uint32_t) dither_blue[i][j] << 1);
        blue_map[i][j][x]=(unsigned char)
          ((value < 0) ? 0 : (value > 255) ? 255 : value);
      }
  /*
    Dither image.
  */
  scanline_pad=ximage->bytes_per_line-
    ((ximage->width*ximage->bits_per_pixel) >> 3);
  i=0;
  j=0;
  q=ximage->data;
  for (y=0; y < (long) image->rows; y++)
  {
    p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
    if (p == (const PixelPacket *) NULL)
      break;
    for (x=0; x < (long) image->columns; x++)
    {
      color.red=red_map[i][j][ScaleQuantumToChar(p->red)] << 8;
      color.green=green_map[i][j][ScaleQuantumToChar(p->green)] << 8;
      color.blue=blue_map[i][j][ScaleQuantumToChar(p->blue)] << 8;
      pixel=(magick_uint32_t) ((color.red & 0xe0) |
        ((magick_uint32_t) (color.green & 0xe0) >> 3) |
        ((magick_uint32_t) (color.blue & 0xc0) >> 6));
      *q++=(magick_uint32_t) pixel;
      p++;
      j++;
      if (j == 16)
        j=0;
    }
    q+=scanline_pad;
    i++;
    if (i == 2)
      i=0;
  }
 done_xditherimage:
  /*
    Free allocated memory.
  */
  for (i=0; i < 2; i++)
    for (j=0; j < 16; j++)
    {
      MagickFreeMemory(green_map[i][j]);
      MagickFreeMemory(blue_map[i][j]);
      MagickFreeMemory(red_map[i][j]);
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X D r a w I m a g e                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXDrawImage draws a line on the image.
%
%  The format of the MagickXDrawImage method is:
%
%    status=MagickXDrawImage(display,pixel,draw_info,image)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXDrawImage returns True if the image is
%      successfully drawd with text.  False is returned is there is a
%      memory shortage.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o draw_info: Specifies a pointer to a MagickXDrawInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%
*/
MagickExport unsigned int
MagickXDrawImage(Display *display,const MagickXPixelInfo *pixel,
                 MagickXDrawInfo *draw_info,Image *image)
{
  GC
    draw_context;

  Image
    *draw_image;

  int
    x,
    y;

  Pixmap
    draw_pixmap;

  register PixelPacket
    *q;

  unsigned int
    depth,
    height,
    matte,
    width;

  Window
    root_window;

  XGCValues
    context_values;

  XImage
    *draw_ximage;

  /*
    Initialize drawd image.
  */
  assert(display != (Display *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  assert(draw_info != (MagickXDrawInfo *) NULL);
  assert(image != (Image *) NULL);
  /*
    Initialize drawd pixmap.
  */
  root_window=XRootWindow(display,XDefaultScreen(display));
  depth=XDefaultDepth(display,XDefaultScreen(display));
  draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
    draw_info->height,(int) depth);
  if (draw_pixmap == (Pixmap) NULL)
    return(False);
  /*
    Initialize graphics info.
  */
  context_values.background=(unsigned long) (~0);
  context_values.foreground=0;
  context_values.line_width=draw_info->line_width;
  draw_context=XCreateGC(display,root_window,GCBackground | GCForeground |
    GCLineWidth,&context_values);
  if (draw_context == (GC) NULL)
    return(False);
  /*
    Clear pixmap.
  */
  (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
    draw_info->height);
  /*
    Draw line to pixmap.
  */
  (void) XSetBackground(display,draw_context,0);
  (void) XSetForeground(display,draw_context,(unsigned long) (~0));
  (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
  (void) XSetStipple(display,draw_context,draw_info->stipple);
  switch (draw_info->element)
  {
    case PointElement:
    default:
    {
      (void) XDrawLines(display,draw_pixmap,draw_context,
        draw_info->coordinate_info,draw_info->number_coordinates,
        CoordModeOrigin);
      break;
    }
    case LineElement:
    {
      (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
        draw_info->line_info.y1,draw_info->line_info.x2,
        draw_info->line_info.y2);
      break;
    }
    case RectangleElement:
    {
      (void) XDrawRectangle(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height);
      break;
    }
    case FillRectangleElement:
    {
      (void) XFillRectangle(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height);
      break;
    }
    case CircleElement:
    case EllipseElement:
    {
      (void) XDrawArc(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height,0,360*64);
      break;
    }
    case FillCircleElement:
    case FillEllipseElement:
    {
      (void) XFillArc(display,draw_pixmap,draw_context,
        (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
        (unsigned int) draw_info->rectangle_info.width,
        (unsigned int) draw_info->rectangle_info.height,0,360*64);
      break;
    }
    case PolygonElement:
    {
      XPoint
        *coordinate_info;

      coordinate_info=draw_info->coordinate_info;
      (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
        draw_info->number_coordinates,CoordModeOrigin);
      (void) XDrawLine(display,draw_pixmap,draw_context,
        coordinate_info[draw_info->number_coordinates-1].x,
        coordinate_info[draw_info->number_coordinates-1].y,
        coordinate_info[0].x,coordinate_info[0].y);
      break;
    }
    case FillPolygonElement:
    {
      (void) XFillPolygon(display,draw_pixmap,draw_context,
        draw_info->coordinate_info,draw_info->number_coordinates,Complex,
        CoordModeOrigin);
      break;
    }
  }
  (void) XFreeGC(display,draw_context);
  /*
    Initialize X image.
  */
  draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
    draw_info->height,AllPlanes,ZPixmap);
  if (draw_ximage == (XImage *) NULL)
    return(False);
  (void) XFreePixmap(display,draw_pixmap);
  /*
    Initialize draw image.
  */
  draw_image=AllocateImage((ImageInfo *) NULL);
  if (draw_image == (Image *) NULL)
    return(False);
  draw_image->columns=draw_info->width;
  draw_image->rows=draw_info->height;
  /*
    Transfer drawn X image to image.
  */
  width=(unsigned int) image->columns;
  height=(unsigned int) image->rows;
  x=0;
  y=0;
  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
  (void) AcquireOnePixelByReference(image,&draw_image->background_color,x,y,&image->exception);
  (void) SetImageType(draw_image,TrueColorMatteType);
  for (y=0; y < (long) draw_image->rows; y++)
  {
    q=SetImagePixels(draw_image,0,y,draw_image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (long) draw_image->columns; x++)
    {
      if (XGetPixel(draw_ximage,x,y) == 0)
        {
          /*
            Set this pixel to the background color.
          */
          *q=draw_image->background_color;
          q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
            TransparentOpacity : OpaqueOpacity);
        }
      else
        {
          /*
            Set this pixel to the pen color.
          */
          q->red=ScaleShortToQuantum(pixel->pen_color.red);
          q->green=ScaleShortToQuantum(pixel->pen_color.green);
          q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
          q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
            OpaqueOpacity : TransparentOpacity);
        }
      q++;
    }
    if (!SyncImagePixels(draw_image))
      break;
  }
  XDestroyImage(draw_ximage);
  draw_ximage=(XImage *) NULL;
  /*
    Determine draw geometry.
  */
  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
  if ((width != (unsigned int) draw_image->columns) ||
      (height != (unsigned int) draw_image->rows))
    {
      char
        image_geometry[MaxTextExtent];

      /*
        Scale image.
      */
      FormatString(image_geometry,"%ux%u",width,height);
      TransformImage(&draw_image,(char *) NULL,image_geometry);
    }
  if (draw_info->degrees != 0.0)
    {
      double
        normalized_degrees;

      Image
        *rotate_image;

      int
        rotations;

      /*
        Rotate image.
      */
      rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
      if (rotate_image == (Image *) NULL)
        return(False);
      DestroyImage(draw_image);
      draw_image=rotate_image;
      /*
        Annotation is relative to the degree of rotation.
      */
      normalized_degrees=draw_info->degrees;
      while (normalized_degrees < -45.0)
        normalized_degrees+=360.0;
      for (rotations=0; normalized_degrees > 45.0; rotations++)
        normalized_degrees-=90.0;
      switch (rotations % 4)
      {
        default:
        case 0:
          break;
        case 1:
        {
          /*
            Rotate 90 degrees.
          */
          x=x-(int) draw_image->columns/2;
          y=y+(int) draw_image->columns/2;
          break;
        }
        case 2:
        {
          /*
            Rotate 180 degrees.
          */
          x=x-(int) draw_image->columns;
          break;
        }
        case 3:
        {
          /*
            Rotate 270 degrees.
          */
          x=x-(int) draw_image->columns/2;
          y=y-(int) (draw_image->rows-(draw_image->columns/2));
          break;
        }
      }
    }
  /*
    Composite text onto the image.
  */
  for (y=0; y < (long) draw_image->rows; y++)
  {
    q=GetImagePixels(draw_image,0,y,draw_image->columns,1);
    if (q == (PixelPacket *) NULL)
      break;
    for (x=0; x < (long) draw_image->columns; x++)
    {
      if (q->opacity != TransparentOpacity)
        q->opacity=OpaqueOpacity;
      q++;
    }
    if (!SyncImagePixels(draw_image))
      break;
  }
  (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
  if (draw_info->stencil == TransparentStencil)
    (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,x,y);
  else
    {
      matte=image->matte;
      (void) CompositeImage(image,OverCompositeOp,draw_image,x,y);
      image->matte=matte;
    }
  DestroyImage(draw_image);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X E r r o r                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXError ignores BadWindow errors for XQueryTree and
%  XGetWindowAttributes, and ignores BadDrawable errors for XGetGeometry, and
%  ignores BadValue errors for XQueryColor.  It returns False in those cases.
%  Otherwise it returns True.
%
%  The format of the MagickXError function is:
%
%      MagickXError(display,error)
%
%  A description of each parameter follows:
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o error: Specifies the error event.
%
%
*/

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

MagickExport int
MagickXError(Display *display,XErrorEvent *error)
{
  assert(display != (Display *) NULL);
  assert(error != (XErrorEvent *) NULL);
  xerror_alert=True;
  switch (error->request_code)
  {
    case X_GetGeometry:
    {
      if (error->error_code == BadDrawable)
        return(False);
      break;
    }
    case X_GetWindowAttributes:
    case X_QueryTree:
    {
      if (error->error_code == BadWindow)
        return(False);
      break;
    }
    case X_QueryColors:
    {
      if (error->error_code == BadValue)
        return(False);
      break;
    }
  }
  return(True);
}

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X F r e e R e s o u r c e s                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXFreeResources frees X11 resources.
%
%  The format of the MagickXFreeResources method is:
%
%      void MagickXFreeResources(Display *display,XVisualInfo *visual_info,
%         XStandardColormap *map_info,MagickXPixelInfo *pixel,
%         XFontStruct *font_info,MagickXResourceInfo *resource_info,
%         MagickXWindowInfo *window_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o font_info: Specifies a pointer to a XFontStruct structure.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o window_info: Specifies a pointer to a X11 MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXFreeResources(Display *display,
                     XVisualInfo *visual_info,
                     XStandardColormap *map_info,
                     MagickXPixelInfo *pixel,
                     XFontStruct *font_info,
                     MagickXResourceInfo *resource_info,
                     MagickXWindowInfo *window_info)
{
  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  if (window_info != (MagickXWindowInfo *) NULL)
    {
      /*
        Free X image.
      */
      if (window_info->ximage != (XImage *) NULL)
        {
          XDestroyImage(window_info->ximage);
          window_info->ximage=(XImage *) NULL;
        }
      if (window_info->id != (Window) NULL)
        {
          /*
            Free destroy window and free cursors.
          */
          if (window_info->id != XRootWindow(display,visual_info->screen))
            (void) XDestroyWindow(display,window_info->id);
          if (window_info->annotate_context != (GC) NULL)
            (void) XFreeGC(display,window_info->annotate_context);
          if (window_info->highlight_context != (GC) NULL)
            (void) XFreeGC(display,window_info->highlight_context);
          if (window_info->widget_context != (GC) NULL)
            (void) XFreeGC(display,window_info->widget_context);
          (void) XFreeCursor(display,window_info->cursor);
          (void) XFreeCursor(display,window_info->busy_cursor);
        }
    }
  /*
    Free font.
  */
  if (font_info != (XFontStruct *) NULL)
    (void) XFreeFont(display,font_info);
  if (map_info != (XStandardColormap *) NULL)
    {
      /*
        Free X Standard Colormap.
      */
      if (resource_info->map_type == (char *) NULL)
        (void) MagickXFreeStandardColormap(display,visual_info,map_info,pixel);
      (void) XFree((void *) map_info);
    }
  /*
    Free X visual info.
  */
  if (visual_info != (XVisualInfo *) NULL)
    (void) XFree((void *) visual_info);
  if (resource_info->close_server)
    (void) XCloseDisplay(display);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X F r e e S t a n d a r d C o l o r m a p                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXFreeStandardColormap frees an X11 colormap.
%
%  The format of the MagickXFreeStandardColormap method is:
%
%      void MagickXFreeStandardColormap(Display *display,
%        const XVisualInfo *visual_info,XStandardColormap *map_info,
%        MagickXPixelInfo *pixel)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%
*/
MagickExport void
MagickXFreeStandardColormap(Display *display,
                            const XVisualInfo *visual_info,
                            XStandardColormap *map_info,
                            MagickXPixelInfo *pixel)
{
  /*
    Free colormap.
  */
  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  (void) XFlush(display);
  if (map_info->colormap != (Colormap) NULL)
    {
      if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
        (void) XFreeColormap(display,map_info->colormap);
      else
        if (pixel != (MagickXPixelInfo *) NULL)
          if ((visual_info->class != TrueColor) &&
              (visual_info->class != DirectColor))
            (void) XFreeColors(display,map_info->colormap,pixel->pixels,
              (int) pixel->colors,0);
    }
  map_info->colormap=(Colormap) NULL;
  if (pixel != (MagickXPixelInfo *) NULL)
    {
      if (pixel->pixels != (unsigned long *) NULL)
        MagickFreeMemory(pixel->pixels);
      pixel->pixels=(unsigned long *) NULL;
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t A n n o t a t e I n f o                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetAnnotateInfo initializes the AnnotateInfo structure.
%
%  The format of the MagickXGetAnnotateInfo method is:
%
%      void MagickXGetAnnotateInfo(MagickXAnnotateInfo *annotate_info)
%
%  A description of each parameter follows:
%
%    o annotate_info: Specifies a pointer to a MagickXAnnotateInfo structure.
%
%
*/
MagickExport void
MagickXGetAnnotateInfo(MagickXAnnotateInfo *annotate_info)
{
  /*
    Initialize annotate structure.
  */
  assert(annotate_info != (MagickXAnnotateInfo *) NULL);
  annotate_info->x=0;
  annotate_info->y=0;
  annotate_info->width=0;
  annotate_info->height=0;
  annotate_info->stencil=ForegroundStencil;
  annotate_info->degrees=0.0;
  annotate_info->font_info=(XFontStruct *) NULL;
  annotate_info->text=(char *) NULL;
  *annotate_info->geometry='\0';
  annotate_info->previous=(MagickXAnnotateInfo *) NULL;
  annotate_info->next=(MagickXAnnotateInfo *) NULL;
  (void) XSupportsLocale();
  (void) XSetLocaleModifiers("");
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t M a p I n f o                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetMapInfo initializes the XStandardColormap structure.
%
%  The format of the XStandardColormap method is:
%
%      void MagickXGetMapInfo(const XVisualInfo *visual_info,
%        const Colormap colormap,XStandardColormap *map_info)
%
%  A description of each parameter follows:
%
%    o colormap: Specifies the ID of the X server colormap.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
%
%
*/
MagickExport void
MagickXGetMapInfo(const XVisualInfo *visual_info,
                  const Colormap colormap,XStandardColormap *map_info)
{
  /*
    Initialize map info.
  */
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  map_info->colormap=colormap;
  map_info->red_max=visual_info->red_mask;
  map_info->red_mult=map_info->red_max != 0 ? 1 : 0;
  if (map_info->red_max != 0)
    while ((map_info->red_max & 0x01) == 0)
    {
      map_info->red_max>>=1;
      map_info->red_mult<<=1;
    }
  map_info->green_max=visual_info->green_mask;
  map_info->green_mult=map_info->green_max != 0 ? 1 : 0;
  if (map_info->green_max != 0)
    while ((map_info->green_max & 0x01) == 0)
    {
      map_info->green_max>>=1;
      map_info->green_mult<<=1;
    }
  map_info->blue_max=visual_info->blue_mask;
  map_info->blue_mult=map_info->blue_max != 0 ? 1 : 0;
  if (map_info->blue_max != 0)
    while ((map_info->blue_max & 0x01) == 0)
    {
      map_info->blue_max>>=1;
      map_info->blue_mult<<=1;
    }
  map_info->base_pixel=0;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t I m a g e I n f o                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetImportInfo initializes the MagickXImportInfo structure.
%
%  The format of the MagickXGetImportInfo method is:
%
%      void MagickXGetImportInfo(MagickXImportInfo *ximage_info)
%
%  A description of each parameter follows:
%
%    o ximage_info: Specifies a pointer to a ImageInfo structure.
%
%
*/
MagickExport void
MagickXGetImportInfo(MagickXImportInfo *ximage_info)
{
  assert(ximage_info != (MagickXImportInfo *) NULL);
  ximage_info->frame=False;
  ximage_info->borders=False;
  ximage_info->screen=False;
  ximage_info->descend=True;
  ximage_info->silent=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t P i x e l P a c k e t                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetPixelPacket initializes the PixelPacket structure.
%
%  The format of the MagickXGetPixelPacket method is:
%
%      void MagickXGetPixelPacket(Display *display,
%        const XVisualInfo *visual_info,const XStandardColormap *map_info,
%        const MagickXResourceInfo *resource_info,Image *image,
%        MagickXPixelInfo *pixel)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%
*/
MagickExport void
MagickXGetPixelPacket(Display *display,
                      const XVisualInfo *visual_info,
                      const XStandardColormap *map_info,
                      const MagickXResourceInfo *resource_info,
                      Image *image,
                      MagickXPixelInfo *pixel)
{
  static const char
    *PenColors[MaxNumberPens]=
    {
      "#000000000000",  /* black */
      "#00000000ffff",  /* blue */
      "#0000ffffffff",  /* cyan */
      "#0000ffff0000",  /* green */
      "#bdbdbdbdbdbd",  /* gray */
      "#ffff00000000",  /* red */
      "#ffff0000ffff",  /* magenta */
      "#ffffffff0000",  /* yellow */
      "#ffffffffffff",  /* white */
      "#bdbdbdbdbdbd",  /* gray */
      "#bdbdbdbdbdbd"   /* gray */
    };

  Colormap
    colormap;

  int
    status;

  register long
    i;

  unsigned int
    packets;

  /*
    Initialize pixel info.
  */
  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  pixel->colors=0;
  if (image != (Image *) NULL)
    if (image->storage_class == PseudoClass)
      pixel->colors=image->colors;
  packets=Max((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
  if (pixel->pixels != (unsigned long *) NULL)
    MagickFreeMemory(pixel->pixels);
  pixel->pixels=
    MagickAllocateArray(unsigned long *,packets,sizeof(unsigned long));
  if (pixel->pixels == (unsigned long *) NULL)
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToGetPixelInfo));
  /*
    Set foreground color.
  */
  colormap=map_info->colormap;
  (void) XParseColor(display,colormap,(char *) ForegroundColor,
    &pixel->foreground_color);
  status=XParseColor(display,colormap,resource_info->foreground_color,
    &pixel->foreground_color);
  if (status == 0)
    MagickError(XServerError,ColorIsNotKnownToServer,
      resource_info->foreground_color);
  pixel->foreground_color.pixel=
    MagickXStandardPixel(map_info,&pixel->foreground_color);
  pixel->foreground_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set background color.
  */
  (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",
                     &pixel->background_color);
  status=XParseColor(display,colormap,resource_info->background_color,
    &pixel->background_color);
  if (status == 0)
    MagickError(XServerError,ColorIsNotKnownToServer,
      resource_info->background_color);
  pixel->background_color.pixel=
    MagickXStandardPixel(map_info,&pixel->background_color);
  pixel->background_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set border color.
  */
  (void) XParseColor(display,colormap,(char *) BorderColor,
    &pixel->border_color);
  status=XParseColor(display,colormap,resource_info->border_color,
    &pixel->border_color);
  if (status == 0)
    MagickError(XServerError,ColorIsNotKnownToServer,
      resource_info->border_color);
  pixel->border_color.pixel=MagickXStandardPixel(map_info,&pixel->border_color);
  pixel->border_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set matte color.
  */
  pixel->matte_color=pixel->background_color;
  if (resource_info->matte_color != (char *) NULL)
    {
      /*
        Matte color is specified as a X resource or command line argument.
      */
      status=XParseColor(display,colormap,resource_info->matte_color,
        &pixel->matte_color);
      if (status == 0)
        MagickError(XServerError,ColorIsNotKnownToServer,
          resource_info->matte_color);
      pixel->matte_color.pixel=MagickXStandardPixel(map_info,&pixel->matte_color);
      pixel->matte_color.flags=DoRed | DoGreen | DoBlue;
    }
  /*
    Set highlight color.
  */
  pixel->highlight_color.red=(unsigned short) (((double)
     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
     (ScaleQuantumToShort((double) MaxRGB-HighlightModulate)));
  pixel->highlight_color.green=(unsigned short) (((double)
     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
     (ScaleQuantumToShort((double) MaxRGB-HighlightModulate)));
  pixel->highlight_color.blue=(unsigned short) (((double)
     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
     (ScaleQuantumToShort((double) MaxRGB-HighlightModulate)));
  pixel->highlight_color.pixel=MagickXStandardPixel(map_info,&pixel->highlight_color);
  pixel->highlight_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set shadow color.
  */
  pixel->shadow_color.red=(unsigned short) (((double)
    pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
  pixel->shadow_color.green=(unsigned short) (((double)
    pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
  pixel->shadow_color.blue=(unsigned short) (((double)
    pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
  pixel->shadow_color.pixel=MagickXStandardPixel(map_info,&pixel->shadow_color);
  pixel->shadow_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set depth color.
  */
  pixel->depth_color.red=(unsigned short) (((double)
    pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
  pixel->depth_color.green=(unsigned short) (((double)
    pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
  pixel->depth_color.blue=(unsigned short) (((double)
    pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
  pixel->depth_color.pixel=MagickXStandardPixel(map_info,&pixel->depth_color);
  pixel->depth_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set trough color.
  */
  pixel->trough_color.red=(unsigned short) (((double)
    pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
  pixel->trough_color.green=(unsigned short) (((double)
    pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
  pixel->trough_color.blue=(unsigned short) (((double)
    pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
  pixel->trough_color.pixel=MagickXStandardPixel(map_info,&pixel->trough_color);
  pixel->trough_color.flags=DoRed | DoGreen | DoBlue;
  /*
    Set pen color.
  */
  for (i=0; i < MaxNumberPens; i++)
  {
    (void) XParseColor(display,colormap,(char *) PenColors[i],
      &pixel->pen_colors[i]);
    status=XParseColor(display,colormap,resource_info->pen_colors[i],
      &pixel->pen_colors[i]);
    if (status == 0)
      MagickError(XServerError,ColorIsNotKnownToServer,
        resource_info->pen_colors[i]);
    pixel->pen_colors[i].pixel=MagickXStandardPixel(map_info,&pixel->pen_colors[i]);
    pixel->pen_colors[i].flags=DoRed | DoGreen | DoBlue;
  }
  pixel->box_color=pixel->background_color;
  pixel->pen_color=pixel->foreground_color;
  pixel->box_index=0;
  pixel->pen_index=1;
  if (image != (Image *) NULL)
    {
      if (resource_info->gamma_correct && (image->gamma != 0.0))
        {
          int
            count;

          /*
            Initialize map relative to display and image gamma.
          */
          count=sscanf(resource_info->display_gamma,"%lf%*[,/]%lf%*[,/]%lf",
            &red_gamma,&green_gamma,&blue_gamma);
          if (count == 1)
            {
              green_gamma=red_gamma;
              blue_gamma=red_gamma;
            }
          red_gamma*=image->gamma;
          green_gamma*=image->gamma;
          blue_gamma*=image->gamma;
        }
      if (image->storage_class == PseudoClass)
        {
          /*
            Initialize pixel array for images of type PseudoClass.
          */
          for (i=0; i < (long) image->colors; i++)
            pixel->pixels[i]=
              MagickXGammaPixel(map_info,image->colormap+i);
          for (i=0; i < MaxNumberPens; i++)
            pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
          pixel->colors+=MaxNumberPens;
        }
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e C l a s s                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceClass queries the X server for the specified
%  resource name or class.  If the resource name or class is not defined
%  in the database, the supplied default value is returned.
%
%  The format of the MagickXGetResourceClass method is:
%
%      char *MagickXGetResourceClass(XrmDatabase database,
%        const char *client_name,const char *keyword,char *resource_default)
%
%  A description of each parameter follows:
%
%    o value: Method MagickXGetResourceClass returns the resource value
%      associated with the name or class.  If none is found, the supplied
%      default value is returned.
%
%    o database: Specifies a resource database; returned from
%      XrmGetStringDatabase.
%
%    o client_name:  Specifies the application name used to retrieve resource
%      info from the X server database.
%
%    o keyword: Specifies the keyword of the value being retrieved.
%
%    o resource_default: Specifies the default value to return if the query
%      fails to find the specified keyword/class.
%
%
*/
MagickExport char *
MagickXGetResourceClass(XrmDatabase database,
                        const char *client_name,const char *keyword,
                        char *resource_default)
{
  char
    resource_class[MaxTextExtent],
    resource_name[MaxTextExtent];

  int
    status;

  static char
    *resource_type;

  XrmValue
    resource_value;

  if (database == (XrmDatabase) NULL)
    return(resource_default);
  *resource_name='\0';
  *resource_class='\0';
  if (keyword != (char *) NULL)
    {
      unsigned char
        c,
        k;

      /*
        Initialize resource keyword and class.
      */
      FormatString(resource_name,"%.1024s.%.1024s",client_name,keyword);
      c=(*client_name);
      if ((c >= XK_a) && (c <= XK_z))
        c-=(XK_a-XK_A);
      else
        if ((c >= XK_agrave) && (c <= XK_odiaeresis))
          c-=(XK_agrave-XK_Agrave);
        else
          if ((c >= XK_oslash) && (c <= XK_thorn))
            c-=(XK_oslash-XK_Ooblique);
      k=(*keyword);
      if ((k >= XK_a) && (k <= XK_z))
        k-=(XK_a-XK_A);
      else
        if ((k >= XK_agrave) && (k <= XK_odiaeresis))
          k-=(XK_agrave-XK_Agrave);
        else
          if ((k >= XK_oslash) && (k <= XK_thorn))
            k-=(XK_oslash-XK_Ooblique);
      FormatString(resource_class,"%c%.1024s.%c%.1024s",c,client_name+1,k,
        keyword+1);
    }
  status=XrmGetResource(database,resource_name,resource_class,&resource_type,
    &resource_value);
  if (status == False)
    return(resource_default);
  return(resource_value.addr);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e D a t a b a s e                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceDatabase creates a new resource database and
%  initializes it.
%
%  The format of the MagickXGetResourceDatabase method is:
%
%      XrmDatabase MagickXGetResourceDatabase(Display *display,
%        const char *client_name)
%
%  A description of each parameter follows:
%
%    o database: Method MagickXGetResourceDatabase returns the database after
%      it is initialized.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o client_name:  Specifies the application name used to retrieve resource
%      info from the X server database.
%
%
*/
MagickExport XrmDatabase
MagickXGetResourceDatabase(Display *display,
                           const char *client_name)
{
  char
    filename[MaxTextExtent];

  register const char
    *p;

  unsigned char
    c;

  XrmDatabase
    resource_database,
    server_database;

  if (display == (Display *) NULL)
    return((XrmDatabase) NULL);
  assert(client_name != (char *) NULL);
  /*
    Initialize resource database.
  */
  XrmInitialize();
  (void) XGetDefault(display,(char *) client_name,(char *) "dummy");
  resource_database=XrmGetDatabase(display);
  /*
    Combine application database.
  */
  if (client_name != (char *) NULL)
    {
      /*
        Get basename of client.
      */
      p=client_name+(strlen(client_name)-1);
      while ((p > client_name) && (*p != '/'))
        p--;
      if (*p == '/')
        client_name=p+1;
    }
  c=(*client_name);
  if ((c >= XK_a) && (c <= XK_z))
    c-=(XK_a-XK_A);
  else
    if ((c >= XK_agrave) && (c <= XK_odiaeresis))
      c-=(XK_agrave-XK_Agrave);
    else
      if ((c >= XK_oslash) && (c <= XK_thorn))
        c-=(XK_oslash-XK_Ooblique);
#if defined(ApplicationDefaults)
  FormatString(filename,"%.1024s%c%.1024s",ApplicationDefaults,c,client_name+1);
  (void) XrmCombineFileDatabase(filename,&resource_database,False);
#endif
  if (XResourceManagerString(display) != (char *) NULL)
    {
      /*
        Combine server database.
      */
      server_database=XrmGetStringDatabase(XResourceManagerString(display));
      XrmCombineDatabase(server_database,&resource_database,False);
    }
  /*
    Merge user preferences database.
  */
#if defined(PreferencesDefaults)
  FormatString(filename,"%.1024s%.1024src",PreferencesDefaults,client_name);
  ExpandFilename(filename);
  (void) XrmCombineFileDatabase(filename,&resource_database,False);
#endif
  return(resource_database);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e I n f o                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceInfo initializes the ResourceInfo structure.
%
%  The format of the MagickXGetResourceInfo method is:
%
%      void MagickXGetResourceInfo(XrmDatabase database,char *client_name,
%        MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o database: Specifies a resource database; returned from
%      XrmGetStringDatabase.
%
%    o client_name:  Specifies the application name used to retrieve
%      resource info from the X server database.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
MagickExport void
MagickXGetResourceInfo(XrmDatabase database,const char *client_name,
                       MagickXResourceInfo *resource_info)
{
  char
    *resource_value;

  /*
    Initialize resource info fields.
  */
  assert(resource_info != (MagickXResourceInfo *) NULL);
  (void) memset(resource_info,0,sizeof(MagickXResourceInfo));
  resource_info->resource_database=database;
  resource_info->image_info=CloneImageInfo((ImageInfo *) NULL);
  resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
  resource_info->close_server=True;
  resource_info->client_name=AllocateString(client_name);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "backdrop",
    (char *) "False");
  resource_info->backdrop=MagickIsTrue(resource_value);
  resource_info->background_color=MagickXGetResourceInstance(database,client_name,
    (char *) "background","#d6d6d6d6d6d6");
  resource_info->border_color=MagickXGetResourceInstance(database,client_name,
    (char *) "borderColor",BorderColor);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "borderWidth",
    (char *) "2");
  resource_info->border_width=MagickAtoI(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "colormap",
    (char *) "shared");
  resource_info->colormap=UndefinedColormap;
  if (LocaleCompare("private",resource_value) == 0)
    resource_info->colormap=PrivateColormap;
  if (LocaleCompare("shared",resource_value) == 0)
    resource_info->colormap=SharedColormap;
  if (resource_info->colormap == UndefinedColormap)
    MagickError(OptionError,UnrecognizedColormapType,resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,
    (char *) "colorRecovery",(char *) "False");
  resource_info->color_recovery=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "confirmExit",
    (char *) "False");
  resource_info->confirm_exit=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "delay",
    (char *) "1");
  resource_info->delay=MagickAtoI(resource_value);
  resource_info->display_gamma=MagickXGetResourceClass(database,client_name,
    (char *) "displayGamma",(char *) "2.2");
  resource_value=MagickXGetResourceClass(database,client_name,
    (char *) "displayWarnings",(char *) "True");
  resource_info->display_warnings=MagickIsTrue(resource_value);
  resource_info->font=MagickXGetResourceClass(database,client_name,(char *) "font",
    (char *) "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1");
  resource_info->font=MagickXGetResourceClass(database,client_name,
    (char *) "fontList",resource_info->font);
  resource_info->font_name[0]=MagickXGetResourceClass(database,client_name,
    (char *) "font1",(char *) "fixed");
  resource_info->font_name[1]=MagickXGetResourceClass(database,client_name,
    (char *) "font2",(char *) "variable");
  resource_info->font_name[2]=MagickXGetResourceClass(database,client_name,
    (char *) "font3",(char *) "5x8");
  resource_info->font_name[3]=MagickXGetResourceClass(database,client_name,
    (char *) "font4",(char *) "6x10");
  resource_info->font_name[4]=MagickXGetResourceClass(database,client_name,
    (char *) "font5",(char *) "7x13bold");
  resource_info->font_name[5]=MagickXGetResourceClass(database,client_name,
    (char *) "font6",(char *) "8x13bold");
  resource_info->font_name[6]=MagickXGetResourceClass(database,client_name,
    (char *) "font7",(char *) "9x15bold");
  resource_info->font_name[7]=MagickXGetResourceClass(database,client_name,
    (char *) "font8",(char *) "10x20");
  resource_info->font_name[8]=MagickXGetResourceClass(database,client_name,
    (char *) "font9",(char *) "12x24");
  resource_info->font_name[9]=MagickXGetResourceClass(database,client_name,
    (char *) "font0",(char *) "fixed");
  resource_info->font_name[10]=MagickXGetResourceClass(database,client_name,
    (char *) "font0",(char *) "fixed");
  resource_info->foreground_color=MagickXGetResourceInstance(database,client_name,
    "foreground",ForegroundColor);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "gammaCorrect",
    (char *) "True");
  resource_info->gamma_correct=MagickIsTrue(resource_value);
  resource_info->image_geometry=MagickXGetResourceClass(database,client_name,
    (char *) "geometry",(char *) NULL);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "gravity",
    (char *) "Center");
  resource_info->gravity=(-1);
  if (LocaleCompare("Forget",resource_value) == 0)
    resource_info->gravity=ForgetGravity;
  if (LocaleCompare("NorthWest",resource_value) == 0)
    resource_info->gravity=NorthWestGravity;
  if (LocaleCompare("North",resource_value) == 0)
    resource_info->gravity=NorthGravity;
  if (LocaleCompare("NorthEast",resource_value) == 0)
    resource_info->gravity=NorthEastGravity;
  if (LocaleCompare("West",resource_value) == 0)
    resource_info->gravity=WestGravity;
  if (LocaleCompare("Center",resource_value) == 0)
    resource_info->gravity=CenterGravity;
  if (LocaleCompare("East",resource_value) == 0)
    resource_info->gravity=EastGravity;
  if (LocaleCompare("SouthWest",resource_value) == 0)
    resource_info->gravity=SouthWestGravity;
  if (LocaleCompare("South",resource_value) == 0)
    resource_info->gravity=SouthGravity;
  if (LocaleCompare("SouthEast",resource_value) == 0)
    resource_info->gravity=SouthEastGravity;
  if (LocaleCompare("Static",resource_value) == 0)
    resource_info->gravity=StaticGravity;
  if (resource_info->gravity == (-1))
    {
      MagickError(OptionError,UnrecognizedGravityType,resource_value);
      resource_info->gravity=CenterGravity;
    }
  if (getcwd(resource_info->home_directory,MaxTextExtent-1) == NULL)
    MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
                     NULL);
  resource_info->icon_geometry=MagickXGetResourceClass(database,client_name,
    (char *) "iconGeometry",(char *) NULL);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "iconic",
    (char *) "False");
  resource_info->iconic=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "immutable",
    LocaleCompare(client_name,(char *) "PerlMagick") == 0 ? (char *) "True" :
    (char *) "False");
  resource_info->immutable=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "magnify",
    (char *) "3");
  resource_info->magnify=MagickAtoI(resource_value);
  resource_info->map_type=MagickXGetResourceClass(database,client_name,(char *) "map",
    (char *) NULL);
  resource_info->matte_color=MagickXGetResourceInstance(database,client_name,
    (char *) "mattecolor",(char *) NULL);
  resource_info->name=MagickXGetResourceClass(database,client_name,(char *) "name",
    (char *) NULL);
  resource_info->pen_colors[0]=MagickXGetResourceClass(database,client_name,
    (char *) "pen1",(char *) "black");
  resource_info->pen_colors[1]=MagickXGetResourceClass(database,client_name,
    (char *) "pen2",(char *) "blue");
  resource_info->pen_colors[2]=MagickXGetResourceClass(database,client_name,
    (char *) "pen3",(char *) "cyan");
  resource_info->pen_colors[3]=MagickXGetResourceClass(database,client_name,
    (char *) "pen4",(char *) "green");
  resource_info->pen_colors[4]=MagickXGetResourceClass(database,client_name,
    (char *) "pen5",(char *) "gray");
  resource_info->pen_colors[5]=MagickXGetResourceClass(database,client_name,
    (char *) "pen6",(char *) "red");
  resource_info->pen_colors[6]=MagickXGetResourceClass(database,client_name,
    (char *) "pen7",(char *) "magenta");
  resource_info->pen_colors[7]=MagickXGetResourceClass(database,client_name,
    (char *) "pen8",(char *) "yellow");
  resource_info->pen_colors[8]=MagickXGetResourceClass(database,client_name,
    (char *) "pen9",(char *) "white");
  resource_info->pen_colors[9]=MagickXGetResourceClass(database,client_name,
    (char *) "pen0",(char *) "gray");
  resource_info->pen_colors[10]=MagickXGetResourceClass(database,client_name,
    (char *) "pen0",(char *) "gray");
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "pause",
    (char *) "0");
  resource_info->pause=MagickAtoI(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "quantum",
    (char *) "1");
  resource_info->quantum=MagickAtoI(resource_value);
  resource_info->text_font=MagickXGetResourceClass(database,client_name,(char *)
    "font",(char *) "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-iso8859-1");
  resource_info->text_font=MagickXGetResourceClass(database,client_name,
    (char *) "textFontList",resource_info->text_font);
  resource_info->title=MagickXGetResourceClass(database,client_name,(char *) "title",
    (char *) NULL);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "undoCache",
    (char *) "16");
  resource_info->undo_cache=MagickAtoL(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "update",
    (char *) "False");
  resource_info->update=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "usePixmap",
    (char *) "False");
  resource_info->use_pixmap=MagickIsTrue(resource_value);
  resource_value=MagickXGetResourceClass(database,client_name,(char *) "sharedMemory",
    (char *) "True");
  resource_info->use_shared_memory=MagickIsTrue(resource_value);
  resource_info->visual_type=MagickXGetResourceClass(database,client_name,
    (char *) "visual",(char *) NULL);
  resource_info->window_group=MagickXGetResourceClass(database,client_name,
    (char *) "windowGroup",(char *) NULL);
  resource_info->window_id=MagickXGetResourceClass(database,client_name,
    (char *) "window",(char *) NULL);
  resource_info->write_filename=MagickXGetResourceClass(database,client_name,
    (char *) "writeFilename",(char *) NULL);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t R e s o u r c e I n s t a n c e                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetResourceInstance queries the X server for the specified
%  resource name.  If the resource name is not defined in the database, the
%  supplied default value is returned.
%
%  The format of the MagickXGetResourceInstance method is:
%
%      char *MagickXGetResourceInstance(XrmDatabase database,
%        const char *client_name,const char *keyword,
%        const char *resource_default)
%
%  A description of each parameter follows:
%
%    o value: Method MagickXGetResourceInstance returns the resource value
%      associated with the name or class.  If none is found, the supplied
%      default value is returned.
%
%    o database: Specifies a resource database; returned from
%      XrmGetStringDatabase.
%
%    o client_name:  Specifies the application name used to retrieve
%      resource info from the X server database.
%
%    o keyword: Specifies the keyword of the value being retrieved.
%
%    o resource_default: Specifies the default value to return if the query
%      fails to find the specified keyword/class.
%
%
*/
MagickExport char *
MagickXGetResourceInstance(XrmDatabase database,
                           const char *client_name,
                           const char *keyword,
                           const char *resource_default)
{
  char
    *resource_type,
    resource_name[MaxTextExtent];

  int
    status;

  XrmValue
    resource_value;

  if (database == (XrmDatabase) NULL)
    return((char *) resource_default);
  *resource_name='\0';
  if (keyword != (char *) NULL)
    FormatString(resource_name,"%.1024s.%.1024s",client_name,keyword);
  status=XrmGetResource(database,resource_name,"GraphicsMagick",
    &resource_type,&resource_value);
  if (status == False)
    return((char *) resource_default);
  return(resource_value.addr);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t S c r e e n D e n s i t y                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetScreenDensity returns the density of the X server screen in
%  dots-per-inch.
%
%  The format of the MagickXGetScreenDensity method is:
%
%      char *MagickXGetScreenDensity(Display *display)
%
%  A description of each parameter follows:
%
%    o density: Method MagickXGetScreenDensity returns the density of the X
%     screen
%      in dots-per-inch.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%
*/
MagickExport char *
MagickXGetScreenDensity(Display *display)
{
  char
    density[MaxTextExtent];

  double
    x_density,
    y_density;

  /*
    Set density as determined by screen size.
  */
  x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
    ((double) DisplayWidthMM(display,XDefaultScreen(display))));
  y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
    ((double) DisplayHeightMM(display,XDefaultScreen(display))));
  FormatString(density,"%gx%g",x_density,y_density);
  return(GetPageGeometry(density));
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X G e t S u b w i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method XGetSubwindow returns the subwindow of a window chosen the
%  user with the pointer and a button press.
%
%  The format of the XGetSubwindow method is:
%
%      Window XGetSubwindow(Display *display,Window window,int x,int y)
%
%  A description of each parameter follows:
%
%    o subwindow: Method XGetSubwindow returns NULL if no subwindow is found
%      otherwise the subwindow is returned.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window.
%
%    o x: the x coordinate of the pointer relative to the origin of the
%      window.
%
%    o y: the y coordinate of the pointer relative to the origin of the
%      window.
%
%
*/
static Window
MagickXGetSubwindow(Display *display,Window window,int x,int y)
{
  Window
    source_window,
    target_window;

  int
    status,
    x_offset,
    y_offset;

  assert(display != (Display *) NULL);
  source_window=XRootWindow(display,XDefaultScreen(display));
  if (window == (Window) NULL)
    return(source_window);
  target_window=window;
  for ( ; ; )
  {
    status=XTranslateCoordinates(display,source_window,window,x,y,
      &x_offset,&y_offset,&target_window);
    if (status != True)
      break;
    if (target_window == (Window) NULL)
      break;
    source_window=window;
    window=target_window;
    x=x_offset;
    y=y_offset;
  }
  if (target_window == (Window) NULL)
    target_window=window;
  return(target_window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t W i n d o w C o l o r                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetWindowColor returns the color of a pixel interactively
%  chosen from the X server.
%
%  The format of the MagickXGetWindowColor method is:
%
%      unsigned int MagickXGetWindowColor(Display *display,
%        MagickXWindows *windows,char *name)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXGetWindowColor returns True if the color is
%      obtained from the X server.  False is returned if any errors occurs.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o name: The name of of the color if found in the X Color Database is
%      returned in this character string.
%
%
*/
MagickExport unsigned int
MagickXGetWindowColor(Display *display,MagickXWindows *windows,char *name)
{
  int
    x,
    y;

  PixelPacket
    pixel;

  RectangleInfo
    crop_info = { 0, 0, 0, 0 };

  unsigned int
    status;

  Window
    child,
    client_window,
    root_window,
    target_window;

  XColor
    color;

  XImage
    *ximage;

  XWindowAttributes
    window_attributes;

  /*
    Choose a pixel from the X server.
  */
  assert(display != (Display *) NULL);
  assert(name != (char *) NULL);
  *name='\0';
  target_window=MagickXSelectWindow(display,&crop_info);
  root_window=XRootWindow(display,XDefaultScreen(display));
  client_window=target_window;
  if (target_window != root_window)
    {
      unsigned int
        d;

      /*
        Get client window.
      */
      status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
      if (status != 0)
        {
          client_window=MagickXClientWindow(display,target_window);
          target_window=client_window;
        }
    }
  /*
    Verify window is viewable.
  */
  status=XGetWindowAttributes(display,target_window,&window_attributes);
  if ((status == False) || (window_attributes.map_state != IsViewable))
    return(False);
  /*
    Get window X image.
  */
  (void) XTranslateCoordinates(display,root_window,target_window,
    (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
  ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
  if (ximage == (XImage *) NULL)
    return(False);
  color.pixel=XGetPixel(ximage,0,0);
  XDestroyImage(ximage);
  ximage=(XImage *) NULL;
  /*
    Match color against the color database.
  */
  (void) XQueryColor(display,window_attributes.colormap,&color);
  pixel.red=ScaleShortToQuantum(color.red);
  pixel.green=ScaleShortToQuantum(color.green);
  pixel.blue=ScaleShortToQuantum(color.blue);
  pixel.opacity=OpaqueOpacity;
  (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
    &windows->image.image->exception);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X G e t W i n d o w I m a g e                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetWindowImage reads an image from the target X window and
%  returns it.  MagickXGetWindowImage optionally descends the window
%  hierarchy and overlays the target image with each child image in an
%  optimized fashion.  Any child window that have the same visual, colormap,
%  and are contained by its parent are exempted.
%
%  The format of the MagickXGetWindowImage method is:
%
%      Image *MagickXGetWindowImage(Display *display,const Window window,
%        const unsigned int borders,const unsigned int level)
%
%  A description of each parameter follows:
%
%    o image: Method MagickXGetWindowImage returns a MIFF image if it can be
%      successfully read from the X window.  A null image is returned if
%      any errors occurs.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies the window to obtain the image from.
%
%    o borders: Specifies whether borders pixels are to be saved with
%      the image.
%
%    o level: Specifies an unsigned integer representing the level of
%      decent in the window hierarchy.  This value must be zero or one on
%      the initial call to MagickXGetWindowImage.  A value of zero returns
%      after one call.  A value of one causes the function to descend the
%      window hierarchy and overlay the target image with each subwindow image.
%
%
*/
static Image *
MagickXGetWindowImage(Display *display,const Window window,
                      const unsigned int borders,const unsigned int level)
{
  typedef struct _ColormapInfo
  {
    Colormap
      colormap;

    XColor
      *colors;

    struct _ColormapInfo
      *next;
  } ColormapInfo;

  typedef struct _WindowInfo
  {
    Window
      window,
      parent;

    Visual
      *visual;

    Colormap
      colormap;

    XSegment
      bounds;

    RectangleInfo
      crop_info;
  } WindowInfo;

  IndexPacket
    index_packet;

  int
    display_height,
    display_width,
    id,
    status,
    x_offset,
    y_offset;

  RectangleInfo
    crop_info;

  register IndexPacket
    *indexes;

  register int
    i;

  static ColormapInfo
    *colormap_info = (ColormapInfo *) NULL;

  static int
    max_windows = 0,
    number_windows = 0;

  static WindowInfo
    *window_info;

  Window
    child,
    root_window;

  XWindowAttributes
    window_attributes;

  /*
    Verify window is viewable.
  */
  assert(display != (Display *) NULL);
  status=XGetWindowAttributes(display,window,&window_attributes);
  if ((status == False) || (window_attributes.map_state != IsViewable))
    return((Image *) NULL);
  /*
    Cropping rectangle is relative to root window.
  */
  root_window=XRootWindow(display,XDefaultScreen(display));
  (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
    &y_offset,&child);
  crop_info.x=x_offset;
  crop_info.y=y_offset;
  crop_info.width=window_attributes.width;
  crop_info.height=window_attributes.height;
  if (borders)
    {
      /*
        Include border in image.
      */
      crop_info.x-=window_attributes.border_width;
      crop_info.y-=window_attributes.border_width;
      crop_info.width+=window_attributes.border_width << 1;
      crop_info.height+=window_attributes.border_width << 1;
    }
  /*
    Crop to root window.
  */
  if (crop_info.x < 0)
    {
      crop_info.width+=crop_info.x;
      crop_info.x=0;
    }
  if (crop_info.y < 0)
    {
      crop_info.height+=crop_info.y;
      crop_info.y=0;
    }
  display_width=XDisplayWidth(display,XDefaultScreen(display));
  if ((int) (crop_info.x+crop_info.width) > display_width)
    crop_info.width=display_width-crop_info.x;
  display_height=XDisplayHeight(display,XDefaultScreen(display));
  if ((int) (crop_info.y+crop_info.height) > display_height)
    crop_info.height=display_height-crop_info.y;
  /*
    Initialize window info attributes.
  */
  if (number_windows >= max_windows)
    {
      /*
        Allocate or resize window info buffer.
      */
      max_windows+=1024;
      if (window_info == (WindowInfo *) NULL)
        window_info=MagickAllocateArray(WindowInfo *,
                                        max_windows,sizeof(WindowInfo));
      else
        MagickReallocMemory(WindowInfo *,window_info,max_windows*sizeof(WindowInfo));
    }
  if (window_info == (WindowInfo *) NULL)
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToReadXImage);
      return((Image *) NULL);
    }
  id=number_windows++;
  window_info[id].window=window;
  window_info[id].visual=window_attributes.visual;
  window_info[id].colormap=window_attributes.colormap;
  window_info[id].bounds.x1=(short) crop_info.x;
  window_info[id].bounds.y1=(short) crop_info.y;
  window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
  window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
  crop_info.x-=x_offset;
  crop_info.y-=y_offset;
  window_info[id].crop_info=crop_info;
  if (level != 0)
    {
      unsigned int
        number_children;

      Window
        *children;

      /*
        Descend the window hierarchy.
      */
      status=XQueryTree(display,window,&root_window,&window_info[id].parent,
        &children,&number_children);
      for (i=0; i < id; i++)
        if ((window_info[i].window == window_info[id].parent) &&
            (window_info[i].visual == window_info[id].visual) &&
            (window_info[i].colormap == window_info[id].colormap))
          if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
              (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
              (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
              (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
            {
              /*
                Eliminate windows not circumscribed by their parent.
              */
              number_windows--;
              break;
            }
      if ((status == True) && (number_children != 0))
        {
          for (i=0; i < (int) number_children; i++)
            (void) MagickXGetWindowImage(display,children[i],False,level+1);
          (void) XFree((void *) children);
        }
    }
  if (level <= 1)
    {
      ColormapInfo
        *next;

      Image
        *composite_image,
        *image;

      int
        y;

      register int
        j,
        x;

      register PixelPacket
        *q;

      register unsigned long
        pixel;

      unsigned int
        import,
        number_colors;

      XColor
        *colors;

      XImage
        *ximage;

      /*
        Get X image for each window in the list.
      */
      image=(Image *) NULL;
      for (id=0; id < number_windows; id++)
      {
        /*
          Does target window intersect top level window?
        */
        import=(window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
          (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
          (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
          (window_info[id].bounds.y1 <= window_info[0].bounds.y2);
        /*
          Is target window contained by another window with the same colormap?
        */
        for (j=0; j < id; j++)
          if ((window_info[id].visual == window_info[j].visual) &&
              (window_info[id].colormap == window_info[j].colormap) &&
              (window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
              (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
              (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
              (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
            import=False;
          else
            if ((window_info[id].visual != window_info[j].visual) ||
                (window_info[id].colormap != window_info[j].colormap))
              if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
                  (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
                  (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
                  (window_info[id].bounds.y1 < window_info[j].bounds.y2))
                import=True;
        if (!import)
          continue;
        /*
          Get X image.
        */
        ximage=XGetImage(display,window_info[id].window,
          (int) window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
          (unsigned int) window_info[id].crop_info.width,
          (unsigned int) window_info[id].crop_info.height,AllPlanes,ZPixmap);
        if (ximage == (XImage *) NULL)
          continue;
        /*
          Initialize window colormap.
        */
        number_colors=0;
        colors=(XColor *) NULL;
        if (window_info[id].colormap != (Colormap) NULL)
          {
            ColormapInfo
              *p;

            /*
              Search colormap list for window colormap.
            */
            number_colors=window_info[id].visual->map_entries;
            for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
              if (p->colormap == window_info[id].colormap)
                break;
            if (p == (ColormapInfo *) NULL)
              {
                /*
                  Get the window colormap.
                */
                colors=MagickAllocateArray(XColor *,number_colors,sizeof(XColor));
                if (colors == (XColor *) NULL)
                  {
                    XDestroyImage(ximage);
                    ximage=(XImage *) NULL;
                    return((Image *) NULL);
                  }
                if ((window_info[id].visual->class != DirectColor) &&
                    (window_info[id].visual->class != TrueColor))
                  for (i=0; i < (int) number_colors; i++)
                  {
                    colors[i].pixel=i;
                    colors[i].pad=0;
                  }
                else
                  {
                    unsigned long
                      blue,
                      blue_bit,
                      green,
                      green_bit,
                      red,
                      red_bit;

                    /*
                      DirectColor or TrueColor visual.
                    */
                    red=0;
                    green=0;
                    blue=0;
                    red_bit=window_info[id].visual->red_mask &
                      (~(window_info[id].visual->red_mask)+1);
                    green_bit=window_info[id].visual->green_mask &
                      (~(window_info[id].visual->green_mask)+1);
                    blue_bit=window_info[id].visual->blue_mask &
                      (~(window_info[id].visual->blue_mask)+1);
                    for (i=0; i < (int) number_colors; i++)
                    {
                      colors[i].pixel=red | green | blue;
                      colors[i].pad=0;
                      red+=red_bit;
                      if (red > window_info[id].visual->red_mask)
                        red=0;
                      green+=green_bit;
                      if (green > window_info[id].visual->green_mask)
                        green=0;
                      blue+=blue_bit;
                      if (blue > window_info[id].visual->blue_mask)
                        blue=0;
                    }
                  }
                (void) XQueryColors(display,window_info[id].colormap,colors,
                 (int) number_colors);
                /*
                  Append colormap to colormap list.
                */
                p=MagickAllocateMemory(ColormapInfo *,sizeof(ColormapInfo));
                if (p == (ColormapInfo *) NULL)
                  return((Image *) NULL);
                p->colormap=window_info[id].colormap;
                p->colors=colors;
                p->next=colormap_info;
                colormap_info=p;
              }
            colors=p->colors;
          }
        /*
          Allocate image structure.
        */
        composite_image=AllocateImage((ImageInfo *) NULL);
        if (composite_image == (Image *) NULL)
          {
            XDestroyImage(ximage);
            ximage=(XImage *) NULL;
            return((Image *) NULL);
          }
        /*
          Convert X image to MIFF format.
        */
        if ((window_info[id].visual->class != TrueColor) &&
            (window_info[id].visual->class != DirectColor))
          composite_image->storage_class=PseudoClass;
        composite_image->columns=ximage->width;
        composite_image->rows=ximage->height;
        switch (composite_image->storage_class)
        {
          case DirectClass:
          default:
          {
            register unsigned long
              color,
              colormap_index;

            unsigned long
              blue_mask,
              blue_shift,
              green_mask,
              green_shift,
              red_mask,
              red_shift;

            /*
              Determine shift and mask for red, green, and blue.
            */
            red_mask=window_info[id].visual->red_mask;
            red_shift=0;
            while ((red_mask & 0x01) == 0)
            {
              red_mask>>=1;
              red_shift++;
            }
            green_mask=window_info[id].visual->green_mask;
            green_shift=0;
            while ((green_mask & 0x01) == 0)
            {
              green_mask>>=1;
              green_shift++;
            }
            blue_mask=window_info[id].visual->blue_mask;
            blue_shift=0;
            while ((blue_mask & 0x01) == 0)
            {
              blue_mask>>=1;
              blue_shift++;
            }
            /*
              Convert X image to DirectClass packets.
            */
            if ((number_colors != 0) &&
                (window_info[id].visual->class == DirectColor))
              for (y=0; y < (long) composite_image->rows; y++)
              {
                q=SetImagePixels(composite_image,0,y,
                  composite_image->columns,1);
                if (q == (PixelPacket *) NULL)
                  break;
                for (x=0; x < (long) composite_image->columns; x++)
                {
                  pixel=XGetPixel(ximage,x,y);
                  colormap_index=(pixel >> red_shift) & red_mask;
                  q->red=ScaleShortToQuantum(colors[colormap_index].red);
                  colormap_index=(pixel >> green_shift) & green_mask;
                  q->green=ScaleShortToQuantum(colors[colormap_index].green);
                  colormap_index=(pixel >> blue_shift) & blue_mask;
                  q->blue=ScaleShortToQuantum(colors[colormap_index].blue);
                  q++;
                }
                if (!SyncImagePixels(composite_image))
                  break;
              }
            else
              for (y=0; y < (long) composite_image->rows; y++)
              {
                q=SetImagePixels(composite_image,0,y,
                  composite_image->columns,1);
                if (q == (PixelPacket *) NULL)
                  break;
                for (x=0; x < (long) composite_image->columns; x++)
                {
                  pixel=XGetPixel(ximage,x,y);
                  color=(pixel >> red_shift) & red_mask;
                  q->red=ScaleShortToQuantum((65535L*color)/red_mask);
                  color=(pixel >> green_shift) & green_mask;
                  q->green=ScaleShortToQuantum((65535L*color)/green_mask);
                  color=(pixel >> blue_shift) & blue_mask;
                  q->blue=ScaleShortToQuantum((65535L*color)/blue_mask);
                  q++;
                }
                if (!SyncImagePixels(composite_image))
                  break;
              }
            break;
          }
          case PseudoClass:
          {
            /*
              Create colormap.
            */
            if ((NULL == colors) ||
                !AllocateImageColormap(composite_image,number_colors))
              {
                XDestroyImage(ximage);
                ximage=(XImage *) NULL;
                DestroyImage(composite_image);
                return((Image *) NULL);
              }
            for (i=0; i < (int) composite_image->colors; i++)
            {
              composite_image->colormap[colors[i].pixel].red=
                ScaleShortToQuantum(colors[i].red);
              composite_image->colormap[colors[i].pixel].green=
                ScaleShortToQuantum(colors[i].green);
              composite_image->colormap[colors[i].pixel].blue=
                ScaleShortToQuantum(colors[i].blue);
            }
            /*
              Convert X image to PseudoClass packets.
            */
            for (y=0; y < (long) composite_image->rows; y++)
            {
              q=SetImagePixels(composite_image,0,y,composite_image->columns,1);
              if (q == (PixelPacket *) NULL)
                break;
              indexes=AccessMutableIndexes(composite_image);
              for (x=0; x < (long) composite_image->columns; x++)
              {
                index_packet=(IndexPacket) XGetPixel(ximage,x,y);
                indexes[x]=index_packet;
                *q++=composite_image->colormap[index_packet];
              }
              if (!SyncImagePixels(composite_image))
                break;
            }
            break;
          }
        }
        XDestroyImage(ximage);
        ximage=(XImage *) NULL;

        /*
          Evaluate image depth.
        */
        composite_image->depth=GetImageDepth(composite_image,&composite_image->exception);
        if (composite_image->depth < 8)
          composite_image->depth=8;

        if (image == (Image *) NULL)
          {
            image=composite_image;
            continue;
          }
        /*
          Composite any children in back-to-front order.
        */
        (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
          &x_offset,&y_offset,&child);
        x_offset-=(int) crop_info.x;
        if (x_offset < 0)
          x_offset=0;
        y_offset-=(int) crop_info.y;
        if (y_offset < 0)
          y_offset=0;
        (void) CompositeImage(image,CopyCompositeOp,composite_image,
          x_offset,y_offset);
      }
      /*
        Free resources.
      */
      while (colormap_info != (ColormapInfo *) NULL)
      {
        next=colormap_info->next;
        MagickFreeMemory(colormap_info->colors);
        MagickFreeMemory(colormap_info);
        colormap_info=next;
      }
      /*
        Free resources and restore initial state.
      */
      MagickFreeMemory(window_info);
      window_info=(WindowInfo *) NULL;
      max_windows=0;
      number_windows=0;
      colormap_info=(ColormapInfo *) NULL;
      return(image);
    }
  return((Image *) NULL);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X G e t W i n d o w I n f o                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXGetWindowInfo initializes the MagickXWindowInfo structure.
%
%  The format of the MagickXGetWindowInfo method is:
%
%      void MagickXGetWindowInfo(Display *display,XVisualInfo *visual_info,
%        XStandardColormap *map_info,MagickXPixelInfo *pixel,
%        XFontStruct *font_info,MagickXResourceInfo *resource_info,
%        MagickXWindowInfo *window)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o map_info: If map_type is specified, this structure is initialized
%      with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%    o font_info: Specifies a pointer to a XFontStruct structure.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
MagickExport void
MagickXGetWindowInfo(Display *display,
                     XVisualInfo *visual_info,
                     XStandardColormap *map_info,
                     MagickXPixelInfo *pixel,
                     XFontStruct *font_info,
                     MagickXResourceInfo *resource_info,
                     MagickXWindowInfo *window)
{
  /*
    Initialize window info.
  */
  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  if (window->id != (Window) NULL)
    {
      (void) XFreeCursor(display,window->cursor);
      (void) XFreeCursor(display,window->busy_cursor);
      if (window->highlight_stipple != (Pixmap) NULL)
        (void) XFreePixmap(display,window->highlight_stipple);
      if (window->shadow_stipple != (Pixmap) NULL)
        (void) XFreePixmap(display,window->shadow_stipple);
    }
  else
    {
      /*
        Initialize these attributes just once.
      */
      window->id=(Window) NULL;
      window->x=XDisplayWidth(display,visual_info->screen) >> 1;
      window->y=XDisplayWidth(display,visual_info->screen) >> 1;
      window->ximage=(XImage *) NULL;
      window->matte_image=(XImage *) NULL;
      window->pixmap=(Pixmap) NULL;
      window->matte_pixmap=(Pixmap) NULL;
      window->mapped=False;
      window->stasis=False;
      window->shared_memory=MagickTrue;
      /* window->segment_info=0; */
#if defined(HasSharedMemory)
      {
        XShmSegmentInfo
          *segment_info;

        if (window->segment_info == (void *) NULL)
          window->segment_info=MagickAllocateArray(void *,2,sizeof(XShmSegmentInfo));
        if (window->segment_info != (void *) NULL)
          {
            segment_info=(XShmSegmentInfo *) window->segment_info;
            segment_info[0].shmid=(-1);
            segment_info[0].shmaddr=NULL;
            segment_info[1].shmid=(-1);
            segment_info[1].shmaddr=NULL;
          }
        else
          {
            window->shared_memory=MagickFalse;
          }
      }
#endif
    }
  /*
    Initialize these attributes every time function is called.
  */
  window->screen=visual_info->screen;
  window->root=XRootWindow(display,visual_info->screen);
  window->visual=visual_info->visual;
  window->storage_class=visual_info->class;
  window->depth=visual_info->depth;
  window->visual_info=visual_info;
  window->map_info=map_info;
  window->pixel_info=pixel;
  window->font_info=font_info;
  window->cursor=XCreateFontCursor(display,XC_left_ptr);
  window->busy_cursor=XCreateFontCursor(display,XC_watch);
  (void) CloneString(&window->name,(char *) NULL);
  window->geometry=(char *) NULL;
  (void) CloneString(&window->icon_name,(char *) NULL);
  window->icon_geometry=resource_info->icon_geometry;
  window->crop_geometry=(char *) NULL;
  window->flags=PSize;
  window->width=1;
  window->height=1;
  window->min_width=1;
  window->min_height=1;
  window->width_inc=1;
  window->height_inc=1;
  window->border_width=resource_info->border_width;
  window->annotate_context=pixel->annotate_context;
  window->highlight_context=pixel->highlight_context;
  window->widget_context=pixel->widget_context;
  window->shadow_stipple=(Pixmap) NULL;
  window->highlight_stipple=(Pixmap) NULL;
  window->use_pixmap=True;
  window->immutable=False;
  window->shape=False;
  window->data=0;
  window->mask=CWBackingStore | CWBackPixel | CWBackPixmap | CWBitGravity |
    CWBorderPixel | CWColormap | CWCursor | CWDontPropagate | CWEventMask |
    CWOverrideRedirect | CWSaveUnder | CWWinGravity;
  window->attributes.background_pixel=pixel->background_color.pixel;
  window->attributes.background_pixmap=(Pixmap) NULL;
  window->attributes.bit_gravity=ForgetGravity;
  window->attributes.backing_store=NotUseful;
  window->attributes.save_under=False;
  window->attributes.border_pixel=pixel->border_color.pixel;
  window->attributes.colormap=map_info->colormap;
  window->attributes.cursor=window->cursor;
  window->attributes.do_not_propagate_mask=NoEventMask;
  window->attributes.event_mask=NoEventMask;
  window->attributes.override_redirect=False;
  window->attributes.win_gravity=NorthWestGravity;
  window->orphan=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X H i g h l i g h t E l l i p s e                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXHighlightEllipse puts a border on the X server around a region
%  defined by highlight_info.
%
%  The format of the MagickXHighlightEllipse method is:
%
%      void MagickXHighlightEllipse(Display *display,Window window,
%        GC annotate_context,const RectangleInfo *highlight_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o annotate_context: Specifies a pointer to a GC structure.
%
%    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any highlighting rectangle.
%
%
*/
MagickExport void
MagickXHighlightEllipse(Display *display,Window window,
                        GC annotate_context,
                        const RectangleInfo *highlight_info)
{
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(annotate_context != (GC) NULL);
  assert(highlight_info != (RectangleInfo *) NULL);
  if ((highlight_info->width < 4) || (highlight_info->height < 4))
    return;
  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
    (int) highlight_info->y,(unsigned int) highlight_info->width-1,
    (unsigned int) highlight_info->height-1,0,360*64);
  (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
    (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
    (unsigned int) highlight_info->height-3,0,360*64);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X H i g h l i g h t L i n e                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXHighlightLine puts a border on the X server around a region
%  defined by highlight_info.
%
%  The format of the MagickXHighlightLine method is:
%
%      void MagickXHighlightLine(Display *display,Window window,
%        GC annotate_context,const XSegment *highlight_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o annotate_context: Specifies a pointer to a GC structure.
%
%    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any highlighting rectangle.
%
%
*/
MagickExport void
MagickXHighlightLine(Display *display,Window window,
                     GC annotate_context,const XSegment *highlight_info)
{
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(annotate_context != (GC) NULL);
  assert(highlight_info != (XSegment *) NULL);
  (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
    highlight_info->y1,highlight_info->x2,highlight_info->y2);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X H i g h l i g h t R e c t a n g l e                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXHighlightRectangle puts a border on the X server around a
%  region defined by highlight_info.
%
%  The format of the MagickXHighlightRectangle method is:
%
%      void MagickXHighlightRectangle(Display *display,Window window,
%        GC annotate_context,const RectangleInfo *highlight_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window structure.
%
%    o annotate_context: Specifies a pointer to a GC structure.
%
%    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any highlighting rectangle.
%
%
*/
MagickExport void
MagickXHighlightRectangle(Display *display,Window window,
                          GC annotate_context,
                          const RectangleInfo *highlight_info)
{
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(annotate_context != (GC) NULL);
  assert(highlight_info != (RectangleInfo *) NULL);
  if ((highlight_info->width < 4) || (highlight_info->height < 4))
    return;
  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
    (int) highlight_info->y,(unsigned int) highlight_info->width-1,
    (unsigned int) highlight_info->height-1);
  (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
    1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
    (unsigned int) highlight_info->height-3);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X I m p o r t I m a g e                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Procedure MagickXImportImage reads an image from an X window.
%
%  The format of the MagickXImportImage method is:
%
%      Image *MagickXImportImage(const ImageInfo *image_info,
%        MagickXImportInfo *ximage_info)
%
%  A description of each parameter follows:
%
%    o image_info: The image info..
%
%    o ximage_info: Specifies a pointer to an MagickXImportInfo structure.
%
%
*/
MagickExport Image *
MagickXImportImage(const ImageInfo *image_info,
                   MagickXImportInfo *ximage_info)
{
  Colormap
    *colormaps;

  Display
    *display;

  Image
    *image;

  int
    number_colormaps,
    number_windows,
    status,
    x;

  RectangleInfo
    crop_info;

  Window
    *children,
    client,
    prior_target,
    root,
    target;

  XTextProperty
    window_name;

  /*
    Open X server connection.
  */
  assert(image_info != (ImageInfo *) NULL);
  assert(ximage_info != (MagickXImportInfo *) NULL);
  display=XOpenDisplay(image_info->server_name);
  if (display == (Display *) NULL)
    {
      MagickError(XServerError,UnableToOpenXServer,
        XDisplayName(image_info->server_name));
      return((Image *) NULL);
    }
  /*
    Set our forgiving error handler.
  */
  (void) XSetErrorHandler(MagickXError);
  /*
    Select target window.
  */
  crop_info.x=0;
  crop_info.y=0;
  crop_info.width=0;
  crop_info.height=0;
  root=XRootWindow(display,XDefaultScreen(display));
  target=(Window) NULL;
  if (image_info->filename[0] != '\0')
    {
      if (LocaleCompare(image_info->filename,"root") == 0)
        target=root;
      else
        {
          /*
            Select window by ID or name.
          */
          if (isdigit((int) (*image_info->filename)))
            target=MagickXWindowByID(display,root,(Window)
              strtol(image_info->filename,(char **) NULL,0));
          if (target == (Window) NULL)
            target=MagickXWindowByName(display,root,image_info->filename);
          if (target == (Window) NULL)
            MagickError(XServerError,NoWindowWithSpecifiedIDExists,
              image_info->filename);
        }
    }
  /*
    If target window is not defined, interactively select one.
  */
  prior_target=target;
  if (target == (Window) NULL)
    target=MagickXSelectWindow(display,&crop_info);
  client=target;   /* obsolete */
  if (target != root)
    {
      unsigned int
        d;

      status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
      if (status != 0)
        {
          for ( ; ; )
          {
            Window
              parent;

            /*
              Find window manager frame.
            */
            status=XQueryTree(display,target,&root,&parent,&children,&d);
            if (status && (children != (Window *) NULL))
              (void) XFree((char *) children);
            if (!status || (parent == (Window) NULL) || (parent == root))
              break;
            target=parent;
          }
          /*
            Get client window.
          */
          client=MagickXClientWindow(display,target);
          if (!ximage_info->frame)
            target=client;
          if (!ximage_info->frame && prior_target)
            target=prior_target;
          (void) XRaiseWindow(display,target);
          MagickXDelay(display,SuspendTime << 4);
        }
    }
  if (ximage_info->screen)
    {
      int
        y;

      Window
        child;

      XWindowAttributes
        window_attributes;

      /*
        Obtain window image directly from screen.
      */
      status=XGetWindowAttributes(display,target,&window_attributes);
      if (status == False)
        {
          MagickError(XServerError,UnableToReadXAttributes,
            image_info->filename);
          (void) XCloseDisplay(display);
          return((Image *) NULL);
        }
      (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
      crop_info.x=x;
      crop_info.y=y;
      crop_info.width=window_attributes.width;
      crop_info.height=window_attributes.height;
      if (ximage_info->borders)
        {
          /*
            Include border in image.
          */
          crop_info.x-=window_attributes.border_width;
          crop_info.y-=window_attributes.border_width;
          crop_info.width+=window_attributes.border_width << 1;
          crop_info.height+=window_attributes.border_width << 1;
        }
      target=root;
    }
  /*
    If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
  */
  number_windows=0;
  status=XGetWMColormapWindows(display,target,&children,&number_windows);
  if ((status == True) && (number_windows > 0))
    {
      ximage_info->descend=True;
      (void) XFree ((char *) children);
    }
  colormaps=XListInstalledColormaps(display,target,&number_colormaps);
  if (number_colormaps > 0)
    {
      if (number_colormaps > 1)
        ximage_info->descend=True;
      (void) XFree((char *) colormaps);
    }
  /*
    Alert the user not to alter the screen.
  */
  if (!ximage_info->silent)
    (void) XBell(display,0);
  /*
    Get image by window id.
  */
  (void) XGrabServer(display);
  image=MagickXGetWindowImage(display,target,ximage_info->borders,
    ximage_info->descend ? 1 : 0);
  (void) XUngrabServer(display);
  if (image == (Image *) NULL)
    MagickError(XServerError,UnableToReadXWindowImage,image_info->filename);
  else
    {
      (void) strlcpy(image->filename,image_info->filename,MaxTextExtent);
      if ((crop_info.width != 0) && (crop_info.height != 0))
        {
          Image
            *clone_image,
            *crop_image;

          /*
            Crop image as defined by the cropping rectangle.
          */
          clone_image=CloneImage(image,0,0,True,&image->exception);
          if (clone_image != (Image *) NULL)
            {
              crop_image=CropImage(clone_image,&crop_info,&image->exception);
              if (crop_image != (Image *) NULL)
                {
                  DestroyImage(image);
                  image=crop_image;
                }
            }
        }
      status=XGetWMName(display,target,&window_name);
      if (status == True)
        {
          if (image_info->filename[0] == '\0')
            {
              /*
                Initialize image filename.
              */
              (void) strlcpy(image->filename,(char *) window_name.value,
                (int) window_name.nitems+1);
              image->filename[window_name.nitems]='\0';
            }
          (void) XFree((void *) window_name.value);
        }
    }
  if (!ximage_info->silent)
    {
      /*
        Alert the user we're done.
      */
      (void) XBell(display,0);
      (void) XBell(display,0);
    }
  (void) XCloseDisplay(display);
  StopTimer(&image->timer);
  return(image);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X I n i t i a l i z e W i n d o w s                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXInitializeWindows initializes the MagickXWindows structure.
%
%  The format of the MagickXInitializeWindows method is:
%
%      MagickXWindows *MagickXInitializeWindows(Display *display,
%        MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o windows: MagickXInitializeWindows returns a pointer to a
%      MagickXWindows structure.
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
*/
MagickExport MagickXWindows *
MagickXInitializeWindows(Display *display,
                         MagickXResourceInfo *resource_info)
{
  Window
    root_window;

  MagickXWindows
    *windows;

  /*
    Allocate windows structure.
  */
  windows=MagickAllocateMemory(MagickXWindows *,sizeof(MagickXWindows));
  if (windows == (MagickXWindows *) NULL)
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToCreateXWindow);
      return((MagickXWindows *) NULL);
    }
  (void) memset(windows,0,sizeof(MagickXWindows));
  windows->pixel_info=MagickAllocateMemory(MagickXPixelInfo *,sizeof(MagickXPixelInfo));
  windows->icon_pixel=MagickAllocateMemory(MagickXPixelInfo *,sizeof(MagickXPixelInfo));
  windows->icon_resources=MagickAllocateMemory(MagickXResourceInfo *,
    sizeof(MagickXResourceInfo));
  if ((windows->pixel_info == (MagickXPixelInfo *) NULL) ||
      (windows->icon_pixel == (MagickXPixelInfo *) NULL) ||
      (windows->icon_resources == (MagickXResourceInfo *) NULL))
    {
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
        UnableToCreateXWindow);
      return((MagickXWindows *) NULL);
    }
  /*
    Initialize windows structure.
  */
  windows->display=display;
  windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",False);
  windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",False);
  windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",False);
  windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",False);
  windows->im_remote_command=XInternAtom(display,"IM_REMOTE_COMMAND",False);
  windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",False);
  windows->im_update_colormap=
    XInternAtom(display,"IM_UPDATE_COLORMAP",False);
  windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",False);
  windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",False);
  windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",False);
  windows->im_exit=XInternAtom(display,"IM_EXIT",False);
  windows->dnd_protocols=XInternAtom(display,"DndProtocol",False);
#if defined(MSWINDOWS)
  (void) XSynchronize(display,IsWindows95());
#endif
  if (IsEventLogged(X11Event))
    {
      (void) XSynchronize(display,True);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %.1024s",
        GetMagickVersion((unsigned long *) NULL));
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  Window Manager: 0x%lx",
        windows->wm_protocols);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    delete window: 0x%lx",
        windows->wm_delete_window);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    take focus: 0x%lx",
        windows->wm_take_focus);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  GraphicsMagick: 0x%lx",
        windows->im_protocols);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    remote command: 0x%lx",
        windows->im_remote_command);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    update widget: 0x%lx",
        windows->im_update_widget);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "    update colormap: 0x%lx",windows->im_update_colormap);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    former image: 0x%lx",
        windows->im_former_image);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    next image: 0x%lx",
        windows->im_next_image);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    retain colors: 0x%lx",
        windows->im_retain_colors);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"    exit: 0x%lx",
        windows->im_exit);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  Drag and Drop: 0x%lx",
        windows->dnd_protocols);
    }
  /*
    Allocate standard colormap.
  */
  windows->map_info=XAllocStandardColormap();
  windows->icon_map=XAllocStandardColormap();
  if ((windows->map_info == (XStandardColormap *) NULL) ||
      (windows->icon_map == (XStandardColormap *) NULL))
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToCreateStandardColormap));
  windows->map_info->colormap=(Colormap) NULL;
  windows->icon_map->colormap=(Colormap) NULL;
  (void) memset((void *) windows->pixel_info, 0, sizeof(MagickXPixelInfo));
  windows->pixel_info->pixels=(unsigned long *) NULL;
  windows->pixel_info->annotate_context=(GC) NULL;
  windows->pixel_info->highlight_context=(GC) NULL;
  windows->pixel_info->widget_context=(GC) NULL;
  windows->font_info=(XFontStruct *) NULL;
  (void) memset((void *) windows->icon_pixel, 0, sizeof(MagickXPixelInfo));
  windows->icon_pixel->annotate_context=(GC) NULL;
  windows->icon_pixel->pixels=(unsigned long *) NULL;
  windows->icon_pixel->highlight_context=(GC) NULL;
  /*
    Allocate visual.
  */
  *windows->icon_resources=(*resource_info);
  windows->icon_resources->map_type=(char *) NULL;
  windows->icon_resources->visual_type=(char *) "default";
  windows->icon_resources->colormap=SharedColormap;
  windows->visual_info=
    MagickXBestVisualInfo(display,windows->map_info,resource_info);
  windows->icon_visual=
    MagickXBestVisualInfo(display,windows->icon_map,windows->icon_resources);
  if ((windows->visual_info == (XVisualInfo *) NULL) ||
      (windows->icon_visual == (XVisualInfo *) NULL))
    MagickFatalError(XServerFatalError,UnableToGetVisual,
      resource_info->visual_type);
  if (IsEventLogged(X11Event))
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  visual id: 0x%lx",
        windows->visual_info->visualid);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  class: %.1024s",
        MagickXVisualClassName(windows->visual_info->class));
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d planes",
        windows->visual_info->depth);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  size of colormap: %d entries",windows->visual_info->colormap_size);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",
        windows->visual_info->red_mask,windows->visual_info->green_mask,
        windows->visual_info->blue_mask);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  significant bits in color: %d bits",
        windows->visual_info->bits_per_rgb);
    }
  /*
    Allocate class and manager hints.
  */
  windows->class_hints=XAllocClassHint();
  windows->manager_hints=XAllocWMHints();
  if ((windows->class_hints == (XClassHint *) NULL) ||
      (windows->manager_hints == (XWMHints *) NULL))
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToAllocateXHints));
  /*
    Determine group leader if we have one.
  */
  root_window=XRootWindow(display,windows->visual_info->screen);
  windows->group_leader.id=(Window) NULL;
  if (resource_info->window_group != (char *) NULL)
    {
      if (isdigit((int) (*resource_info->window_group)))
        windows->group_leader.id=MagickXWindowByID(display,root_window,(Window)
          strtol((char *) resource_info->window_group,(char **) NULL,0));
      if (windows->group_leader.id == (Window) NULL)
        windows->group_leader.id=
          MagickXWindowByName(display,root_window,resource_info->window_group);
    }
  return(windows);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e C u r s o r                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeCursor creates a crosshairs X11 cursor.
%
%  The format of the MagickXMakeCursor method is:
%
%      Cursor MagickXMakeCursor(Display *display,Window window,
%        Colormap colormap,char *background_color,char *foreground_color)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies the ID of the window for which the cursor is
%      assigned.
%
%    o colormap: Specifies the ID of the colormap from which the background
%      and foreground color will be retrieved.
%
%    o background_color: Specifies the color to use for the cursor background.
%
%    o foreground_color: Specifies the color to use for the cursor foreground.
%
%
*/
MagickExport Cursor
MagickXMakeCursor(Display *display,Window window,
                  Colormap colormap,char *background_color,
                  char *foreground_color)
{
#define scope_height 17
#define scope_x_hot 8
#define scope_y_hot 8
#define scope_width 17

  static const unsigned char
    scope_bits[] =
    {
      0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
      0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
      0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
      0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
      0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
    },
    scope_mask_bits[] =
    {
      0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
      0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
      0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
      0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
      0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
    };

  Cursor
    cursor;

  Pixmap
    mask,
    source;

  XColor
    background,
    foreground;

  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(colormap != (Colormap) NULL);
  assert(background_color != (char *) NULL);
  assert(foreground_color != (char *) NULL);
  source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
    scope_height);
  mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
    scope_width,scope_height);
  if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
    {
      MagickError(XServerError,UnableToCreatePixmap,(char *) NULL);
      return((Cursor) NULL);
    }
  (void) XParseColor(display,colormap,background_color,&background);
  (void) XParseColor(display,colormap,foreground_color,&foreground);
  cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
    scope_x_hot,scope_y_hot);
  (void) XFreePixmap(display,source);
  (void) XFreePixmap(display,mask);
  return(cursor);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e I m a g e                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeImage creates an X11 image.  If the image size differs
%  from the X11 image size, the image is first resized.
%
%  The format of the MagickXMakeImage method is:
%
%      unsigned int MagickXMakeImage(Display *display,
%        const MagickXResourceInfo *resource_info,MagickXWindowInfo *window,
%        Image *image,unsigned int width,unsigned int height)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXMakeImage returns True if the X image is
%      successfully created.  False is returned is there is a memory shortage.
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o width: Specifies the width in pixels of the rectangular area to
%      display.
%
%    o height: Specifies the height in pixels of the rectangular area to
%      display.
%
%
*/
static const char *
MagickXImageFormatToString(int xformat)
{
  static const char
    *formats[] =
    {
      "XYBitmap",
      "XYPixmap",
      "ZPixmap"
    };

  const char
    *format = "Unknown";

  if ((size_t) xformat < sizeof(formats)/sizeof(formats[0]))
    format=formats[xformat];

  return format;
}
static const char *
MagickXByteOrderToString(int xbyte_order)
{
  static const char
    *byte_orders[] =
    {
      "LSBFirst",
      "MSBFirst"
    };

  const char
    *byte_order = "Unknown";

  if ((size_t) xbyte_order < sizeof(byte_orders)/sizeof(byte_orders[0]))
    byte_order=byte_orders[xbyte_order];

  return byte_order;
}
MagickExport unsigned int
MagickXMakeImage(Display *display,
                 const MagickXResourceInfo *resource_info,
                 MagickXWindowInfo *window,
                 Image *image,
                 unsigned int width,unsigned int height)
{
  int
    depth,
    format;

  size_t
    length;

  XImage
    *matte_image,
    *ximage;

  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(width != 0);
  assert(height != 0);
  if ((window->width == 0) || (window->height == 0))
    return(False);
  /*
    Apply user transforms to the image.
  */
  (void) XDefineCursor(display,window->id,window->busy_cursor);
  (void) XFlush(display);
  depth=window->depth;
  if (window->destroy && window->image)
    DestroyImage(window->image);
  window->image=image;
  window->destroy=False;
  if (window->image != (Image *) NULL)
    {
      MonitorHandler
        handler=(MonitorHandler) NULL;

      handler=SetMonitorHandler((MonitorHandler) NULL);
      if (window->crop_geometry)
        {
          Image
            *crop_image;

          RectangleInfo
            crop_info;

          /*
            Crop image.
          */
          SetGeometry(window->image,&crop_info);
          (void) GetGeometry(window->crop_geometry,&crop_info.x,&crop_info.y,
            &crop_info.width,&crop_info.height);
          crop_image=CropImage(window->image,&crop_info,&image->exception);
          if (crop_image != (Image *) NULL)
            {
              if (window->image != image)
                DestroyImage(window->image);
              window->image=crop_image;
              window->destroy=MagickTrue;
            }
        }
      if ((width != (unsigned int) window->image->columns) ||
          (height != (unsigned int) window->image->rows))
        {
          Image
            *resize_image;

          /*
            Resize image.
          */
          resize_image=(Image *) NULL;
          if ((window->pixel_info->colors != 0) ||
              (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) ||
              (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
            {
              /*
                The resized image should be in the same storage class
                as the original (or bad things will happen).
              */
              if (window->image->storage_class == PseudoClass)
                resize_image=SampleImage(window->image,width,height,
                                         &image->exception);
              else
                resize_image=ThumbnailImage(window->image,width,height,
                                            &image->exception);
            }
          else
            {
              resize_image=ZoomImage(window->image,width,height,
                                     &image->exception);
            }
          if (resize_image != (Image *) NULL)
            {
              if (window->image != image)
                DestroyImage(window->image);
              window->image=resize_image;
              window->destroy=MagickTrue;
            }
        }
      if ((window->image->matte != MagickFalse) &&
          (window->pixel_info->colors == 0)
          /* && (window->immutable == MagickFalse) */)
        {
          Image
            *texture;

          /*
            Tile background with texture according to opacity
          */
          strlcpy(resource_info->image_info->filename,"image:checkerboard",
                  sizeof(resource_info->image_info->filename));
          texture=ReadImage(resource_info->image_info,&window->image->exception);
          if (texture != (Image *) NULL)
            {
              Image
                *textured_image;

              textured_image=CloneImage(window->image,0,0,MagickTrue,
                                        &window->image->exception);
              if (textured_image != (Image *) NULL)
                {
                  if (TextureImage(textured_image,texture) != MagickFail)
                    {
                      if (window->image != image)
                        DestroyImage(window->image);
                      window->image=textured_image;
                      window->destroy=MagickTrue;
                    }
                  else
                    {
                      DestroyImage(textured_image);
                    }
                }
              DestroyImage(texture);
              texture=(Image *) NULL;
            }
          }
      width=(unsigned int) window->image->columns;
      assert(width == window->image->columns);
      height=(unsigned int) window->image->rows;
      assert(height == window->image->rows);
      (void) SetMonitorHandler(handler);
    }
  /*
    Create X image.
  */
  ximage=(XImage *) NULL;
  format=(depth == 1) ? XYBitmap : ZPixmap;
#if defined(HasSharedMemory)
  window->shared_memory &= XShmQueryExtension(display);
  if (window->shared_memory)
    {
      XShmSegmentInfo
        *segment_info;

      size_t
        shm_extent;

      segment_info=(XShmSegmentInfo *) window->segment_info;
      segment_info[1].shmid=(-1);
      segment_info[1].shmaddr=NULL;
      shm_extent=0;
      ximage=XShmCreateImage(display,window->visual,depth,format,(char *) NULL,
                             &segment_info[1],width,height);
      window->shared_memory &= (ximage != (XImage *) NULL);

      if (window->shared_memory)
        {
          shm_extent=MagickArraySize(ximage->height,ximage->bytes_per_line);
          window->shared_memory &= (shm_extent != 0);
        }

      if (window->shared_memory)
        segment_info[1].shmid=shmget(IPC_PRIVATE,shm_extent,IPC_CREAT | 0777);
      window->shared_memory &= (segment_info[1].shmid >= 0);

      if (window->shared_memory)
        segment_info[1].shmaddr=(char *) MagickShmAt(segment_info[1].shmid,0,0);
      window->shared_memory &= (segment_info[1].shmaddr != NULL);

      if (!window->shared_memory)
        {
          /*
            Clean up if there is an error.
          */
          if (ximage != (XImage *) NULL)
            {
              XDestroyImage(ximage);
              ximage=(XImage *) NULL;
            }

          if (segment_info[1].shmaddr)
            {
              (void) MagickShmDt(segment_info[1].shmaddr);
              segment_info[1].shmaddr=NULL;
            }

          if (segment_info[1].shmid >= 0)
            {
              (void) MagickShmCtl(segment_info[1].shmid,IPC_RMID,0);
              segment_info[1].shmid=(-1);
            }
        }
    }
#endif
  /*
    Allocate X image pixel data.
  */
#if defined(HasSharedMemory)
  if (window->shared_memory)
    {
      XShmSegmentInfo
        *segment_info;

      Status
        shm_attached;

      (void) XSync(display,False);
      xerror_alert=False;
      segment_info=(XShmSegmentInfo *) window->segment_info;
      ximage->data=segment_info[1].shmaddr;
      segment_info[1].readOnly=False;
      shm_attached=XShmAttach(display,&segment_info[1]);
      if (shm_attached)
        (void) XSync(display,False);
      if (!shm_attached || xerror_alert)
        {
          window->shared_memory=False;
          if (shm_attached)
            (void) XShmDetach(display,&segment_info[1]);
          ximage->data=NULL;
          XDestroyImage(ximage);
          ximage=(XImage *) NULL;
          if (segment_info[1].shmid >= 0)
            {
              if (segment_info[1].shmaddr != NULL)
                (void) MagickShmDt(segment_info[1].shmaddr);
              (void) MagickShmCtl(segment_info[1].shmid,IPC_RMID,0);
              segment_info[1].shmaddr=NULL;
              segment_info[1].shmid=(-1);
            }
        }
    }
#endif
  if (!window->shared_memory)
    {
      ximage=XCreateImage(display,window->visual,depth,format,0,(char *) NULL,
        width,height,XBitmapPad(display),0);
    }
  if (ximage == (XImage *) NULL)
    {
      /*
        Unable to create X image.
      */
      (void) XDefineCursor(display,window->id,window->cursor);
      return(False);
    }
  if (IsEventLogged(X11Event))
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  width x height: %dx%d",
        ximage->width,ximage->height);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  format: %s",
                            MagickXImageFormatToString(ximage->format));
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  byte order: %s",
                            MagickXByteOrderToString(ximage->byte_order));
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
        ximage->bitmap_bit_order,ximage->bitmap_pad);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d",
        ximage->depth);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  bytes per line: %d",
        ximage->bytes_per_line);
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  bits per pixel: %d",
        ximage->bits_per_pixel);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
        ximage->green_mask,ximage->blue_mask);
    }
  if (!window->shared_memory)
    {
      if (ximage->format == XYBitmap)
        {
          ximage->data=
            MagickAllocateArray(char *,
                                MagickArraySize(ximage->height,
                                                ximage->bytes_per_line),
                                ximage->depth);
          if (ximage->data != (char *) NULL)
            (void) memset(ximage->data,0,
                          (size_t) ximage->height*ximage->bytes_per_line*
                          ximage->depth);
        }
      else
        {
          ximage->data=
            MagickAllocateArray(char *,ximage->height,ximage->bytes_per_line);
          if (ximage->data != (char *) NULL)
            (void) memset(ximage->data,0,
                          (size_t) ximage->height*ximage->bytes_per_line);
        }
    }
  if (ximage->data == (char *) NULL)
    {
      /*
        Unable to allocate pixel data.
      */
      XDestroyImage(ximage);
      ximage=(XImage *) NULL;
      (void) XDefineCursor(display,window->id,window->cursor);
      return(False);
    }
  if (window->ximage != (XImage *) NULL)
    {
      /*
        Destroy previous X image.
      */
      /* length=(size_t) window->ximage->bytes_per_line*window->ximage->height; */
#if defined(HasSharedMemory)
      if (window->segment_info != (XShmSegmentInfo *) NULL)
        {
          XShmSegmentInfo
            *segment_info;

          segment_info=(XShmSegmentInfo *) window->segment_info;
          if (segment_info[0].shmid >= 0)
            {
              (void) XSync(display,False);
              (void) XShmDetach(display,&segment_info[0]);
              (void) XSync(display,False);
              if (segment_info[0].shmaddr != NULL)
                (void) MagickShmDt(segment_info[0].shmaddr);
              (void) MagickShmCtl(segment_info[0].shmid,IPC_RMID,0);
              segment_info[0].shmaddr=NULL;
              segment_info[0].shmid=(-1);
              window->ximage->data=(char *) NULL;
            }
        }
#endif
      MagickFreeMemory(window->ximage->data);
      XDestroyImage(window->ximage);
      window->ximage=(XImage *) NULL;
    }
#if defined(HasSharedMemory)
  if (window->segment_info != (XShmSegmentInfo *) NULL)
    {
      XShmSegmentInfo
        *segment_info;

      segment_info=(XShmSegmentInfo *) window->segment_info;
      segment_info[0]=segment_info[1];
    }
#endif
  window->ximage=ximage;
  matte_image=(XImage *) NULL;
  if (window->shape && (window->image != (Image *) NULL))
    if (window->image->matte &&
        (width <= (unsigned int) XDisplayWidth(display,window->screen)) &&
        (height <= (unsigned int) XDisplayHeight(display,window->screen)))
      {
        /*
          Create matte image.
        */
        matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
          (char *) NULL,width,height,XBitmapPad(display),0);
        if (IsEventLogged(X11Event))
          {
            (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
            (void) LogMagickEvent(X11Event,GetMagickModule(),
              "  width, height: %dx%d",matte_image->width,matte_image->height);
          }
        if (matte_image != (XImage *) NULL)
          {
            /*
              Allocate matte image pixel data.
            */
            length=MagickArraySize(MagickArraySize(matte_image->bytes_per_line,
                                                   matte_image->height),
                                   matte_image->depth);
            matte_image->data=MagickAllocateMemory(char *,length);
            if (matte_image->data == (char *) NULL)
              {
                XDestroyImage(matte_image);
                matte_image=(XImage *) NULL;
              }
          }
      }
  if (window->matte_image != (XImage *) NULL)
    {
      /*
        Free matte image.
      */
      MagickFreeMemory(window->matte_image->data);
      XDestroyImage(window->matte_image);
      window->matte_image=(XImage *) NULL;
    }
  window->matte_image=matte_image;
  if (window->matte_pixmap != (Pixmap) NULL)
    {
      (void) XFreePixmap(display,window->matte_pixmap);
      window->matte_pixmap=(Pixmap) NULL;
#if defined(HasShape)
      if (window->shape)
        XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
#endif
    }
  window->stasis=False;
  /*
    Convert pixels to X image data.
  */
  if (window->image != (Image *) NULL)
    {
      if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
          (ximage->bitmap_bit_order == LSBFirst)))
        MagickXMakeImageLSBFirst(resource_info,window,window->image,ximage,
          matte_image);
      else
        MagickXMakeImageMSBFirst(resource_info,window,window->image,ximage,
          matte_image);
    }
  if (window->matte_image != (XImage *) NULL)
    {
      /*
        Create matte pixmap.
      */
      window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
      if (window->matte_pixmap != (Pixmap) NULL)
        {
          GC
            graphics_context;

          XGCValues
            context_values;

          /*
            Copy matte image to matte pixmap.
          */
          context_values.background=1;
          context_values.foreground=0;
          graphics_context=XCreateGC(display,window->matte_pixmap,
            GCBackground | GCForeground,&context_values);
          (void) XPutImage(display,window->matte_pixmap,graphics_context,
            window->matte_image,0,0,0,0,width,height);
          (void) XFreeGC(display,graphics_context);
#if defined(HasShape)
          if (window->shape)
            XShapeCombineMask(display,window->id,ShapeBounding,0,0,
              window->matte_pixmap,ShapeSet);
#endif
        }
      }
  (void) MagickXMakePixmap(display,resource_info,window);
  /*
    Restore cursor.
  */
  (void) XDefineCursor(display,window->id,window->cursor);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X M a k e I m a g e L S B F i r s t                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeImageLSBFirst initializes the pixel data of an X11 Image.
%  The X image pixels are copied in least-significant bit and byte first
%  order.  The server's scanline pad is respected.  Rather than using one or
%  two general cases, many special cases are found here to help speed up the
%  image conversion.
%
%  The format of the MagickXMakeImageLSBFirst method is:
%
%      void MagickXMakeMagnifyImage(Display *display,MagickXWindows *windows)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo structure.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o ximage: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%    o matte_image: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
*/
static void
MagickXMakeImageLSBFirst(const MagickXResourceInfo *resource_info,
                         const MagickXWindowInfo *window,Image *image,
                         XImage *ximage,XImage *matte_image)
{
  int
    y;

  register const IndexPacket
    *indexes;

  register int
    x;

  register const PixelPacket
    *p;

  register unsigned char
    *q;

  unsigned char
    bit,
    byte;

  unsigned int
    scanline_pad;

  unsigned long
    pixel,
    *pixels;

  XStandardColormap
    *map_info;

  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(image != (Image *) NULL);
  scanline_pad=ximage->bytes_per_line-
    ((ximage->width*ximage->bits_per_pixel) >> 3);
  map_info=window->map_info;
  pixels=window->pixel_info->pixels;
  q=(unsigned char *) ximage->data;
  x=0;
  if (ximage->format == XYBitmap)
    {
      register unsigned short
        polarity;

      unsigned char
        background,
        foreground;

      /*
        Convert image to big-endian bitmap.
      */
      background=(PixelIntensity(&window->pixel_info->foreground_color) <
        PixelIntensity(&window->pixel_info->background_color) ?  0x80 : 0x00);
      foreground=(PixelIntensity(&window->pixel_info->background_color) <
        PixelIntensity(&window->pixel_info->foreground_color) ?  0x80 : 0x00);
      polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
      if (image->colors == 2)
        polarity=PixelIntensity(&image->colormap[0]) <
          PixelIntensity(&image->colormap[1]);
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        indexes=AccessImmutableIndexes(image);
        bit=0;
        byte=0;
        for (x=0; x < (long) image->columns; x++)
        {
          byte>>=1;
          if (indexes[x] == polarity)
            byte|=foreground;
          else
            byte|=background;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
        }
        if (bit != 0)
          *q=byte >> (8-bit);
        q+=scanline_pad;
      }
    }
  else
    if (window->pixel_info->colors != 0)
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to 2 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]] & 0x0f;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) (pixel << 6);
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]] & 0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to 8 bit color-mapped X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]];
              *q++=(unsigned char) pixel;
            }
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          register int
            k;

          register unsigned int
            bytes_per_pixel;

          /*
            Convert to multi-byte color-mapped X image.
          */
          bytes_per_pixel=ximage->bits_per_pixel >> 3;
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=pixels[indexes[x]];
              for (k=0; k < (int) bytes_per_pixel; k++)
              {
                *q++=(unsigned char) pixel;
                pixel>>=8;
              }
            }
            q+=scanline_pad;
          }
          break;
        }
      }
    else
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to contiguous 2 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            nibble=0;
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) (pixel << 6);
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to contiguous 4 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            nibble=0;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) pixel;
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to contiguous 8 bit continuous-tone X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            for (x=0; x < (long) image->columns; x++)
            {
              pixel=MagickXGammaPixel(map_info,p);
              *q++=(unsigned char) pixel;
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
              (map_info->green_max == 255) && (map_info->blue_max == 255) &&
              (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
              (map_info->blue_mult == 1))
            {
              /*
                Convert to 32 bit continuous-tone X image.
              */
              for (y=0; y < (long) image->rows; y++)
              {
                p=AcquireImagePixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                    (blue_gamma != 1.0))
                  {
                    /*
                      Gamma correct image.
                    */
                    for (x=(long) image->columns; x > 0; x--)
                    {
                      *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                      *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                      *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                      *q++=0;
                      p++;
                    }
                    continue;
                  }
                for (x=(long) image->columns; x > 0; x--)
                {
                  *q++=ScaleQuantumToChar((Quantum) p->blue);
                  *q++=ScaleQuantumToChar((Quantum) p->green);
                  *q++=ScaleQuantumToChar((Quantum) p->red);
                  *q++=0;
                  p++;
                }
              }
            }
          else
            if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
                (map_info->green_max == 255) && (map_info->blue_max == 255) &&
                (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
                (map_info->blue_mult == 65536L))
              {
                /*
                  Convert to 32 bit continuous-tone X image.
                */
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (const PixelPacket *) NULL)
                    break;
                  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                      (blue_gamma != 1.0))
                    {
                      /*
                        Gamma correct image.
                      */
                      for (x=(long) image->columns; x > 0; x--)
                      {
                        *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                        *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                        *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                        *q++=0;
                        p++;
                      }
                      continue;
                    }
                  for (x=(long) image->columns; x > 0; x--)
                  {
                    *q++=ScaleQuantumToChar((Quantum) p->red);
                    *q++=ScaleQuantumToChar((Quantum) p->green);
                    *q++=ScaleQuantumToChar((Quantum) p->blue);
                    *q++=0;
                    p++;
                  }
                }
              }
            else
              {
                register int
                  k;

                register unsigned int
                  bytes_per_pixel;

                /*
                  Convert to multi-byte continuous-tone X image.
                */
                bytes_per_pixel=ximage->bits_per_pixel >> 3;
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (PixelPacket *) NULL)
                    break;
                  for (x=0; x < (long) image->columns; x++)
                  {
                    pixel=MagickXGammaPixel(map_info,p);
                    for (k=0; k < (int) bytes_per_pixel; k++)
                    {
                      *q++=(unsigned char) pixel;
                      pixel>>=8;
                    }
                    p++;
                  }
                  q+=scanline_pad;
                }
              }
          break;
        }
      }
  if (matte_image != (XImage *) NULL)
    {
      /*
        Initialize matte image.
      */
      scanline_pad=matte_image->bytes_per_line-
        ((matte_image->width*matte_image->bits_per_pixel) >> 3);
      q=(unsigned char *) matte_image->data;
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        bit=0;
        byte=0;
        for (x=0; x < (long) image->columns; x++)
        {
          byte>>=1;
          if (p->opacity == TransparentOpacity)
            byte|=0x80;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
          p++;
        }
        if (bit != 0)
          *q=byte >> (8-bit);
        q+=scanline_pad;
      }
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   M a g i c k X M a k e I m a g e M S B F i r s t                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeImageMSBFirst initializes the pixel data of an X11 Image.
%  The X image pixels are copied in most-significant bit and byte first order.
%  The server's scanline pad is also respected. Rather than using one or two
%  general cases, many special cases are found here to help speed up the image
%  conversion.
%
%  The format of the MagickXMakeImageMSBFirst method is:
%
%      MagickXMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o ximage: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%    o matte_image: Specifies a pointer to a XImage structure;  returned from
%      XCreateImage.
%
%
*/
static void
MagickXMakeImageMSBFirst(const MagickXResourceInfo *resource_info,
                         const MagickXWindowInfo *window,Image *image,
                         XImage *ximage,XImage *matte_image)
{
  int
    y;

  register const IndexPacket
    *indexes;

  register int
    x;

  register const PixelPacket
    *p;

  register unsigned char
    *q;

  unsigned char
    bit,
    byte;

  unsigned int
    scanline_pad;

  unsigned long
    pixel,
    *pixels;

  XStandardColormap
    *map_info;

  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  assert(image != (Image *) NULL);
  scanline_pad=ximage->bytes_per_line-
    ((ximage->width*ximage->bits_per_pixel) >> 3);
  map_info=window->map_info;
  pixels=window->pixel_info->pixels;
  q=(unsigned char *) ximage->data;
  x=0;
  if (ximage->format == XYBitmap)
    {
      register unsigned short
        polarity;

      unsigned char
        background,
        foreground;

      /*
        Convert image to big-endian bitmap.
      */
      background=(PixelIntensity(&window->pixel_info->foreground_color) <
        PixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
      foreground=(PixelIntensity(&window->pixel_info->background_color) <
        PixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
      polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
      if (image->colors == 2)
        polarity=PixelIntensity(&image->colormap[0]) <
          PixelIntensity(&image->colormap[1]);
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        indexes=AccessImmutableIndexes(image);
        bit=0;
        byte=0;
        for (x=(long) image->columns; x > 0; x--)
        {
          byte<<=1;
          if (*indexes++ == polarity)
            byte|=foreground;
          else
            byte|=background;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
        }
        if (bit != 0)
          *q=byte << (8-bit);
        q+=scanline_pad;
      }
    }
  else
    if (window->pixel_info->colors != 0)
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to 2 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=pixels[*indexes++] & 0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 6);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit color-mapped X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=pixels[*indexes++] & 0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to 8 bit color-mapped X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=(long) image->columns; x > 0; x--)
              *q++=(unsigned char) (pixels[*indexes++]);
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          register int
            k;

          register unsigned int
            bytes_per_pixel;

          unsigned char
            channel[sizeof(unsigned long)];

          /*
            Convert to 8 bit color-mapped X image.
          */
          bytes_per_pixel=ximage->bits_per_pixel >> 3;
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AccessImmutableIndexes(image);
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=pixels[*indexes++];
              for (k=bytes_per_pixel-1; k >= 0; k--)
              {
                channel[k]=(unsigned char) pixel;
                pixel>>=8;
              }
              for (k=0; k < (int) bytes_per_pixel; k++)
                *q++=channel[k];
            }
            q+=scanline_pad;
          }
          break;
        }
      }
    else
      switch (ximage->bits_per_pixel)
      {
        case 2:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 6);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 2:
                {
                  *q|=(unsigned char) (pixel << 2);
                  nibble++;
                  break;
                }
                case 3:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 4:
        {
          register unsigned int
            nibble;

          /*
            Convert to 4 bit continuous-tone X image.
          */
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            nibble=0;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=MagickXGammaPixel(map_info,p);
              pixel&=0xf;
              switch (nibble)
              {
                case 0:
                {
                  *q=(unsigned char) (pixel << 4);
                  nibble++;
                  break;
                }
                case 1:
                {
                  *q|=(unsigned char) pixel;
                  q++;
                  nibble=0;
                  break;
                }
              }
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        case 6:
        case 8:
        {
          /*
            Convert to 8 bit continuous-tone X image.
          */
          if (resource_info->color_recovery &&
              resource_info->quantize_info->dither)
            {
              MagickXDitherImage(image,ximage);
              break;
            }
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            for (x=(long) image->columns; x > 0; x--)
            {
              pixel=MagickXGammaPixel(map_info,p);
              *q++=(unsigned char) pixel;
              p++;
            }
            q+=scanline_pad;
          }
          break;
        }
        default:
        {
          if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
              (map_info->green_max == 255) && (map_info->blue_max == 255) &&
              (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
              (map_info->blue_mult == 1))
            {
              /*
                Convert to 32 bit continuous-tone X image.
              */
              for (y=0; y < (long) image->rows; y++)
              {
                p=AcquireImagePixels(image,0,y,image->columns,1,
                  &image->exception);
                if (p == (const PixelPacket *) NULL)
                  break;
                if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                    (blue_gamma != 1.0))
                  {
                    /*
                      Gamma correct image.
                    */
                    for (x=(long) image->columns; x > 0; x--)
                    {
                      *q++=0;
                      *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                      *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                      *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                      p++;
                    }
                    continue;
                  }
                for (x=(long) image->columns; x > 0; x--)
                {
                  *q++=0;
                  *q++=ScaleQuantumToChar((Quantum) p->red);
                  *q++=ScaleQuantumToChar((Quantum) p->green);
                  *q++=ScaleQuantumToChar((Quantum) p->blue);
                  p++;
                }
              }
            }
          else
            if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
                (map_info->green_max == 255) && (map_info->blue_max == 255) &&
                (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
                (map_info->blue_mult == 65536L))
              {
                /*
                  Convert to 32 bit continuous-tone X image.
                */
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (const PixelPacket *) NULL)
                    break;
                  if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
                      (blue_gamma != 1.0))
                    {
                      /*
                        Gamma correct image.
                      */
                      for (x=(long) image->columns; x > 0; x--)
                      {
                        *q++=0;
                        *q++=ScaleQuantumToChar(MagickXBlueGamma(p->blue));
                        *q++=ScaleQuantumToChar(MagickXGreenGamma(p->green));
                        *q++=ScaleQuantumToChar(MagickXRedGamma(p->red));
                        p++;
                      }
                      continue;
                    }
                  for (x=(long) image->columns; x > 0; x--)
                  {
                    *q++=0;
                    *q++=ScaleQuantumToChar((Quantum) p->blue);
                    *q++=ScaleQuantumToChar((Quantum) p->green);
                    *q++=ScaleQuantumToChar((Quantum) p->red);
                    p++;
                  }
                }
              }
            else
              {
                register int
                  k;

                register unsigned int
                  bytes_per_pixel;

                unsigned char
                  channel[sizeof(unsigned long)];

                /*
                  Convert to multi-byte continuous-tone X image.
                */
                bytes_per_pixel=ximage->bits_per_pixel >> 3;
                for (y=0; y < (long) image->rows; y++)
                {
                  p=AcquireImagePixels(image,0,y,image->columns,1,
                    &image->exception);
                  if (p == (const PixelPacket *) NULL)
                    break;
                  for (x=(long) image->columns; x > 0; x--)
                  {
                    pixel=MagickXGammaPixel(map_info,p);
                    for (k=bytes_per_pixel-1; k >= 0; k--)
                    {
                      channel[k]=(unsigned char) pixel;
                      pixel>>=8;
                    }
                    for (k=0; k < (int) bytes_per_pixel; k++)
                      *q++=channel[k];
                    p++;
                  }
                  q+=scanline_pad;
                }
              }
          break;
        }
      }
  if (matte_image != (XImage *) NULL)
    {
      /*
        Initialize matte image.
      */
      scanline_pad=matte_image->bytes_per_line-
        ((matte_image->width*matte_image->bits_per_pixel) >> 3);
      q=(unsigned char *) matte_image->data;
      for (y=0; y < (long) image->rows; y++)
      {
        p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
        if (p == (const PixelPacket *) NULL)
          break;
        bit=0;
        byte=0;
        for (x=(long) image->columns; x > 0; x--)
        {
          byte<<=1;
          if (p->opacity == TransparentOpacity)
            byte|=0x01;
          bit++;
          if (bit == 8)
            {
              *q++=byte;
              bit=0;
              byte=0;
            }
          p++;
        }
        if (bit != 0)
          *q=byte << (8-bit);
        q+=scanline_pad;
      }
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e M a g n i f y I m a g e                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeMagnifyImage magnifies a region of an X image and
%  displays it.
%
%  The format of the MagickXMakeMagnifyImage method is:
%
%      MagickXMakeMagnifyImage(display,windows)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%
*/
MagickExport void
MagickXMakeMagnifyImage(Display *display,MagickXWindows *windows)
{
  char
    tuple[MaxTextExtent];

  int
    y;

  long
    n;

  register int
    x;

  register long
    i;

  register unsigned char
    *p,
    *q;

  PixelPacket
    color;

  static char
    text[MaxTextExtent];

  static unsigned int
    previous_magnify = 0;

  static MagickXWindowInfo
    magnify_window;

  unsigned int
    height,
    j,
    k,
    l,
    magnify,
    scanline_pad,
    width;

  XImage
    *ximage;

  /*
    Check boundary conditions.
  */
  assert(display != (Display *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  magnify=1;
  for (n=1; n < (long) windows->magnify.data; n++)
    magnify<<=1;
  while ((magnify*windows->image.ximage->width) < windows->magnify.width)
    magnify<<=1;
  while ((magnify*windows->image.ximage->height) < windows->magnify.height)
    magnify<<=1;
  while (magnify > windows->magnify.width)
    magnify>>=1;
  while (magnify > windows->magnify.height)
    magnify>>=1;
  if (magnify == 0)
    {
      if (previous_magnify != 0)
        magnify = previous_magnify;
      else
        magnify = 1;
    }
  if (magnify != previous_magnify)
    {
      unsigned int
        status;

      XTextProperty
        window_name;

      /*
        New magnify factor:  update magnify window name.
      */
      i=0;
      while ((1 << i) <= (int) magnify)
        i++;
      FormatString(windows->magnify.name,"Magnify %luX",i);
      status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
      if (status != 0)
        {
          XSetWMName(display,windows->magnify.id,&window_name);
          XSetWMIconName(display,windows->magnify.id,&window_name);
          (void) XFree((void *) window_name.value);
        }
    }
  previous_magnify=magnify;
  ximage=windows->image.ximage;
  width=windows->magnify.ximage->width;
  height=windows->magnify.ximage->height;
  if ((windows->magnify.x < 0) ||
      (windows->magnify.x >= windows->image.ximage->width))
    windows->magnify.x=windows->image.ximage->width >> 1;
  x=windows->magnify.x-((width/magnify) >> 1);
  if (x < 0)
    x=0;
  else
    if (x > (int) (ximage->width-(width/magnify)))
      x=ximage->width-width/magnify;
  if ((windows->magnify.y < 0) ||
      (windows->magnify.y >= windows->image.ximage->height))
    windows->magnify.y=windows->image.ximage->height >> 1;
  y=windows->magnify.y-((height/magnify) >> 1);
  if (y < 0)
    y=0;
  else
    if (y > (int) (ximage->height-(height/magnify)))
      y=ximage->height-height/magnify;
  q=(unsigned char *) windows->magnify.ximage->data;
  scanline_pad=windows->magnify.ximage->bytes_per_line-
    ((width*windows->magnify.ximage->bits_per_pixel) >> 3);
  if (ximage->bits_per_pixel < 8)
    {
      register unsigned char
        background,
        byte,
        foreground,
        p_bit,
        q_bit;

      register unsigned int
        plane;

      MagickXPixelInfo
        *pixel_info;

      pixel_info=windows->magnify.pixel_info;
      switch (ximage->bitmap_bit_order)
      {
        case LSBFirst:
        {
          /*
            Magnify little-endian bitmap.
          */
          background=0x00;
          foreground=0x80;
          if (ximage->format == XYBitmap)
            {
              background=(PixelIntensity(&pixel_info->foreground_color) <
                PixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
              foreground=(PixelIntensity(&pixel_info->background_color) <
                PixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
              if (windows->magnify.depth > 1)
                Swap(background,foreground);
            }
          for (i=0; i < (long) height; i+=magnify)
          {
            /*
              Propogate pixel magnify rows.
            */
            for (j=0; j < magnify; j++)
            {
              p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
                ((x*ximage->bits_per_pixel) >> 3);
              p_bit=(x*ximage->bits_per_pixel) & 0x07;
              q_bit=0;
              byte=0;
              for (k=0; k < width; k+=magnify)
              {
                /*
                  Propogate pixel magnify columns.
                */
                for (l=0; l < magnify; l++)
                {
                  /*
                    Propogate each bit plane.
                  */
                  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
                  {
                    byte>>=1;
                    if (*p & (0x01 << (p_bit+plane)))
                      byte|=foreground;
                    else
                      byte|=background;
                    q_bit++;
                    if (q_bit == 8)
                      {
                        *q++=byte;
                        q_bit=0;
                        byte=0;
                      }
                  }
                }
                p_bit+=ximage->bits_per_pixel;
                if (p_bit == 8)
                  {
                    p++;
                    p_bit=0;
                  }
                if (q_bit != 0)
                  *q=byte >> (8-q_bit);
                q+=scanline_pad;
              }
            }
            y++;
          }
          break;
        }
        case MSBFirst:
        default:
        {
          /*
            Magnify big-endian bitmap.
          */
          background=0x00;
          foreground=0x01;
          if (ximage->format == XYBitmap)
            {
              background=(PixelIntensity(&pixel_info->foreground_color) <
                PixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
              foreground=(PixelIntensity(&pixel_info->background_color) <
                PixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
              if (windows->magnify.depth > 1)
                Swap(background,foreground);
            }
          for (i=0; i < (long) height; i+=magnify)
          {
            /*
              Propogate pixel magnify rows.
            */
            for (j=0; j < magnify; j++)
            {
              p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
                ((x*ximage->bits_per_pixel) >> 3);
              p_bit=(x*ximage->bits_per_pixel) & 0x07;
              q_bit=0;
              byte=0;
              for (k=0; k < width; k+=magnify)
              {
                /*
                  Propogate pixel magnify columns.
                */
                for (l=0; l < magnify; l++)
                {
                  /*
                    Propogate each bit plane.
                  */
                  for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
                  {
                    byte<<=1;
                    if (*p & (0x80 >> (p_bit+plane)))
                      byte|=foreground;
                    else
                      byte|=background;
                    q_bit++;
                    if (q_bit == 8)
                      {
                        *q++=byte;
                        q_bit=0;
                        byte=0;
                      }
                  }
                }
                p_bit+=ximage->bits_per_pixel;
                if (p_bit == 8)
                  {
                    p++;
                    p_bit=0;
                  }
                if (q_bit != 0)
                  *q=byte << (8-q_bit);
                q+=scanline_pad;
              }
            }
            y++;
          }
          break;
        }
      }
    }
  else
    switch (ximage->bits_per_pixel)
    {
      case 6:
      case 8:
      {
        /*
          Magnify 8 bit X image.
        */
        for (i=0; i < (long) height; i+=magnify)
        {
          /*
            Propogate pixel magnify rows.
          */
          for (j=0; j < magnify; j++)
          {
            p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
              ((x*ximage->bits_per_pixel) >> 3);
            for (k=0; k < width; k+=magnify)
            {
              /*
                Propogate pixel magnify columns.
              */
              for (l=0; l < magnify; l++)
                *q++=(*p);
              p++;
            }
            q+=scanline_pad;
          }
          y++;
        }
        break;
      }
      default:
      {
        register unsigned int
          bytes_per_pixel,
          m;

        /*
          Magnify multi-byte X image.
        */
        bytes_per_pixel=ximage->bits_per_pixel >> 3;
        for (i=0; i < (long) height; i+=magnify)
        {
          /*
            Propogate pixel magnify rows.
          */
          for (j=0; j < magnify; j++)
          {
            p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
              ((x*ximage->bits_per_pixel) >> 3);
            for (k=0; k < width; k+=magnify)
            {
              /*
                Propogate pixel magnify columns.
              */
              for (l=0; l < magnify; l++)
                for (m=0; m < bytes_per_pixel; m++)
                  *q++=(*(p+m));
              p+=bytes_per_pixel;
            }
            q+=scanline_pad;
          }
          y++;
        }
        break;
      }
    }
  /*
    Copy X image to magnify pixmap.
  */
  x=windows->magnify.x-((width/magnify) >> 1);
  if (x < 0)
    x=(width >> 1)-windows->magnify.x*magnify;
  else
    if (x > (int) (ximage->width-(width/magnify)))
      x=(ximage->width-windows->magnify.x)*magnify-(width >> 1);
    else
      x=0;
  y=windows->magnify.y-((height/magnify) >> 1);
  if (y < 0)
    y=(height >> 1)-windows->magnify.y*magnify;
  else
    if (y > (int) (ximage->height-(height/magnify)))
      y=(ximage->height-windows->magnify.y)*magnify-(height >> 1);
    else
      y=0;
  if ((x != 0) || (y != 0))
    (void) XFillRectangle(display,windows->magnify.pixmap,
      windows->magnify.annotate_context,0,0,width,height);
  (void) XPutImage(display,windows->magnify.pixmap,
    windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
    height-y);
  if ((magnify > 1) && ((magnify <= (width >> 1)) &&
      (magnify <= (height >> 1))))
    {
      RectangleInfo
        highlight_info;

      /*
        Highlight center pixel.
      */
      highlight_info.x=(long) windows->magnify.width >> 1;
      highlight_info.y=(long) windows->magnify.height >> 1;
      highlight_info.width=magnify;
      highlight_info.height=magnify;
      (void) XDrawRectangle(display,windows->magnify.pixmap,
        windows->magnify.highlight_context,(int) highlight_info.x,
        (int) highlight_info.y,(unsigned int) highlight_info.width-1,
        (unsigned int) highlight_info.height-1);
      if (magnify > 2)
        (void) XDrawRectangle(display,windows->magnify.pixmap,
          windows->magnify.annotate_context,(int) highlight_info.x+1,
          (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
          (unsigned int) highlight_info.height-3);
    }
  /*
    Show center pixel color.
  */
  (void) AcquireOnePixelByReference(windows->image.image,&color,windows->magnify.x,
                        windows->magnify.y,&windows->image.image->exception);
  GetColorTuple(&color,windows->image.image->depth,windows->image.image->matte,
    False,tuple);
  FormatString(text," %+d%+d  %.1024s ",windows->magnify.x,windows->magnify.y,
    tuple);
  height=windows->magnify.font_info->ascent+windows->magnify.font_info->descent;
  x=windows->magnify.font_info->max_bounds.width >> 1;
  y=windows->magnify.font_info->ascent+(height >> 2);
  (void) XDrawImageString(display,windows->magnify.pixmap,
    windows->magnify.annotate_context,x,y,text,(int) strlen(text));
  y+=height;
  (void) QueryColorname(windows->image.image,&color,X11Compliance,text,
    &windows->image.image->exception);
  (void) XDrawImageString(display,windows->magnify.pixmap,
    windows->magnify.annotate_context,x,y,text,(int) strlen(text));
  /*
    Refresh magnify window.
  */
  magnify_window=windows->magnify;
  magnify_window.x=0;
  magnify_window.y=0;
  MagickXRefreshWindow(display,&magnify_window,(XEvent *) NULL);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e P i x m a p                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakePixmap creates an X11 pixmap.
%
%  The format of the MagickXMakePixmap method is:
%
%      unsigned int MagickXMakePixmap(Display *display,
%                                     const MagickXResourceInfo *resource_info,
%                                     MagickXWindowInfo *window)
%
%  A description of each parameter follows:
%
%    o status: Method MagickXMakePixmap returns True if the X pixmap is
%      successfully created.  False is returned is there is a memory shortage.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%
*/
static unsigned int
MagickXMakePixmap(Display *display,
                  const MagickXResourceInfo *resource_info,
                  MagickXWindowInfo *window)
{
  unsigned int
    height,
    width;

  assert(display != (Display *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(window != (MagickXWindowInfo  *) NULL);
  if (window->pixmap != (Pixmap) NULL)
    {
      /*
        Destroy previous X pixmap.
      */
      (void) XFreePixmap(display,window->pixmap);
      window->pixmap=(Pixmap) NULL;
    }
  if (!window->use_pixmap)
    return(False);
  if (window->ximage == (XImage *) NULL)
    return(False);
  /*
    Display busy cursor.
  */
  (void) XDefineCursor(display,window->id,window->busy_cursor);
  (void) XFlush(display);
  /*
    Create pixmap.
  */
  width=window->ximage->width;
  height=window->ximage->height;
  window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
  if (window->pixmap == (Pixmap) NULL)
    {
      /*
        Unable to allocate pixmap.
      */
      (void) XDefineCursor(display,window->id,window->cursor);
      return(False);
    }
  /*
    Copy X image to pixmap.
  */
#if defined(HasSharedMemory)
  if (window->shared_memory)
    (void) XShmPutImage(display,window->pixmap,window->annotate_context,window->ximage,
      0,0,0,0,width,height,True);
#endif
  if (!window->shared_memory)
    (void) XPutImage(display,window->pixmap,window->annotate_context,
      window->ximage,0,0,0,0,width,height);
  if (IsEventLogged(X11Event))
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
        width,height);
    }
  /*
    Restore cursor.
  */
  (void) XDefineCursor(display,window->id,window->cursor);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e S t a n d a r d C o l o r m a p                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeStandardColormap creates an X11 Standard Colormap.
%
%  The format of the MagickXMakeStandardColormap method is:
%
%      MagickXMakeStandardColormap(display,visual_info,resource_info,image,
%        map_info,pixel)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
%      returned from XGetVisualInfo.
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%    o image: Specifies a pointer to an Image structure;  returned from
%      ReadImage.
%
%    o map_info: If a Standard Colormap type is specified, this structure is
%      initialized with info from the Standard Colormap.
%
%    o pixel: Specifies a pointer to a MagickXPixelInfo structure.
%
%
*/

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

static int IntensityCompare(const void *x,const void *y)
{
  DiversityPacket
    *color_1,
    *color_2;

  color_1=(DiversityPacket *) x;
  color_2=(DiversityPacket *) y;
  return((int) (PixelIntensity(color_2)-PixelIntensity(color_1)));
}

static int PopularityCompare(const void *x,const void *y)
{
  DiversityPacket
    *color_1,
    *color_2;

  color_1=(DiversityPacket *) x;
  color_2=(DiversityPacket *) y;
  return((int) color_2->count-(int) color_1->count);
}

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

MagickExport void
MagickXMakeStandardColormap(Display *display,
                            XVisualInfo *visual_info,
                            MagickXResourceInfo *resource_info,
                            Image *image,
                            XStandardColormap *map_info,
                            MagickXPixelInfo *pixel)
{
  Colormap
    colormap;

  int
    status;

  register IndexPacket
    *indexes;

  register PixelPacket
    *q;

  register long
    i;

  unsigned long
    number_colors,
    retain_colors;

  unsigned short
    gray_value;

  XColor
    color,
    *colors,
    *p;

  assert(display != (Display *) NULL);
  assert(visual_info != (XVisualInfo *) NULL);
  assert(map_info != (XStandardColormap *) NULL);
  assert(resource_info != (MagickXResourceInfo *) NULL);
  assert(pixel != (MagickXPixelInfo *) NULL);
  if (resource_info->map_type != (char *) NULL)
    {
      /*
        Standard Colormap is already defined (i.e. xstdcmap).
      */
      MagickXGetPixelPacket(display,visual_info,map_info,resource_info,image,
        pixel);
      number_colors=(unsigned int) (map_info->base_pixel+
        (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
      if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
        if (!image->matte && !resource_info->color_recovery &&
            resource_info->quantize_info->dither &&
            (number_colors < MaxColormapSize))
          {
            Image
              *map_image;

            /*
              Improve image appearance with error diffusion.
            */
            map_image=AllocateImage((ImageInfo *) NULL);
            if (map_image == (Image *) NULL)
              MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
                MagickMsg(XServerFatalError,UnableToDitherImage));
            map_image->columns=number_colors;
            map_image->rows=1;
            /*
              Initialize colormap image.
            */
            q=SetImagePixels(map_image,0,0,map_image->columns,1);
            if (q != (PixelPacket *) NULL)
              {
                for (i=0; i < (long) number_colors; i++)
                {
                  q->red=0;
                  if (map_info->red_max != 0)
                    q->red=(Quantum) (((double) MaxRGB*
                      (i/map_info->red_mult))/map_info->red_max+0.5);
                  q->green=0;
                  if (map_info->green_max != 0)
                    q->green=(Quantum) (((double) MaxRGB*
                      ((i/map_info->green_mult) % (map_info->green_max+1)))/
                      map_info->green_max+0.5);
                  q->blue=0;
                  if (map_info->blue_max != 0)
                    q->blue=(Quantum) (((double) MaxRGB*
                      (i % map_info->green_mult))/map_info->blue_max+0.5);
                  q->opacity=TransparentOpacity;
                  q++;
                }
                (void) SyncImagePixels(map_image);
                (void) MapImage(image,map_image,True);
              }
            MagickXGetPixelPacket(display,visual_info,map_info,resource_info,image,
              pixel);
            (void) SetImageType(image,TrueColorType);
            DestroyImage(map_image);
          }
      if (IsEventLogged(X11Event))
        {
          (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
          (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
            map_info->colormap);
          (void) LogMagickEvent(X11Event,GetMagickModule(),
            "  red, green, blue max: %lu %lu %lu",map_info->red_max,
            map_info->green_max,map_info->blue_max);
          (void) LogMagickEvent(X11Event,GetMagickModule(),
            "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
            map_info->green_mult,map_info->blue_mult);
        }
      return;
    }
  if ((visual_info->class != DirectColor) &&
      (visual_info->class != TrueColor))
    if ((image->storage_class == DirectClass) ||
        ((int) image->colors > visual_info->colormap_size))
      {
        QuantizeInfo
          quantize_info;

        /*
          Image has more colors than the visual supports.
        */
        quantize_info=(*resource_info->quantize_info);
        quantize_info.number_colors=visual_info->colormap_size;
        (void) QuantizeImage(&quantize_info,image);
      }
  /*
    Free previous and create new colormap.
  */
  (void) MagickXFreeStandardColormap(display,visual_info,map_info,pixel);
  colormap=XDefaultColormap(display,visual_info->screen);
  if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
    colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
      visual_info->visual,visual_info->class == DirectColor ?
      AllocAll : AllocNone);
  if (colormap == (Colormap) NULL)
    MagickFatalError3(ResourceLimitError,MemoryAllocationFailed,
      UnableToCreateColormap);
  /*
    Initialize the map and pixel info structures.
  */
  MagickXGetMapInfo(visual_info,colormap,map_info);
  MagickXGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
  /*
    Allocating colors in server colormap is based on visual class.
  */
  switch (visual_info->class)
  {
    case StaticGray:
    case StaticColor:
    {
      /*
        Define Standard Colormap for StaticGray or StaticColor visual.
      */
      number_colors=image->colors;
      colors=MagickAllocateArray(XColor *,
                                 visual_info->colormap_size,sizeof(XColor));
      if (colors == (XColor *) NULL)
        MagickFatalError3(ResourceLimitError,MemoryAllocationFailed,
          UnableToCreateColormap);
      p=colors;
      color.flags=DoRed | DoGreen | DoBlue;
      for (i=0; i < (long) image->colors; i++)
      {
        color.red=ScaleQuantumToShort(MagickXRedGamma(image->colormap[i].red));
        color.green=ScaleQuantumToShort(MagickXGreenGamma(image->colormap[i].green));
        color.blue=ScaleQuantumToShort(MagickXBlueGamma(image->colormap[i].blue));
        if (visual_info->class != StaticColor)
          {
            gray_value=(unsigned short) PixelIntensity(&color);
            color.red=gray_value;
            color.green=gray_value;
            color.blue=gray_value;
          }
        status=XAllocColor(display,colormap,&color);
        if (status == 0)
          {
            colormap=XCopyColormapAndFree(display,colormap);
            (void) XAllocColor(display,colormap,&color);
          }
        pixel->pixels[i]=color.pixel;
        *p++=color;
      }
      break;
    }
    case GrayScale:
    case PseudoColor:
    {
      unsigned int
        colormap_type;

      /*
        Define Standard Colormap for GrayScale or PseudoColor visual.
      */
      number_colors=image->colors;
      colors=MagickAllocateArray(XColor *,
                                 visual_info->colormap_size,sizeof(XColor));
      if (colors == (XColor *) NULL)
        MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
          UnableToCreateColormap);
      /*
        Preallocate our GUI colors.
      */
      (void) XAllocColor(display,colormap,&pixel->foreground_color);
      (void) XAllocColor(display,colormap,&pixel->background_color);
      (void) XAllocColor(display,colormap,&pixel->border_color);
      (void) XAllocColor(display,colormap,&pixel->matte_color);
      (void) XAllocColor(display,colormap,&pixel->highlight_color);
      (void) XAllocColor(display,colormap,&pixel->shadow_color);
      (void) XAllocColor(display,colormap,&pixel->depth_color);
      (void) XAllocColor(display,colormap,&pixel->trough_color);
      for (i=0; i < MaxNumberPens; i++)
        (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
      /*
        Determine if image colors will "fit" into X server colormap.
      */
      colormap_type=resource_info->colormap;
      status=XAllocColorCells(display,colormap,False,(unsigned long *) NULL,0,
        pixel->pixels,(int) image->colors);
      if (status != 0)
        colormap_type=PrivateColormap;
      if (colormap_type == SharedColormap)
        {
          DiversityPacket
            *diversity;

          int
            y;

          register int
            x;

          unsigned short
            colormap_index;

          XColor
            *server_colors;

          /*
            Define Standard colormap for shared GrayScale or PseudoColor visual.
          */
          diversity=MagickAllocateArray(DiversityPacket *,
                                        image->colors,sizeof(DiversityPacket));
          if (diversity == (DiversityPacket *) NULL)
            MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
              UnableToCreateColormap);
          for (i=0; i < (long) image->colors; i++)
          {
            diversity[i].red=image->colormap[i].red;
            diversity[i].green=image->colormap[i].green;
            diversity[i].blue=image->colormap[i].blue;
            diversity[i].index=(unsigned short) i;
            diversity[i].count=0;
          }
          for (y=0; y < (long) image->rows; y++)
          {
            q=GetImagePixels(image,0,y,image->columns,1);
            if (q == (PixelPacket *) NULL)
              break;
            indexes=AccessMutableIndexes(image);
            for (x=0; x < (long) image->columns; x++)
              diversity[indexes[x]].count++;
          }
          /*
            Sort colors by decreasing intensity.
          */
          qsort((void *) diversity,image->colors,sizeof(DiversityPacket),
            IntensityCompare);
          for (i=0; i < (long) image->colors; i+=Max(image->colors >> 4,2))
            diversity[i].count<<=4;  /* increase this colors popularity */
          diversity[image->colors-1].count<<=4;
          qsort((void *) diversity,image->colors,sizeof(DiversityPacket),
            PopularityCompare);
          /*
            Allocate colors.
          */
          p=colors;
          color.flags=DoRed | DoGreen | DoBlue;
          for (i=0; i < (long) image->colors; i++)
          {
            colormap_index=diversity[i].index;
            color.red=
              ScaleQuantumToShort(MagickXRedGamma(image->colormap[colormap_index].red));
            color.green=
              ScaleQuantumToShort(MagickXGreenGamma(image->colormap[colormap_index].green));
            color.blue=
              ScaleQuantumToShort(MagickXBlueGamma(image->colormap[colormap_index].blue));
            if (visual_info->class != PseudoColor)
              {
                gray_value=(unsigned short) PixelIntensity(&color);
                color.red=gray_value;
                color.green=gray_value;
                color.blue=gray_value;
              }
            status=XAllocColor(display,colormap,&color);
            if (status == 0)
              break;
            pixel->pixels[colormap_index]=color.pixel;
            *p++=color;
          }
          /*
            Read X server colormap.
          */
          server_colors=MagickAllocateArray(XColor *,
                                            visual_info->colormap_size,
                                            sizeof(XColor));
          if (server_colors == (XColor *) NULL)
            MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
              UnableToCreateColormap);
          for (x=0; x < visual_info->colormap_size; x++)
            server_colors[x].pixel=(unsigned long) x;
          (void) XQueryColors(display,colormap,server_colors,
            (int) Min(visual_info->colormap_size,256));
          /*
            Select remaining colors from X server colormap.
          */
          for (; i < (long) image->colors; i++)
          {
            colormap_index=diversity[i].index;
            color.red=
              ScaleQuantumToShort(MagickXRedGamma(image->colormap[colormap_index].red));
            color.green=
              ScaleQuantumToShort(MagickXGreenGamma(image->colormap[colormap_index].green));
            color.blue=
              ScaleQuantumToShort(MagickXBlueGamma(image->colormap[colormap_index].blue));
            if (visual_info->class != PseudoColor)
              {
                gray_value=(unsigned short) PixelIntensity(&color);
                color.red=gray_value;
                color.green=gray_value;
                color.blue=gray_value;
              }
            MagickXBestPixel(display,colormap,server_colors,(unsigned int)
              visual_info->colormap_size,&color);
            pixel->pixels[colormap_index]=color.pixel;
            *p++=color;
          }
          if ((int) image->colors < visual_info->colormap_size)
            {
              /*
                Fill up colors array-- more choices for pen colors.
              */
              retain_colors=Min(visual_info->colormap_size-image->colors,256);
              for (i=0; i < (long) retain_colors; i++)
                *p++=server_colors[i];
              number_colors+=retain_colors;
            }
          MagickFreeMemory(server_colors);
          MagickFreeMemory(diversity);
          break;
        }
      /*
        Define Standard colormap for private GrayScale or PseudoColor visual.
      */
      if (status == 0)
        {
          /*
            Not enough colormap entries in the colormap-- Create a new colormap.
          */
          colormap=XCreateColormap(display,
            XRootWindow(display,visual_info->screen),visual_info->visual,
            AllocNone);
          if (colormap == (Colormap) NULL)
            MagickFatalError3(ResourceLimitError,MemoryAllocationFailed,
              UnableToCreateColormap);
          map_info->colormap=colormap;
          if ((int) image->colors < visual_info->colormap_size)
            {
              /*
                Retain colors from the default colormap to help lessens the
                effects of colormap flashing.
              */
              retain_colors=Min(visual_info->colormap_size-image->colors,256);
              p=colors+image->colors;
              for (i=0; i < (long) retain_colors; i++)
              {
                p->pixel=(unsigned long) i;
                p++;
              }
              (void) XQueryColors(display,
                XDefaultColormap(display,visual_info->screen),
                colors+image->colors,(int) retain_colors);
              /*
                Transfer colors from default to private colormap.
              */
              (void) XAllocColorCells(display,colormap,False,(unsigned long *)
                NULL,0,pixel->pixels,(int) retain_colors);
              p=colors+image->colors;
              for (i=0; i < (long) retain_colors; i++)
              {
                p->pixel=pixel->pixels[i];
                p++;
              }
              (void) XStoreColors(display,colormap,colors+image->colors,
                (int) retain_colors);
              number_colors+=retain_colors;
            }
          (void) XAllocColorCells(display,colormap,False,(unsigned long *) NULL,
            0,pixel->pixels,(int) image->colors);
        }
      /*
        Store the image colormap.
      */
      p=colors;
      color.flags=DoRed | DoGreen | DoBlue;
      for (i=0; i < (long) image->colors; i++)
      {
        color.red=ScaleQuantumToShort(MagickXRedGamma(image->colormap[i].red));
        color.green=ScaleQuantumToShort(MagickXGreenGamma(image->colormap[i].green));
        color.blue=ScaleQuantumToShort(MagickXBlueGamma(image->colormap[i].blue));
        if (visual_info->class != PseudoColor)
          {
            gray_value=(unsigned short) PixelIntensity(&color);
            color.red=gray_value;
            color.green=gray_value;
            color.blue=gray_value;
          }
        color.pixel=pixel->pixels[i];
        *p++=color;
      }
      (void) XStoreColors(display,colormap,colors,(int) image->colors);
      break;
    }
    case TrueColor:
    case DirectColor:
    default:
    {
      unsigned int
        linear_colormap;

      /*
        Define Standard Colormap for TrueColor or DirectColor visual.
      */
      number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
        (map_info->green_max*map_info->green_mult)+
        (map_info->blue_max*map_info->blue_mult)+1);
      linear_colormap=(number_colors > 4096) ||
        (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
         ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
         ((int) (map_info->blue_max+1) == visual_info->colormap_size));
      if (linear_colormap)
        number_colors=visual_info->colormap_size;
      /*
        Allocate color array.
      */
      colors=MagickAllocateArray(XColor *,number_colors,sizeof(XColor));
      if (colors == (XColor *) NULL)
        MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
          UnableToCreateColormap);
      /*
        Initialize linear color ramp.
      */
      p=colors;
      color.flags=DoRed | DoGreen | DoBlue;
      if (linear_colormap)
        for (i=0; i < (long) number_colors; i++)
        {
          color.blue=(unsigned short) 0;
          if (map_info->blue_max != 0)
            color.blue=(unsigned short) ((unsigned long)
              ((65535L*(i % map_info->green_mult))/map_info->blue_max));
          color.green=color.blue;
          color.red=color.blue;
          color.pixel=MagickXStandardPixel(map_info,&color);
          *p++=color;
        }
      else
        for (i=0; i < (long) number_colors; i++)
        {
          color.red=(unsigned short) 0;
          if (map_info->red_max != 0)
            color.red=(unsigned short) ((unsigned long)
              ((65535L*(i/map_info->red_mult))/map_info->red_max));
          color.green=(unsigned int) 0;
          if (map_info->green_max != 0)
            color.green=(unsigned short) ((unsigned long)
              ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
                map_info->green_max));
          color.blue=(unsigned short) 0;
          if (map_info->blue_max != 0)
            color.blue=(unsigned short) ((unsigned long)
              ((65535L*(i % map_info->green_mult))/map_info->blue_max));
          color.pixel=MagickXStandardPixel(map_info,&color);
          *p++=color;
        }
      if ((visual_info->class == DirectColor) &&
          (colormap != XDefaultColormap(display,visual_info->screen)))
        (void) XStoreColors(display,colormap,colors,(int) number_colors);
      else
        for (i=0; i < (long) number_colors; i++)
          (void) XAllocColor(display,colormap,&colors[i]);
      break;
    }
  }
  if ((visual_info->class != DirectColor) &&
      (visual_info->class != TrueColor))
    {
      /*
        Set foreground, background, border, etc. pixels.
      */
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->foreground_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->background_color);
      if (pixel->background_color.pixel == pixel->foreground_color.pixel)
        {
          /*
            Foreground and background colors must differ.
          */
          pixel->background_color.red=(~pixel->foreground_color.red);
          pixel->background_color.green=
            (~pixel->foreground_color.green);
          pixel->background_color.blue=
            (~pixel->foreground_color.blue);
          MagickXBestPixel(display,colormap,colors,(int) number_colors,
            &pixel->background_color);
        }
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->border_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->matte_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->highlight_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->shadow_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->depth_color);
      MagickXBestPixel(display,colormap,colors,(int) number_colors,
        &pixel->trough_color);
      for (i=0; i < MaxNumberPens; i++)
      {
        MagickXBestPixel(display,colormap,colors,(int) number_colors,
          &pixel->pen_colors[i]);
        pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
      }
      pixel->colors=image->colors+MaxNumberPens;
    }
  MagickFreeMemory(colors);
  if (IsEventLogged(X11Event))
    {
      (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
      (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
        map_info->colormap);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue max: %lu %lu %lu",map_info->red_max,
        map_info->green_max,map_info->blue_max);
      (void) LogMagickEvent(X11Event,GetMagickModule(),
        "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
        map_info->green_mult,map_info->blue_mult);
    }
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X M a k e W i n d o w                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMakeWindow creates an X11 window.
%
%  The format of the MagickXMakeWindow method is:
%
%      void MagickXMakeWindow(Display *display,Window parent,char **argv,
%        int argc,XClassHint *class_hint,XWMHints *manager_hints,
%        MagickXWindowInfo *window_info)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o parent: Specifies the parent window_info.
%
%    o argv: Specifies the application's argument list.
%
%    o argc: Specifies the number of arguments.
%
%    o class_hint: Specifies a pointer to a X11 XClassHint structure.
%
%    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
%
%    o window_info: Specifies a pointer to a X11 MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXMakeWindow(Display *display,Window parent,char **argv,
                  int argc,XClassHint *class_hint,XWMHints *manager_hints,
                  MagickXWindowInfo *window_info)
{
#define MinWindowSize  64

  Atom
    atom_list[2];

  int
    gravity,
    status;

  static XTextProperty
    icon_name,
    window_name;

  XSizeHints
    *size_hints;

  /*
    Set window info hints.
  */
  assert(display != (Display *) NULL);
  assert(window_info != (MagickXWindowInfo *) NULL);
  size_hints=XAllocSizeHints();
  if (size_hints == (XSizeHints *) NULL)
    MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
      MagickMsg(XServerFatalError,UnableToMakeXWindow));
  size_hints->flags=(long) window_info->flags;
  size_hints->x=window_info->x;
  size_hints->y=window_info->y;
  size_hints->width=window_info->width;
  size_hints->height=window_info->height;
  if (window_info->immutable)
    {
      /*
        Window size cannot be changed.
      */
      size_hints->min_width=size_hints->width;
      size_hints->min_height=size_hints->height;
      size_hints->max_width=size_hints->width;
      size_hints->max_height=size_hints->height;
      size_hints->flags|=PMinSize;
      size_hints->flags|=PMaxSize;
    }
  else
    {
      /*
        Window size can be changed.
      */
      size_hints->min_width=window_info->min_width;
      size_hints->min_height=window_info->min_height;
      size_hints->flags|=PResizeInc;
      size_hints->width_inc=window_info->width_inc;
      size_hints->height_inc=window_info->height_inc;
#if !defined(PRE_R4_ICCCM)
      size_hints->flags|=PBaseSize;
      size_hints->base_width=size_hints->width_inc;
      size_hints->base_height=size_hints->height_inc;
#endif
    }
  gravity=NorthWestGravity;
  if (window_info->geometry != (char *) NULL)
    {
      char
        default_geometry[MaxTextExtent],
        geometry[MaxTextExtent];

      int
        flags;

      register char
        *p;

      /*
        User specified geometry.
      */
      FormatString(default_geometry,"%dx%d",size_hints->width,
        size_hints->height);
      (void) strlcpy(geometry,window_info->geometry,MaxTextExtent);
      p=geometry;
      while (strlen(p) != 0)
      {
        if (!isspace((int) (*p)) && (*p != '%'))
          p++;
        else
          (void) memmove(p,p+1,strlen(p+1)+1);
      }
      flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
        window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
        &size_hints->width,&size_hints->height,&gravity);
      if ((flags & WidthValue) && (flags & HeightValue))
        size_hints->flags|=USSize;
      if ((flags & XValue) && (flags & YValue))
        {
          size_hints->flags|=USPosition;
          window_info->x=size_hints->x;
          window_info->y=size_hints->y;
        }
    }
#if !defined(PRE_R4_ICCCM)
  size_hints->win_gravity=gravity;
  size_hints->flags|=PWinGravity;
#endif
  if (window_info->id == (Window) NULL)
    window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
      window_info->width,window_info->height,window_info->border_width,
      window_info->depth,InputOutput,window_info->visual,window_info->mask,
      &window_info->attributes);
  else
    {
      unsigned int
        mask;

      XEvent
        sans_event;

      XWindowChanges
        window_changes;

      /*
        Window already exists;  change relevant attributes.
      */
      (void) XChangeWindowAttributes(display,window_info->id,window_info->mask,
        &window_info->attributes);
      mask=ConfigureNotify;
      while (XCheckTypedWindowEvent(display,window_info->id,mask,&sans_event));
      window_changes.x=window_info->x;
      window_changes.y=window_info->y;
      window_changes.width=window_info->width;
      window_changes.height=window_info->height;
      mask=CWWidth | CWHeight;
      if (window_info->flags & USPosition)
        mask|=CWX | CWY;
      (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
        mask,&window_changes);
    }
  if (window_info->id == (Window) NULL)
    MagickFatalError(XServerFatalError,UnableToCreateXWindow,
      window_info->name);
  status=XStringListToTextProperty(&window_info->name,1,&window_name);
  if (status == 0)
    MagickFatalError(XServerFatalError,UnableToCreateTextProperty,
      window_info->name);
  status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
  if (status == 0)
    MagickFatalError(XServerFatalError,UnableToCreateTextProperty,
      window_info->icon_name);
  if (window_info->icon_geometry != (char *) NULL)
    {
      int
        flags,
        height,
        width;

      /*
        User specified icon geometry.
      */
      size_hints->flags|=USPosition;
      flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
        (char *) NULL,0,size_hints,&manager_hints->icon_x,
        &manager_hints->icon_y,&width,&height,&gravity);
      if ((flags & XValue) && (flags & YValue))
        manager_hints->flags|=IconPositionHint;
    }
  XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
    size_hints,manager_hints,class_hint);
  if (window_name.value != NULL)
    {
      (void) XFree((void *) window_name.value);
      window_name.value = NULL;
      window_name.nitems=0;
    }
  if (icon_name.value != NULL)
    {
      (void) XFree((void *) icon_name.value);
      icon_name.value = NULL;
      icon_name.nitems=0;
    }
  atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",False);
  atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",False);
  (void) XSetWMProtocols(display,window_info->id,atom_list,2);
  (void) XFree((void *) size_hints);
  if (window_info->shape)
    {
#if defined(HasShape)
      int
        error_base=0,
        event_base=0;

      /*
        Can we apply a non-rectangular shaping mask?
      */
      window_info->shape&=XShapeQueryExtension(display,&error_base,&event_base);
#else
      window_info->shape=False;
#endif
    }
  if (window_info->shared_memory)
    {
#if defined(HasSharedMemory)
      /*
        Can we we use shared memory with this window?
      */
      window_info->shared_memory&=XShmQueryExtension(display);
#else
      window_info->shared_memory=False;
#endif
    }
  window_info->image=(Image *) NULL;
  window_info->destroy=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X P r o g r e s s M o n i t o r                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXMagickMonitor displays the progress a task is making in
%  completing a task.
%
%  The format of the MagickXMagickMonitor method is:
%
%      unsigned int MagickXMagickMonitor(const char *task,
%        const magick_int64_t quantum,const magick_uint64_t span,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o task: Identifies the task in progress.
%
%    o quantum: Specifies the quantum position within the span which represents
%      how much progress has been made in completing a task.
%
%    o span: Specifies the span relative to completing a task.
%
%    o exception: Return any errors or warnings in this structure.
%
*/
MagickExport unsigned int
MagickXMagickMonitor(const char *task,
                     const magick_int64_t quantum,const magick_uint64_t span,
                     ExceptionInfo *exception)
{
  MagickXWindows
    *windows;

  ARG_NOT_USED(exception);
  windows=MagickXSetWindows((MagickXWindows *) ~0);
  if (windows == (MagickXWindows *) NULL)
    return(True);
  MagickXMonitorWidget(windows->display,windows,task,quantum,span);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X Q u e r y C o l o r D a t a b a s e                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXQueryColorDatabase looks up a RGB values for a color given
%  in the target string.
%
%  The format of the MagickXQueryColorDatabase method is:
%
%      unsigned int MagickXQueryColorDatabase(const char *target,XColor *color)
%
%  A description of each parameter follows:
%
%    o status:  Method MagickXQueryColorDatabase returns True if the RGB values
%      of the target color is defined, otherwise False is returned.
%
%    o target: Specifies the color to lookup in the X color database.
%
%    o color: A pointer to an PixelPacket structure.  The RGB value of the target
%      color is returned as this value.
%
%
*/
MagickExport unsigned int
MagickXQueryColorDatabase(const char *target,XColor *color)
{
  Colormap
    colormap;

  int
    status;

  static Display
    *display = (Display *) NULL;

  XColor
    xcolor;

  /*
    Initialize color return value.
  */
  assert(color != (XColor *) NULL);
  color->red=0;
  color->green=0;
  color->blue=0;
  color->flags=DoRed | DoGreen | DoBlue;
  if ((target == (char *) NULL) || (*target == '\0'))
    target="#ffffffffffff";
  /*
    Let the X server define the color for us.
  */
  if (display == (Display *) NULL)
    display=XOpenDisplay((char *) NULL);
  if (display == (Display *) NULL)
    {
      MagickError(XServerError,ColorIsNotKnownToServer,target);
      return(False);
    }
  colormap=XDefaultColormap(display,XDefaultScreen(display));
  status=XParseColor(display,colormap,(char *) target,&xcolor);
  if (status == False)
    MagickError(XServerError,ColorIsNotKnownToServer,target);
  else
    {
      color->red=xcolor.red;
      color->green=xcolor.green;
      color->blue=xcolor.blue;
      color->flags=xcolor.flags;
    }
  return(status != 0);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X Q u e r y P o s i t i o n                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXQueryPosition gets the pointer coordinates relative to a
%  window.
%
%  The format of the MagickXQueryPosition method is:
%
%      void MagickXQueryPosition(Display *display,const Window window,
%                                int *x,int *y)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a Window.
%
%    o x: Return the x coordinate of the pointer relative to the origin of the
%      window.
%
%    o y: Return the y coordinate of the pointer relative to the origin of the
%      window.
%
%
*/
MagickExport void
MagickXQueryPosition(Display *display,const Window window,int *x,int *y)
{
  int
    x_root,
    y_root;

  unsigned int
    mask;

  Window
    root_window;

  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(x != (int *) NULL);
  assert(y != (int *) NULL);
  (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
    x,y,&mask);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X R e f r e s h W i n d o w                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXRefreshWindow refreshes an image in a X window.
%
%  The format of the MagickXRefreshWindow method is:
%
%      void MagickXRefreshWindow(Display *display,
%        const MagickXWindowInfo *window,const XEvent *event)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
%      the entire image is refreshed.
%
%
*/
MagickExport void
MagickXRefreshWindow(Display *display,const MagickXWindowInfo *window,
                     const XEvent *event)
{
  int
    x,
    y;

  unsigned int
    height,
    width;

  assert(display != (Display *) NULL);
  assert(window != (MagickXWindowInfo *) NULL);
  if (window->ximage == (XImage *) NULL)
    return;
  if (event != (XEvent *) NULL)
    {
      /*
        Determine geometry from expose event.
      */
      x=event->xexpose.x;
      y=event->xexpose.y;
      width=event->xexpose.width;
      height=event->xexpose.height;
    }
  else
    {
      XEvent
        sans_event;

      /*
        Refresh entire window; discard outstanding expose events.
      */
      x=0;
      y=0;
      width=window->width;
      height=window->height;
      while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event));
    }
  /*
    Check boundary conditions.
  */
  if ((window->ximage->width-(x+window->x)) < (int) width)
    width=window->ximage->width-(x+window->x);
  if ((window->ximage->height-(y+window->y)) < (int) height)
    height=window->ximage->height-(y+window->y);
  /*
    Refresh image.
  */
  (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
  if (window->pixmap != (Pixmap) NULL)
    {
      if (window->depth > 1)
        (void) XCopyArea(display,window->pixmap,window->id,
          window->annotate_context,x+window->x,y+window->y,width,height,x,y);
      else
        (void) XCopyPlane(display,window->pixmap,window->id,
          window->highlight_context,x+window->x,y+window->y,width,height,
          x,y,1L);
    }
  else
    {
#if defined(HasSharedMemory)
      if (window->shared_memory)
        (void) XShmPutImage(display,window->id,window->annotate_context,
          window->ximage,x+window->x,y+window->y,x,y,width,height,True);
#endif /* defined(HasSharedMemory) */
      if (!window->shared_memory)
        (void) XPutImage(display,window->id,window->annotate_context,
          window->ximage,x+window->x,y+window->y,x,y,width,height);
    }
  (void) XSetClipMask(display,window->annotate_context,None);
  (void) XFlush(display);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X R e m o t e C o m m a n d                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  MagickXRemoteCommand() forces a remote display(1) to display the specified
%  image filename.
%
%  The format of the MagickXRemoteCommand method is:
%
%      unsigned int MagickXRemoteCommand(Display *display,const char *window,
%        const char *filename)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies the name or id of an X window.
%
%    o filename: The name of the image filename to display.
%
%
*/
MagickExport unsigned int
MagickXRemoteCommand(Display *display,const char *window,
                     const char *filename)
{
  Atom
    remote_atom;

  Window
    remote_window,
    root_window;

  assert(filename != (char *) NULL);
  if (display == (Display *) NULL)
    display=XOpenDisplay((char *) NULL);
  if (display == (Display *) NULL)
    {
      MagickError(XServerError,UnableToOpenXServer,(char *) NULL);
      return(False);
    }
  remote_atom=XInternAtom(display,"IM_PROTOCOLS",False);
  remote_window=(Window) NULL;
  root_window=XRootWindow(display,XDefaultScreen(display));
  if (window != (char *) NULL)
    {
      /*
        Search window hierarchy and identify any clients by name or ID.
      */
      if (isdigit((int) (*window)))
        remote_window=MagickXWindowByID(display,root_window,(Window)
          strtol((char *) window,(char **) NULL,0));
      if (remote_window == (Window) NULL)
        remote_window=MagickXWindowByName(display,root_window,window);
    }
  if (remote_window == (Window) NULL)
    remote_window=MagickXWindowByProperty(display,root_window,remote_atom);
  if (remote_window == (Window) NULL)
    {
      MagickError(XServerError,UnableToConnectToRemoteDisplay,(char *) NULL);
      return(False);
    }
  /*
    Send remote command.
  */
  remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",False);
  (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
    PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
  (void) XSync(display,False);
  return(True);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X R e t a i n W i n d o w C o l o r s                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXRetainWindowColors sets X11 color resources on a window.
%  This preserves the colors associated with an image displayed on the window.
%
%  The format of the MagickXRetainWindowColors method is:
%
%      void MagickXRetainWindowColors(Display *display,const Window window)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server; returned from
%      XOpenDisplay.
%
%    o window: Specifies a pointer to a MagickXWindowInfo structure.
%
%
*/
MagickExport void
MagickXRetainWindowColors(Display *display,const Window window)
{
  Atom
    property;

  Pixmap
    pixmap;

  /*
    Put property on the window.
  */
  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  property=XInternAtom(display,"_XSETROOT_ID",False);
  if (property == (Atom) NULL)
    {
      MagickError(XServerError,UnableToCreateProperty,"_XSETROOT_ID");
      return;
    }
  pixmap=XCreatePixmap(display,window,1,1,1);
  if (pixmap == (Pixmap) NULL)
    {
      MagickError(XServerError,UnableToCreatePixmap,(char *) NULL);
      return;
    }
  (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
    (unsigned char *) &pixmap,1);
  (void) XSetCloseDownMode(display,RetainPermanent);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S e l e c t W i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSelectWindow allows a user to select a window using the
%  mouse.  If the mouse moves, a cropping rectangle is drawn and the extents
%  of the rectangle is returned in the crop_info structure.
%
%  The format of the MagickXSelectWindow function is:
%
%      target_window=MagickXSelectWindow(display,crop_info)
%
%  A description of each parameter follows:
%
%    o window: MagickXSelectWindow returns the window id.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
%      contains the extents of any cropping rectangle.
%
%
*/
static Window
MagickXSelectWindow(Display *display,RectangleInfo *crop_info)
{
#define MinimumCropArea  (unsigned int) 9

  Cursor
    target_cursor;

  GC
    annotate_context;

  int
    presses,
    status,
    x_offset,
    y_offset;

  Window
    root_window,
    target_window;

  XEvent
    event;

  XGCValues
    context_values;

  /*
    Initialize graphic context.
  */
  assert(display != (Display *) NULL);
  assert(crop_info != (RectangleInfo *) NULL);
  root_window=XRootWindow(display,XDefaultScreen(display));
  context_values.background=XBlackPixel(display,XDefaultScreen(display));
  context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
  context_values.function=GXinvert;
  context_values.plane_mask=
    context_values.background ^ context_values.foreground;
  context_values.subwindow_mode=IncludeInferiors;
  annotate_context=XCreateGC(display,root_window,GCBackground | GCForeground |
    GCFunction | GCSubwindowMode,&context_values);
  if (annotate_context == (GC) NULL)
    return(False);
  /*
    Grab the pointer using target cursor.
  */
  target_cursor=MagickXMakeCursor(display,root_window,XDefaultColormap(display,
    XDefaultScreen(display)),(char *) "white",(char *) "black");
  status=XGrabPointer(display,root_window,False,(unsigned int)
    (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
    GrabModeAsync,root_window,target_cursor,CurrentTime);
  if (status != GrabSuccess)
    {
      MagickError(XServerError,UnableToGrabMouse,(char *) NULL);
      return(False);
    }
  /*
    Select a window.
  */
  crop_info->width=0;
  crop_info->height=0;
  presses=0;
  target_window=(Window) NULL;
  x_offset=0;
  y_offset=0;
  do
  {
    if ((crop_info->width*crop_info->height) >= MinimumCropArea)
      (void) XDrawRectangle(display,root_window,annotate_context,
        (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
        (unsigned int) crop_info->height-1);
    /*
      Allow another event.
    */
    (void) XAllowEvents(display,SyncPointer,CurrentTime);
    (void) XWindowEvent(display,root_window,ButtonPressMask |
      ButtonReleaseMask | ButtonMotionMask,&event);
    if ((crop_info->width*crop_info->height) >= MinimumCropArea)
      (void) XDrawRectangle(display,root_window,annotate_context,
        (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
        (unsigned int) crop_info->height-1);
    switch (event.type)
    {
      case ButtonPress:
      {
        target_window=MagickXGetSubwindow(display,event.xbutton.subwindow,
          event.xbutton.x,event.xbutton.y);
        if (target_window == (Window) NULL)
          target_window=root_window;
        x_offset=event.xbutton.x_root;
        y_offset=event.xbutton.y_root;
        crop_info->x=x_offset;
        crop_info->y=y_offset;
        crop_info->width=0;
        crop_info->height=0;
        presses++;
        break;
      }
      case ButtonRelease:
      {
        presses--;
        break;
      }
      case MotionNotify:
      {
        /*
          Discard pending button motion events.
        */
        while (XCheckMaskEvent(display,ButtonMotionMask,&event));
        crop_info->x=event.xmotion.x;
        crop_info->y=event.xmotion.y;
        /*
          Check boundary conditions.
        */
        if ((int) crop_info->x < x_offset)
          crop_info->width=(unsigned int) (x_offset-crop_info->x);
        else
          {
            crop_info->width=(unsigned int) (crop_info->x-x_offset);
            crop_info->x=x_offset;
          }
        if ((int) crop_info->y < y_offset)
          crop_info->height=(unsigned int) (y_offset-crop_info->y);
        else
          {
            crop_info->height=(unsigned int) (crop_info->y-y_offset);
            crop_info->y=y_offset;
          }
      }
      default:
        break;
    }
  }
  while ((target_window == (Window) NULL) || (presses > 0));
  (void) XUngrabPointer(display,CurrentTime);
  (void) XFreeCursor(display,target_cursor);
  (void) XFreeGC(display,annotate_context);
  if ((crop_info->width*crop_info->height) < MinimumCropArea)
    {
      crop_info->width=0;
      crop_info->height=0;
    }
  if ((crop_info->width != 0) && (crop_info->height != 0))
    target_window=root_window;
  return(target_window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S i g n a l H a n d l e r                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSignalHandler is called if the program execution is
%  interrupted.
%
%  The format of the MagickXSignalHandler method is:
%
%      void MagickXSetCursorState(Display *display,MagickXWindows *windows,
%        const unsigned int state)
%
%
*/

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

MagickExport void
MagickXSignalHandler(int status)
{
  DestroyMagick();
  Exit(status);
}

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S e t C u r s o r S t a t e                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSetCursorState sets the cursor state to busy, otherwise the
%  cursor are reset to their default.
%
%  The format of the XMagickXSetCursorState method is:
%
%      MagickXSetCursorState(display,windows,state)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o windows: Specifies a pointer to a MagickXWindows structure.
%
%    o state: An unsigned integer greater than 0 sets the cursor state
%      to busy, otherwise the cursor are reset to their default.
%
%
*/
MagickExport void
MagickXSetCursorState(Display *display,
                      MagickXWindows *windows,
                      const unsigned int state)
{
  assert(display != (Display *) NULL);
  assert(windows != (MagickXWindows *) NULL);
  if (state)
    {
      (void) XDefineCursor(display,windows->image.id,
        windows->image.busy_cursor);
      (void) XDefineCursor(display,windows->pan.id,windows->pan.busy_cursor);
      (void) XDefineCursor(display,windows->magnify.id,
        windows->magnify.busy_cursor);
      (void) XDefineCursor(display,windows->command.id,
        windows->command.busy_cursor);
    }
  else
    {
      (void) XDefineCursor(display,windows->image.id,windows->image.cursor);
      (void) XDefineCursor(display,windows->pan.id,windows->pan.cursor);
      (void) XDefineCursor(display,windows->magnify.id,windows->magnify.cursor);
      (void) XDefineCursor(display,windows->command.id,windows->command.cursor);
      (void) XDefineCursor(display,windows->command.id,windows->widget.cursor);
      (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
    }
  windows->info.mapped=False;
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X S e t W i n d o w s                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXSetWindows sets the X windows structure if the windows info
%  is specified.  Otherwise the current windows structure is returned.
%
%  The format of the MagickXSetWindows method is:
%
%      MagickXWindows *MagickXSetWindows(MagickXWindows *windows_info)
%
%  A description of each parameter follows:
%
%    o windows: Method MagickXSetWindows returns a pointer to the
%      MagickXWindows structure.
%
%    o windows_info: Initialize the Windows structure with this information.
%
*/
MagickExport MagickXWindows *
MagickXSetWindows(MagickXWindows *windows_info)
{
  static MagickXWindows
    *windows = (MagickXWindows *) NULL;

  if (windows_info != (MagickXWindows *) ~0)
    {
      MagickFreeMemory(windows);
      windows=windows_info;
    }
  return(windows);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X U s e r P r e f e r e n c e s                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXUserPreferences saves the preferences in a configuration
%  file in the users' home directory.
%
%  The format of the MagickXUserPreferences method is:
%
%      void MagickXUserPreferences(MagickXResourceInfo *resource_info)
%
%  A description of each parameter follows:
%
%    o resource_info: Specifies a pointer to a X11 MagickXResourceInfo
%      structure.
%
%
*/
MagickExport void
MagickXUserPreferences(MagickXResourceInfo *resource_info)
{
#if defined(PreferencesDefaults)
  const char
    *client_name;

  char
    cache[MaxTextExtent],
    filename[MaxTextExtent],
    specifier[MaxTextExtent];

  const char
    *value;

  XrmDatabase
    preferences_database;

  /*
    Save user preferences to the client configuration file.
  */
  assert(resource_info != (MagickXResourceInfo *) NULL);
  client_name=GetClientName();
  preferences_database=XrmGetStringDatabase("");
  FormatString(specifier,"%.1024s.backdrop",client_name);
  value=MagickBoolToString(resource_info->backdrop);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.colormap",client_name);
  value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.confirmExit",client_name);
  value=MagickBoolToString(resource_info->confirm_exit);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.displayWarnings",client_name);
  value=MagickBoolToString(resource_info->display_warnings);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.dither",client_name);
  value=MagickBoolToString(resource_info->quantize_info->dither);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.gammaCorrect",client_name);
  value=MagickBoolToString(resource_info->gamma_correct);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(specifier,"%.1024s.undoCache",client_name);
  FormatString(cache,"%lu",resource_info->undo_cache);
  XrmPutStringResource(&preferences_database,specifier,cache);
  FormatString(specifier,"%.1024s.usePixmap",client_name);
  value=MagickBoolToString(resource_info->use_pixmap);
  XrmPutStringResource(&preferences_database,specifier,(char *) value);
  FormatString(filename,"%.1024s%.1024src",PreferencesDefaults,client_name);
  ExpandFilename(filename);
  XrmPutFileDatabase(preferences_database,filename);
#endif /* defined(PreferencesDefaults) */
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X V i s u a l C l a s s N a m e                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXVisualClassName returns the visual class name as a character
%  string.
%
%  The format of the MagickXVisualClassName method is:
%
%      char *MagickXVisualClassName(const int visual_class)
%
%  A description of each parameter follows:
%
%    o visual_type: MagickXVisualClassName returns the visual class as a
%      character string.
%
%    o class: Specifies the visual class.
%
%
*/
static char *
MagickXVisualClassName(const int visual_class)
{
  switch (visual_class)
  {
    case StaticGray: return((char *) "StaticGray");
    case GrayScale: return((char *) "GrayScale");
    case StaticColor: return((char *) "StaticColor");
    case PseudoColor: return((char *) "PseudoColor");
    case TrueColor: return((char *) "TrueColor");
    case DirectColor: return((char *) "DirectColor");
  }
  return((char *) "unknown visual class");
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W a r n i n g                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWarning displays a warning reason in a Notice widget.
%
%  The format of the MagickXWarning method is:
%
%      void MagickXWarning(const unsigned int warning,const char *reason,
%        const char *description)
%
%  A description of each parameter follows:
%
%    o warning: Specifies the numeric warning category.
%
%    o reason: Specifies the reason to display before terminating the
%      program.
%
%    o description: Specifies any description to the reason.
%
%
*/
MagickExport void
MagickXWarning(const ExceptionType warning,
               const char *reason,const char *description)
{
  char
    text[MaxTextExtent];

  MagickXWindows
    *windows;

  ARG_NOT_USED(warning);
  if (reason == (char *) NULL)
    return;
  (void) strlcpy(text,reason,MaxTextExtent);
  (void) strlcat(text,":",MaxTextExtent);
  windows=MagickXSetWindows((MagickXWindows *) ~0);
  MagickXNoticeWidget(windows->display,windows,text,(char *) description);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W i n d o w B y I D                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWindowByID locates a child window with a given ID.  If not
%  window with the given name is found, 0 is returned.   Only the window
%  specified and its subwindows are searched.
%
%  The format of the MagickXWindowByID function is:
%
%      child=MagickXWindowByID(display,window,id)
%
%  A description of each parameter follows:
%
%    o child: MagickXWindowByID returns the window with the specified
%      id.  If no windows are found, MagickXWindowByID returns 0.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o id: Specifies the id of the window to locate.
%
%
*/
MagickExport Window
MagickXWindowByID(Display *display,const Window root_window,
                  const unsigned long id)
{
  RectangleInfo
    rectangle_info;

  register int
    i;

  unsigned int
    number_children;

  Window
    child,
    *children,
    window;

  assert(display != (Display *) NULL);
  assert(root_window != (Window) NULL);
  if (id == 0)
    return(MagickXSelectWindow(display,&rectangle_info));
  if (root_window == id)
    return(id);
  if (!XQueryTree(display,root_window,&child,&child,&children,&number_children))
    return((Window) NULL);
  window=(Window) NULL;
  for (i=0; i < (int) number_children; i++)
  {
    /*
      Search each child and their children.
    */
    window=MagickXWindowByID(display,children[i],id);
    if (window != (Window) NULL)
      break;
  }
  if (children != (Window *) NULL)
    (void) XFree((void *) children);
  return(window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W i n d o w B y N a m e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWindowByName locates a window with a given name on a display.
%  If no window with the given name is found, 0 is returned. If more than
%  one window has the given name, the first one is returned.  Only root and
%  its children are searched.
%
%  The format of the MagickXWindowByName function is:
%
%      window=MagickXWindowByName(display,root_window,name)
%
%  A description of each parameter follows:
%
%    o window: MagickXWindowByName returns the window id.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o root_window: Specifies the id of the root window.
%
%    o name: Specifies the name of the window to locate.
%
%
*/
MagickExport Window
MagickXWindowByName(Display *display,const Window root_window,
                    const char *name)
{
  register int
    i;

  unsigned int
    number_children;

  Window
    *children,
    child,
    window;

  XTextProperty
    window_name;

  assert(display != (Display *) NULL);
  assert(root_window != (Window) NULL);
  assert(name != (char *) NULL);
  if (XGetWMName(display,root_window,&window_name) != 0)
    if (LocaleCompare((char *) window_name.value,name) == 0)
      return(root_window);
  if (!XQueryTree(display,root_window,&child,&child,&children,&number_children))
    return((Window) NULL);
  window=(Window) NULL;
  for (i=0; i < (int) number_children; i++)
  {
    /*
      Search each child and their children.
    */
    window=MagickXWindowByName(display,children[i],name);
    if (window != (Window) NULL)
      break;
  }
  if (children != (Window *) NULL)
    (void) XFree((void *) children);
  return(window);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a g i c k X W i n d o w B y P r o p e r y                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method MagickXWindowByProperty locates a child window with a given property.
%  If no window with the given name is found, 0 is returned.  If more than
%  one window has the given property, the first one is returned.  Only the
%  window specified and its subwindows are searched.
%
%  The format of the MagickXWindowByProperty function is:
%
%      child=MagickXWindowByProperty(display,window,property)
%
%  A description of each parameter follows:
%
%    o child: MagickXWindowByProperty returns the window id with the specified
%      property.  If no windows are found, MagickXWindowByProperty returns 0.
%
%    o display: Specifies a pointer to the Display structure;  returned from
%      XOpenDisplay.
%
%    o property: Specifies the property of the window to locate.
%
%
*/
MagickExport Window
MagickXWindowByProperty(Display *display,const Window window,
                        const Atom property)
{
  Atom
    type;

  int
    format,
    status;

  unsigned char
    *data;

  unsigned int
    i,
    number_children;

  unsigned long
    after,
    number_items;

  Window
    child,
    *children,
    parent,
    root;

  assert(display != (Display *) NULL);
  assert(window != (Window) NULL);
  assert(property != (Atom) NULL);
  status=XQueryTree(display,window,&root,&parent,&children,&number_children);
  if (status == 0)
    return((Window) NULL);
  type=(Atom) NULL;
  child=(Window) NULL;
  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
  {
    status=XGetWindowProperty(display,children[i],property,0L,0L,False,
      (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
    if (data != NULL)
      (void) XFree((void *) data);
    if ((status == Success) && (type != (Atom) NULL))
      child=children[i];
  }
  for (i=0; (i < number_children) && (child == (Window) NULL); i++)
    child=MagickXWindowByProperty(display,children[i],property);
  if (children != (Window *) NULL)
    (void) XFree((void *) children);
  return(child);
}
#endif /* HasX11 */
