v13i033: ImageMagick - Graphics display programs, Part17/21

cristy at dupont.com cristy at dupont.com
Fri May 24 13:20:24 AEST 1991


Submitted-by: cristy at dupont.com
Posting-number: Volume 13, Issue 33
Archive-name: imagemagic/part17

#!/bin/sh
# this is img.17 (part 17 of ImageMagick)
# do not concatenate these parts, unpack them in order with /bin/sh
# file ImageMagick/display.c continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 17; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping ImageMagick/display.c'
else
echo 'x - continuing file ImageMagick/display.c'
sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/display.c' &&
%    3    press and drag to define a region of the image to magnify
%
%  Keys
%    1-9  press to change the level of magnification
%    <    press to half the image size
%    >    press to double the image size
%    /    press to rotate the image 90 degrees clockwise
%    \    press to rotate the image 90 degrees counter-clockwise
%    r    press to reflect the image scanlines
%    o    press to restore the image to its original size
%    w    press to restore the image window to its original size
%    m    press to map or unmap the magnify window
%    i    press to display information about the image
%    n    press to display the next image
%    q    press to discard all images and exit program
%
%
*/
X
/*
X  Include declarations.
*/
#include "display.h"
#include "image.h"
#include "X.h"
X
/*
X  Define declarations.
*/
#define ConstrainMagnifyFactor(image_window,magnify_window,magnify)  \
{  \
X  while ((magnify*image_window->ximage->width) < magnify_window->width)  \
X    magnify<<=1;  \
X  while ((magnify*image_window->ximage->height) < magnify_window->height)  \
X    magnify<<=1;  \
X  if (magnify > magnify_window->width)  \
X    magnify=magnify_window->width;  \
X  if (magnify > magnify_window->height)  \
X    magnify=magnify_window->height;  \
}
#define ConfigureWindowState  0x0001
#define ControlState  0x0002
#define DefaultState  0x0004
#define ExitState  0x0008
#define ImageMappedState  0x0010
#define HighlightState  0x0020
#define InfoMappedState  0x0040
#define MagnifyState  0x0080
#define MagnifyMappedState  0x0100
X
/*
X  Forward declarations.
*/
static Cursor
X  XMakeCursor();
X
static unsigned int
X  XReflectImageWindow(),
X  XResizeImageWindow(),
X  XRotateImageWindow();
X
static void
X  XDisplayImageWindow(),
X  XMagnifyImageWindow(),
X  XMakeMagnifyImage(),
X  XMenuWindow(),
X  XPanImageWindow();
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   E r r o r                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function Error displays an error message and then terminates the program.
%
%  The format of the Error routine is:
%
%      Error(message,qualifier)
%
%  A description of each parameter follows:
%
%    o message: Specifies the message to display before terminating the
%      program.
%
%    o qualifier: Specifies any qualifier to the message.
%
%
*/
void Error(message,qualifier)
char
X  *message,
X  *qualifier;
{
X  (void) fprintf(stderr,"%s: %s",application_name,message);
X  if (qualifier != (char *) NULL)
X    (void) fprintf(stderr," (%s)",qualifier);
X  (void) fprintf(stderr,".\n");
X  exit(1);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   U s a g e                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function Usage displays the program command syntax.
%
%  The format of the Usage routine is:
%
%      Usage(message,terminate)
%
%  A description of each parameter follows:
%
%    o message: Specifies a specific message to display to the user.
%
%    o terminate: A value other than zero is returned if the program is to 
%      terminate immediately.
%
*/
static void Usage(message,terminate)
char
X  *message;
X
unsigned int
X  terminate;
{
X  char
X    **p;
X
X  static char
X    *buttons[]=
X    {
X      "Control-1",
X      "     press and drag to pan the image",
X      "1    press and drag to select a command from a pop-up menu",
X      "2    press and drag to define a region of the image to clip",
X      "3    press and drag to define a region of the image to magnify",
X      (char *) NULL
X    },
X    *keys[]=
X    {
X      "1-9  press to change the level of magnification",
X      "<    press to half the image size",
X      ">    press to double the image size",
X      "/    press to rotate the image 90 degrees clockwise",
X      "\\    press to rotate the image 90 degrees counter-clockwise",
X      "r    press to reflect the image scanlines",
X      "o    press to restore the image to its original size",
X      "w    press to restore the image window to its original size",
X      "m    press to map or unmap the magnify window",
X      "i    press to display information about the image",
X      "n    press to display the next image",
X      "q    press to discard all images and exit program",
X      (char *) NULL
X    },
X    *options[]=
X    {
X      "-backdrop           display image centered on a backdrop",
X      "-clip geometry      preferred size and location of the clipped image",
X      "-colors value       preferred number of colors in the image",
X      "-compress type      compress image: RunlengthEncoded or QEncoded",
X      "-delay seconds      display the next image after pausing",
X      "-display server     display image to this X server",
X      "-dither             apply Floyd/Steinberg error diffusion to image",
X      "-enhance            apply a digital filter to enhance a noisy image",
X      "-gamma value        level of gamma correction",
X      "-geometry geometry  preferred size and location of the image window",
X      "-gray               transform image to gray scale colors",
X      "-inverse            apply color inversion to image",
X      "-magnify value      level of image magnification",
X      "-map type           display image using this Standard Colormap",
X      "-monochrome         transform image to black and white",
X      "-noise              reduce noise with a noise peak elimination filter",
X      "-normalize          tranform image to span the full range of colors",
X      "-print file         write image as Postscript to a file",
X      "-reflect            reflect the image scanlines",
X      "-root               display image on the root window",
X      "-rotate degrees     apply Paeth rotation to the image",
X      "-scale geometry     preferred size factors of the image",
X      "-scene number       image scene number",
X      "-treedepth value    depth of the color classification tree",
X      "-verbose            print detailed information about the image",
X      "-visual type        display image using this visual type",
X      "-write file         write image to a file",
X      (char *) NULL
X    };
X  if (message != (char *) NULL)
X    (void) fprintf(stderr,"Can't continue, %s\n\n",message);
X  (void) fprintf(stderr,
X    "Usage: %s [-options ...] file [ [-options ...] file ...]\n",
X    application_name);
X  (void) fprintf(stderr,"\nWhere options include: \n");
X  for (p=options; *p != (char *) NULL; p++)
X    (void) fprintf(stderr,"  %s\n",*p);
X  (void) fprintf(stderr,
X    "\nIn addition to those listed above, you can specify these standard X\n");
X  (void) fprintf(stderr,
X    "resources as command line options:  -background, -bordercolor,\n");
X  (void) fprintf(stderr,
X    "-borderwidth, -font, -foreground, -iconGeometry, -iconic, -name, or\n");
X  (void) fprintf(stderr,"-title.\n");
X  (void) fprintf(stderr,
X    "\nChange '-' to '+' in any option above to reverse its effect.  For\n");
X  (void) fprintf(stderr,
X    "example, specify +compress to store the image as uncompressed.\n");
X  (void) fprintf(stderr,
X    "\nSpecify 'file' as '-' for standard input or output.\n");
X  (void) fprintf(stderr,"\nButtons: \n");
X  for (p=buttons; *p != (char *) NULL; p++)
X    (void) fprintf(stderr,"  %s\n",*p);
X  (void) fprintf(stderr,"\nKeys: \n");
X  for (p=keys; *p != (char *) NULL; p++)
X    (void) fprintf(stderr,"  %s\n",*p);
X  if (terminate)
X    exit(1);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   U s e r C o m m a n d                                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function UserCommand makes a transform to the image or image window as
%  specified by a user menu button or keyboard command.
%
%  The format of the UserCommand routine is:
%
%    UserCommand(display,resource_info,info_window,image_window,magnify_window,
%      image,command,timeout,state);
%
%  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 XResourceInfo structure.
%
%    o info_window: Specifies a pointer to a XWindowInfo structure.
%
%    o image_window: Specifies a pointer to a XWindowInfo structure.
%
%    o magnify_window: Specifies a pointer to a XWindowInfo structure.
%
%    o image: Specifies a pointer to a Image structure;  UserCommand
%      may transform the image and return a new image pointer.
%
%    o timeout: Specifies an unsigned long;  UserCommand may modify this
%      value.
%
%    o state: Specifies an unsigned int;  UserCommand may return a
%      modified state.
%
%
*/
static void UserCommand(display,resource_info,info_window,image_window,
X  magnify_window,command,image,timeout,state)
Display
X  *display;
X
XXResourceInfo
X  *resource_info;
X
XXWindowInfo
X  *info_window,
X  *image_window,
X  *magnify_window;
X
char
X  *command;
X
Image
X  **image;
X
unsigned long
X  *timeout;
X
unsigned int
X  *state;
{
X  XWindowInfo
X    window;
X
X  XWindowChanges
X    window_changes;
X
X  if (*state & InfoMappedState)
X    XWithdrawWindow(display,info_window->id,info_window->screen);
X  /*
X    Process user command.
X  */
X  switch (*command)
X  {
X    case 'i':
X    {
X      char
X        text[256];
X
X      /*
X        Display information about the image in the info window.
X      */
X      (void) sprintf(text,"[%d] %s %dx%d %s \0",(*image)->scene,
X        (*image)->filename,image_window->ximage->width,
X        image_window->ximage->height,
X        XVisualClassName(info_window->visual_info));
X      if ((*image)->colors > 0)
X        (void) sprintf(text,"%s%dc \0",text,(*image)->colors);
X      info_window->width=XTextWidth(info_window->font_info,text,strlen(text));
X      info_window->height=
X        info_window->font_info->ascent+info_window->font_info->descent+4;
X      XResizeWindow(display,info_window->id,info_window->width,
X        info_window->height);
X      XMapWindow(display,info_window->id);
X      XClearWindow(display,info_window->id);
X      XDrawString(display,info_window->id,info_window->graphic_context,2,
X        info_window->font_info->ascent+2,text,strlen(text));
X      break;
X    }
X    case '<':
X    case '>':
X    {
X      /*
X        Half or double the image size.
X      */
X      window=(*image_window);
X      if (*command == '>')
X        {
X          window.width=image_window->ximage->width << 1;
X          window.height=image_window->ximage->height << 1;
X        }
X      else
X        {
X          window.width=image_window->ximage->width >> 1;
X          window.height=image_window->ximage->height >> 1;
X          if ((window.width == 0) || (window.height == 0))
X            break;
X        }
X      (void) XResizeImageWindow(display,resource_info,info_window,&window,
X        *image);
X      image_window->ximage=window.ximage;
X      window_changes.width=image_window->ximage->width;
X      if (window_changes.width > XDisplayWidth(display,image_window->screen))
X        window_changes.width=XDisplayWidth(display,image_window->screen);
X      window_changes.height=image_window->ximage->height;
X      if (window_changes.height > XDisplayHeight(display,image_window->screen))
X        window_changes.height=XDisplayHeight(display,image_window->screen);
X      if ((image_window->width == window_changes.width) &&
X          (image_window->height == window_changes.height))
X        XDisplayImageWindow(display,image_window,0,0,image_window->width,
X          image_window->height);
X      else
X        {
X          /*
X            Resize image window.
X          */
X          XReconfigureWMWindow(display,image_window->id,image_window->screen,
X            CWWidth | CWHeight,&window_changes);
X          *state|=ConfigureWindowState;
X        }
X      break;
X    }
X    case '/':
X    case '\\':
X    {
X      unsigned int
X        status;
X
X      /*
X        Rotate image 90 degrees to the right or left.
X      */
X      status=XRotateImageWindow(display,info_window,image_window,
X        (unsigned int) (*command == '/' ? 90 : 270),image);
X      if (!status)
X        break;
X      window=(*image_window);
X      window.width=image_window->ximage->height;
X      window.height=image_window->ximage->width;
X      (void) XResizeImageWindow(display,resource_info,info_window,&window,
X        *image);
X      image_window->ximage=window.ximage;
X      window_changes.width=image_window->ximage->width;
X      if (window_changes.width > XDisplayWidth(display,image_window->screen))
X        window_changes.width=XDisplayWidth(display,image_window->screen);
X      window_changes.height=image_window->ximage->height;
X      if (window_changes.height > XDisplayHeight(display,image_window->screen))
X        window_changes.height=XDisplayHeight(display,image_window->screen);
X      if ((image_window->width == window_changes.width) &&
X          (image_window->height == window_changes.height))
X        XDisplayImageWindow(display,image_window,0,0,image_window->width,
X          image_window->height);
X      else
X        {
X          /*
X            Resize image window.
X          */
X          XReconfigureWMWindow(display,image_window->id,image_window->screen,
X            CWWidth | CWHeight,&window_changes);
X          *state|=ConfigureWindowState;
X        }
X      break;
X    }
X    case 'r':
X    {
X      /*
X        Reflect image scanlines.
X      */
X      (void) XReflectImageWindow(display,info_window,image_window,image);
X      (void) XResizeImageWindow(display,resource_info,info_window,image_window,
X        *image);
X      XDisplayImageWindow(display,image_window,0,0,image_window->width,
X        image_window->height);
X      break;
X    }
X    case 'o':
X    case 'w':
X    {
X      /*
X        Restore image or image window to its original size.
X      */
X      if (image_window->clip_geometry != (char *) NULL)
X        {
X          unsigned int
X            clip_height,
X            clip_width;
X
X          /*
X            Retain the image clipping offsets;  discard geometry.
X          */
X          (void) XParseGeometry(image_window->clip_geometry,&image_window->x,
X            &image_window->y,&clip_width,&clip_height);
X          image_window->x=(-image_window->x);
X          image_window->y=(-image_window->y);
X          (void) free((char *) image_window->clip_geometry);
X          image_window->clip_geometry=(char *) NULL;
X        }
X      window=(*image_window);
X      window.width=(*image)->columns;
X      window.height=(*image)->rows;
X      (void) XResizeImageWindow(display,resource_info,info_window,&window,
X        *image);
X      image_window->ximage=window.ximage;
X      window_changes.width=image_window->ximage->width;
X      if (window_changes.width > XDisplayWidth(display,image_window->screen))
X        window_changes.width=XDisplayWidth(display,image_window->screen);
X      window_changes.height=image_window->ximage->height;
X      if (window_changes.height > XDisplayHeight(display,image_window->screen))
X        window_changes.height=XDisplayHeight(display,image_window->screen);
X      if ((*command == 'o') ||
X          ((image_window->width == window_changes.width) &&
X           (image_window->height == window_changes.height)))
X        XDisplayImageWindow(display,image_window,0,0,image_window->width,
X          image_window->height);
X      else
X        {
X          /*
X            Resize image window.
X          */
X          XReconfigureWMWindow(display,image_window->id,image_window->screen,
X            CWWidth | CWHeight,&window_changes);
X          *state|=ConfigureWindowState;
X        }
X      break;
X    }
X    case 'm':
X    {
X      /*
X        Unmap or unmap magnify image.
X      */
X      if (*state & MagnifyMappedState)
X        XWithdrawWindow(display,magnify_window->id,magnify_window->screen);
X      else
X        {
X          ConstrainMagnifyFactor(image_window,magnify_window,
X            resource_info->magnify);
X          XMakeMagnifyImage(magnify_window,image_window->ximage,
X            resource_info->magnify);
X          XMapRaised(display,magnify_window->id);
X        }
X      break;
X    }
X    case 'n':
X    {
X      /*
X        Display next image.
X      */
X      *timeout=0;
X      break;
X    }
X    case 'q':
X    {
X      /*
X        Exit program
X      */
X      *state|=ExitState;  /* exit program */
X      break;
X    }
X    case ' ':
X    case '\0':
X      break;
X    default:
X    {
X      XBell(display,0);
X      break;
X    }
X  }
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   X C l i p I m a g e W i n d o w                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function XClipImageWindow displays a rectangle whose sizes changes as
%  the pointer moves.  When the mouse button is released, the geometry of
%  the image region defined within the rectangle is returned.
%
%  The format of the XClipImageWindow routine is:
%
%    XClipImageWindow(display,info_window,image_window,image,x_offset,y_offset)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o info_window: Specifies a pointer to a XWindowInfo structure.
%
%    o image_window: Specifies a pointer to a XWindowInfo structure.
%
%    o image: Specifies a pointer to a Image structure; returned from
%      ReadImage.
%
%    o x_offset: Specifies the initial offset in the x-direction of the
%      rectangle.
%
%    o y_offset: Specifies the initial offset in the y-direction of the
%      rectangle.
%
%
*/
static void XClipImageWindow(display,info_window,image_window,image,x_offset,
X  y_offset)
Display
X  *display;
X
XXWindowInfo
X  *info_window,
X  *image_window;
X
Image
X  *image;
X
int
X  x_offset,
X  y_offset;
{
#define ClipRectangle(x,y,width,height)  \
{  \
X  if ((width >= MinRectangle) && (height >= MinRectangle))  \
X    {  \
X      XSetFunction(display,image_window->graphic_context,GXinvert);  \
X      XDrawRectangle(display,image_window->id,image_window->graphic_context,  \
X        x,y,width-1,height-1);  \
X      XDrawRectangle(display,image_window->id,image_window->graphic_context,  \
X        x+1,y+1,width-3,height-3);  \
X      XSetFunction(display,image_window->graphic_context,GXcopy);  \
X    }  \
}
#define MinRectangle  3
X
X  char
X    text[256];
X
X  register int
X    x,
X    y;
X
X  register unsigned int
X    height,
X    width;
X
X  unsigned int
X    state;
X
X  XEvent
X    event;
X
X  /*
X    Set the width of info window.
X  */
X  state=DefaultState;
X  (void) sprintf(text," %dx%d%+d%+d \0",image_window->width,
X    image_window->height,image_window->width,image_window->height);
X  info_window->width=XTextWidth(info_window->font_info,text,strlen(text));
X  info_window->height=
X    info_window->font_info->ascent+info_window->font_info->descent+4;
X  XResizeWindow(display,info_window->id,info_window->width,
X    info_window->height);
X  /*
X    Size rectangle as pointer moves until the mouse button is released.
X  */
X  x=x_offset;
X  y=y_offset;
X  width=0;
X  height=0;
X  do
X  {
X    if ((width >= MinRectangle) && (height >= MinRectangle))
X      {
X        /*
X          Display info and draw clipping rectangle.
X        */
X        if (!(state & InfoMappedState))
X          {
X            XMapWindow(display,info_window->id);
X            state|=InfoMappedState;
X          }
X        (void) sprintf(text," %dx%d%+d%+d\0",width,height,x,y);
X        XClearWindow(display,info_window->id);
X        XDrawString(display,info_window->id,info_window->graphic_context,2,
X          info_window->font_info->ascent+2,text,strlen(text));
X        ClipRectangle(x,y,width,height);
X      }
X    else
X      if (state & InfoMappedState)
X        {
X          /*
X            Clipping rectangle is too small;  withdraw info window.
X          */
X          XWithdrawWindow(display,info_window->id,info_window->screen);
X          state&=(~InfoMappedState);
X        }
X    /*
X      Wait for next event.
X    */
X    XMaskEvent(display,ButtonPressMask | Button2MotionMask | ButtonReleaseMask,
X      &event);
X    ClipRectangle(x,y,width,height);
X    switch (event.type)
X    {
X      case ButtonPress:
X        break;
X      case ButtonRelease:
X      {
X        /*
X          User has committed to clipping rectangle.
X        */
X        if (event.xbutton.button != Button2)
X          break;
X        state|=ExitState;
X        break;
X      }
X      case MotionNotify:
X      {
X        /*
X          Discard pending button motion events.
X        */
X        while (XCheckMaskEvent(display,Button2MotionMask,&event));
X        x=event.xmotion.x;
X        y=event.xmotion.y;
X        /*
X          Check boundary conditions.
X        */
X        if (x < 0)
X          x=0;
X        else
X          if (x > image_window->width)
X            x=image_window->width-1;
X        if (x < x_offset)
X          width=(unsigned int) (x_offset-x);
X        else
X          {
X            width=(unsigned int) (x-x_offset);
X            x=x_offset;
X          }
X        if (y < 0)
X          y=0;
X        else
X          if (y > image_window->height)
X            y=image_window->height-1;
X        if (y < y_offset)
X          height=(unsigned int) (y_offset-y);
X        else
X          {
X            height=(unsigned int) (y-y_offset);
X            y=y_offset;
X          }
X      }
X      default:
X        break;
X    }
X  } while (!(state & ExitState));
X  if (state & InfoMappedState)
X    XWithdrawWindow(display,info_window->id,info_window->screen);
X  if ((width >= MinRectangle) && (height >= MinRectangle))
X    {
X      int
X        clip_x,
X        clip_y;
X
X      unsigned int
X        clip_height,
X        clip_width;
X
X      unsigned long
X        scale_factor;
X
X      XWindowChanges
X        window_changes;
X
X      /*
X        Check boundary conditions.
X      */
X      if (((x+(int) width) < image_window->x) ||
X          ((y+(int) height) < image_window->y) ||
X          (x > (image_window->x+image_window->ximage->width)) ||
X          (y > (image_window->y+image_window->ximage->height)))
X        return;
X      if (x < image_window->x)
X        {
X          width-=(unsigned int) (image_window->x-x);
X          x=image_window->x;
X        }
X      if (y < image_window->y)
X        {
X          height-=(unsigned int) (image_window->y-y);
X          y=image_window->y;
X        }
X      if ((x+(int) width) > (image_window->x+image_window->ximage->width))
X        width=(unsigned int) (image_window->x+image_window->ximage->width);
X      if ((y+(int) height) > (image_window->y+image_window->ximage->height))
X        height=(unsigned int) (image_window->y+image_window->ximage->height);
X      x-=image_window->x;
X      y-=image_window->y;
X      /*
X        Clipping geometry is relative to any previous clip geometry.
X      */
X      clip_x=0;
X      clip_y=0;
X      clip_width=image->columns;
X      clip_height=image->rows;
X      if (image_window->clip_geometry != (char *) NULL)
X        (void) XParseGeometry(image_window->clip_geometry,&clip_x,&clip_y,
X          &clip_width,&clip_height);
X      else
X        {
X          /*
X            Allocate clip geometry string.
X          */
X          image_window->clip_geometry=(char *) malloc(256);
X          if (image_window->clip_geometry == (char *) NULL)
X            Error("unable to clip X image",image_window->name);
X        }
X      /*
X        Define the clip geometry string from the clipping rectangle.
X      */
X      scale_factor=(clip_width << 14)/image_window->ximage->width;
X      if (x > 0)
X        clip_x+=(x*scale_factor+8191) >> 14;
X      clip_width=(width*scale_factor+8191) >> 14;
X      if (clip_width == 0)
X        clip_width=1;
X      scale_factor=(clip_height << 14)/image_window->ximage->height;
X      if (y > 0)
X        clip_y+=(y*scale_factor+8191) >> 14;
X      clip_height=(height*scale_factor+8191) >> 14;
X      if (clip_height == 0)
X        clip_height=1;
X      (void) sprintf(image_window->clip_geometry,"%dx%d%+d%+d\0",clip_width,
X        clip_height,clip_x,clip_y);
X      /*
X        Reconfigure image window as defined by clipping rectangle.
X      */
X      window_changes.width=width;
X      window_changes.height=height;
X      XReconfigureWMWindow(display,image_window->id,image_window->screen,
X        CWWidth | CWHeight,&window_changes);
X    }
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   X D i s p l a y I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function XDisplayImage displays an image via X11.
%
%  The format of the XDisplayImage routine is:
%
%      displayed_image=XDisplayImage(display,resource_info,argv,argc,image,
%        clip_geometry,image_geometry,terminate)
%
%  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 XResourceInfo structure.
%
%    o argv: Specifies the application's argument list.
%
%    o argc: Specifies the number of arguments.
%
%    o image: Specifies a pointer to a Image structure; returned from
%      ReadImage.
%
%    o clip_geometry: Returns a pointer to a clip geometry string.
%      This geometry defines a subregion of the image.
%
%    o image_geometry: Returns a pointer to a image geometry string.
%      The specified width and height of this geometry string are absolute.
%
%    o terminate: A value other than zero is returned if the user requests
%      the program to terminate immediately.
%
%
*/
static Image *XDisplayImage(display,resource_info,argv,argc,image,
X  clip_geometry,image_geometry,terminate)
Display
X  *display;
X
XXResourceInfo
X  *resource_info;
X
char
X  **argv;
X
int
X  argc;
X
Image
X  *image;
X
char
X  **clip_geometry,
X  **image_geometry;
X
unsigned int
X  *terminate;
{
#define MagnifySize  256  /* must be a power of 2 */
X
X  Atom
X    delete_property,
X    protocols_property;
X
X  Colormap
X    colormap;
X
X  char
X    text[256];
X
X  Cursor
X    arrow_cursor,
X    watch_cursor;
X
X  GC
X    graphic_context;
X
X  unsigned int
X    state;
X
X  unsigned long
X    timeout;
X
X  Window
X    root_window;
X
X  XClassHint
X    *class_hint;
X
X  XColor
X    color;
X
X  XEvent
X    event;
X
X  XFontStruct
X    *font_info;
X
X  XGCValues
X    graphic_context_value;
X
X  XPixelInfo
X    pixel_info;
X
X  XStandardColormap
X    *map_info;
X
X  XVisualInfo
X    *visual_info;
X
X  XWindowInfo
X    backdrop_window,
X    icon_window,
X    image_window,
X    info_window,
X    magnify_window,
X    menu_window,
X    superclass_window;
X
X  XWMHints
X    *manager_hints;
X
X  /*
X    Discard outstanding X events.
X  */
X  while (XEventsQueued(display,QueuedAfterFlush) > 0)
X    XNextEvent(display,&event);
X  /*
X    Get the best visual this server supports.
X  */
X  visual_info=XBestVisualInfo(display,resource_info->visual_type,
X    resource_info->map_type,&map_info);
X  if (visual_info == (XVisualInfo *) NULL)
X    Error("unable to get visual",resource_info->visual_type);
X  /*
X    Initialize colormap.
X  */
X  pixel_info.pixels=(unsigned long *) NULL;
X  if (resource_info->map_type == (char *) NULL)
X    {
X      /*
X        Create Standard Colormap.
X      */
X      map_info=XMakeStandardColormap(display,visual_info,resource_info,
X        &pixel_info,image);
X      colormap=map_info->colormap;
X    }
X  else
X    {
X      if (image->class == PseudoClass)
X        {
X          register int
X            i;
X
X          /*
X            Initialize pixel array for images of type PseudoClass.
X          */
X          pixel_info.pixels=(unsigned long *)
X            malloc((unsigned int) image->colors*sizeof(unsigned long));
X          if (pixel_info.pixels == (unsigned long *) NULL)
X            Error("unable to create colormap","memory allocation failed");
X          for (i=0; i < image->colors; i++)
X            pixel_info.pixels[i]=XStandardPixel(map_info,image->colormap[i],8);
X        }
X      /*
X        Define background/border/foreground pixels.
X      */
X      colormap=map_info->colormap;
X      XParseColor(display,colormap,resource_info->background_color,&color);
X      pixel_info.background_pixel=XStandardPixel(map_info,color,16);
X      XParseColor(display,colormap,resource_info->border_color,&color);
X      pixel_info.border_pixel=XStandardPixel(map_info,color,16);
X      XParseColor(display,colormap,resource_info->foreground_color,&color);
X      pixel_info.foreground_pixel=XStandardPixel(map_info,color,16);
X    }
X  /*
X    Initialize font info.
X  */
X  (void) sprintf(text," %+d%+d #%02x%02x%02x \0",image->columns,image->rows,
X    MaxRgb,MaxRgb,MaxRgb);
X  font_info=XBestFont(display,resource_info,text,image->columns >> 1);
X  if (font_info == (XFontStruct *) NULL)
X    Error("unable to load font",resource_info->font_name);
X  /*
X    Initialize cursor.
X  */
X  arrow_cursor=XCreateFontCursor(display,XC_arrow);
X  watch_cursor=XCreateFontCursor(display,XC_watch);
X  if ((arrow_cursor == (Cursor) NULL) || (watch_cursor == (Cursor) NULL))
X    Error("unable to create cursor",(char *) NULL);
X  /*
X    Initialize atoms.
X  */
X  protocols_property=XInternAtom(display,"WM_PROTOCOLS",False);
X  delete_property=XInternAtom(display,"WM_DELETE_WINDOW",False);
X  if ((protocols_property == (Atom) NULL) || (delete_property == (Atom) NULL))
X    Error("unable to create property",(char *) NULL);
X  /*
X    Initialize class and manager hints.
X  */
X  class_hint=XAllocClassHint();
X  manager_hints=XAllocWMHints();
X  if ((class_hint == (XClassHint *) NULL) ||
X      (manager_hints == (XWMHints *) NULL))
X    Error("unable to allocate X hints",(char *) NULL);
X  if (resource_info->name == (char *) NULL)
X    class_hint->res_name=application_name;
X  else
X    class_hint->res_name=resource_info->name;
X  class_hint->res_class=(char *) "ImageMagick";
X  manager_hints->flags=InputHint | StateHint;
X  manager_hints->input=False;
X  manager_hints->initial_state=NormalState;
X  /*
X    Window superclass.
X  */
X  superclass_window.screen=visual_info->screen;
X  superclass_window.depth=visual_info->depth;
X  superclass_window.visual_info=visual_info;
X  superclass_window.map_info=map_info;
X  superclass_window.pixel_info=(&pixel_info);
X  superclass_window.font_info=font_info;
X  superclass_window.cursor=arrow_cursor;
X  superclass_window.busy_cursor=watch_cursor;
X  superclass_window.name="ImageMagick SuperClass";
X  superclass_window.geometry=(char *) NULL;
X  superclass_window.icon_geometry=resource_info->icon_geometry;
X  superclass_window.clip_geometry=(char *) NULL;
X  superclass_window.flags=PSize;
X  superclass_window.x=0;
X  superclass_window.y=0;
X  superclass_window.width=1;
X  superclass_window.height=1;
X  superclass_window.min_width=0;
X  superclass_window.min_height=0;
X  superclass_window.width_inc=1;
X  superclass_window.height_inc=1;
X  superclass_window.border_width=2;
X  superclass_window.immutable=True;
X  superclass_window.attributes.background_pixel=pixel_info.background_pixel;
X  superclass_window.attributes.background_pixmap=(Pixmap) NULL;
X  superclass_window.attributes.backing_store=WhenMapped;
X  superclass_window.attributes.bit_gravity=ForgetGravity;
X  superclass_window.attributes.border_pixel=pixel_info.border_pixel;
X  superclass_window.attributes.colormap=colormap;
X  superclass_window.attributes.cursor=arrow_cursor;
X  superclass_window.attributes.do_not_propagate_mask=NoEventMask;
X  superclass_window.attributes.event_mask=NoEventMask;
X  superclass_window.attributes.override_redirect=False;
X  superclass_window.attributes.save_under=False;
X  superclass_window.attributes.win_gravity=NorthWestGravity;
X  superclass_window.graphic_context=(GC) NULL;
X  superclass_window.ximage=(XImage *) NULL;
X  /*
X    Initialize graphic context.
X  */
X  root_window=XRootWindow(display,visual_info->screen);
X  XMakeWindow(display,root_window,argv,argc,class_hint,manager_hints,
X    delete_property,&superclass_window);
X  graphic_context_value.background=pixel_info.background_pixel;
X  graphic_context_value.foreground=pixel_info.foreground_pixel;
X  graphic_context_value.font=font_info->fid;
X  graphic_context_value.function=GXcopy;
X  graphic_context_value.plane_mask=AllPlanes;
X  graphic_context=XCreateGC(display,superclass_window.id,GCBackground |
X    GCFont | GCForeground | GCFunction | GCPlaneMask,&graphic_context_value);
X  if (graphic_context == (GC) NULL)
X    Error("unable to create graphic context",(char *) NULL);
X  superclass_window.graphic_context=graphic_context;
X  /*
X    Initialize icon window.
X  */
X  icon_window=superclass_window;
X  icon_window.name="ImageMagick Icon";
X  XBestIconSize(display,&icon_window,image);
X  icon_window.attributes.event_mask=ExposureMask | StructureNotifyMask;
X  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
X  manager_hints->input=False;
X  manager_hints->initial_state=IconicState;
X  manager_hints->window_group=superclass_window.id;
X  XMakeWindow(display,root_window,argv,argc,class_hint,manager_hints,
X    delete_property,&icon_window);
X  /*
X    Initialize image window.
X  */
X  image_window=superclass_window;
X  image_window.name=(char *) malloc(256);
X  if (image_window.name == NULL)
X    Error("unable to create image window","memory allocation failed");
X  if (resource_info->title == (char *) NULL)
X    (void) sprintf(image_window.name,"ImageMagick: %s\0",image->filename);
X  else
X    (void) strcpy(image_window.name,resource_info->title);
X  image_window.geometry=resource_info->image_geometry;
X  image_window.width=image->columns;
X  if (image_window.width > XDisplayWidth(display,visual_info->screen))
X    image_window.width=XDisplayWidth(display,visual_info->screen);
X  image_window.height=image->rows;
X  if (image_window.height > XDisplayHeight(display,visual_info->screen))
X    image_window.height=XDisplayHeight(display,visual_info->screen);
X  image_window.border_width=resource_info->border_width;
X  backdrop_window=superclass_window;
X  if (resource_info->backdrop)
X    {
X      /*
X        Initialize backdrop window.
X      */
X      backdrop_window.name="ImageMagick Background";
X      backdrop_window.flags=USSize | USPosition;
X      backdrop_window.width=XDisplayWidth(display,visual_info->screen);
X      backdrop_window.height=XDisplayHeight(display,visual_info->screen);
X      backdrop_window.border_width=0;
X      backdrop_window.attributes.do_not_propagate_mask=
X        ButtonPressMask | ButtonReleaseMask;
X      manager_hints->flags=IconWindowHint | InputHint | StateHint |
X        WindowGroupHint;
X      manager_hints->icon_window=icon_window.id;
X      manager_hints->input=True;
X      manager_hints->initial_state=
X        resource_info->iconic ? IconicState : NormalState;
X      manager_hints->window_group=superclass_window.id;
X      XMakeWindow(display,root_window,argv,argc,class_hint,manager_hints,
X        delete_property,&backdrop_window);
X      XSetTransientForHint(display,backdrop_window.id,backdrop_window.id);
X      XMapWindow(display,backdrop_window.id);
X      /*
X        Position image in the center the backdrop.
X      */
X      image_window.flags|=USPosition;
X      image_window.x=XDisplayWidth(display,visual_info->screen)/2-
X        (image_window.width+image_window.border_width)/2;
X      image_window.y=XDisplayHeight(display,visual_info->screen)/2-
X        (image_window.height+image_window.border_width)/2;
X    }
X  image_window.immutable=False;
X  image_window.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
X    ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
X    KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
X    StructureNotifyMask;
X  manager_hints->flags=
X    IconWindowHint | InputHint | StateHint | WindowGroupHint;
X  manager_hints->icon_window=icon_window.id;
X  manager_hints->input=True;
X  manager_hints->initial_state=
X    resource_info->iconic ? IconicState : NormalState;
X  manager_hints->window_group=superclass_window.id;
X  XMakeWindow(display,(resource_info->backdrop ? backdrop_window.id :
X    root_window),argv,argc,class_hint,manager_hints,delete_property,
X    &image_window);
X  XMapWindow(display,image_window.id);
X  /*
X    Initialize image X image structure.
X  */
X  image_window.x=0;
X  image_window.y=0;
X  image_window.ximage=XMakeImage(display,resource_info,&image_window,image,
X    image->columns,image->rows);
X  if (image_window.ximage == (XImage *) NULL)
X    Error("unable to create X image",(char *) NULL);
X  /*
X    Initialize magnify window and cursor.
X  */
X  magnify_window=superclass_window;
X  magnify_window.cursor=XMakeCursor(display,image_window.id,colormap,
X    resource_info->background_color,resource_info->foreground_color);
X  if (magnify_window.cursor == (Cursor) NULL)
X    Error("unable to create cursor",(char *) NULL);
X  magnify_window.name="ImageMagick Magnifier";
X  magnify_window.width=MagnifySize;
X  magnify_window.height=MagnifySize;
X  magnify_window.min_width=MagnifySize;
X  magnify_window.min_height=MagnifySize;
X  magnify_window.width_inc=MagnifySize;
X  magnify_window.height_inc=MagnifySize;
X  magnify_window.immutable=False;
X  magnify_window.attributes.cursor=magnify_window.cursor;
X  magnify_window.attributes.event_mask=
X    ExposureMask | KeyPressMask | StructureNotifyMask;
X  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
X  manager_hints->input=False;
X  manager_hints->initial_state=NormalState;
X  manager_hints->window_group=superclass_window.id;
X  XMakeWindow(display,root_window,argv,argc,class_hint,manager_hints,
X    delete_property,&magnify_window);
X  /*
X    Initialize magnify window X image structure.
X  */
X  magnify_window.x=image->columns >> 1;
X  magnify_window.y=image->rows >> 1;
X  magnify_window.ximage=XMakeImage(display,resource_info,&magnify_window,
X    (Image *) NULL,magnify_window.width,magnify_window.height);
X  if (magnify_window.ximage == (XImage *) NULL)
X    Error("unable to create magnify image",(char *) NULL);
X  /*
X    Initialize menu window.
X  */
X  menu_window=superclass_window;
X  menu_window.name="ImageMagick Menu";
X  menu_window.flags=PSize | PPosition;
X  menu_window.attributes.override_redirect=True;
X  menu_window.attributes.save_under=True;
X  menu_window.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
X    ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
X    OwnerGrabButtonMask;
X  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
X  manager_hints->input=False;
X  manager_hints->initial_state=NormalState;
X  manager_hints->window_group=superclass_window.id;
X  XMakeWindow(display,root_window,argv,argc,class_hint,manager_hints,
X    delete_property,&menu_window);
X  XSetTransientForHint(display,menu_window.id,image_window.id);
X  /*
X    Initialize info window.
X  */
X  info_window=superclass_window;
X  info_window.name="ImageMagick Info";
X  info_window.flags=PSize | PPosition;
X  info_window.x=2;
X  info_window.y=2;
X  info_window.attributes.event_mask=StructureNotifyMask;
X  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
X  manager_hints->input=False;
X  manager_hints->initial_state=NormalState;
X  manager_hints->window_group=superclass_window.id;
X  XMakeWindow(display,image_window.id,argv,argc,class_hint,manager_hints,
X    delete_property,&info_window);
X  /*
X    Respond to events.
X  */
X  state=DefaultState;
X  timeout=(~0);
X  do
X  {
X    /*
X      Handle a window event.
X    */
X    if (resource_info->delay > 0)
X      if (XEventsQueued(display,QueuedAfterFlush) == 0)
X        {
X          /*
X            Block if delay > 0.
X          */
X          (void) sleep(1);
X          continue;
X        }
X    XNextEvent(display,&event);
X    switch (event.type)
X    {
X      case ButtonPress:
X      {
X        if (event.xbutton.window == image_window.id)
X          switch (event.xbutton.button)
X          {
X            case Button1:
X            {
X              static char
X                command[256];
X
X              if (state & ControlState)
X                {
X                  /*
X                    User pressed the image pan button.
X                  */
X                  XPanImageWindow(display,&info_window,&image_window,
X                    event.xbutton.x,event.xbutton.y);
X                  break;
X                }
X              /*
X                Select a command from the pop-up menu.
X              */
X              XMenuWindow(display,&menu_window,event.xbutton.x_root,
X                event.xbutton.y_root,command);
X              UserCommand(display,resource_info,&info_window,&image_window,
X                &magnify_window,command,&image,&timeout,&state);
X              break;
X            }
X            case Button2:
X            {
X              /*
X                User pressed the image clip button.
X              */
X              XClipImageWindow(display,&info_window,&image_window,image,
X                event.xbutton.x,event.xbutton.y);
X              break;
X            }
X            case Button3:
X            {
X              /*
X                User pressed the image magnify button.
X              */
X              magnify_window.x=event.xbutton.x-image_window.x;
X              magnify_window.y=event.xbutton.y-image_window.y;
X              if (state & MagnifyMappedState)
X                XRaiseWindow(display,magnify_window.id);
X              else
X                {
X                  XMapRaised(display,magnify_window.id);
X                  state|=MagnifyMappedState;
X                  XWindowEvent(display,magnify_window.id,ExposureMask,&event);
X                }
X              XMagnifyImageWindow(display,resource_info,&info_window,
X                &image_window,&magnify_window);
X              break;
X            }
X            default:
X              break;
X          }
X        break;
X      }
X      case ClientMessage:
X      {
X        /*
X          If client window delete message, exit.
X        */
X        if (event.xclient.message_type == protocols_property)
X          if (*event.xclient.data.l == delete_property)
X            if (event.xclient.window == image_window.id)
X              state|=ExitState;
X            else
X              XWithdrawWindow(display,event.xclient.window,
X                visual_info->screen);
X        break;
X      }
X      case ConfigureNotify:
X      {
X        if (event.xconfigure.window == image_window.id)
X          {
X            static unsigned long
X              scale_factor;
X
X            /*
X              Image window has a new configuration.
X            */
X            image_window.x=0;
X            image_window.y=0;
X            if ((event.xconfigure.width == image_window.width) &&
X                (event.xconfigure.height == image_window.height))
X              break;
X            /*
X              Make magnify offset proportional to the window size.
X            */
X            scale_factor=(event.xconfigure.width << 14)/image_window.width;
X            magnify_window.x=(magnify_window.x*scale_factor+8191) >> 14;
X            scale_factor=(event.xconfigure.height << 14)/image_window.height;
X            magnify_window.y=(magnify_window.y*scale_factor+8191) >> 14;
X            image_window.width=event.xconfigure.width;
X            image_window.height=event.xconfigure.height;
X            if (!(state & ImageMappedState))
X              break;
X            /*
X              Make font proportional to the window size.
X            */
X            (void) sprintf(text," %+d%+d #%02x%02x%02x \0",image_window.width,
X              image_window.height,MaxRgb,MaxRgb,MaxRgb);
X            XFreeFont(display,font_info);
X            font_info=
X              XBestFont(display,resource_info,text,image_window.width >> 1);
X            if (font_info == (XFontStruct *) NULL)
X              Error("unable to load font",resource_info->font_name);
X            XSetFont(display,superclass_window.graphic_context,font_info->fid);
X            superclass_window.font_info=font_info;
X            icon_window.font_info=font_info;
X            backdrop_window.font_info=font_info;
X            image_window.font_info=font_info;
X            magnify_window.font_info=font_info;
X            menu_window.font_info=font_info;
X            info_window.font_info=font_info;
X            /*
X              If ConfigureState, image is already resized.
X            */
X            if (state & ConfigureWindowState)
X              state&=(~ConfigureWindowState);
X            else
X              (void) XResizeImageWindow(display,resource_info,&info_window,
X                &image_window,image);
X            while
X              (XCheckWindowEvent(display,image_window.id,ExposureMask,&event));
X            XDisplayImageWindow(display,&image_window,0,0,image_window.width,
X              image_window.height);
X            break;
X          }
X        if (event.xconfigure.window == magnify_window.id)
X          {
X            /*
X              Magnify window has a new configuration.
X            */
X            magnify_window.width=event.xconfigure.width;
X            magnify_window.height=event.xconfigure.height;
X            if (((magnify_window.width % magnify_window.width_inc) != 0) ||
X                ((magnify_window.height % magnify_window.height_inc) != 0))
X              break;
X            XDestroyImage(magnify_window.ximage);
X            magnify_window.ximage=XMakeImage(display,resource_info,
X              &magnify_window,(Image *) NULL,magnify_window.width,
X              magnify_window.height);
X            if (magnify_window.ximage == (XImage *) NULL)
X              Error("unable to create magnify image",(char *) NULL);
X            ConstrainMagnifyFactor((&image_window),(&magnify_window),
X              resource_info->magnify);
X            XMakeMagnifyImage(&magnify_window,image_window.ximage,
X              resource_info->magnify);
X            XPutImage(display,magnify_window.id,magnify_window.graphic_context,
X              magnify_window.ximage,0,0,0,0,magnify_window.width,
X              magnify_window.height);
X            break;
X          }
X        if (event.xconfigure.window == icon_window.id)
X          {
X            /*
X              Icon window has a new configuration.
X            */
X            icon_window.width=event.xconfigure.width;
X            icon_window.height=event.xconfigure.height;
X            break;
X          }
X      }
X      case EnterNotify:
X      {
X        /*
X          Selectively install colormap.
X        */
X        if (colormap != XDefaultColormap(display,visual_info->screen))
X          if (event.xcrossing.mode != NotifyUngrab)
X            XInductColormap(display,colormap);
X        break;
X      }
X      case Expose:
X      {
X        /*
X          Repaint windows that are now exposed.
X        */
X        if (event.xexpose.window == image_window.id)
X          {
X            XDisplayImageWindow(display,&image_window,event.xexpose.x,
X              event.xexpose.y,(unsigned int) event.xexpose.width,
X              (unsigned int) event.xexpose.height);
X            /*
X              Reset timeout after expose.
X            */
X            if (resource_info->delay == 0)
X              timeout=(~0);
X            else
X              timeout=time((long *) 0)+resource_info->delay;
X            break;
X          }
X        if (event.xexpose.window == magnify_window.id)
X          {
X            XPutImage(display,magnify_window.id,magnify_window.graphic_context,
X              magnify_window.ximage,event.xexpose.x,event.xexpose.y,
X              event.xexpose.x,event.xexpose.y,
X              (unsigned int) event.xexpose.width,
X              (unsigned int) event.xexpose.height);
X            break;
X          }
X        if (event.xexpose.window == icon_window.id)
X          {
X            XPutImage(display,icon_window.id,icon_window.graphic_context,
X              icon_window.ximage,event.xexpose.x,event.xexpose.y,
X              event.xexpose.x,event.xexpose.y,
X              (unsigned int) event.xexpose.width,
X              (unsigned int) event.xexpose.height);
X            break;
X          }
X        break;
X      }
X      case KeyPress:
X      {
X        static char
X          command[256];
X
X        static KeySym
X          key_symbol;
X
X        /*
X          Respond to a user key press.
X        */
X        if (state & ConfigureWindowState)
X          {
X            XBell(display,0);
X            break;
X          }
X        *command=(char) NULL;
X        XLookupString((XKeyEvent *) &event.xkey,command,sizeof(command),
X          &key_symbol,(XComposeStatus *) NULL);
X        if (key_symbol == XK_Control_L)
X          state|=ControlState;
X        else
X          if (key_symbol == XK_Help)
X            Usage((char *) NULL,False);
X          else
X            if (!IsCursorKey(key_symbol) && !isdigit(*command))
X              UserCommand(display,resource_info,&info_window,&image_window,
X                &magnify_window,command,&image,&timeout,&state);
X            else
X              {
X                /*
X                  User specified a magnify factor or position.
X                */
X                if (!(state & MagnifyMappedState))
X                  break;
X                if (key_symbol == XK_Home)
X                  {
X                    magnify_window.x=0;
X                    magnify_window.y=0;
X                  }
X                if (key_symbol == XK_Left)
X                  magnify_window.x--;
X                if (key_symbol == XK_Up)
X                  magnify_window.y--;
X                if (key_symbol == XK_Right)
X                  magnify_window.x++;
X                if (key_symbol == XK_Down)
X                  magnify_window.y++;
X                if (isdigit(*command))
X                  resource_info->magnify=1 << atoi(command);
X                /*
X                  Magnify image.
X                */
X                ConstrainMagnifyFactor((&image_window),(&magnify_window),
X                  resource_info->magnify);
X                XMakeMagnifyImage(&magnify_window,image_window.ximage,
X                  resource_info->magnify);
X                XPutImage(display,magnify_window.id,
X                  magnify_window.graphic_context,magnify_window.ximage,0,0,0,0,
X                  magnify_window.width,magnify_window.height);
X              }
X        break;
X      }
X      case KeyRelease:
X      {
X        static char
X          command[256];
X
X        static KeySym
X          key_symbol;
X
X        /*
X          Respond to a user key release.
X        */
X        *command=(char) NULL;
X        XLookupString((XKeyEvent *) &event.xkey,command,sizeof(command),
X          &key_symbol,(XComposeStatus *) NULL);
X        if (key_symbol == XK_Control_L)
X          state&=(~ControlState);
X        break;
X      }
X      case LeaveNotify:
X      {
X        /*
X          Selectively uninstall colormap.
X        */
X        if (colormap != XDefaultColormap(display,visual_info->screen))
X          if (event.xcrossing.mode != NotifyUngrab)
X            XUninductColormap(display,colormap);
X        break;
X      }
X      case MapNotify:
X      {
X        if (event.xmap.window == image_window.id)
X          {
X            state|=ImageMappedState;
X            break;
X          }
X        if (event.xmap.window == magnify_window.id)
X          {
X            state|=MagnifyMappedState;
X            break;
X          }
X        if (event.xmap.window == info_window.id)
X          {
X            state|=InfoMappedState;
X            break;
X          }
X        if (event.xmap.window == icon_window.id)
X          {
X            /*
X              Create icon image.
X            */
X            icon_window.ximage=XMakeImage(display,resource_info,&icon_window,
X              image,icon_window.width,icon_window.height);
X            if (icon_window.ximage == (XImage *) NULL)
X              Error("unable to create icon image",(char *) NULL);
X            break;
X          }
X        break;
X      }
X      case MappingNotify:
X      {
X        XRefreshKeyboardMapping(&event.xmapping);
X        break;
X      }
X      case UnmapNotify:
X      {
X        if (event.xunmap.window == image_window.id)
X          {
X            state&=(~ImageMappedState);
X            /*
X              Unmap magnify window.
X            */
X            if (state & MagnifyMappedState)
X              XWithdrawWindow(display,magnify_window.id,magnify_window.screen);
X            break;
X          }
X        if (event.xunmap.window == magnify_window.id)
X          {
X            /*
X              Destroy magnify image.
X            */
X            state&=(~MagnifyMappedState);
X            break;
X          }
X        if (event.xunmap.window == info_window.id)
X          {
X            state&=(~InfoMappedState);
X            break;
X          }
X        if (event.xunmap.window == icon_window.id)
X          {
X            /*
X              Destroy icon image.
X            */
X            XDestroyImage(icon_window.ximage);
X            icon_window.ximage=(XImage *) NULL;
X            break;
X          }
X        break;
X      }
X      default:
X        break;
X    }
X  }
X  while ((timeout > time((long *) 0)) && !(state & ExitState));
X  /*
X    Initialize function return values.
X  */
X  *terminate=state & ExitState;
X  *clip_geometry=image_window.clip_geometry;
X  if ((image->columns == image_window.ximage->width) &&
X      (image->rows == image_window.ximage->height))
X    *image_geometry=(char *) NULL;
X  else
X    {
X      *image_geometry=(char *) malloc(256);
X      if (*image_geometry == (char *) NULL)
X        Error("unable to transform X image",(char *) NULL);
X      (void) sprintf(*image_geometry,"%dx%d\0",image_window.ximage->width,
X        image_window.ximage->height);
X    }
X  /*
X    Free up memory.
X  */
X  XDestroyWindow(display,info_window.id);
X  XDestroyWindow(display,menu_window.id);
X  XDestroyWindow(display,magnify_window.id);
X  XDestroyImage(magnify_window.ximage);
X  XDestroyWindow(display,image_window.id);
X  XDestroyImage(image_window.ximage);
X  (void) free((char *) image_window.name);
X  if (resource_info->backdrop)
X    XDestroyWindow(display,backdrop_window.id);
X  XDestroyWindow(display,icon_window.id);
X  if (icon_window.ximage != (XImage *) NULL)
X    XDestroyImage(icon_window.ximage);
X  XDestroyWindow(display,superclass_window.id);
X  XFreeGC(display,graphic_context);
X  XFree((char *) class_hint);
X  XFree((char *) manager_hints);
X  XFreeCursor(display,arrow_cursor);
X  XFreeCursor(display,watch_cursor);
X  XFreeCursor(display,magnify_window.cursor);
X  XFreeFont(display,font_info);
X  /*
X    Discard pending events before freeing colormap.
X  */
X  while (XEventsQueued(display,QueuedAfterFlush) > 0)
X    XNextEvent(display,&event);
X  if (resource_info->map_type == (char *) NULL)
X    if (colormap != XDefaultColormap(display,visual_info->screen))
X      XFreeColormap(display,colormap);
X    else
X      if ((visual_info->class == GrayScale) ||
X          (visual_info->class == PseudoColor))
X        XFreeColors(display,colormap,pixel_info.pixels,(int) image->colors,0);
X  if (pixel_info.pixels != (unsigned long *) NULL)
X    (void) free((char *) pixel_info.pixels);
X  XFree((char *) map_info);
X  XFree((char *) visual_info);
X  return(image);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   X D i s p l a y I m a g e W i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function XDisplayImageWindow displays an image in a X window.
%
%  The format of the XDisplayImageWindow routine is:
%
%      XDisplayImageWindow(display,image_window,x,y,width,height)
%
%  A description of each parameter follows:
%
%    o display: Specifies a connection to an X server;  returned from
%      XOpenDisplay.
%
%    o image_window: Specifies a pointer to a XWindowInfo structure.
%
%    o x: Specifies the x coordinate relative to the image window.
%
%    o y: Specifies the y coordinate relative to the image window.
%
%    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 void XDisplayImageWindow(display,image_window,x,y,width,height)
Display
X  *display;
X
XXWindowInfo
X  *image_window;
X
register int
X  x,
X  y;
X
register unsigned int
X  height,
X  width;
{
X  /*
X    Check boundary conditions.
X  */
X  if ((x+(int) width) > (int) image_window->width)
X    width=(unsigned int) ((int) image_window->width-x);
X  if ((y+(int) height) > (int) image_window->height)
X    height=(unsigned int) ((int) image_window->height-y);
X  if (x < image_window->x)
X    {
X      XClearArea(display,image_window->id,x,y,
X        (unsigned int) (image_window->x-x),(unsigned int) (y+(int) height),
X        False);
X      width-=(unsigned int) (image_window->x-x);
X      x=image_window->x;
X    }
X  if (y < image_window->y)
X    {
X      XClearArea(display,image_window->id,x,y,width,
X        (unsigned int) (image_window->y-y),False);
X      height-=(unsigned int) (image_window->y-y);
X      y=image_window->y;
X    }
X  if ((x+(int) width) > (image_window->x+image_window->ximage->width))
X    {
X      width=(unsigned int) (image_window->x+image_window->ximage->width);
X      XClearArea(display,image_window->id,width,y,image_window->width-width,
X        image_window->height,False);
X    }
X  if ((y+(int) height) > (image_window->y+image_window->ximage->height))
X    {
X      height=(unsigned int) (image_window->y+image_window->ximage->height);
X      XClearArea(display,image_window->id,x,height,width,image_window->height-
X        height,False);
X    }
X  /*
X    Display image.
X  */
X  XPutImage(display,image_window->id,image_window->graphic_context,
X    image_window->ximage,x-image_window->x,y-image_window->y,x,y,width,height);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   X D i s p l a y R o o t I m a g e                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function XDisplayRootImage displays an image in the root window.
%
%  The format of the XDisplayRootImage routine is:
%
%      XDisplayRootImage(display,resource_info,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 XResourceInfo structure.
%
%    o image: Specifies a pointer to a Image structure; returned from
%      ReadImage.
%
%
*/
static void XDisplayRootImage(display,resource_info,image)
Display
X  *display;
X
XXResourceInfo
X  *resource_info;
X
Image
X  *image;
{
X  Atom
X    property,
X    type;
X
X  Colormap
X    colormap;
X
X  int
X    format,
X    i;
X
X  Pixmap
X    pixmap;
X
X  unsigned char
X    *data;
X
X  unsigned int
X    height,
X    number_children,
X    width;
X
X  unsigned long
X    after,
X    length;
X
X  Window
X    *children,
X    parent,
X    root,
X    root_window;
X
X  XColor
X    color;
X
X  XGCValues
X    graphic_context_value;
X
X  XPixelInfo
X    pixel_info;
X
X  XStandardColormap
X    *map_info;
X
X  XWindowInfo
X    image_window;
X
X  XVisualInfo
X    *visual_info;
X
X  /*
X    Initialize visual info.
X  */
X  if ((resource_info->visual_type != (char *) NULL) ||
X      (resource_info->map_type != (char *) NULL))
X    visual_info=XBestVisualInfo(display,resource_info->visual_type,
X      resource_info->map_type,&map_info);
X  else
X    {
X      int
X        number_visuals;
X
X      XVisualInfo
X        visual_template;
X
X      /*
X        Get the default visual.
X      */
X      visual_template.visualid=
X        XVisualIDFromVisual(XDefaultVisual(display,XDefaultScreen(display)));
X      visual_info=XGetVisualInfo(display,VisualIDMask,&visual_template,
X        &number_visuals);
X    }
X  if (visual_info == (XVisualInfo *) NULL)
X    Error("unable to get visual",resource_info->visual_type);
X  if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
X    Error("visual must be server default",resource_info->visual_type);
X  /*
X    Determine if root window is virtual.
X  */
X  root_window=XRootWindow(display,visual_info->screen);
X  property=XInternAtom(display,"__SWM_VROOT",False);
X  XQueryTree(display,root_window,&root,&parent,&children,&number_children);
X  for (i=0; i < number_children; i++)
X  {
X    (void) XGetWindowProperty(display,children[i],property,0L,1L,False,
X      XA_WINDOW,&type,&format,&length,&after,&data);
X    if ((format == 32) && (length == 1) && (after == 0))
X      {
X        /*
X          Root window is a virtual root.
X        */
X        root_window=(*((Window *) data));
X        break;
X      }
X  }
X  if (children != (Window *) NULL)
X    XFree((char *) children);
X  /*
X    If there are previous resources on the root window, destroy them.
X  */
X  property=XInternAtom(display,"_XSETROOT_ID",False);
X  if (property == (Atom) NULL)
X    Error("unable to create X property","_XSETROOT_ID");
X  (void) XGetWindowProperty(display,root_window,property,0L,1L,True,
X    AnyPropertyType,&type,&format,&length,&after,&data);
X  if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
X    {
X      /*
X        Free previous resources on the root window.
X      */
X      XKillClient(display,*((Pixmap *) data));
X      XFree((char *) data);
X    }
X  /*
X    Initialize colormap.
X  */
X  pixel_info.pixels=(unsigned long *) NULL;
X  if (resource_info->map_type == (char *) NULL)
X    {
X      /*
X        Create Standard Colormap.
X      */
X      map_info=XMakeStandardColormap(display,visual_info,resource_info,
X        &pixel_info,image);
X      colormap=map_info->colormap;
X    }
X  else
X    {
X      if (image->class == PseudoClass)
X        {
X          register int
X            i;
X
X          /*
X            Initialize pixel array for images of type PseudoClass.
X          */
X          pixel_info.pixels=(unsigned long *)
X            malloc((unsigned int) image->colors*sizeof(unsigned long));
X          if (pixel_info.pixels == (unsigned long *) NULL)
X            Error("unable to create colormap","memory allocation failed");
X          for (i=0; i < image->colors; i++)
X            pixel_info.pixels[i]=XStandardPixel(map_info,image->colormap[i],8);
X        }
X      /*
X        Define background/border/foreground pixels.
X      */
X      colormap=map_info->colormap;
X      XParseColor(display,colormap,resource_info->background_color,&color);
X      pixel_info.background_pixel=XStandardPixel(map_info,color,16);
X      XParseColor(display,colormap,resource_info->border_color,&color);
X      pixel_info.border_pixel=XStandardPixel(map_info,color,16);
X      XParseColor(display,colormap,resource_info->foreground_color,&color);
X      pixel_info.foreground_pixel=XStandardPixel(map_info,color,16);
X    }
X  /*
X    The colormap must be the default colormap.
X  */
X  if (colormap != XDefaultColormap(display,visual_info->screen))
X    Error("unable to display X image on the root window","too many colors");
X  /*
X    Initialize image window attributes.
X  */
X  image_window.id=root_window;
X  image_window.visual_info=visual_info;
X  image_window.screen=visual_info->screen;
X  image_window.depth=visual_info->depth;
X  image_window.clip_geometry=(char *) NULL;
X  image_window.map_info=map_info;
X  image_window.pixel_info=(&pixel_info);
X  image_window.x=0;
X  image_window.y=0;
X  image_window.width=image->columns;
X  if (image_window.width > XDisplayWidth(display,visual_info->screen))
X    image_window.width=XDisplayWidth(display,visual_info->screen);
X  image_window.height=image->rows;
X  if (image_window.height > XDisplayHeight(display,visual_info->screen))
X    image_window.height=XDisplayHeight(display,visual_info->screen);
X  image_window.border_width=resource_info->border_width;
X  /*
X    Graphic context superclass.
X  */
X  graphic_context_value.background=pixel_info.background_pixel;
X  graphic_context_value.foreground=pixel_info.foreground_pixel;
X  graphic_context_value.fill_style=FillSolid;
X  graphic_context_value.function=GXcopy;
X  graphic_context_value.plane_mask=AllPlanes;
X  image_window.graphic_context=XCreateGC(display,image_window.id,
X    GCBackground | GCFillStyle | GCForeground | GCFunction | GCPlaneMask,
X    &graphic_context_value);
X  if (image_window.graphic_context == (GC) NULL)
X    Error("unable to create graphic context",(char *) NULL);
X  /*
X    Create the X image.
X  */
X  image_window.ximage=XMakeImage(display,resource_info,&image_window,image,
X    image->columns,image->rows);
X  if (image_window.ximage == (XImage *) NULL)
X    Error("unable to create X image",(char *) NULL);
X  /*
X    Adjust image dimensions as specified by backdrop or geometry options.
X  */
X  width=image_window.width;
X  height=image_window.height;
X  if (resource_info->backdrop)
X    {
X      /*
X        Center image on root window.
X      */
X      image_window.x=
X        XDisplayWidth(display,visual_info->screen)/2-image->columns/2;
X      image_window.y=
X        XDisplayHeight(display,visual_info->screen)/2-image->rows/2;
X      width=XDisplayWidth(display,visual_info->screen);
X      height=XDisplayHeight(display,visual_info->screen);
X    }
X  if (resource_info->image_geometry != (char *) NULL)
X    {
X      char
X        default_geometry[256];
X
X      int
X        flags,
X        gravity;
X
X      XSizeHints
X        *size_hints;
X
X      /*
X        User specified geometry.
X      */
X      size_hints=XAllocSizeHints();
X      if (size_hints == (XSizeHints *) NULL)
X        Error("unable to display on root","memory allocation failed");
X      size_hints->flags=(long int) NULL;
X      (void) sprintf(default_geometry,"%dx%d\0",width,height);
X      flags=XWMGeometry(display,visual_info->screen,
X        resource_info->image_geometry,default_geometry,
X        image_window.border_width,size_hints,&image_window.x,&image_window.y,
X        (int *) &width,(int *) &height,&gravity);
X      if (flags & (XValue | YValue))
X        {
X          width=XDisplayWidth(display,visual_info->screen);
X          height=XDisplayHeight(display,visual_info->screen);
X        }
X      XFree((char *) size_hints);
X    }
X  /*
X    Create the root pixmap.
X  */
X  pixmap=
X    XCreatePixmap(display,image_window.id,width,height,image_window.depth);
X  if (pixmap == (Pixmap) NULL)
X    Error("unable to create X pixmap",(char *) NULL);
X  /*
X    Display pixmap on the root window.
X  */
X  if ((width > image_window.width) || (height > image_window.height))
X    {
X      /*
X        Surround the image by pixels of the background color.
X      */
X      XSetForeground(display,image_window.graphic_context,
X        pixel_info.background_pixel);
X      XFillRectangle(display,pixmap,image_window.graphic_context,0,0,width,
X        height);
X      XSetForeground(display,image_window.graphic_context,
X        pixel_info.foreground_pixel);
X    }
X  XPutImage(display,pixmap,image_window.graphic_context,image_window.ximage,
X    0,0,image_window.x,image_window.y,image_window.width,image_window.height);
X  XSetWindowBackgroundPixmap(display,image_window.id,pixmap);
X  XClearWindow(display,image_window.id);
X  /*
X    Free resources.
X  */
X  if (pixel_info.pixels != (unsigned long *) NULL)
X    (void) free((char *) pixel_info.pixels);
X  XFreePixmap(display,pixmap);
X  XDestroyImage(image_window.ximage);
X  XFreeGC(display,image_window.graphic_context);
X  XFree((char *) visual_info);
X  XFree((char *) map_info);
X  /*
X    Put property on root window and set close-down mode to RetainPermanent.
X  */
X  pixmap=XCreatePixmap(display,image_window.id,1,1,1);
X  if (pixmap == (Pixmap) NULL)
X    Error("unable to create X pixmap",(char *) NULL);
X  XChangeProperty(display,image_window.id,property,XA_PIXMAP,32,PropModeReplace,
X    (unsigned char *) &pixmap,1);
X  XSetCloseDownMode(display,RetainPermanent);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   X M a g n i f y I m a g e W i n d o w                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function XMagnifyImageWindow magnifies portions of the image as indicated
%  by the pointer.  The magnified portion is displayed in a separate window.
%
%  The format of the XMagnifyImageWindow routine is:
%
%    XMagnifyImageWindow(display,resource_info,info_window,image_window,
%      magnify_window)
%
%  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 XResourceInfo structure.
%
%    o info_window: Specifies a pointer to a XWindowInfo structure.
%
%    o image_window: Specifies a pointer to a XWindowInfo structure.
%
%    o magnify_window: Specifies a pointer to a XWindowInfo structure.
%
%
*/
static void XMagnifyImageWindow(display,resource_info,info_window,image_window,
SHAR_EOF
true || echo 'restore of ImageMagick/display.c failed'
fi
echo 'End of ImageMagick part 17'
echo 'File ImageMagick/display.c is continued in part 18'
echo 18 > _shar_seq_.tmp
exit 0
--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources-x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list