| /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %               DDDD   IIIII  SSSSS  PPPP   L       AAA   Y   Y               % | 
 | %               D   D    I    SS     P   P  L      A   A   Y Y                % | 
 | %               D   D    I     SSS   PPPP   L      AAAAA    Y                 % | 
 | %               D   D    I       SS  P      L      A   A    Y                 % | 
 | %               DDDD   IIIII  SSSSS  P      LLLLL  A   A    Y                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %        MagickCore Methods to Interactively Display and Edit an Image        % | 
 | %                                                                             % | 
 | %                             Software Design                                 % | 
 | %                               John Cristy                                   % | 
 | %                                July 1992                                    % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      % | 
 | %  dedicated to making software imaging solutions freely available.           % | 
 | %                                                                             % | 
 | %  You may not use this file except in compliance with the License.  You may  % | 
 | %  obtain a copy of the License at                                            % | 
 | %                                                                             % | 
 | %    http://www.imagemagick.org/script/license.php                            % | 
 | %                                                                             % | 
 | %  Unless required by applicable law or agreed to in writing, software        % | 
 | %  distributed under the License is distributed on an "AS IS" BASIS,          % | 
 | %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   % | 
 | %  See the License for the specific language governing permissions and        % | 
 | %  limitations under the License.                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | % | 
 | */ | 
 |  | 
 | /* | 
 |   Include declarations. | 
 | */ | 
 | #include "MagickCore/studio.h" | 
 | #include "MagickCore/artifact.h" | 
 | #include "MagickCore/blob.h" | 
 | #include "MagickCore/cache.h" | 
 | #include "MagickCore/cache-private.h" | 
 | #include "MagickCore/client.h" | 
 | #include "MagickCore/color.h" | 
 | #include "MagickCore/colorspace.h" | 
 | #include "MagickCore/composite.h" | 
 | #include "MagickCore/constitute.h" | 
 | #include "MagickCore/decorate.h" | 
 | #include "MagickCore/delegate.h" | 
 | #include "MagickCore/display.h" | 
 | #include "MagickCore/display-private.h" | 
 | #include "MagickCore/draw.h" | 
 | #include "MagickCore/effect.h" | 
 | #include "MagickCore/enhance.h" | 
 | #include "MagickCore/exception.h" | 
 | #include "MagickCore/exception-private.h" | 
 | #include "MagickCore/fx.h" | 
 | #include "MagickCore/geometry.h" | 
 | #include "MagickCore/image.h" | 
 | #include "MagickCore/image-private.h" | 
 | #include "MagickCore/list.h" | 
 | #include "MagickCore/log.h" | 
 | #include "MagickCore/magick.h" | 
 | #include "MagickCore/memory_.h" | 
 | #include "MagickCore/monitor.h" | 
 | #include "MagickCore/monitor-private.h" | 
 | #include "MagickCore/montage.h" | 
 | #include "MagickCore/option.h" | 
 | #include "MagickCore/paint.h" | 
 | #include "MagickCore/pixel.h" | 
 | #include "MagickCore/pixel-accessor.h" | 
 | #include "MagickCore/PreRvIcccm.h" | 
 | #include "MagickCore/property.h" | 
 | #include "MagickCore/quantum.h" | 
 | #include "MagickCore/quantum-private.h" | 
 | #include "MagickCore/resize.h" | 
 | #include "MagickCore/resource_.h" | 
 | #include "MagickCore/shear.h" | 
 | #include "MagickCore/segment.h" | 
 | #include "MagickCore/string_.h" | 
 | #include "MagickCore/string-private.h" | 
 | #include "MagickCore/transform.h" | 
 | #include "MagickCore/threshold.h" | 
 | #include "MagickCore/utility.h" | 
 | #include "MagickCore/utility-private.h" | 
 | #include "MagickCore/version.h" | 
 | #include "MagickCore/widget.h" | 
 | #include "MagickCore/widget-private.h" | 
 | #include "MagickCore/xwindow.h" | 
 | #include "MagickCore/xwindow-private.h" | 
 |  | 
 | #if defined(MAGICKCORE_X11_DELEGATE) | 
 | /* | 
 |   Define declarations. | 
 | */ | 
 | #define MaxColors  MagickMin((ssize_t) windows->visual_info->colormap_size,256L) | 
 |  | 
 | /* | 
 |   Constant declarations. | 
 | */ | 
 | static const unsigned char | 
 |   HighlightBitmap[8] = | 
 |   { | 
 |     0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 | 
 |   }, | 
 |   OpaqueBitmap[8] = | 
 |   { | 
 |     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | 
 |   }, | 
 |   ShadowBitmap[8] = | 
 |   { | 
 |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 
 |   }; | 
 |  | 
 | static const char | 
 |   *PageSizes[] = | 
 |   { | 
 |     "Letter", | 
 |     "Tabloid", | 
 |     "Ledger", | 
 |     "Legal", | 
 |     "Statement", | 
 |     "Executive", | 
 |     "A3", | 
 |     "A4", | 
 |     "A5", | 
 |     "B4", | 
 |     "B5", | 
 |     "Folio", | 
 |     "Quarto", | 
 |     "10x14", | 
 |     (char *) NULL | 
 |   }; | 
 |  | 
 | /* | 
 |   Help widget declarations. | 
 | */ | 
 | static const char | 
 |   *ImageAnnotateHelp[] = | 
 |   { | 
 |     "In annotate mode, the Command widget has these options:", | 
 |     "", | 
 |     "    Font Name", | 
 |     "      fixed", | 
 |     "      variable", | 
 |     "      5x8", | 
 |     "      6x10", | 
 |     "      7x13bold", | 
 |     "      8x13bold", | 
 |     "      9x15bold", | 
 |     "      10x20", | 
 |     "      12x24", | 
 |     "      Browser...", | 
 |     "    Font Color", | 
 |     "      black", | 
 |     "      blue", | 
 |     "      cyan", | 
 |     "      green", | 
 |     "      gray", | 
 |     "      red", | 
 |     "      magenta", | 
 |     "      yellow", | 
 |     "      white", | 
 |     "      transparent", | 
 |     "      Browser...", | 
 |     "    Font Color", | 
 |     "      black", | 
 |     "      blue", | 
 |     "      cyan", | 
 |     "      green", | 
 |     "      gray", | 
 |     "      red", | 
 |     "      magenta", | 
 |     "      yellow", | 
 |     "      white", | 
 |     "      transparent", | 
 |     "      Browser...", | 
 |     "    Rotate Text", | 
 |     "      -90", | 
 |     "      -45", | 
 |     "      -30", | 
 |     "      0", | 
 |     "      30", | 
 |     "      45", | 
 |     "      90", | 
 |     "      180", | 
 |     "      Dialog...", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "Choose a font name from the Font Name sub-menu.  Additional", | 
 |     "font names can be specified with the font browser.  You can", | 
 |     "change the menu names by setting the X resources font1", | 
 |     "through font9.", | 
 |     "", | 
 |     "Choose a font color from the Font Color sub-menu.", | 
 |     "Additional font colors can be specified with the color", | 
 |     "browser.  You can change the menu colors by setting the X", | 
 |     "resources pen1 through pen9.", | 
 |     "", | 
 |     "If you select the color browser and press Grab, you can", | 
 |     "choose the font color by moving the pointer to the desired", | 
 |     "color on the screen and press any button.", | 
 |     "", | 
 |     "If you choose to rotate the text, choose Rotate Text from the", | 
 |     "menu and select an angle.  Typically you will only want to", | 
 |     "rotate one line of text at a time.  Depending on the angle you", | 
 |     "choose, subsequent lines may end up overwriting each other.", | 
 |     "", | 
 |     "Choosing a font and its color is optional.  The default font", | 
 |     "is fixed and the default color is black.  However, you must", | 
 |     "choose a location to begin entering text and press button 1.", | 
 |     "An underscore character will appear at the location of the", | 
 |     "pointer.  The cursor changes to a pencil to indicate you are", | 
 |     "in text mode.  To exit immediately, press Dismiss.", | 
 |     "", | 
 |     "In text mode, any key presses will display the character at", | 
 |     "the location of the underscore and advance the underscore", | 
 |     "cursor.  Enter your text and once completed press Apply to", | 
 |     "finish your image annotation.  To correct errors press BACK", | 
 |     "SPACE.  To delete an entire line of text, press DELETE.  Any", | 
 |     "text that exceeds the boundaries of the image window is", | 
 |     "automagically continued onto the next line.", | 
 |     "", | 
 |     "The actual color you request for the font is saved in the", | 
 |     "image.  However, the color that appears in your image window", | 
 |     "may be different.  For example, on a monochrome screen the", | 
 |     "text will appear black or white even if you choose the color", | 
 |     "red as the font color.  However, the image saved to a file", | 
 |     "with -write is written with red lettering.  To assure the", | 
 |     "correct color text in the final image, any PseudoClass image", | 
 |     "is promoted to DirectClass (see miff(5)).  To force a", | 
 |     "PseudoClass image to remain PseudoClass, use -colors.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageChopHelp[] = | 
 |   { | 
 |     "In chop mode, the Command widget has these options:", | 
 |     "", | 
 |     "    Direction", | 
 |     "      horizontal", | 
 |     "      vertical", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "If the you choose the horizontal direction (this the", | 
 |     "default), the area of the image between the two horizontal", | 
 |     "endpoints of the chop line is removed.  Otherwise, the area", | 
 |     "of the image between the two vertical endpoints of the chop", | 
 |     "line is removed.", | 
 |     "", | 
 |     "Select a location within the image window to begin your chop,", | 
 |     "press and hold any button.  Next, move the pointer to", | 
 |     "another location in the image.  As you move a line will", | 
 |     "connect the initial location and the pointer.  When you", | 
 |     "release the button, the area within the image to chop is", | 
 |     "determined by which direction you choose from the Command", | 
 |     "widget.", | 
 |     "", | 
 |     "To cancel the image chopping, move the pointer back to the", | 
 |     "starting point of the line and release the button.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageColorEditHelp[] = | 
 |   { | 
 |     "In color edit mode, the Command widget has these options:", | 
 |     "", | 
 |     "    Method", | 
 |     "      point", | 
 |     "      replace", | 
 |     "      floodfill", | 
 |     "      filltoborder", | 
 |     "      reset", | 
 |     "    Pixel Color", | 
 |     "      black", | 
 |     "      blue", | 
 |     "      cyan", | 
 |     "      green", | 
 |     "      gray", | 
 |     "      red", | 
 |     "      magenta", | 
 |     "      yellow", | 
 |     "      white", | 
 |     "      Browser...", | 
 |     "    Border Color", | 
 |     "      black", | 
 |     "      blue", | 
 |     "      cyan", | 
 |     "      green", | 
 |     "      gray", | 
 |     "      red", | 
 |     "      magenta", | 
 |     "      yellow", | 
 |     "      white", | 
 |     "      Browser...", | 
 |     "    Fuzz", | 
 |     "      0%", | 
 |     "      2%", | 
 |     "      5%", | 
 |     "      10%", | 
 |     "      15%", | 
 |     "      Dialog...", | 
 |     "    Undo", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "Choose a color editing method from the Method sub-menu", | 
 |     "of the Command widget.  The point method recolors any pixel", | 
 |     "selected with the pointer until the button is released.  The", | 
 |     "replace method recolors any pixel that matches the color of", | 
 |     "the pixel you select with a button press.  Floodfill recolors", | 
 |     "any pixel that matches the color of the pixel you select with", | 
 |     "a button press and is a neighbor.  Whereas filltoborder recolors", | 
 |     "any neighbor pixel that is not the border color.  Finally reset", | 
 |     "changes the entire image to the designated color.", | 
 |     "", | 
 |     "Next, choose a pixel color from the Pixel Color sub-menu.", | 
 |     "Additional pixel colors can be specified with the color", | 
 |     "browser.  You can change the menu colors by setting the X", | 
 |     "resources pen1 through pen9.", | 
 |     "", | 
 |     "Now press button 1 to select a pixel within the image window", | 
 |     "to change its color.  Additional pixels may be recolored as", | 
 |     "prescribed by the method you choose.", | 
 |     "", | 
 |     "If the Magnify widget is mapped, it can be helpful in positioning", | 
 |     "your pointer within the image (refer to button 2).", | 
 |     "", | 
 |     "The actual color you request for the pixels is saved in the", | 
 |     "image.  However, the color that appears in your image window", | 
 |     "may be different.  For example, on a monochrome screen the", | 
 |     "pixel will appear black or white even if you choose the", | 
 |     "color red as the pixel color.  However, the image saved to a", | 
 |     "file with -write is written with red pixels.  To assure the", | 
 |     "correct color text in the final image, any PseudoClass image", | 
 |     "is promoted to DirectClass (see miff(5)).  To force a", | 
 |     "PseudoClass image to remain PseudoClass, use -colors.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageCompositeHelp[] = | 
 |   { | 
 |     "First a widget window is displayed requesting you to enter an", | 
 |     "image name. Press Composite, Grab or type a file name.", | 
 |     "Press Cancel if you choose not to create a composite image.", | 
 |     "When you choose Grab, move the pointer to the desired window", | 
 |     "and press any button.", | 
 |     "", | 
 |     "If the Composite image does not have any matte information,", | 
 |     "you are informed and the file browser is displayed again.", | 
 |     "Enter the name of a mask image.  The image is typically", | 
 |     "grayscale and the same size as the composite image.  If the", | 
 |     "image is not grayscale, it is converted to grayscale and the", | 
 |     "resulting intensities are used as matte information.", | 
 |     "", | 
 |     "A small window appears showing the location of the cursor in", | 
 |     "the image window. You are now in composite mode.  To exit", | 
 |     "immediately, press Dismiss.  In composite mode, the Command", | 
 |     "widget has these options:", | 
 |     "", | 
 |     "    Operators", | 
 |     "      Over", | 
 |     "      In", | 
 |     "      Out", | 
 |     "      Atop", | 
 |     "      Xor", | 
 |     "      Plus", | 
 |     "      Minus", | 
 |     "      Add", | 
 |     "      Subtract", | 
 |     "      Difference", | 
 |     "      Multiply", | 
 |     "      Bumpmap", | 
 |     "      Copy", | 
 |     "      CopyRed", | 
 |     "      CopyGreen", | 
 |     "      CopyBlue", | 
 |     "      CopyOpacity", | 
 |     "      Clear", | 
 |     "    Dissolve", | 
 |     "    Displace", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "Choose a composite operation from the Operators sub-menu of", | 
 |     "the Command widget.  How each operator behaves is described", | 
 |     "below.  Image window is the image currently displayed on", | 
 |     "your X server and image is the image obtained with the File", | 
 |     "Browser widget.", | 
 |     "", | 
 |     "Over     The result is the union of the two image shapes,", | 
 |     "         with image obscuring image window in the region of", | 
 |     "         overlap.", | 
 |     "", | 
 |     "In       The result is simply image cut by the shape of", | 
 |     "         image window.  None of the image data of image", | 
 |     "         window is in the result.", | 
 |     "", | 
 |     "Out      The resulting image is image with the shape of", | 
 |     "         image window cut out.", | 
 |     "", | 
 |     "Atop     The result is the same shape as image image window,", | 
 |     "         with image obscuring image window where the image", | 
 |     "         shapes overlap.  Note this differs from over", | 
 |     "         because the portion of image outside image window's", | 
 |     "         shape does not appear in the result.", | 
 |     "", | 
 |     "Xor      The result is the image data from both image and", | 
 |     "         image window that is outside the overlap region.", | 
 |     "         The overlap region is blank.", | 
 |     "", | 
 |     "Plus     The result is just the sum of the image data.", | 
 |     "         Output values are cropped to QuantumRange (no overflow).", | 
 |     "", | 
 |     "Minus    The result of image - image window, with underflow", | 
 |     "         cropped to zero.", | 
 |     "", | 
 |     "Add      The result of image + image window, with overflow", | 
 |     "         wrapping around (mod 256).", | 
 |     "", | 
 |     "Subtract The result of image - image window, with underflow", | 
 |     "         wrapping around (mod 256).  The add and subtract", | 
 |     "         operators can be used to perform reversible", | 
 |     "         transformations.", | 
 |     "", | 
 |     "Difference", | 
 |     "         The result of abs(image - image window).  This", | 
 |     "         useful for comparing two very similar images.", | 
 |     "", | 
 |     "Multiply", | 
 |     "         The result of image * image window.  This", | 
 |     "         useful for the creation of drop-shadows.", | 
 |     "", | 
 |     "Bumpmap  The result of surface normals from image * image", | 
 |     "         window.", | 
 |     "", | 
 |     "Copy     The resulting image is image window replaced with", | 
 |     "         image.  Here the matte information is ignored.", | 
 |     "", | 
 |     "CopyRed  The red layer of the image window is replace with", | 
 |     "         the red layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "CopyGreen", | 
 |     "         The green layer of the image window is replace with", | 
 |     "         the green layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "CopyBlue The blue layer of the image window is replace with", | 
 |     "         the blue layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "CopyOpacity", | 
 |     "         The matte layer of the image window is replace with", | 
 |     "         the matte layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "The image compositor requires a matte, or alpha channel in", | 
 |     "the image for some operations.  This extra channel usually", | 
 |     "defines a mask which represents a sort of a cookie-cutter", | 
 |     "for the image.  This the case when matte is opaque (full", | 
 |     "coverage) for pixels inside the shape, zero outside, and", | 
 |     "between 0 and QuantumRange on the boundary.  If image does not", | 
 |     "have a matte channel, it is initialized with 0 for any pixel", | 
 |     "matching in color to pixel location (0,0), otherwise QuantumRange.", | 
 |     "", | 
 |     "If you choose Dissolve, the composite operator becomes Over.  The", | 
 |     "image matte channel percent transparency is initialized to factor.", | 
 |     "The image window is initialized to (100-factor). Where factor is the", | 
 |     "value you specify in the Dialog widget.", | 
 |     "", | 
 |     "Displace shifts the image pixels as defined by a displacement", | 
 |     "map.  With this option, image is used as a displacement map.", | 
 |     "Black, within the displacement map, is a maximum positive", | 
 |     "displacement.  White is a maximum negative displacement and", | 
 |     "middle gray is neutral.  The displacement is scaled to determine", | 
 |     "the pixel shift.  By default, the displacement applies in both the", | 
 |     "horizontal and vertical directions.  However, if you specify a mask,", | 
 |     "image is the horizontal X displacement and mask the vertical Y", | 
 |     "displacement.", | 
 |     "", | 
 |     "Note that matte information for image window is not retained", | 
 |     "for colormapped X server visuals (e.g. StaticColor,", | 
 |     "StaticColor, GrayScale, PseudoColor).  Correct compositing", | 
 |     "behavior may require a TrueColor or DirectColor visual or a", | 
 |     "Standard Colormap.", | 
 |     "", | 
 |     "Choosing a composite operator is optional.  The default", | 
 |     "operator is replace.  However, you must choose a location to", | 
 |     "composite your image and press button 1.  Press and hold the", | 
 |     "button before releasing and an outline of the image will", | 
 |     "appear to help you identify your location.", | 
 |     "", | 
 |     "The actual colors of the composite image is saved.  However,", | 
 |     "the color that appears in image window may be different.", | 
 |     "For example, on a monochrome screen image window will appear", | 
 |     "black or white even though your composited image may have", | 
 |     "many colors.  If the image is saved to a file it is written", | 
 |     "with the correct colors.  To assure the correct colors are", | 
 |     "saved in the final image, any PseudoClass image is promoted", | 
 |     "to DirectClass (see miff(5)).  To force a PseudoClass image", | 
 |     "to remain PseudoClass, use -colors.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageCutHelp[] = | 
 |   { | 
 |     "In cut mode, the Command widget has these options:", | 
 |     "", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "To define a cut region, press button 1 and drag.  The", | 
 |     "cut region is defined by a highlighted rectangle that", | 
 |     "expands or contracts as it follows the pointer.  Once you", | 
 |     "are satisfied with the cut region, release the button.", | 
 |     "You are now in rectify mode.  In rectify mode, the Command", | 
 |     "widget has these options:", | 
 |     "", | 
 |     "    Cut", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "You can make adjustments by moving the pointer to one of the", | 
 |     "cut rectangle corners, pressing a button, and dragging.", | 
 |     "Finally, press Cut to commit your copy region.  To", | 
 |     "exit without cutting the image, press Dismiss.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageCopyHelp[] = | 
 |   { | 
 |     "In copy mode, the Command widget has these options:", | 
 |     "", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "To define a copy region, press button 1 and drag.  The", | 
 |     "copy region is defined by a highlighted rectangle that", | 
 |     "expands or contracts as it follows the pointer.  Once you", | 
 |     "are satisfied with the copy region, release the button.", | 
 |     "You are now in rectify mode.  In rectify mode, the Command", | 
 |     "widget has these options:", | 
 |     "", | 
 |     "    Copy", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "You can make adjustments by moving the pointer to one of the", | 
 |     "copy rectangle corners, pressing a button, and dragging.", | 
 |     "Finally, press Copy to commit your copy region.  To", | 
 |     "exit without copying the image, press Dismiss.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageCropHelp[] = | 
 |   { | 
 |     "In crop mode, the Command widget has these options:", | 
 |     "", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "To define a cropping region, press button 1 and drag.  The", | 
 |     "cropping region is defined by a highlighted rectangle that", | 
 |     "expands or contracts as it follows the pointer.  Once you", | 
 |     "are satisfied with the cropping region, release the button.", | 
 |     "You are now in rectify mode.  In rectify mode, the Command", | 
 |     "widget has these options:", | 
 |     "", | 
 |     "    Crop", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "You can make adjustments by moving the pointer to one of the", | 
 |     "cropping rectangle corners, pressing a button, and dragging.", | 
 |     "Finally, press Crop to commit your cropping region.  To", | 
 |     "exit without cropping the image, press Dismiss.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageDrawHelp[] = | 
 |   { | 
 |     "The cursor changes to a crosshair to indicate you are in", | 
 |     "draw mode.  To exit immediately, press Dismiss.  In draw mode,", | 
 |     "the Command widget has these options:", | 
 |     "", | 
 |     "    Element", | 
 |     "      point", | 
 |     "      line", | 
 |     "      rectangle", | 
 |     "      fill rectangle", | 
 |     "      circle", | 
 |     "      fill circle", | 
 |     "      ellipse", | 
 |     "      fill ellipse", | 
 |     "      polygon", | 
 |     "      fill polygon", | 
 |     "    Color", | 
 |     "      black", | 
 |     "      blue", | 
 |     "      cyan", | 
 |     "      green", | 
 |     "      gray", | 
 |     "      red", | 
 |     "      magenta", | 
 |     "      yellow", | 
 |     "      white", | 
 |     "      transparent", | 
 |     "      Browser...", | 
 |     "    Stipple", | 
 |     "      Brick", | 
 |     "      Diagonal", | 
 |     "      Scales", | 
 |     "      Vertical", | 
 |     "      Wavy", | 
 |     "      Translucent", | 
 |     "      Opaque", | 
 |     "      Open...", | 
 |     "    Width", | 
 |     "      1", | 
 |     "      2", | 
 |     "      4", | 
 |     "      8", | 
 |     "      16", | 
 |     "      Dialog...", | 
 |     "    Undo", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "Choose a drawing primitive from the Element sub-menu.", | 
 |     "", | 
 |     "Choose a color from the Color sub-menu.  Additional", | 
 |     "colors can be specified with the color browser.", | 
 |     "", | 
 |     "If you choose the color browser and press Grab, you can", | 
 |     "select the color by moving the pointer to the desired", | 
 |     "color on the screen and press any button.  The transparent", | 
 |     "color updates the image matte channel and is useful for", | 
 |     "image compositing.", | 
 |     "", | 
 |     "Choose a stipple, if appropriate, from the Stipple sub-menu.", | 
 |     "Additional stipples can be specified with the file browser.", | 
 |     "Stipples obtained from the file browser must be on disk in the", | 
 |     "X11 bitmap format.", | 
 |     "", | 
 |     "Choose a width, if appropriate, from the Width sub-menu.  To", | 
 |     "choose a specific width select the Dialog widget.", | 
 |     "", | 
 |     "Choose a point in the Image window and press button 1 and", | 
 |     "hold.  Next, move the pointer to another location in the", | 
 |     "image.  As you move, a line connects the initial location and", | 
 |     "the pointer.  When you release the button, the image is", | 
 |     "updated with the primitive you just drew.  For polygons, the", | 
 |     "image is updated when you press and release the button without", | 
 |     "moving the pointer.", | 
 |     "", | 
 |     "To cancel image drawing, move the pointer back to the", | 
 |     "starting point of the line and release the button.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *DisplayHelp[] = | 
 |   { | 
 |     "BUTTONS", | 
 |     "  The effects of each button press is described below.  Three", | 
 |     "  buttons are required.  If you have a two button mouse,", | 
 |     "  button 1 and 3 are returned.  Press ALT and button 3 to", | 
 |     "  simulate button 2.", | 
 |     "", | 
 |     "  1    Press this button to map or unmap the Command widget.", | 
 |     "", | 
 |     "  2    Press and drag to define a region of the image to", | 
 |     "       magnify.", | 
 |     "", | 
 |     "  3    Press and drag to choose from a select set of commands.", | 
 |     "       This button behaves differently if the image being", | 
 |     "       displayed is a visual image directory.  Here, choose a", | 
 |     "       particular tile of the directory and press this button and", | 
 |     "       drag to select a command from a pop-up menu.  Choose from", | 
 |     "       these menu items:", | 
 |     "", | 
 |     "           Open", | 
 |     "           Next", | 
 |     "           Former", | 
 |     "           Delete", | 
 |     "           Update", | 
 |     "", | 
 |     "       If you choose Open, the image represented by the tile is", | 
 |     "       displayed.  To return to the visual image directory, choose", | 
 |     "       Next from the Command widget.  Next and Former moves to the", | 
 |     "       next or former image respectively.  Choose Delete to delete", | 
 |     "       a particular image tile.  Finally, choose Update to", | 
 |     "       synchronize all the image tiles with their respective", | 
 |     "       images.", | 
 |     "", | 
 |     "COMMAND WIDGET", | 
 |     "  The Command widget lists a number of sub-menus and commands.", | 
 |     "  They are", | 
 |     "", | 
 |     "      File", | 
 |     "        Open...", | 
 |     "        Next", | 
 |     "        Former", | 
 |     "        Select...", | 
 |     "        Save...", | 
 |     "        Print...", | 
 |     "        Delete...", | 
 |     "        New...", | 
 |     "        Visual Directory...", | 
 |     "        Quit", | 
 |     "      Edit", | 
 |     "        Undo", | 
 |     "        Redo", | 
 |     "        Cut", | 
 |     "        Copy", | 
 |     "        Paste", | 
 |     "      View", | 
 |     "        Half Size", | 
 |     "        Original Size", | 
 |     "        Double Size", | 
 |     "        Resize...", | 
 |     "        Apply", | 
 |     "        Refresh", | 
 |     "        Restore", | 
 |     "      Transform", | 
 |     "        Crop", | 
 |     "        Chop", | 
 |     "        Flop", | 
 |     "        Flip", | 
 |     "        Rotate Right", | 
 |     "        Rotate Left", | 
 |     "        Rotate...", | 
 |     "        Shear...", | 
 |     "        Roll...", | 
 |     "        Trim Edges", | 
 |     "      Enhance", | 
 |     "        Brightness...", | 
 |     "        Saturation...", | 
 |     "        Hue...", | 
 |     "        Gamma...", | 
 |     "        Sharpen...", | 
 |     "        Dull", | 
 |     "        Contrast Stretch...", | 
 |     "        Sigmoidal Contrast...", | 
 |     "        Normalize", | 
 |     "        Equalize", | 
 |     "        Negate", | 
 |     "        Grayscale", | 
 |     "        Map...", | 
 |     "        Quantize...", | 
 |     "      Effects", | 
 |     "        Despeckle", | 
 |     "        Emboss", | 
 |     "        Reduce Noise", | 
 |     "        Add Noise", | 
 |     "        Sharpen...", | 
 |     "        Blur...", | 
 |     "        Threshold...", | 
 |     "        Edge Detect...", | 
 |     "        Spread...", | 
 |     "        Shade...", | 
 |     "        Painting...", | 
 |     "        Segment...", | 
 |     "      F/X", | 
 |     "        Solarize...", | 
 |     "        Sepia Tone...", | 
 |     "        Swirl...", | 
 |     "        Implode...", | 
 |     "        Vignette...", | 
 |     "        Wave...", | 
 |     "        Oil Painting...", | 
 |     "        Charcoal Drawing...", | 
 |     "      Image Edit", | 
 |     "        Annotate...", | 
 |     "        Draw...", | 
 |     "        Color...", | 
 |     "        Matte...", | 
 |     "        Composite...", | 
 |     "        Add Border...", | 
 |     "        Add Frame...", | 
 |     "        Comment...", | 
 |     "        Launch...", | 
 |     "        Region of Interest...", | 
 |     "      Miscellany", | 
 |     "        Image Info", | 
 |     "        Zoom Image", | 
 |     "        Show Preview...", | 
 |     "        Show Histogram", | 
 |     "        Show Matte", | 
 |     "        Background...", | 
 |     "        Slide Show", | 
 |     "        Preferences...", | 
 |     "      Help", | 
 |     "        Overview", | 
 |     "        Browse Documentation", | 
 |     "        About Display", | 
 |     "", | 
 |     "  Menu items with a indented triangle have a sub-menu.  They", | 
 |     "  are represented above as the indented items.  To access a", | 
 |     "  sub-menu item, move the pointer to the appropriate menu and", | 
 |     "  press a button and drag.  When you find the desired sub-menu", | 
 |     "  item, release the button and the command is executed.  Move", | 
 |     "  the pointer away from the sub-menu if you decide not to", | 
 |     "  execute a particular command.", | 
 |     "", | 
 |     "KEYBOARD ACCELERATORS", | 
 |     "  Accelerators are one or two key presses that effect a", | 
 |     "  particular command.  The keyboard accelerators that", | 
 |     "  display(1) understands is:", | 
 |     "", | 
 |     "  Ctl+O     Press to open an image from a file.", | 
 |     "", | 
 |     "  space     Press to display the next image.", | 
 |     "", | 
 |     "            If the image is a multi-paged document such as a Postscript", | 
 |     "            document, you can skip ahead several pages by preceding", | 
 |     "            this command with a number.  For example to display the", | 
 |     "            third page beyond the current page, press 3<space>.", | 
 |     "", | 
 |     "  backspace Press to display the former image.", | 
 |     "", | 
 |     "            If the image is a multi-paged document such as a Postscript", | 
 |     "            document, you can skip behind several pages by preceding", | 
 |     "            this command with a number.  For example to display the", | 
 |     "            third page preceding the current page, press 3<backspace>.", | 
 |     "", | 
 |     "  Ctl+S     Press to write the image to a file.", | 
 |     "", | 
 |     "  Ctl+P     Press to print the image to a Postscript printer.", | 
 |     "", | 
 |     "  Ctl+D     Press to delete an image file.", | 
 |     "", | 
 |     "  Ctl+N     Press to create a blank canvas.", | 
 |     "", | 
 |     "  Ctl+Q     Press to discard all images and exit program.", | 
 |     "", | 
 |     "  Ctl+Z     Press to undo last image transformation.", | 
 |     "", | 
 |     "  Ctl+R     Press to redo last image transformation.", | 
 |     "", | 
 |     "  Ctl+X     Press to cut a region of the image.", | 
 |     "", | 
 |     "  Ctl+C     Press to copy a region of the image.", | 
 |     "", | 
 |     "  Ctl+V     Press to paste a region to the image.", | 
 |     "", | 
 |     "  <         Press to half the image size.", | 
 |     "", | 
 |     "  -         Press to return to the original image size.", | 
 |     "", | 
 |     "  >         Press to double the image size.", | 
 |     "", | 
 |     "  %         Press to resize the image to a width and height you", | 
 |     "            specify.", | 
 |     "", | 
 |     "Cmd-A       Press to make any image transformations permanent." | 
 |     "", | 
 |     "            By default, any image size transformations are applied", | 
 |     "            to the original image to create the image displayed on", | 
 |     "            the X server.  However, the transformations are not", | 
 |     "            permanent (i.e. the original image does not change", | 
 |     "            size only the X image does).  For example, if you", | 
 |     "            press > the X image will appear to double in size,", | 
 |     "            but the original image will in fact remain the same size.", | 
 |     "            To force the original image to double in size, press >", | 
 |     "            followed by Cmd-A.", | 
 |     "", | 
 |     "  @         Press to refresh the image window.", | 
 |     "", | 
 |     "  C         Press to cut out a rectangular region of the image.", | 
 |     "", | 
 |     "  [         Press to chop the image.", | 
 |     "", | 
 |     "  H         Press to flop image in the horizontal direction.", | 
 |     "", | 
 |     "  V         Press to flip image in the vertical direction.", | 
 |     "", | 
 |     "  /         Press to rotate the image 90 degrees clockwise.", | 
 |     "", | 
 |     " \\         Press to rotate the image 90 degrees counter-clockwise.", | 
 |     "", | 
 |     "  *         Press to rotate the image the number of degrees you", | 
 |     "            specify.", | 
 |     "", | 
 |     "  S         Press to shear the image the number of degrees you", | 
 |     "            specify.", | 
 |     "", | 
 |     "  R         Press to roll the image.", | 
 |     "", | 
 |     "  T         Press to trim the image edges.", | 
 |     "", | 
 |     "  Shft-H    Press to vary the image hue.", | 
 |     "", | 
 |     "  Shft-S    Press to vary the color saturation.", | 
 |     "", | 
 |     "  Shft-L    Press to vary the color brightness.", | 
 |     "", | 
 |     "  Shft-G    Press to gamma correct the image.", | 
 |     "", | 
 |     "  Shft-C    Press to sharpen the image contrast.", | 
 |     "", | 
 |     "  Shft-Z    Press to dull the image contrast.", | 
 |     "", | 
 |     "  =         Press to perform histogram equalization on the image.", | 
 |     "", | 
 |     "  Shft-N    Press to perform histogram normalization on the image.", | 
 |     "", | 
 |     "  Shft-~    Press to negate the colors of the image.", | 
 |     "", | 
 |     "  .         Press to convert the image colors to gray.", | 
 |     "", | 
 |     "  Shft-#    Press to set the maximum number of unique colors in the", | 
 |     "            image.", | 
 |     "", | 
 |     "  F2        Press to reduce the speckles in an image.", | 
 |     "", | 
 |     "  F3        Press to eliminate peak noise from an image.", | 
 |     "", | 
 |     "  F4        Press to add noise to an image.", | 
 |     "", | 
 |     "  F5        Press to sharpen an image.", | 
 |     "", | 
 |     "  F6        Press to delete an image file.", | 
 |     "", | 
 |     "  F7        Press to threshold the image.", | 
 |     "", | 
 |     "  F8        Press to detect edges within an image.", | 
 |     "", | 
 |     "  F9        Press to emboss an image.", | 
 |     "", | 
 |     "  F10       Press to displace pixels by a random amount.", | 
 |     "", | 
 |     "  F11       Press to negate all pixels above the threshold level.", | 
 |     "", | 
 |     "  F12       Press to shade the image using a distant light source.", | 
 |     "", | 
 |     "  F13       Press to lighten or darken image edges to create a 3-D effect.", | 
 |     "", | 
 |     "  F14       Press to segment the image by color.", | 
 |     "", | 
 |     "  Meta-S    Press to swirl image pixels about the center.", | 
 |     "", | 
 |     "  Meta-I    Press to implode image pixels about the center.", | 
 |     "", | 
 |     "  Meta-W    Press to alter an image along a sine wave.", | 
 |     "", | 
 |     "  Meta-P    Press to simulate an oil painting.", | 
 |     "", | 
 |     "  Meta-C    Press to simulate a charcoal drawing.", | 
 |     "", | 
 |     "  Alt-A     Press to annotate the image with text.", | 
 |     "", | 
 |     "  Alt-D     Press to draw on an image.", | 
 |     "", | 
 |     "  Alt-P     Press to edit an image pixel color.", | 
 |     "", | 
 |     "  Alt-M     Press to edit the image matte information.", | 
 |     "", | 
 |     "  Alt-V     Press to composite the image with another.", | 
 |     "", | 
 |     "  Alt-B     Press to add a border to the image.", | 
 |     "", | 
 |     "  Alt-F     Press to add an ornamental border to the image.", | 
 |     "", | 
 |     "  Alt-Shft-!", | 
 |     "            Press to add an image comment.", | 
 |     "", | 
 |     "  Ctl-A     Press to apply image processing techniques to a region", | 
 |     "            of interest.", | 
 |     "", | 
 |     "  Shft-?    Press to display information about the image.", | 
 |     "", | 
 |     "  Shft-+    Press to map the zoom image window.", | 
 |     "", | 
 |     "  Shft-P    Press to preview an image enhancement, effect, or f/x.", | 
 |     "", | 
 |     "  F1        Press to display helpful information about display(1).", | 
 |     "", | 
 |     "  Find      Press to browse documentation about ImageMagick.", | 
 |     "", | 
 |     "  1-9       Press to change the level of magnification.", | 
 |     "", | 
 |     "  Use the arrow keys to move the image one pixel up, down,", | 
 |     "  left, or right within the magnify window.  Be sure to first", | 
 |     "  map the magnify window by pressing button 2.", | 
 |     "", | 
 |     "  Press ALT and one of the arrow keys to trim off one pixel", | 
 |     "  from any side of the image.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageMatteEditHelp[] = | 
 |   { | 
 |     "Matte information within an image is useful for some", | 
 |     "operations such as image compositing (See IMAGE", | 
 |     "COMPOSITING).  This extra channel usually defines a mask", | 
 |     "which represents a sort of a cookie-cutter for the image.", | 
 |     "This the case when matte is opaque (full coverage) for", | 
 |     "pixels inside the shape, zero outside, and between 0 and", | 
 |     "QuantumRange on the boundary.", | 
 |     "", | 
 |     "A small window appears showing the location of the cursor in", | 
 |     "the image window. You are now in matte edit mode.  To exit", | 
 |     "immediately, press Dismiss.  In matte edit mode, the Command", | 
 |     "widget has these options:", | 
 |     "", | 
 |     "    Method", | 
 |     "      point", | 
 |     "      replace", | 
 |     "      floodfill", | 
 |     "      filltoborder", | 
 |     "      reset", | 
 |     "    Border Color", | 
 |     "      black", | 
 |     "      blue", | 
 |     "      cyan", | 
 |     "      green", | 
 |     "      gray", | 
 |     "      red", | 
 |     "      magenta", | 
 |     "      yellow", | 
 |     "      white", | 
 |     "      Browser...", | 
 |     "    Fuzz", | 
 |     "      0%", | 
 |     "      2%", | 
 |     "      5%", | 
 |     "      10%", | 
 |     "      15%", | 
 |     "      Dialog...", | 
 |     "    Matte", | 
 |     "      Opaque", | 
 |     "      Transparent", | 
 |     "      Dialog...", | 
 |     "    Undo", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "Choose a matte editing method from the Method sub-menu of", | 
 |     "the Command widget.  The point method changes the matte value", | 
 |     "of any pixel selected with the pointer until the button is", | 
 |     "is released.  The replace method changes the matte value of", | 
 |     "any pixel that matches the color of the pixel you select with", | 
 |     "a button press.  Floodfill changes the matte value of any pixel", | 
 |     "that matches the color of the pixel you select with a button", | 
 |     "press and is a neighbor.  Whereas filltoborder changes the matte", | 
 |     "value any neighbor pixel that is not the border color.  Finally", | 
 |     "reset changes the entire image to the designated matte value.", | 
 |     "", | 
 |     "Choose Matte Value and pick Opaque or Transarent.  For other values", | 
 |     "select the Dialog entry.  Here a dialog appears requesting a matte", | 
 |     "value.  The value you select is assigned as the opacity value of the", | 
 |     "selected pixel or pixels.", | 
 |     "", | 
 |     "Now, press any button to select a pixel within the image", | 
 |     "window to change its matte value.", | 
 |     "", | 
 |     "If the Magnify widget is mapped, it can be helpful in positioning", | 
 |     "your pointer within the image (refer to button 2).", | 
 |     "", | 
 |     "Matte information is only valid in a DirectClass image.", | 
 |     "Therefore, any PseudoClass image is promoted to DirectClass", | 
 |     "(see miff(5)).  Note that matte information for PseudoClass", | 
 |     "is not retained for colormapped X server visuals (e.g.", | 
 |     "StaticColor, StaticColor, GrayScale, PseudoColor) unless you", | 
 |     "immediately save your image to a file (refer to Write).", | 
 |     "Correct matte editing behavior may require a TrueColor or", | 
 |     "DirectColor visual or a Standard Colormap.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImagePanHelp[] = | 
 |   { | 
 |     "When an image exceeds the width or height of the X server", | 
 |     "screen, display maps a small panning icon.  The rectangle", | 
 |     "within the panning icon shows the area that is currently", | 
 |     "displayed in the image window.  To pan about the image,", | 
 |     "press any button and drag the pointer within the panning", | 
 |     "icon.  The pan rectangle moves with the pointer and the", | 
 |     "image window is updated to reflect the location of the", | 
 |     "rectangle within the panning icon.  When you have selected", | 
 |     "the area of the image you wish to view, release the button.", | 
 |     "", | 
 |     "Use the arrow keys to pan the image one pixel up, down,", | 
 |     "left, or right within the image window.", | 
 |     "", | 
 |     "The panning icon is withdrawn if the image becomes smaller", | 
 |     "than the dimensions of the X server screen.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImagePasteHelp[] = | 
 |   { | 
 |     "A small window appears showing the location of the cursor in", | 
 |     "the image window. You are now in paste mode.  To exit", | 
 |     "immediately, press Dismiss.  In paste mode, the Command", | 
 |     "widget has these options:", | 
 |     "", | 
 |     "    Operators", | 
 |     "      over", | 
 |     "      in", | 
 |     "      out", | 
 |     "      atop", | 
 |     "      xor", | 
 |     "      plus", | 
 |     "      minus", | 
 |     "      add", | 
 |     "      subtract", | 
 |     "      difference", | 
 |     "      replace", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "Choose a composite operation from the Operators sub-menu of", | 
 |     "the Command widget.  How each operator behaves is described", | 
 |     "below.  Image window is the image currently displayed on", | 
 |     "your X server and image is the image obtained with the File", | 
 |     "Browser widget.", | 
 |     "", | 
 |     "Over     The result is the union of the two image shapes,", | 
 |     "         with image obscuring image window in the region of", | 
 |     "         overlap.", | 
 |     "", | 
 |     "In       The result is simply image cut by the shape of", | 
 |     "         image window.  None of the image data of image", | 
 |     "         window is in the result.", | 
 |     "", | 
 |     "Out      The resulting image is image with the shape of", | 
 |     "         image window cut out.", | 
 |     "", | 
 |     "Atop     The result is the same shape as image image window,", | 
 |     "         with image obscuring image window where the image", | 
 |     "         shapes overlap.  Note this differs from over", | 
 |     "         because the portion of image outside image window's", | 
 |     "         shape does not appear in the result.", | 
 |     "", | 
 |     "Xor      The result is the image data from both image and", | 
 |     "         image window that is outside the overlap region.", | 
 |     "         The overlap region is blank.", | 
 |     "", | 
 |     "Plus     The result is just the sum of the image data.", | 
 |     "         Output values are cropped to QuantumRange (no overflow).", | 
 |     "         This operation is independent of the matte", | 
 |     "         channels.", | 
 |     "", | 
 |     "Minus    The result of image - image window, with underflow", | 
 |     "         cropped to zero.", | 
 |     "", | 
 |     "Add      The result of image + image window, with overflow", | 
 |     "         wrapping around (mod 256).", | 
 |     "", | 
 |     "Subtract The result of image - image window, with underflow", | 
 |     "         wrapping around (mod 256).  The add and subtract", | 
 |     "         operators can be used to perform reversible", | 
 |     "         transformations.", | 
 |     "", | 
 |     "Difference", | 
 |     "         The result of abs(image - image window).  This", | 
 |     "         useful for comparing two very similar images.", | 
 |     "", | 
 |     "Copy     The resulting image is image window replaced with", | 
 |     "         image.  Here the matte information is ignored.", | 
 |     "", | 
 |     "CopyRed  The red layer of the image window is replace with", | 
 |     "         the red layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "CopyGreen", | 
 |     "         The green layer of the image window is replace with", | 
 |     "         the green layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "CopyBlue The blue layer of the image window is replace with", | 
 |     "         the blue layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "CopyOpacity", | 
 |     "         The matte layer of the image window is replace with", | 
 |     "         the matte layer of the image.  The other layers are", | 
 |     "         untouched.", | 
 |     "", | 
 |     "The image compositor requires a matte, or alpha channel in", | 
 |     "the image for some operations.  This extra channel usually", | 
 |     "defines a mask which represents a sort of a cookie-cutter", | 
 |     "for the image.  This the case when matte is opaque (full", | 
 |     "coverage) for pixels inside the shape, zero outside, and", | 
 |     "between 0 and QuantumRange on the boundary.  If image does not", | 
 |     "have a matte channel, it is initialized with 0 for any pixel", | 
 |     "matching in color to pixel location (0,0), otherwise QuantumRange.", | 
 |     "", | 
 |     "Note that matte information for image window is not retained", | 
 |     "for colormapped X server visuals (e.g. StaticColor,", | 
 |     "StaticColor, GrayScale, PseudoColor).  Correct compositing", | 
 |     "behavior may require a TrueColor or DirectColor visual or a", | 
 |     "Standard Colormap.", | 
 |     "", | 
 |     "Choosing a composite operator is optional.  The default", | 
 |     "operator is replace.  However, you must choose a location to", | 
 |     "paste your image and press button 1.  Press and hold the", | 
 |     "button before releasing and an outline of the image will", | 
 |     "appear to help you identify your location.", | 
 |     "", | 
 |     "The actual colors of the pasted image is saved.  However,", | 
 |     "the color that appears in image window may be different.", | 
 |     "For example, on a monochrome screen image window will appear", | 
 |     "black or white even though your pasted image may have", | 
 |     "many colors.  If the image is saved to a file it is written", | 
 |     "with the correct colors.  To assure the correct colors are", | 
 |     "saved in the final image, any PseudoClass image is promoted", | 
 |     "to DirectClass (see miff(5)).  To force a PseudoClass image", | 
 |     "to remain PseudoClass, use -colors.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageROIHelp[] = | 
 |   { | 
 |     "In region of interest mode, the Command widget has these", | 
 |     "options:", | 
 |     "", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "To define a region of interest, press button 1 and drag.", | 
 |     "The region of interest is defined by a highlighted rectangle", | 
 |     "that expands or contracts as it follows the pointer.  Once", | 
 |     "you are satisfied with the region of interest, release the", | 
 |     "button.  You are now in apply mode.  In apply mode the", | 
 |     "Command widget has these options:", | 
 |     "", | 
 |     "      File", | 
 |     "        Save...", | 
 |     "        Print...", | 
 |     "      Edit", | 
 |     "        Undo", | 
 |     "        Redo", | 
 |     "      Transform", | 
 |     "        Flop", | 
 |     "        Flip", | 
 |     "        Rotate Right", | 
 |     "        Rotate Left", | 
 |     "      Enhance", | 
 |     "        Hue...", | 
 |     "        Saturation...", | 
 |     "        Brightness...", | 
 |     "        Gamma...", | 
 |     "        Spiff", | 
 |     "        Dull", | 
 |     "        Contrast Stretch", | 
 |     "        Sigmoidal Contrast...", | 
 |     "        Normalize", | 
 |     "        Equalize", | 
 |     "        Negate", | 
 |     "        Grayscale", | 
 |     "        Map...", | 
 |     "        Quantize...", | 
 |     "      Effects", | 
 |     "        Despeckle", | 
 |     "        Emboss", | 
 |     "        Reduce Noise", | 
 |     "        Sharpen...", | 
 |     "        Blur...", | 
 |     "        Threshold...", | 
 |     "        Edge Detect...", | 
 |     "        Spread...", | 
 |     "        Shade...", | 
 |     "        Raise...", | 
 |     "        Segment...", | 
 |     "      F/X", | 
 |     "        Solarize...", | 
 |     "        Sepia Tone...", | 
 |     "        Swirl...", | 
 |     "        Implode...", | 
 |     "        Vignette...", | 
 |     "        Wave...", | 
 |     "        Oil Painting...", | 
 |     "        Charcoal Drawing...", | 
 |     "      Miscellany", | 
 |     "        Image Info", | 
 |     "        Zoom Image", | 
 |     "        Show Preview...", | 
 |     "        Show Histogram", | 
 |     "        Show Matte", | 
 |     "      Help", | 
 |     "      Dismiss", | 
 |     "", | 
 |     "You can make adjustments to the region of interest by moving", | 
 |     "the pointer to one of the rectangle corners, pressing a", | 
 |     "button, and dragging.  Finally, choose an image processing", | 
 |     "technique from the Command widget.  You can choose more than", | 
 |     "one image processing technique to apply to an area.", | 
 |     "Alternatively, you can move the region of interest before", | 
 |     "applying another image processing technique.  To exit, press", | 
 |     "Dismiss.", | 
 |     (char *) NULL, | 
 |   }, | 
 |   *ImageRotateHelp[] = | 
 |   { | 
 |     "In rotate mode, the Command widget has these options:", | 
 |     "", | 
 |     "    Pixel Color", | 
 |     "      black", | 
 |     "      blue", | 
 |     "      cyan", | 
 |     "      green", | 
 |     "      gray", | 
 |     "      red", | 
 |     "      magenta", | 
 |     "      yellow", | 
 |     "      white", | 
 |     "      Browser...", | 
 |     "    Direction", | 
 |     "      horizontal", | 
 |     "      vertical", | 
 |     "    Help", | 
 |     "    Dismiss", | 
 |     "", | 
 |     "Choose a background color from the Pixel Color sub-menu.", | 
 |     "Additional background colors can be specified with the color", | 
 |     "browser.  You can change the menu colors by setting the X", | 
 |     "resources pen1 through pen9.", | 
 |     "", | 
 |     "If you choose the color browser and press Grab, you can", | 
 |     "select the background color by moving the pointer to the", | 
 |     "desired color on the screen and press any button.", | 
 |     "", | 
 |     "Choose a point in the image window and press this button and", | 
 |     "hold.  Next, move the pointer to another location in the", | 
 |     "image.  As you move a line connects the initial location and", | 
 |     "the pointer.  When you release the button, the degree of", | 
 |     "image rotation is determined by the slope of the line you", | 
 |     "just drew.  The slope is relative to the direction you", | 
 |     "choose from the Direction sub-menu of the Command widget.", | 
 |     "", | 
 |     "To cancel the image rotation, move the pointer back to the", | 
 |     "starting point of the line and release the button.", | 
 |     (char *) NULL, | 
 |   }; | 
 |  | 
 | /* | 
 |   Enumeration declarations. | 
 | */ | 
 | typedef enum | 
 | { | 
 |   CopyMode, | 
 |   CropMode, | 
 |   CutMode | 
 | } ClipboardMode; | 
 |  | 
 | typedef enum | 
 | { | 
 |   OpenCommand, | 
 |   NextCommand, | 
 |   FormerCommand, | 
 |   SelectCommand, | 
 |   SaveCommand, | 
 |   PrintCommand, | 
 |   DeleteCommand, | 
 |   NewCommand, | 
 |   VisualDirectoryCommand, | 
 |   QuitCommand, | 
 |   UndoCommand, | 
 |   RedoCommand, | 
 |   CutCommand, | 
 |   CopyCommand, | 
 |   PasteCommand, | 
 |   HalfSizeCommand, | 
 |   OriginalSizeCommand, | 
 |   DoubleSizeCommand, | 
 |   ResizeCommand, | 
 |   ApplyCommand, | 
 |   RefreshCommand, | 
 |   RestoreCommand, | 
 |   CropCommand, | 
 |   ChopCommand, | 
 |   FlopCommand, | 
 |   FlipCommand, | 
 |   RotateRightCommand, | 
 |   RotateLeftCommand, | 
 |   RotateCommand, | 
 |   ShearCommand, | 
 |   RollCommand, | 
 |   TrimCommand, | 
 |   HueCommand, | 
 |   SaturationCommand, | 
 |   BrightnessCommand, | 
 |   GammaCommand, | 
 |   SpiffCommand, | 
 |   DullCommand, | 
 |   ContrastStretchCommand, | 
 |   SigmoidalContrastCommand, | 
 |   NormalizeCommand, | 
 |   EqualizeCommand, | 
 |   NegateCommand, | 
 |   GrayscaleCommand, | 
 |   MapCommand, | 
 |   QuantizeCommand, | 
 |   DespeckleCommand, | 
 |   EmbossCommand, | 
 |   ReduceNoiseCommand, | 
 |   AddNoiseCommand, | 
 |   SharpenCommand, | 
 |   BlurCommand, | 
 |   ThresholdCommand, | 
 |   EdgeDetectCommand, | 
 |   SpreadCommand, | 
 |   ShadeCommand, | 
 |   RaiseCommand, | 
 |   SegmentCommand, | 
 |   SolarizeCommand, | 
 |   SepiaToneCommand, | 
 |   SwirlCommand, | 
 |   ImplodeCommand, | 
 |   VignetteCommand, | 
 |   WaveCommand, | 
 |   OilPaintCommand, | 
 |   CharcoalDrawCommand, | 
 |   AnnotateCommand, | 
 |   DrawCommand, | 
 |   ColorCommand, | 
 |   MatteCommand, | 
 |   CompositeCommand, | 
 |   AddBorderCommand, | 
 |   AddFrameCommand, | 
 |   CommentCommand, | 
 |   LaunchCommand, | 
 |   RegionofInterestCommand, | 
 |   ROIHelpCommand, | 
 |   ROIDismissCommand, | 
 |   InfoCommand, | 
 |   ZoomCommand, | 
 |   ShowPreviewCommand, | 
 |   ShowHistogramCommand, | 
 |   ShowMatteCommand, | 
 |   BackgroundCommand, | 
 |   SlideShowCommand, | 
 |   PreferencesCommand, | 
 |   HelpCommand, | 
 |   BrowseDocumentationCommand, | 
 |   VersionCommand, | 
 |   SaveToUndoBufferCommand, | 
 |   FreeBuffersCommand, | 
 |   NullCommand | 
 | } CommandType; | 
 |  | 
 | typedef enum | 
 | { | 
 |   AnnotateNameCommand, | 
 |   AnnotateFontColorCommand, | 
 |   AnnotateBackgroundColorCommand, | 
 |   AnnotateRotateCommand, | 
 |   AnnotateHelpCommand, | 
 |   AnnotateDismissCommand, | 
 |   TextHelpCommand, | 
 |   TextApplyCommand, | 
 |   ChopDirectionCommand, | 
 |   ChopHelpCommand, | 
 |   ChopDismissCommand, | 
 |   HorizontalChopCommand, | 
 |   VerticalChopCommand, | 
 |   ColorEditMethodCommand, | 
 |   ColorEditColorCommand, | 
 |   ColorEditBorderCommand, | 
 |   ColorEditFuzzCommand, | 
 |   ColorEditUndoCommand, | 
 |   ColorEditHelpCommand, | 
 |   ColorEditDismissCommand, | 
 |   CompositeOperatorsCommand, | 
 |   CompositeDissolveCommand, | 
 |   CompositeDisplaceCommand, | 
 |   CompositeHelpCommand, | 
 |   CompositeDismissCommand, | 
 |   CropHelpCommand, | 
 |   CropDismissCommand, | 
 |   RectifyCopyCommand, | 
 |   RectifyHelpCommand, | 
 |   RectifyDismissCommand, | 
 |   DrawElementCommand, | 
 |   DrawColorCommand, | 
 |   DrawStippleCommand, | 
 |   DrawWidthCommand, | 
 |   DrawUndoCommand, | 
 |   DrawHelpCommand, | 
 |   DrawDismissCommand, | 
 |   MatteEditMethod, | 
 |   MatteEditBorderCommand, | 
 |   MatteEditFuzzCommand, | 
 |   MatteEditValueCommand, | 
 |   MatteEditUndoCommand, | 
 |   MatteEditHelpCommand, | 
 |   MatteEditDismissCommand, | 
 |   PasteOperatorsCommand, | 
 |   PasteHelpCommand, | 
 |   PasteDismissCommand, | 
 |   RotateColorCommand, | 
 |   RotateDirectionCommand, | 
 |   RotateCropCommand, | 
 |   RotateSharpenCommand, | 
 |   RotateHelpCommand, | 
 |   RotateDismissCommand, | 
 |   HorizontalRotateCommand, | 
 |   VerticalRotateCommand, | 
 |   TileLoadCommand, | 
 |   TileNextCommand, | 
 |   TileFormerCommand, | 
 |   TileDeleteCommand, | 
 |   TileUpdateCommand | 
 | } ModeType; | 
 |  | 
 | /* | 
 |   Stipples. | 
 | */ | 
 | #define BricksWidth  20 | 
 | #define BricksHeight  20 | 
 | #define DiagonalWidth  16 | 
 | #define DiagonalHeight  16 | 
 | #define HighlightWidth  8 | 
 | #define HighlightHeight  8 | 
 | #define OpaqueWidth  8 | 
 | #define OpaqueHeight  8 | 
 | #define ScalesWidth  16 | 
 | #define ScalesHeight  16 | 
 | #define ShadowWidth  8 | 
 | #define ShadowHeight  8 | 
 | #define VerticalWidth  16 | 
 | #define VerticalHeight  16 | 
 | #define WavyWidth  16 | 
 | #define WavyHeight  16 | 
 |  | 
 | /* | 
 |   Constant declaration. | 
 | */ | 
 | static const int | 
 |   RoiDelta = 8; | 
 |  | 
 | static const unsigned char | 
 |   BricksBitmap[] = | 
 |   { | 
 |     0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, | 
 |     0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, | 
 |     0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, | 
 |     0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, | 
 |     0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01 | 
 |   }, | 
 |   DiagonalBitmap[] = | 
 |   { | 
 |     0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, | 
 |     0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, | 
 |     0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22 | 
 |   }, | 
 |   ScalesBitmap[] = | 
 |   { | 
 |     0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80, | 
 |     0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, | 
 |     0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e | 
 |   }, | 
 |   VerticalBitmap[] = | 
 |   { | 
 |     0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, | 
 |     0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, | 
 |     0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 | 
 |   }, | 
 |   WavyBitmap[] = | 
 |   { | 
 |     0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff, | 
 |     0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf, | 
 |     0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f | 
 |   }; | 
 |  | 
 | /* | 
 |   Function prototypes. | 
 | */ | 
 | static CommandType | 
 |   XImageWindowCommand(Display *,XResourceInfo *,XWindows *, | 
 |     const MagickStatusType,KeySym,Image **,ExceptionInfo *); | 
 |  | 
 | static Image | 
 |   *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType, | 
 |     Image **,ExceptionInfo *), | 
 |   *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType), | 
 |   *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *, | 
 |     ExceptionInfo *), | 
 |   *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *, | 
 |     ExceptionInfo *); | 
 |  | 
 | static MagickBooleanType | 
 |   XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *, | 
 |     ExceptionInfo *), | 
 |   XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **, | 
 |     ExceptionInfo *), | 
 |   XChopImage(Display *,XResourceInfo *,XWindows *,Image **, | 
 |     ExceptionInfo *), | 
 |   XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode, | 
 |     ExceptionInfo *), | 
 |   XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **, | 
 |     ExceptionInfo *), | 
 |   XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *, | 
 |     ExceptionInfo *), | 
 |   XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *), | 
 |   XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **, | 
 |     ExceptionInfo *), | 
 |   XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **, | 
 |     ExceptionInfo *), | 
 |   XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *), | 
 |   XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *), | 
 |   XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **, | 
 |     ExceptionInfo *), | 
 |   XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *), | 
 |   XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *), | 
 |   XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *); | 
 |  | 
 | static void | 
 |   XDrawPanRectangle(Display *,XWindows *), | 
 |   XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **, | 
 |     ExceptionInfo *), | 
 |   XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *), | 
 |   XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *), | 
 |   XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *), | 
 |   XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType, | 
 |     const KeySym,ExceptionInfo *), | 
 |   XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *), | 
 |   XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *), | 
 |   XTranslateImage(Display *,XWindows *,Image *,const KeySym); | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %   D i s p l a y I m a g e s                                                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  DisplayImages() displays an image sequence to any X window screen.  It | 
 | %  returns a value other than 0 if successful.  Check the exception member | 
 | %  of image to determine the reason for any failure. | 
 | % | 
 | %  The format of the DisplayImages method is: | 
 | % | 
 | %      MagickBooleanType DisplayImages(const ImageInfo *image_info, | 
 | %        Image *images,ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o image_info: the image info. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info, | 
 |   Image *images,ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     *argv[1]; | 
 |  | 
 |   Display | 
 |     *display; | 
 |  | 
 |   Image | 
 |     *image; | 
 |  | 
 |   register ssize_t | 
 |     i; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XrmDatabase | 
 |     resource_database; | 
 |  | 
 |   XResourceInfo | 
 |     resource_info; | 
 |  | 
 |   assert(image_info != (const ImageInfo *) NULL); | 
 |   assert(image_info->signature == MagickSignature); | 
 |   assert(images != (Image *) NULL); | 
 |   assert(images->signature == MagickSignature); | 
 |   if (images->debug != MagickFalse) | 
 |     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); | 
 |   display=XOpenDisplay(image_info->server_name); | 
 |   if (display == (Display *) NULL) | 
 |     { | 
 |       (void) ThrowMagickException(exception,GetMagickModule(),XServerError, | 
 |         "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name)); | 
 |       return(MagickFalse); | 
 |     } | 
 |   if (exception->severity != UndefinedException) | 
 |     CatchException(exception); | 
 |   (void) XSetErrorHandler(XError); | 
 |   resource_database=XGetResourceDatabase(display,GetClientName()); | 
 |   (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info)); | 
 |   XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info); | 
 |   if (image_info->page != (char *) NULL) | 
 |     resource_info.image_geometry=AcquireString(image_info->page); | 
 |   resource_info.immutable=MagickTrue; | 
 |   argv[0]=AcquireString(GetClientName()); | 
 |   state=DefaultState; | 
 |   for (i=0; (state & ExitState) == 0; i++) | 
 |   { | 
 |     if ((images->iterations != 0) && (i >= (ssize_t) images->iterations)) | 
 |       break; | 
 |     image=GetImageFromList(images,i % GetImageListLength(images)); | 
 |     (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception); | 
 |   } | 
 |   SetErrorHandler((ErrorHandler) NULL); | 
 |   SetWarningHandler((WarningHandler) NULL); | 
 |   argv[0]=DestroyString(argv[0]); | 
 |   (void) XCloseDisplay(display); | 
 |   XDestroyResourceInfo(&resource_info); | 
 |   if (exception->severity != UndefinedException) | 
 |     return(MagickFalse); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %   R e m o t e D i s p l a y C o m m a n d                                   % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  RemoteDisplayCommand() encourages a remote display program to display the | 
 | %  specified image filename. | 
 | % | 
 | %  The format of the RemoteDisplayCommand method is: | 
 | % | 
 | %      MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info, | 
 | %        const char *window,const char *filename,ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o image_info: the image info. | 
 | % | 
 | %    o window: Specifies the name or id of an X window. | 
 | % | 
 | %    o filename: the name of the image filename to display. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info, | 
 |   const char *window,const char *filename,ExceptionInfo *exception) | 
 | { | 
 |   Display | 
 |     *display; | 
 |  | 
 |   MagickStatusType | 
 |     status; | 
 |  | 
 |   assert(image_info != (const ImageInfo *) NULL); | 
 |   assert(image_info->signature == MagickSignature); | 
 |   assert(filename != (char *) NULL); | 
 |   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); | 
 |   display=XOpenDisplay(image_info->server_name); | 
 |   if (display == (Display *) NULL) | 
 |     { | 
 |       (void) ThrowMagickException(exception,GetMagickModule(),XServerError, | 
 |         "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name)); | 
 |       return(MagickFalse); | 
 |     } | 
 |   (void) XSetErrorHandler(XError); | 
 |   status=XRemoteCommand(display,window,filename); | 
 |   (void) XCloseDisplay(display); | 
 |   return(status != 0 ? MagickTrue : MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X A n n o t a t e E d i t I m a g e                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XAnnotateEditImage() annotates the image with text. | 
 | % | 
 | %  The format of the XAnnotateEditImage method is: | 
 | % | 
 | %      MagickBooleanType XAnnotateEditImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | */ | 
 |  | 
 | static inline ssize_t MagickMax(const ssize_t x,const ssize_t y) | 
 | { | 
 |   if (x > y) | 
 |     return(x); | 
 |   return(y); | 
 | } | 
 |  | 
 | static inline ssize_t MagickMin(const ssize_t x,const ssize_t y) | 
 | { | 
 |   if (x < y) | 
 |     return(x); | 
 |   return(y); | 
 | } | 
 |  | 
 | static MagickBooleanType XAnnotateEditImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *AnnotateMenu[] = | 
 |     { | 
 |       "Font Name", | 
 |       "Font Color", | 
 |       "Box Color", | 
 |       "Rotate Text", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }, | 
 |     *TextMenu[] = | 
 |     { | 
 |       "Help", | 
 |       "Apply", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static const ModeType | 
 |     AnnotateCommands[] = | 
 |     { | 
 |       AnnotateNameCommand, | 
 |       AnnotateFontColorCommand, | 
 |       AnnotateBackgroundColorCommand, | 
 |       AnnotateRotateCommand, | 
 |       AnnotateHelpCommand, | 
 |       AnnotateDismissCommand | 
 |     }, | 
 |     TextCommands[] = | 
 |     { | 
 |       TextHelpCommand, | 
 |       TextApplyCommand | 
 |     }; | 
 |  | 
 |   static MagickBooleanType | 
 |     transparent_box = MagickTrue, | 
 |     transparent_pen = MagickFalse; | 
 |  | 
 |   static MagickRealType | 
 |     degrees = 0.0; | 
 |  | 
 |   static unsigned int | 
 |     box_id = MaxNumberPens-2, | 
 |     font_id = 0, | 
 |     pen_id = 0; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   const char | 
 |     *ColorMenu[MaxNumberPens+1]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   GC | 
 |     annotate_context; | 
 |  | 
 |   int | 
 |     id, | 
 |     pen_number, | 
 |     status, | 
 |     x, | 
 |     y; | 
 |  | 
 |   KeySym | 
 |     key_symbol; | 
 |  | 
 |   register char | 
 |     *p; | 
 |  | 
 |   register ssize_t | 
 |     i; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XAnnotateInfo | 
 |     *annotate_info, | 
 |     *previous_info; | 
 |  | 
 |   XColor | 
 |     color; | 
 |  | 
 |   XFontStruct | 
 |     *font_info; | 
 |  | 
 |   XEvent | 
 |     event, | 
 |     text_event; | 
 |  | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Annotate"); | 
 |   windows->command.data=4; | 
 |   (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   cursor=XCreateFontCursor(display,XC_left_side); | 
 |   (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ", | 
 |           x+windows->image.x,y+windows->image.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,AnnotateMenu,&event); | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         if (id < 0) | 
 |           continue; | 
 |         switch (AnnotateCommands[id]) | 
 |         { | 
 |           case AnnotateNameCommand: | 
 |           { | 
 |             const char | 
 |               *FontMenu[MaxNumberFonts]; | 
 |  | 
 |             int | 
 |               font_number; | 
 |  | 
 |             /* | 
 |               Initialize menu selections. | 
 |             */ | 
 |             for (i=0; i < MaxNumberFonts; i++) | 
 |               FontMenu[i]=resource_info->font_name[i]; | 
 |             FontMenu[MaxNumberFonts-2]="Browser..."; | 
 |             FontMenu[MaxNumberFonts-1]=(const char *) NULL; | 
 |             /* | 
 |               Select a font name from the pop-up menu. | 
 |             */ | 
 |             font_number=XMenuWidget(display,windows,AnnotateMenu[id], | 
 |               (const char **) FontMenu,command); | 
 |             if (font_number < 0) | 
 |               break; | 
 |             if (font_number == (MaxNumberFonts-2)) | 
 |               { | 
 |                 static char | 
 |                   font_name[MaxTextExtent] = "fixed"; | 
 |  | 
 |                 /* | 
 |                   Select a font name from a browser. | 
 |                 */ | 
 |                 resource_info->font_name[font_number]=font_name; | 
 |                 XFontBrowserWidget(display,windows,"Select",font_name); | 
 |                 if (*font_name == '\0') | 
 |                   break; | 
 |               } | 
 |             /* | 
 |               Initialize font info. | 
 |             */ | 
 |             font_info=XLoadQueryFont(display,resource_info->font_name[ | 
 |               font_number]); | 
 |             if (font_info == (XFontStruct *) NULL) | 
 |               { | 
 |                 XNoticeWidget(display,windows,"Unable to load font:", | 
 |                   resource_info->font_name[font_number]); | 
 |                 break; | 
 |               } | 
 |             font_id=(unsigned int) font_number; | 
 |             (void) XFreeFont(display,font_info); | 
 |             break; | 
 |           } | 
 |           case AnnotateFontColorCommand: | 
 |           { | 
 |             /* | 
 |               Initialize menu selections. | 
 |             */ | 
 |             for (i=0; i < (int) (MaxNumberPens-2); i++) | 
 |               ColorMenu[i]=resource_info->pen_colors[i]; | 
 |             ColorMenu[MaxNumberPens-2]="transparent"; | 
 |             ColorMenu[MaxNumberPens-1]="Browser..."; | 
 |             ColorMenu[MaxNumberPens]=(const char *) NULL; | 
 |             /* | 
 |               Select a pen color from the pop-up menu. | 
 |             */ | 
 |             pen_number=XMenuWidget(display,windows,AnnotateMenu[id], | 
 |               (const char **) ColorMenu,command); | 
 |             if (pen_number < 0) | 
 |               break; | 
 |             transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue : | 
 |               MagickFalse; | 
 |             if (transparent_pen != MagickFalse) | 
 |               break; | 
 |             if (pen_number == (MaxNumberPens-1)) | 
 |               { | 
 |                 static char | 
 |                   color_name[MaxTextExtent] = "gray"; | 
 |  | 
 |                 /* | 
 |                   Select a pen color from a dialog. | 
 |                 */ | 
 |                 resource_info->pen_colors[pen_number]=color_name; | 
 |                 XColorBrowserWidget(display,windows,"Select",color_name); | 
 |                 if (*color_name == '\0') | 
 |                   break; | 
 |               } | 
 |             /* | 
 |               Set pen color. | 
 |             */ | 
 |             (void) XParseColor(display,windows->map_info->colormap, | 
 |               resource_info->pen_colors[pen_number],&color); | 
 |             XBestPixel(display,windows->map_info->colormap,(XColor *) NULL, | 
 |               (unsigned int) MaxColors,&color); | 
 |             windows->pixel_info->pen_colors[pen_number]=color; | 
 |             pen_id=(unsigned int) pen_number; | 
 |             break; | 
 |           } | 
 |           case AnnotateBackgroundColorCommand: | 
 |           { | 
 |             /* | 
 |               Initialize menu selections. | 
 |             */ | 
 |             for (i=0; i < (int) (MaxNumberPens-2); i++) | 
 |               ColorMenu[i]=resource_info->pen_colors[i]; | 
 |             ColorMenu[MaxNumberPens-2]="transparent"; | 
 |             ColorMenu[MaxNumberPens-1]="Browser..."; | 
 |             ColorMenu[MaxNumberPens]=(const char *) NULL; | 
 |             /* | 
 |               Select a pen color from the pop-up menu. | 
 |             */ | 
 |             pen_number=XMenuWidget(display,windows,AnnotateMenu[id], | 
 |               (const char **) ColorMenu,command); | 
 |             if (pen_number < 0) | 
 |               break; | 
 |             transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue : | 
 |               MagickFalse; | 
 |             if (transparent_box != MagickFalse) | 
 |               break; | 
 |             if (pen_number == (MaxNumberPens-1)) | 
 |               { | 
 |                 static char | 
 |                   color_name[MaxTextExtent] = "gray"; | 
 |  | 
 |                 /* | 
 |                   Select a pen color from a dialog. | 
 |                 */ | 
 |                 resource_info->pen_colors[pen_number]=color_name; | 
 |                 XColorBrowserWidget(display,windows,"Select",color_name); | 
 |                 if (*color_name == '\0') | 
 |                   break; | 
 |               } | 
 |             /* | 
 |               Set pen color. | 
 |             */ | 
 |             (void) XParseColor(display,windows->map_info->colormap, | 
 |               resource_info->pen_colors[pen_number],&color); | 
 |             XBestPixel(display,windows->map_info->colormap,(XColor *) NULL, | 
 |               (unsigned int) MaxColors,&color); | 
 |             windows->pixel_info->pen_colors[pen_number]=color; | 
 |             box_id=(unsigned int) pen_number; | 
 |             break; | 
 |           } | 
 |           case AnnotateRotateCommand: | 
 |           { | 
 |             int | 
 |               entry; | 
 |  | 
 |             static char | 
 |               angle[MaxTextExtent] = "30.0"; | 
 |  | 
 |             static const char | 
 |               *RotateMenu[] = | 
 |               { | 
 |                 "-90", | 
 |                 "-45", | 
 |                 "-30", | 
 |                 "0", | 
 |                 "30", | 
 |                 "45", | 
 |                 "90", | 
 |                 "180", | 
 |                 "Dialog...", | 
 |                 (char *) NULL, | 
 |               }; | 
 |  | 
 |             /* | 
 |               Select a command from the pop-up menu. | 
 |             */ | 
 |             entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu, | 
 |               command); | 
 |             if (entry < 0) | 
 |               break; | 
 |             if (entry != 8) | 
 |               { | 
 |                 degrees=InterpretLocaleValue(RotateMenu[entry],(char **) NULL); | 
 |                 break; | 
 |               } | 
 |             (void) XDialogWidget(display,windows,"OK","Enter rotation angle:", | 
 |               angle); | 
 |             if (*angle == '\0') | 
 |               break; | 
 |             degrees=InterpretLocaleValue(angle,(char **) NULL); | 
 |             break; | 
 |           } | 
 |           case AnnotateHelpCommand: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Annotation",ImageAnnotateHelp); | 
 |             break; | 
 |           } | 
 |           case AnnotateDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Change to text entering mode. | 
 |         */ | 
 |         x=event.xbutton.x; | 
 |         y=event.xbutton.y; | 
 |         state|=ExitState; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |         break; | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Annotation",ImageAnnotateHelp); | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         /* | 
 |           Map and unmap Info widget as cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |   if ((state & EscapeState) != 0) | 
 |     return(MagickTrue); | 
 |   /* | 
 |     Set font info and check boundary conditions. | 
 |   */ | 
 |   font_info=XLoadQueryFont(display,resource_info->font_name[font_id]); | 
 |   if (font_info == (XFontStruct *) NULL) | 
 |     { | 
 |       XNoticeWidget(display,windows,"Unable to load font:", | 
 |         resource_info->font_name[font_id]); | 
 |       font_info=windows->font_info; | 
 |     } | 
 |   if ((x+font_info->max_bounds.width) >= (int) windows->image.width) | 
 |     x=(int) windows->image.width-font_info->max_bounds.width; | 
 |   if (y < (int) (font_info->ascent+font_info->descent)) | 
 |     y=(int) font_info->ascent+font_info->descent; | 
 |   if (((int) font_info->max_bounds.width > (int) windows->image.width) || | 
 |       ((font_info->ascent+font_info->descent) >= (int) windows->image.height)) | 
 |     return(MagickFalse); | 
 |   /* | 
 |     Initialize annotate structure. | 
 |   */ | 
 |   annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info)); | 
 |   if (annotate_info == (XAnnotateInfo *) NULL) | 
 |     return(MagickFalse); | 
 |   XGetAnnotateInfo(annotate_info); | 
 |   annotate_info->x=x; | 
 |   annotate_info->y=y; | 
 |   if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse)) | 
 |     annotate_info->stencil=OpaqueStencil; | 
 |   else | 
 |     if (transparent_box == MagickFalse) | 
 |       annotate_info->stencil=BackgroundStencil; | 
 |     else | 
 |       annotate_info->stencil=ForegroundStencil; | 
 |   annotate_info->height=(unsigned int) font_info->ascent+font_info->descent; | 
 |   annotate_info->degrees=degrees; | 
 |   annotate_info->font_info=font_info; | 
 |   annotate_info->text=(char *) AcquireQuantumMemory((size_t) | 
 |     windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL, | 
 |     sizeof(*annotate_info->text)); | 
 |   if (annotate_info->text == (char *) NULL) | 
 |     return(MagickFalse); | 
 |   /* | 
 |     Create cursor and set graphic context. | 
 |   */ | 
 |   cursor=XCreateFontCursor(display,XC_pencil); | 
 |   (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |   annotate_context=windows->image.annotate_context; | 
 |   (void) XSetFont(display,annotate_context,font_info->fid); | 
 |   (void) XSetBackground(display,annotate_context, | 
 |     windows->pixel_info->pen_colors[box_id].pixel); | 
 |   (void) XSetForeground(display,annotate_context, | 
 |     windows->pixel_info->pen_colors[pen_id].pixel); | 
 |   /* | 
 |     Begin annotating the image with text. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Text"); | 
 |   windows->command.data=0; | 
 |   (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL); | 
 |   state=DefaultState; | 
 |   (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1); | 
 |   text_event.xexpose.width=(int) font_info->max_bounds.width; | 
 |   text_event.xexpose.height=font_info->max_bounds.ascent+ | 
 |     font_info->max_bounds.descent; | 
 |   p=annotate_info->text; | 
 |   do | 
 |   { | 
 |     /* | 
 |       Display text cursor. | 
 |     */ | 
 |     *p='\0'; | 
 |     (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1); | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         (void) XSetBackground(display,annotate_context, | 
 |           windows->pixel_info->background_color.pixel); | 
 |         (void) XSetForeground(display,annotate_context, | 
 |           windows->pixel_info->foreground_color.pixel); | 
 |         id=XCommandWidget(display,windows,AnnotateMenu,&event); | 
 |         (void) XSetBackground(display,annotate_context, | 
 |           windows->pixel_info->pen_colors[box_id].pixel); | 
 |         (void) XSetForeground(display,annotate_context, | 
 |           windows->pixel_info->pen_colors[pen_id].pixel); | 
 |         if (id < 0) | 
 |           continue; | 
 |         switch (TextCommands[id]) | 
 |         { | 
 |           case TextHelpCommand: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Annotation",ImageAnnotateHelp); | 
 |             (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |             break; | 
 |           } | 
 |           case TextApplyCommand: | 
 |           { | 
 |             /* | 
 |               Finished annotating. | 
 |             */ | 
 |             annotate_info->width=(unsigned int) XTextWidth(font_info, | 
 |               annotate_info->text,(int) strlen(annotate_info->text)); | 
 |             XRefreshWindow(display,&windows->image,&text_event); | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         continue; | 
 |       } | 
 |     /* | 
 |       Erase text cursor. | 
 |     */ | 
 |     text_event.xexpose.x=x; | 
 |     text_event.xexpose.y=y-font_info->max_bounds.ascent; | 
 |     (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y, | 
 |       (unsigned int) text_event.xexpose.width,(unsigned int) | 
 |       text_event.xexpose.height,MagickFalse); | 
 |     XRefreshWindow(display,&windows->image,&text_event); | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         if (event.xbutton.button == Button2) | 
 |           { | 
 |             /* | 
 |               Request primary selection. | 
 |             */ | 
 |             (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, | 
 |               windows->image.id,CurrentTime); | 
 |             break; | 
 |           } | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |       { | 
 |         if (event.xexpose.count == 0) | 
 |           { | 
 |             XAnnotateInfo | 
 |               *text_info; | 
 |  | 
 |             /* | 
 |               Refresh Image window. | 
 |             */ | 
 |             XRefreshWindow(display,&windows->image,(XEvent *) NULL); | 
 |             text_info=annotate_info; | 
 |             while (text_info != (XAnnotateInfo *) NULL) | 
 |             { | 
 |               if (annotate_info->stencil == ForegroundStencil) | 
 |                 (void) XDrawString(display,windows->image.id,annotate_context, | 
 |                   text_info->x,text_info->y,text_info->text, | 
 |                   (int) strlen(text_info->text)); | 
 |               else | 
 |                 (void) XDrawImageString(display,windows->image.id, | 
 |                   annotate_context,text_info->x,text_info->y,text_info->text, | 
 |                   (int) strlen(text_info->text)); | 
 |               text_info=text_info->previous; | 
 |             } | 
 |             (void) XDrawString(display,windows->image.id,annotate_context, | 
 |               x,y,"_",1); | 
 |           } | 
 |         break; | 
 |       } | 
 |       case KeyPress: | 
 |       { | 
 |         int | 
 |           length; | 
 |  | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         length=XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         *(command+length)='\0'; | 
 |         if (((event.xkey.state & ControlMask) != 0) || | 
 |             ((event.xkey.state & Mod1Mask) != 0)) | 
 |           state|=ModifierState; | 
 |         if ((state & ModifierState) != 0) | 
 |           switch ((int) key_symbol) | 
 |           { | 
 |             case XK_u: | 
 |             case XK_U: | 
 |             { | 
 |               key_symbol=DeleteCommand; | 
 |               break; | 
 |             } | 
 |             default: | 
 |               break; | 
 |           } | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_BackSpace: | 
 |           { | 
 |             /* | 
 |               Erase one character. | 
 |             */ | 
 |             if (p == annotate_info->text) | 
 |               { | 
 |                 if (annotate_info->previous == (XAnnotateInfo *) NULL) | 
 |                   break; | 
 |                 else | 
 |                   { | 
 |                     /* | 
 |                       Go to end of the previous line of text. | 
 |                     */ | 
 |                     annotate_info=annotate_info->previous; | 
 |                     p=annotate_info->text; | 
 |                     x=annotate_info->x+annotate_info->width; | 
 |                     y=annotate_info->y; | 
 |                     if (annotate_info->width != 0) | 
 |                       p+=strlen(annotate_info->text); | 
 |                     break; | 
 |                   } | 
 |               } | 
 |             p--; | 
 |             x-=XTextWidth(font_info,p,1); | 
 |             text_event.xexpose.x=x; | 
 |             text_event.xexpose.y=y-font_info->max_bounds.ascent; | 
 |             XRefreshWindow(display,&windows->image,&text_event); | 
 |             break; | 
 |           } | 
 |           case XK_bracketleft: | 
 |           { | 
 |             key_symbol=XK_Escape; | 
 |             break; | 
 |           } | 
 |           case DeleteCommand: | 
 |           { | 
 |             /* | 
 |               Erase the entire line of text. | 
 |             */ | 
 |             while (p != annotate_info->text) | 
 |             { | 
 |               p--; | 
 |               x-=XTextWidth(font_info,p,1); | 
 |               text_event.xexpose.x=x; | 
 |               XRefreshWindow(display,&windows->image,&text_event); | 
 |             } | 
 |             break; | 
 |           } | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Finished annotating. | 
 |             */ | 
 |             annotate_info->width=(unsigned int) XTextWidth(font_info, | 
 |               annotate_info->text,(int) strlen(annotate_info->text)); | 
 |             XRefreshWindow(display,&windows->image,&text_event); | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             /* | 
 |               Draw a single character on the Image window. | 
 |             */ | 
 |             if ((state & ModifierState) != 0) | 
 |               break; | 
 |             if (*command == '\0') | 
 |               break; | 
 |             *p=(*command); | 
 |             if (annotate_info->stencil == ForegroundStencil) | 
 |               (void) XDrawString(display,windows->image.id,annotate_context, | 
 |                 x,y,p,1); | 
 |             else | 
 |               (void) XDrawImageString(display,windows->image.id, | 
 |                 annotate_context,x,y,p,1); | 
 |             x+=XTextWidth(font_info,p,1); | 
 |             p++; | 
 |             if ((x+font_info->max_bounds.width) < (int) windows->image.width) | 
 |               break; | 
 |           } | 
 |           case XK_Return: | 
 |           case XK_KP_Enter: | 
 |           { | 
 |             /* | 
 |               Advance to the next line of text. | 
 |             */ | 
 |             *p='\0'; | 
 |             annotate_info->width=(unsigned int) XTextWidth(font_info, | 
 |               annotate_info->text,(int) strlen(annotate_info->text)); | 
 |             if (annotate_info->next != (XAnnotateInfo *) NULL) | 
 |               { | 
 |                 /* | 
 |                   Line of text already exists. | 
 |                 */ | 
 |                 annotate_info=annotate_info->next; | 
 |                 x=annotate_info->x; | 
 |                 y=annotate_info->y; | 
 |                 p=annotate_info->text; | 
 |                 break; | 
 |               } | 
 |             annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory( | 
 |               sizeof(*annotate_info->next)); | 
 |             if (annotate_info->next == (XAnnotateInfo *) NULL) | 
 |               return(MagickFalse); | 
 |             *annotate_info->next=(*annotate_info); | 
 |             annotate_info->next->previous=annotate_info; | 
 |             annotate_info=annotate_info->next; | 
 |             annotate_info->text=(char *) AcquireQuantumMemory((size_t) | 
 |               windows->image.width/MagickMax((ssize_t) | 
 |               font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text)); | 
 |             if (annotate_info->text == (char *) NULL) | 
 |               return(MagickFalse); | 
 |             annotate_info->y+=annotate_info->height; | 
 |             if (annotate_info->y > (int) windows->image.height) | 
 |               annotate_info->y=(int) annotate_info->height; | 
 |             annotate_info->next=(XAnnotateInfo *) NULL; | 
 |             x=annotate_info->x; | 
 |             y=annotate_info->y; | 
 |             p=annotate_info->text; | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case KeyRelease: | 
 |       { | 
 |         /* | 
 |           Respond to a user key release. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         state&=(~ModifierState); | 
 |         break; | 
 |       } | 
 |       case SelectionNotify: | 
 |       { | 
 |         Atom | 
 |           type; | 
 |  | 
 |         int | 
 |           format; | 
 |  | 
 |         unsigned char | 
 |           *data; | 
 |  | 
 |         unsigned long | 
 |           after, | 
 |           length; | 
 |  | 
 |         /* | 
 |           Obtain response from primary selection. | 
 |         */ | 
 |         if (event.xselection.property == (Atom) None) | 
 |           break; | 
 |         status=XGetWindowProperty(display,event.xselection.requestor, | 
 |           event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING, | 
 |           &type,&format,&length,&after,&data); | 
 |         if ((status != Success) || (type != XA_STRING) || (format == 32) || | 
 |             (length == 0)) | 
 |           break; | 
 |         /* | 
 |           Annotate Image window with primary selection. | 
 |         */ | 
 |         for (i=0; i < (ssize_t) length; i++) | 
 |         { | 
 |           if ((char) data[i] != '\n') | 
 |             { | 
 |               /* | 
 |                 Draw a single character on the Image window. | 
 |               */ | 
 |               *p=(char) data[i]; | 
 |               (void) XDrawString(display,windows->image.id,annotate_context, | 
 |                 x,y,p,1); | 
 |               x+=XTextWidth(font_info,p,1); | 
 |               p++; | 
 |               if ((x+font_info->max_bounds.width) < (int) windows->image.width) | 
 |                 continue; | 
 |             } | 
 |           /* | 
 |             Advance to the next line of text. | 
 |           */ | 
 |           *p='\0'; | 
 |           annotate_info->width=(unsigned int) XTextWidth(font_info, | 
 |             annotate_info->text,(int) strlen(annotate_info->text)); | 
 |           if (annotate_info->next != (XAnnotateInfo *) NULL) | 
 |             { | 
 |               /* | 
 |                 Line of text already exists. | 
 |               */ | 
 |               annotate_info=annotate_info->next; | 
 |               x=annotate_info->x; | 
 |               y=annotate_info->y; | 
 |               p=annotate_info->text; | 
 |               continue; | 
 |             } | 
 |           annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory( | 
 |             sizeof(*annotate_info->next)); | 
 |           if (annotate_info->next == (XAnnotateInfo *) NULL) | 
 |             return(MagickFalse); | 
 |           *annotate_info->next=(*annotate_info); | 
 |           annotate_info->next->previous=annotate_info; | 
 |           annotate_info=annotate_info->next; | 
 |           annotate_info->text=(char *) AcquireQuantumMemory((size_t) | 
 |             windows->image.width/MagickMax((ssize_t) | 
 |             font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text)); | 
 |           if (annotate_info->text == (char *) NULL) | 
 |             return(MagickFalse); | 
 |           annotate_info->y+=annotate_info->height; | 
 |           if (annotate_info->y > (int) windows->image.height) | 
 |             annotate_info->y=(int) annotate_info->height; | 
 |           annotate_info->next=(XAnnotateInfo *) NULL; | 
 |           x=annotate_info->x; | 
 |           y=annotate_info->y; | 
 |           p=annotate_info->text; | 
 |         } | 
 |         (void) XFree((void *) data); | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XFreeCursor(display,cursor); | 
 |   /* | 
 |     Annotation is relative to image configuration. | 
 |   */ | 
 |   width=(unsigned int) image->columns; | 
 |   height=(unsigned int) image->rows; | 
 |   x=0; | 
 |   y=0; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |   /* | 
 |     Initialize annotated image. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   while (annotate_info != (XAnnotateInfo *) NULL) | 
 |   { | 
 |     if (annotate_info->width == 0) | 
 |       { | 
 |         /* | 
 |           No text on this line--  go to the next line of text. | 
 |         */ | 
 |         previous_info=annotate_info->previous; | 
 |         annotate_info->text=(char *) | 
 |           RelinquishMagickMemory(annotate_info->text); | 
 |         annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info); | 
 |         annotate_info=previous_info; | 
 |         continue; | 
 |       } | 
 |     /* | 
 |       Determine pixel index for box and pen color. | 
 |     */ | 
 |     windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id]; | 
 |     if (windows->pixel_info->colors != 0) | 
 |       for (i=0; i < (ssize_t) windows->pixel_info->colors; i++) | 
 |         if (windows->pixel_info->pixels[i] == | 
 |             windows->pixel_info->pen_colors[box_id].pixel) | 
 |           { | 
 |             windows->pixel_info->box_index=(unsigned short) i; | 
 |             break; | 
 |           } | 
 |     windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id]; | 
 |     if (windows->pixel_info->colors != 0) | 
 |       for (i=0; i < (ssize_t) windows->pixel_info->colors; i++) | 
 |         if (windows->pixel_info->pixels[i] == | 
 |             windows->pixel_info->pen_colors[pen_id].pixel) | 
 |           { | 
 |             windows->pixel_info->pen_index=(unsigned short) i; | 
 |             break; | 
 |           } | 
 |     /* | 
 |       Define the annotate geometry string. | 
 |     */ | 
 |     annotate_info->x=(int) | 
 |       width*(annotate_info->x+windows->image.x)/windows->image.ximage->width; | 
 |     annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+ | 
 |       windows->image.y)/windows->image.ximage->height; | 
 |     (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent, | 
 |       "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width, | 
 |       height*annotate_info->height/windows->image.ximage->height, | 
 |       annotate_info->x+x,annotate_info->y+y); | 
 |     /* | 
 |       Annotate image with text. | 
 |     */ | 
 |     status=XAnnotateImage(display,windows->pixel_info,annotate_info,image, | 
 |       exception); | 
 |     if (status == 0) | 
 |       return(MagickFalse); | 
 |     /* | 
 |       Free up memory. | 
 |     */ | 
 |     previous_info=annotate_info->previous; | 
 |     annotate_info->text=DestroyString(annotate_info->text); | 
 |     annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info); | 
 |     annotate_info=previous_info; | 
 |   } | 
 |   (void) XSetForeground(display,annotate_context, | 
 |     windows->pixel_info->foreground_color.pixel); | 
 |   (void) XSetBackground(display,annotate_context, | 
 |     windows->pixel_info->background_color.pixel); | 
 |   (void) XSetFont(display,annotate_context,windows->font_info->fid); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   (void) XFreeFont(display,font_info); | 
 |   /* | 
 |     Update image configuration. | 
 |   */ | 
 |   XConfigureImageColormap(display,resource_info,windows,image,exception); | 
 |   (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X B a c k g r o u n d I m a g e                                           % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XBackgroundImage() displays the image in the background of a window. | 
 | % | 
 | %  The format of the XBackgroundImage method is: | 
 | % | 
 | %      MagickBooleanType XBackgroundImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XBackgroundImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 | #define BackgroundImageTag  "Background/Image" | 
 |  | 
 |   int | 
 |     status; | 
 |  | 
 |   static char | 
 |     window_id[MaxTextExtent] = "root"; | 
 |  | 
 |   XResourceInfo | 
 |     background_resources; | 
 |  | 
 |   /* | 
 |     Put image in background. | 
 |   */ | 
 |   status=XDialogWidget(display,windows,"Background", | 
 |     "Enter window id (id 0x00 selects window with pointer):",window_id); | 
 |   if (*window_id == '\0') | 
 |     return(MagickFalse); | 
 |   (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |     exception); | 
 |   XInfoWidget(display,windows,BackgroundImageTag); | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   background_resources=(*resource_info); | 
 |   background_resources.window_id=window_id; | 
 |   background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse; | 
 |   status=XDisplayBackgroundImage(display,&background_resources,*image, | 
 |     exception); | 
 |   if (status != MagickFalse) | 
 |     XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |       windows->im_retain_colors,CurrentTime); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   (void) XMagickCommand(display,resource_info,windows,UndoCommand,image, | 
 |     exception); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X C h o p I m a g e                                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XChopImage() chops the X image. | 
 | % | 
 | %  The format of the XChopImage method is: | 
 | % | 
 | %    MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info, | 
 | %      XWindows *windows,Image **image,ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XChopImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *ChopMenu[] = | 
 |     { | 
 |       "Direction", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static ModeType | 
 |     direction = HorizontalChopCommand; | 
 |  | 
 |   static const ModeType | 
 |     ChopCommands[] = | 
 |     { | 
 |       ChopDirectionCommand, | 
 |       ChopHelpCommand, | 
 |       ChopDismissCommand | 
 |     }, | 
 |     DirectionCommands[] = | 
 |     { | 
 |       HorizontalChopCommand, | 
 |       VerticalChopCommand | 
 |     }; | 
 |  | 
 |   char | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Image | 
 |     *chop_image; | 
 |  | 
 |   int | 
 |     id, | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     scale_factor; | 
 |  | 
 |   RectangleInfo | 
 |     chop_info; | 
 |  | 
 |   unsigned int | 
 |     distance, | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   XSegment | 
 |     segment_info; | 
 |  | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Chop"); | 
 |   windows->command.data=1; | 
 |   (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ", | 
 |           x+windows->image.x,y+windows->image.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,ChopMenu,&event); | 
 |         if (id < 0) | 
 |           continue; | 
 |         switch (ChopCommands[id]) | 
 |         { | 
 |           case ChopDirectionCommand: | 
 |           { | 
 |             char | 
 |               command[MaxTextExtent]; | 
 |  | 
 |             static const char | 
 |               *Directions[] = | 
 |               { | 
 |                 "horizontal", | 
 |                 "vertical", | 
 |                 (char *) NULL, | 
 |               }; | 
 |  | 
 |             /* | 
 |               Select a command from the pop-up menu. | 
 |             */ | 
 |             id=XMenuWidget(display,windows,ChopMenu[id],Directions,command); | 
 |             if (id >= 0) | 
 |               direction=DirectionCommands[id]; | 
 |             break; | 
 |           } | 
 |           case ChopHelpCommand: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Chop",ImageChopHelp); | 
 |             break; | 
 |           } | 
 |           case ChopDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           User has committed to start point of chopping line. | 
 |         */ | 
 |         segment_info.x1=(short int) event.xbutton.x; | 
 |         segment_info.x2=(short int) event.xbutton.x; | 
 |         segment_info.y1=(short int) event.xbutton.y; | 
 |         segment_info.y2=(short int) event.xbutton.y; | 
 |         state|=ExitState; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |         break; | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         char | 
 |           command[MaxTextExtent]; | 
 |  | 
 |         KeySym | 
 |           key_symbol; | 
 |  | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Chop",ImageChopHelp); | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXinvert); | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         /* | 
 |           Map and unmap Info widget as text cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |       } | 
 |     } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |   if ((state & EscapeState) != 0) | 
 |     return(MagickTrue); | 
 |   /* | 
 |     Draw line as pointer moves until the mouse button is released. | 
 |   */ | 
 |   chop_info.width=0; | 
 |   chop_info.height=0; | 
 |   chop_info.x=0; | 
 |   chop_info.y=0; | 
 |   distance=0; | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (distance > 9) | 
 |       { | 
 |         /* | 
 |           Display info and draw chopping line. | 
 |         */ | 
 |         if (windows->info.mapped == MagickFalse) | 
 |           (void) XMapWindow(display,windows->info.id); | 
 |         (void) FormatLocaleString(text,MaxTextExtent, | 
 |           " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double) | 
 |           chop_info.height,(double) chop_info.x,(double) chop_info.y); | 
 |         XInfoWidget(display,windows,text); | 
 |         XHighlightLine(display,windows->image.id, | 
 |           windows->image.highlight_context,&segment_info); | 
 |       } | 
 |     else | 
 |       if (windows->info.mapped != MagickFalse) | 
 |         (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (distance > 9) | 
 |       XHighlightLine(display,windows->image.id, | 
 |         windows->image.highlight_context,&segment_info); | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         segment_info.x2=(short int) event.xmotion.x; | 
 |         segment_info.y2=(short int) event.xmotion.y; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |       { | 
 |         /* | 
 |           User has committed to chopping line. | 
 |         */ | 
 |         segment_info.x2=(short int) event.xbutton.x; | 
 |         segment_info.y2=(short int) event.xbutton.y; | 
 |         state|=ExitState; | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |         break; | 
 |       case MotionNotify: | 
 |       { | 
 |         segment_info.x2=(short int) event.xmotion.x; | 
 |         segment_info.y2=(short int) event.xmotion.y; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |     /* | 
 |       Check boundary conditions. | 
 |     */ | 
 |     if (segment_info.x2 < 0) | 
 |       segment_info.x2=0; | 
 |     else | 
 |       if (segment_info.x2 > windows->image.ximage->width) | 
 |         segment_info.x2=windows->image.ximage->width; | 
 |     if (segment_info.y2 < 0) | 
 |       segment_info.y2=0; | 
 |     else | 
 |       if (segment_info.y2 > windows->image.ximage->height) | 
 |         segment_info.y2=windows->image.ximage->height; | 
 |     distance=(unsigned int) | 
 |       (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+ | 
 |        ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1))); | 
 |     /* | 
 |       Compute chopping geometry. | 
 |     */ | 
 |     if (direction == HorizontalChopCommand) | 
 |       { | 
 |         chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1); | 
 |         chop_info.x=(ssize_t) windows->image.x+segment_info.x1; | 
 |         chop_info.height=0; | 
 |         chop_info.y=0; | 
 |         if (segment_info.x1 > (int) segment_info.x2) | 
 |           { | 
 |             chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1); | 
 |             chop_info.x=(ssize_t) windows->image.x+segment_info.x2; | 
 |           } | 
 |       } | 
 |     else | 
 |       { | 
 |         chop_info.width=0; | 
 |         chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1); | 
 |         chop_info.x=0; | 
 |         chop_info.y=(ssize_t) windows->image.y+segment_info.y1; | 
 |         if (segment_info.y1 > segment_info.y2) | 
 |           { | 
 |             chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1); | 
 |             chop_info.y=(ssize_t) windows->image.y+segment_info.y2; | 
 |           } | 
 |       } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |   (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |   if (distance <= 9) | 
 |     return(MagickTrue); | 
 |   /* | 
 |     Image chopping is relative to image configuration. | 
 |   */ | 
 |   (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |     exception); | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   windows->image.window_changes.width=windows->image.ximage->width- | 
 |     (unsigned int) chop_info.width; | 
 |   windows->image.window_changes.height=windows->image.ximage->height- | 
 |     (unsigned int) chop_info.height; | 
 |   width=(unsigned int) (*image)->columns; | 
 |   height=(unsigned int) (*image)->rows; | 
 |   x=0; | 
 |   y=0; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |   scale_factor=(MagickRealType) width/windows->image.ximage->width; | 
 |   chop_info.x+=x; | 
 |   chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5); | 
 |   chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5); | 
 |   scale_factor=(MagickRealType) height/windows->image.ximage->height; | 
 |   chop_info.y+=y; | 
 |   chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5); | 
 |   chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5); | 
 |   /* | 
 |     Chop image. | 
 |   */ | 
 |   chop_image=ChopImage(*image,&chop_info,exception); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if (chop_image == (Image *) NULL) | 
 |     return(MagickFalse); | 
 |   *image=DestroyImage(*image); | 
 |   *image=chop_image; | 
 |   /* | 
 |     Update image configuration. | 
 |   */ | 
 |   XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |   (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X C o l o r E d i t I m a g e                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XColorEditImage() allows the user to interactively change the color of one | 
 | %  pixel for a DirectColor image or one colormap entry for a PseudoClass image. | 
 | % | 
 | %  The format of the XColorEditImage method is: | 
 | % | 
 | %      MagickBooleanType XColorEditImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 | %          ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XColorEditImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *ColorEditMenu[] = | 
 |     { | 
 |       "Method", | 
 |       "Pixel Color", | 
 |       "Border Color", | 
 |       "Fuzz", | 
 |       "Undo", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static const ModeType | 
 |     ColorEditCommands[] = | 
 |     { | 
 |       ColorEditMethodCommand, | 
 |       ColorEditColorCommand, | 
 |       ColorEditBorderCommand, | 
 |       ColorEditFuzzCommand, | 
 |       ColorEditUndoCommand, | 
 |       ColorEditHelpCommand, | 
 |       ColorEditDismissCommand | 
 |     }; | 
 |  | 
 |   static PaintMethod | 
 |     method = PointMethod; | 
 |  | 
 |   static unsigned int | 
 |     pen_id = 0; | 
 |  | 
 |   static XColor | 
 |     border_color = { 0, 0, 0, 0, 0, 0 }; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   int | 
 |     entry, | 
 |     id, | 
 |     x, | 
 |     x_offset, | 
 |     y, | 
 |     y_offset; | 
 |  | 
 |   register Quantum | 
 |     *q; | 
 |  | 
 |   register ssize_t | 
 |     i; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XColor | 
 |     color; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Color Edit"); | 
 |   windows->command.data=4; | 
 |   (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Make cursor. | 
 |   */ | 
 |   cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap, | 
 |     resource_info->background_color,resource_info->foreground_color); | 
 |   (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ", | 
 |           x+windows->image.x,y+windows->image.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,ColorEditMenu,&event); | 
 |         if (id < 0) | 
 |           { | 
 |             (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |             continue; | 
 |           } | 
 |         switch (ColorEditCommands[id]) | 
 |         { | 
 |           case ColorEditMethodCommand: | 
 |           { | 
 |             char | 
 |               **methods; | 
 |  | 
 |             /* | 
 |               Select a method from the pop-up menu. | 
 |             */ | 
 |             methods=(char **) GetCommandOptions(MagickMethodOptions); | 
 |             if (methods == (char **) NULL) | 
 |               break; | 
 |             entry=XMenuWidget(display,windows,ColorEditMenu[id], | 
 |               (const char **) methods,command); | 
 |             if (entry >= 0) | 
 |               method=(PaintMethod) ParseCommandOption(MagickMethodOptions, | 
 |                 MagickFalse,methods[entry]); | 
 |             methods=DestroyStringList(methods); | 
 |             break; | 
 |           } | 
 |           case ColorEditColorCommand: | 
 |           { | 
 |             const char | 
 |               *ColorMenu[MaxNumberPens]; | 
 |  | 
 |             int | 
 |               pen_number; | 
 |  | 
 |             /* | 
 |               Initialize menu selections. | 
 |             */ | 
 |             for (i=0; i < (int) (MaxNumberPens-2); i++) | 
 |               ColorMenu[i]=resource_info->pen_colors[i]; | 
 |             ColorMenu[MaxNumberPens-2]="Browser..."; | 
 |             ColorMenu[MaxNumberPens-1]=(const char *) NULL; | 
 |             /* | 
 |               Select a pen color from the pop-up menu. | 
 |             */ | 
 |             pen_number=XMenuWidget(display,windows,ColorEditMenu[id], | 
 |               (const char **) ColorMenu,command); | 
 |             if (pen_number < 0) | 
 |               break; | 
 |             if (pen_number == (MaxNumberPens-2)) | 
 |               { | 
 |                 static char | 
 |                   color_name[MaxTextExtent] = "gray"; | 
 |  | 
 |                 /* | 
 |                   Select a pen color from a dialog. | 
 |                 */ | 
 |                 resource_info->pen_colors[pen_number]=color_name; | 
 |                 XColorBrowserWidget(display,windows,"Select",color_name); | 
 |                 if (*color_name == '\0') | 
 |                   break; | 
 |               } | 
 |             /* | 
 |               Set pen color. | 
 |             */ | 
 |             (void) XParseColor(display,windows->map_info->colormap, | 
 |               resource_info->pen_colors[pen_number],&color); | 
 |             XBestPixel(display,windows->map_info->colormap,(XColor *) NULL, | 
 |               (unsigned int) MaxColors,&color); | 
 |             windows->pixel_info->pen_colors[pen_number]=color; | 
 |             pen_id=(unsigned int) pen_number; | 
 |             break; | 
 |           } | 
 |           case ColorEditBorderCommand: | 
 |           { | 
 |             const char | 
 |               *ColorMenu[MaxNumberPens]; | 
 |  | 
 |             int | 
 |               pen_number; | 
 |  | 
 |             /* | 
 |               Initialize menu selections. | 
 |             */ | 
 |             for (i=0; i < (int) (MaxNumberPens-2); i++) | 
 |               ColorMenu[i]=resource_info->pen_colors[i]; | 
 |             ColorMenu[MaxNumberPens-2]="Browser..."; | 
 |             ColorMenu[MaxNumberPens-1]=(const char *) NULL; | 
 |             /* | 
 |               Select a pen color from the pop-up menu. | 
 |             */ | 
 |             pen_number=XMenuWidget(display,windows,ColorEditMenu[id], | 
 |               (const char **) ColorMenu,command); | 
 |             if (pen_number < 0) | 
 |               break; | 
 |             if (pen_number == (MaxNumberPens-2)) | 
 |               { | 
 |                 static char | 
 |                   color_name[MaxTextExtent] = "gray"; | 
 |  | 
 |                 /* | 
 |                   Select a pen color from a dialog. | 
 |                 */ | 
 |                 resource_info->pen_colors[pen_number]=color_name; | 
 |                 XColorBrowserWidget(display,windows,"Select",color_name); | 
 |                 if (*color_name == '\0') | 
 |                   break; | 
 |               } | 
 |             /* | 
 |               Set border color. | 
 |             */ | 
 |             (void) XParseColor(display,windows->map_info->colormap, | 
 |               resource_info->pen_colors[pen_number],&border_color); | 
 |             break; | 
 |           } | 
 |           case ColorEditFuzzCommand: | 
 |           { | 
 |             static char | 
 |               fuzz[MaxTextExtent]; | 
 |  | 
 |             static const char | 
 |               *FuzzMenu[] = | 
 |               { | 
 |                 "0%", | 
 |                 "2%", | 
 |                 "5%", | 
 |                 "10%", | 
 |                 "15%", | 
 |                 "Dialog...", | 
 |                 (char *) NULL, | 
 |               }; | 
 |  | 
 |             /* | 
 |               Select a command from the pop-up menu. | 
 |             */ | 
 |             entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu, | 
 |               command); | 
 |             if (entry < 0) | 
 |               break; | 
 |             if (entry != 5) | 
 |               { | 
 |                 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],(double) | 
 |                   QuantumRange+1.0); | 
 |                 break; | 
 |               } | 
 |             (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent); | 
 |             (void) XDialogWidget(display,windows,"Ok", | 
 |               "Enter fuzz factor (0.0 - 99.9%):",fuzz); | 
 |             if (*fuzz == '\0') | 
 |               break; | 
 |             (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent); | 
 |             (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0); | 
 |             break; | 
 |           } | 
 |           case ColorEditUndoCommand: | 
 |           { | 
 |             (void) XMagickCommand(display,resource_info,windows,UndoCommand, | 
 |               image,exception); | 
 |             break; | 
 |           } | 
 |           case ColorEditHelpCommand: | 
 |           default: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Annotation",ImageColorEditHelp); | 
 |             break; | 
 |           } | 
 |           case ColorEditDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |         } | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if ((event.xbutton.window != windows->image.id) && | 
 |             (event.xbutton.window != windows->magnify.id)) | 
 |           break; | 
 |         /* | 
 |           exit loop. | 
 |         */ | 
 |         x=event.xbutton.x; | 
 |         y=event.xbutton.y; | 
 |         (void) XMagickCommand(display,resource_info,windows, | 
 |           SaveToUndoBufferCommand,image,exception); | 
 |         state|=UpdateConfigurationState; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if ((event.xbutton.window != windows->image.id) && | 
 |             (event.xbutton.window != windows->magnify.id)) | 
 |           break; | 
 |         /* | 
 |           Update colormap information. | 
 |         */ | 
 |         x=event.xbutton.x; | 
 |         y=event.xbutton.y; | 
 |         XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |         (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |         XInfoWidget(display,windows,text); | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         state&=(~UpdateConfigurationState); | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         KeySym | 
 |           key_symbol; | 
 |  | 
 |         if (event.xkey.window == windows->magnify.id) | 
 |           { | 
 |             Window | 
 |               window; | 
 |  | 
 |             window=windows->magnify.id; | 
 |             while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ; | 
 |           } | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Annotation",ImageColorEditHelp); | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         /* | 
 |           Map and unmap Info widget as cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |     if (event.xany.window == windows->magnify.id) | 
 |       { | 
 |         x=windows->magnify.x-windows->image.x; | 
 |         y=windows->magnify.y-windows->image.y; | 
 |       } | 
 |     x_offset=x; | 
 |     y_offset=y; | 
 |     if ((state & UpdateConfigurationState) != 0) | 
 |       { | 
 |         CacheView | 
 |           *image_view; | 
 |  | 
 |         int | 
 |           x, | 
 |           y; | 
 |  | 
 |         /* | 
 |           Pixel edit is relative to image configuration. | 
 |         */ | 
 |         (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1, | 
 |           MagickTrue); | 
 |         color=windows->pixel_info->pen_colors[pen_id]; | 
 |         XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel); | 
 |         width=(unsigned int) (*image)->columns; | 
 |         height=(unsigned int) (*image)->rows; | 
 |         x=0; | 
 |         y=0; | 
 |         if (windows->image.crop_geometry != (char *) NULL) | 
 |           (void) XParseGeometry(windows->image.crop_geometry,&x,&y, | 
 |             &width,&height); | 
 |         x_offset=(int) | 
 |           (width*(windows->image.x+x_offset)/windows->image.ximage->width+x); | 
 |         y_offset=(int) | 
 |           (height*(windows->image.y+y_offset)/windows->image.ximage->height+y); | 
 |         if ((x_offset < 0) || (y_offset < 0)) | 
 |           continue; | 
 |         if ((x_offset >= (int) (*image)->columns) || | 
 |             (y_offset >= (int) (*image)->rows)) | 
 |           continue; | 
 |         image_view=AcquireCacheView(*image); | 
 |         switch (method) | 
 |         { | 
 |           case PointMethod: | 
 |           default: | 
 |           { | 
 |             /* | 
 |               Update color information using point algorithm. | 
 |             */ | 
 |             if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse) | 
 |               return(MagickFalse); | 
 |             q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset, | 
 |               (ssize_t) y_offset,1,1,exception); | 
 |             if (q == (Quantum *) NULL) | 
 |               break; | 
 |             SetPixelRed(*image,ScaleShortToQuantum(color.red),q); | 
 |             SetPixelGreen(*image,ScaleShortToQuantum(color.green),q); | 
 |             SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q); | 
 |             (void) SyncCacheViewAuthenticPixels(image_view,exception); | 
 |             break; | 
 |           } | 
 |           case ReplaceMethod: | 
 |           { | 
 |             PixelInfo | 
 |               pixel, | 
 |               target; | 
 |  | 
 |             Quantum | 
 |               virtual_pixel[CompositePixelChannel]; | 
 |  | 
 |             /* | 
 |               Update color information using replace algorithm. | 
 |             */ | 
 |             (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset, | 
 |               (ssize_t) y_offset,virtual_pixel,exception); | 
 |             target.red=virtual_pixel[RedPixelChannel]; | 
 |             target.green=virtual_pixel[GreenPixelChannel]; | 
 |             target.blue=virtual_pixel[BluePixelChannel]; | 
 |             target.alpha=virtual_pixel[AlphaPixelChannel]; | 
 |             if ((*image)->storage_class == DirectClass) | 
 |               { | 
 |                 for (y=0; y < (int) (*image)->rows; y++) | 
 |                 { | 
 |                   q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y, | 
 |                     (*image)->columns,1,exception); | 
 |                   if (q == (Quantum *) NULL) | 
 |                     break; | 
 |                   for (x=0; x < (int) (*image)->columns; x++) | 
 |                   { | 
 |                     GetPixelInfoPixel(*image,q,&pixel); | 
 |                     if (IsFuzzyEquivalencePixelInfo(&pixel,&target)) | 
 |                       { | 
 |                         SetPixelRed(*image,ScaleShortToQuantum( | 
 |                           color.red),q); | 
 |                         SetPixelGreen(*image,ScaleShortToQuantum( | 
 |                           color.green),q); | 
 |                         SetPixelBlue(*image,ScaleShortToQuantum( | 
 |                           color.blue),q); | 
 |                       } | 
 |                     q+=GetPixelChannels(*image); | 
 |                   } | 
 |                   if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) | 
 |                     break; | 
 |                 } | 
 |               } | 
 |             else | 
 |               { | 
 |                 for (i=0; i < (ssize_t) (*image)->colors; i++) | 
 |                   if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target)) | 
 |                     { | 
 |                       (*image)->colormap[i].red=ScaleShortToQuantum( | 
 |                         color.red); | 
 |                       (*image)->colormap[i].green=ScaleShortToQuantum( | 
 |                         color.green); | 
 |                       (*image)->colormap[i].blue=ScaleShortToQuantum( | 
 |                         color.blue); | 
 |                     } | 
 |                 (void) SyncImage(*image,exception); | 
 |               } | 
 |             break; | 
 |           } | 
 |           case FloodfillMethod: | 
 |           case FillToBorderMethod: | 
 |           { | 
 |             DrawInfo | 
 |               *draw_info; | 
 |  | 
 |             PixelInfo | 
 |               target; | 
 |  | 
 |             /* | 
 |               Update color information using floodfill algorithm. | 
 |             */ | 
 |             (void) GetOneVirtualMagickPixel(*image, | 
 |               GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t) | 
 |               y_offset,&target,exception); | 
 |             if (method == FillToBorderMethod) | 
 |               { | 
 |                 target.red=(MagickRealType) | 
 |                   ScaleShortToQuantum(border_color.red); | 
 |                 target.green=(MagickRealType) | 
 |                   ScaleShortToQuantum(border_color.green); | 
 |                 target.blue=(MagickRealType) | 
 |                   ScaleShortToQuantum(border_color.blue); | 
 |               } | 
 |             draw_info=CloneDrawInfo(resource_info->image_info, | 
 |               (DrawInfo *) NULL); | 
 |             (void) QueryColorCompliance(resource_info->pen_colors[pen_id], | 
 |               AllCompliance,&draw_info->fill,exception); | 
 |             (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t) | 
 |               x_offset,(ssize_t) y_offset,method == FloodfillMethod ? | 
 |               MagickFalse : MagickTrue,exception); | 
 |             draw_info=DestroyDrawInfo(draw_info); | 
 |             break; | 
 |           } | 
 |           case ResetMethod: | 
 |           { | 
 |             /* | 
 |               Update color information using reset algorithm. | 
 |             */ | 
 |             if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse) | 
 |               return(MagickFalse); | 
 |             for (y=0; y < (int) (*image)->rows; y++) | 
 |             { | 
 |               q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y, | 
 |                 (*image)->columns,1,exception); | 
 |               if (q == (Quantum *) NULL) | 
 |                 break; | 
 |               for (x=0; x < (int) (*image)->columns; x++) | 
 |               { | 
 |                 SetPixelRed(*image,ScaleShortToQuantum(color.red),q); | 
 |                 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q); | 
 |                 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q); | 
 |                 q+=GetPixelChannels(*image); | 
 |               } | 
 |               if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) | 
 |                 break; | 
 |             } | 
 |             break; | 
 |           } | 
 |         } | 
 |         image_view=DestroyCacheView(image_view); | 
 |         state&=(~UpdateConfigurationState); | 
 |       } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   (void) XFreeCursor(display,cursor); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X C o m p o s i t e I m a g e                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XCompositeImage() requests an image name from the user, reads the image and | 
 | %  composites it with the X window image at a location the user chooses with | 
 | %  the pointer. | 
 | % | 
 | %  The format of the XCompositeImage method is: | 
 | % | 
 | %      MagickBooleanType XCompositeImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XCompositeImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static char | 
 |     displacement_geometry[MaxTextExtent] = "30x30", | 
 |     filename[MaxTextExtent] = "\0"; | 
 |  | 
 |   static const char | 
 |     *CompositeMenu[] = | 
 |     { | 
 |       "Operators", | 
 |       "Dissolve", | 
 |       "Displace", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static CompositeOperator | 
 |     compose = CopyCompositeOp; | 
 |  | 
 |   static const ModeType | 
 |     CompositeCommands[] = | 
 |     { | 
 |       CompositeOperatorsCommand, | 
 |       CompositeDissolveCommand, | 
 |       CompositeDisplaceCommand, | 
 |       CompositeHelpCommand, | 
 |       CompositeDismissCommand | 
 |     }; | 
 |  | 
 |   char | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   Image | 
 |     *composite_image; | 
 |  | 
 |   int | 
 |     entry, | 
 |     id, | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     blend, | 
 |     scale_factor; | 
 |  | 
 |   RectangleInfo | 
 |     highlight_info, | 
 |     composite_info; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   /* | 
 |     Request image file name from user. | 
 |   */ | 
 |   XFileBrowserWidget(display,windows,"Composite",filename); | 
 |   if (*filename == '\0') | 
 |     return(MagickTrue); | 
 |   /* | 
 |     Read image. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   (void) CopyMagickString(resource_info->image_info->filename,filename, | 
 |     MaxTextExtent); | 
 |   composite_image=ReadImage(resource_info->image_info,exception); | 
 |   CatchException(exception); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if (composite_image == (Image *) NULL) | 
 |     return(MagickFalse); | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Composite"); | 
 |   windows->command.data=1; | 
 |   (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   composite_info.x=(ssize_t) windows->image.x+x; | 
 |   composite_info.y=(ssize_t) windows->image.y+y; | 
 |   composite_info.width=0; | 
 |   composite_info.height=0; | 
 |   cursor=XCreateFontCursor(display,XC_ul_angle); | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |   blend=0.0; | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ", | 
 |           (long) composite_info.x,(long) composite_info.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     highlight_info=composite_info; | 
 |     highlight_info.x=composite_info.x-windows->image.x; | 
 |     highlight_info.y=composite_info.y-windows->image.y; | 
 |     XHighlightRectangle(display,windows->image.id, | 
 |       windows->image.highlight_context,&highlight_info); | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     XHighlightRectangle(display,windows->image.id, | 
 |       windows->image.highlight_context,&highlight_info); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,CompositeMenu,&event); | 
 |         if (id < 0) | 
 |           continue; | 
 |         switch (CompositeCommands[id]) | 
 |         { | 
 |           case CompositeOperatorsCommand: | 
 |           { | 
 |             char | 
 |               command[MaxTextExtent], | 
 |               **operators; | 
 |  | 
 |             /* | 
 |               Select a command from the pop-up menu. | 
 |             */ | 
 |             operators=GetCommandOptions(MagickComposeOptions); | 
 |             if (operators == (char **) NULL) | 
 |               break; | 
 |             entry=XMenuWidget(display,windows,CompositeMenu[id], | 
 |               (const char **) operators,command); | 
 |             if (entry >= 0) | 
 |               compose=(CompositeOperator) ParseCommandOption( | 
 |                 MagickComposeOptions,MagickFalse,operators[entry]); | 
 |             operators=DestroyStringList(operators); | 
 |             break; | 
 |           } | 
 |           case CompositeDissolveCommand: | 
 |           { | 
 |             static char | 
 |               factor[MaxTextExtent] = "20.0"; | 
 |  | 
 |             /* | 
 |               Dissolve the two images a given percent. | 
 |             */ | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             (void) XDialogWidget(display,windows,"Dissolve", | 
 |               "Enter the blend factor (0.0 - 99.9%):",factor); | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXinvert); | 
 |             if (*factor == '\0') | 
 |               break; | 
 |             blend=InterpretLocaleValue(factor,(char **) NULL); | 
 |             compose=DissolveCompositeOp; | 
 |             break; | 
 |           } | 
 |           case CompositeDisplaceCommand: | 
 |           { | 
 |             /* | 
 |               Get horizontal and vertical scale displacement geometry. | 
 |             */ | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             (void) XDialogWidget(display,windows,"Displace", | 
 |               "Enter the horizontal and vertical scale:",displacement_geometry); | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXinvert); | 
 |             if (*displacement_geometry == '\0') | 
 |               break; | 
 |             compose=DisplaceCompositeOp; | 
 |             break; | 
 |           } | 
 |           case CompositeHelpCommand: | 
 |           { | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Composite",ImageCompositeHelp); | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXinvert); | 
 |             break; | 
 |           } | 
 |           case CompositeDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Button Press: 0x%lx %u +%d+%d",event.xbutton.window, | 
 |             event.xbutton.button,event.xbutton.x,event.xbutton.y); | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Change cursor. | 
 |         */ | 
 |         composite_info.width=composite_image->columns; | 
 |         composite_info.height=composite_image->rows; | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         composite_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |         composite_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |       { | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Button Release: 0x%lx %u +%d+%d",event.xbutton.window, | 
 |             event.xbutton.button,event.xbutton.x,event.xbutton.y); | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         if ((composite_info.width != 0) && (composite_info.height != 0)) | 
 |           { | 
 |             /* | 
 |               User has selected the location of the composite image. | 
 |             */ | 
 |             composite_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |             composite_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |             state|=ExitState; | 
 |           } | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         char | 
 |           command[MaxTextExtent]; | 
 |  | 
 |         KeySym | 
 |           key_symbol; | 
 |  | 
 |         int | 
 |           length; | 
 |  | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         length=XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         *(command+length)='\0'; | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             composite_image=DestroyImage(composite_image); | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Composite",ImageCompositeHelp); | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXinvert); | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         /* | 
 |           Map and unmap Info widget as text cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |         composite_info.x=(ssize_t) windows->image.x+x; | 
 |         composite_info.y=(ssize_t) windows->image.y+y; | 
 |         break; | 
 |       } | 
 |       default: | 
 |       { | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d", | 
 |             event.type); | 
 |         break; | 
 |       } | 
 |     } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   (void) XFreeCursor(display,cursor); | 
 |   if ((state & EscapeState) != 0) | 
 |     return(MagickTrue); | 
 |   /* | 
 |     Image compositing is relative to image configuration. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   width=(unsigned int) image->columns; | 
 |   height=(unsigned int) image->rows; | 
 |   x=0; | 
 |   y=0; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |   scale_factor=(MagickRealType) width/windows->image.ximage->width; | 
 |   composite_info.x+=x; | 
 |   composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5); | 
 |   composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5); | 
 |   scale_factor=(MagickRealType) height/windows->image.ximage->height; | 
 |   composite_info.y+=y; | 
 |   composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5); | 
 |   composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5); | 
 |   if ((composite_info.width != composite_image->columns) || | 
 |       (composite_info.height != composite_image->rows)) | 
 |     { | 
 |       Image | 
 |         *resize_image; | 
 |  | 
 |       /* | 
 |         Scale composite image. | 
 |       */ | 
 |       resize_image=ResizeImage(composite_image,composite_info.width, | 
 |         composite_info.height,composite_image->filter,composite_image->blur, | 
 |         exception); | 
 |       composite_image=DestroyImage(composite_image); | 
 |       if (resize_image == (Image *) NULL) | 
 |         { | 
 |           XSetCursorState(display,windows,MagickFalse); | 
 |           return(MagickFalse); | 
 |         } | 
 |       composite_image=resize_image; | 
 |     } | 
 |   if (compose == DisplaceCompositeOp) | 
 |     (void) SetImageArtifact(composite_image,"compose:args", | 
 |       displacement_geometry); | 
 |   if (blend != 0.0) | 
 |     { | 
 |       CacheView | 
 |         *image_view; | 
 |  | 
 |       int | 
 |         y; | 
 |  | 
 |       Quantum | 
 |         opacity; | 
 |  | 
 |       register int | 
 |         x; | 
 |  | 
 |       register Quantum | 
 |         *q; | 
 |  | 
 |       /* | 
 |         Create mattes for blending. | 
 |       */ | 
 |       (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception); | 
 |       opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)- | 
 |         ((ssize_t) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100); | 
 |       if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) | 
 |         return(MagickFalse); | 
 |       image->matte=MagickTrue; | 
 |       image_view=AcquireCacheView(image); | 
 |       for (y=0; y < (int) image->rows; y++) | 
 |       { | 
 |         q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1, | 
 |           exception); | 
 |         if (q == (Quantum *) NULL) | 
 |           break; | 
 |         for (x=0; x < (int) image->columns; x++) | 
 |         { | 
 |           SetPixelAlpha(image,opacity,q); | 
 |           q+=GetPixelChannels(image); | 
 |         } | 
 |         if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) | 
 |           break; | 
 |       } | 
 |       image_view=DestroyCacheView(image_view); | 
 |     } | 
 |   /* | 
 |     Composite image with X Image window. | 
 |   */ | 
 |   (void) CompositeImage(image,compose,composite_image,composite_info.x, | 
 |     composite_info.y,exception); | 
 |   composite_image=DestroyImage(composite_image); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   /* | 
 |     Update image configuration. | 
 |   */ | 
 |   XConfigureImageColormap(display,resource_info,windows,image,exception); | 
 |   (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X C o n f i g u r e I m a g e                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XConfigureImage() creates a new X image.  It also notifies the window | 
 | %  manager of the new image size and configures the transient widows. | 
 | % | 
 | %  The format of the XConfigureImage method is: | 
 | % | 
 | %      MagickBooleanType XConfigureImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XConfigureImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     geometry[MaxTextExtent]; | 
 |  | 
 |   MagickStatusType | 
 |     status; | 
 |  | 
 |   size_t | 
 |     mask, | 
 |     height, | 
 |     width; | 
 |  | 
 |   ssize_t | 
 |     x, | 
 |     y; | 
 |  | 
 |   XSizeHints | 
 |     *size_hints; | 
 |  | 
 |   XWindowChanges | 
 |     window_changes; | 
 |  | 
 |   /* | 
 |     Dismiss if window dimensions are zero. | 
 |   */ | 
 |   width=(unsigned int) windows->image.window_changes.width; | 
 |   height=(unsigned int) windows->image.window_changes.height; | 
 |   if (image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |       "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width, | 
 |       windows->image.ximage->height,(double) width,(double) height); | 
 |   if ((width*height) == 0) | 
 |     return(MagickTrue); | 
 |   x=0; | 
 |   y=0; | 
 |   /* | 
 |     Resize image to fit Image window dimensions. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   (void) XFlush(display); | 
 |   if (((int) width != windows->image.ximage->width) || | 
 |       ((int) height != windows->image.ximage->height)) | 
 |     image->taint=MagickTrue; | 
 |   windows->magnify.x=(int) | 
 |     width*windows->magnify.x/windows->image.ximage->width; | 
 |   windows->magnify.y=(int) | 
 |     height*windows->magnify.y/windows->image.ximage->height; | 
 |   windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width); | 
 |   windows->image.y=(int) | 
 |     (height*windows->image.y/windows->image.ximage->height); | 
 |   status=XMakeImage(display,resource_info,&windows->image,image, | 
 |     (unsigned int) width,(unsigned int) height,exception); | 
 |   if (status == MagickFalse) | 
 |     XNoticeWidget(display,windows,"Unable to configure X image:", | 
 |       windows->image.name); | 
 |   /* | 
 |     Notify window manager of the new configuration. | 
 |   */ | 
 |   if (resource_info->image_geometry != (char *) NULL) | 
 |     (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!", | 
 |       resource_info->image_geometry); | 
 |   else | 
 |     (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!", | 
 |       XDisplayWidth(display,windows->image.screen), | 
 |       XDisplayHeight(display,windows->image.screen)); | 
 |   (void) ParseMetaGeometry(geometry,&x,&y,&width,&height); | 
 |   window_changes.width=(int) width; | 
 |   if (window_changes.width > XDisplayWidth(display,windows->image.screen)) | 
 |     window_changes.width=XDisplayWidth(display,windows->image.screen); | 
 |   window_changes.height=(int) height; | 
 |   if (window_changes.height > XDisplayHeight(display,windows->image.screen)) | 
 |     window_changes.height=XDisplayHeight(display,windows->image.screen); | 
 |   mask=(size_t) (CWWidth | CWHeight); | 
 |   if (resource_info->backdrop) | 
 |     { | 
 |       mask|=CWX | CWY; | 
 |       window_changes.x=(int) | 
 |         ((XDisplayWidth(display,windows->image.screen)/2)-(width/2)); | 
 |       window_changes.y=(int) | 
 |         ((XDisplayHeight(display,windows->image.screen)/2)-(height/2)); | 
 |     } | 
 |   (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen, | 
 |     (unsigned int) mask,&window_changes); | 
 |   (void) XClearWindow(display,windows->image.id); | 
 |   XRefreshWindow(display,&windows->image,(XEvent *) NULL); | 
 |   /* | 
 |     Update Magnify window configuration. | 
 |   */ | 
 |   if (windows->magnify.mapped != MagickFalse) | 
 |     XMakeMagnifyImage(display,windows,exception); | 
 |   windows->pan.crop_geometry=windows->image.crop_geometry; | 
 |   XBestIconSize(display,&windows->pan,image); | 
 |   while (((windows->pan.width << 1) < MaxIconSize) && | 
 |          ((windows->pan.height << 1) < MaxIconSize)) | 
 |   { | 
 |     windows->pan.width<<=1; | 
 |     windows->pan.height<<=1; | 
 |   } | 
 |   if (windows->pan.geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y, | 
 |       &windows->pan.width,&windows->pan.height); | 
 |   window_changes.width=(int) windows->pan.width; | 
 |   window_changes.height=(int) windows->pan.height; | 
 |   size_hints=XAllocSizeHints(); | 
 |   if (size_hints != (XSizeHints *) NULL) | 
 |     { | 
 |       /* | 
 |         Set new size hints. | 
 |       */ | 
 |       size_hints->flags=PSize | PMinSize | PMaxSize; | 
 |       size_hints->width=window_changes.width; | 
 |       size_hints->height=window_changes.height; | 
 |       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; | 
 |       (void) XSetNormalHints(display,windows->pan.id,size_hints); | 
 |       (void) XFree((void *) size_hints); | 
 |     } | 
 |   (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen, | 
 |     (unsigned int) (CWWidth | CWHeight),&window_changes); | 
 |   /* | 
 |     Update icon window configuration. | 
 |   */ | 
 |   windows->icon.crop_geometry=windows->image.crop_geometry; | 
 |   XBestIconSize(display,&windows->icon,image); | 
 |   window_changes.width=(int) windows->icon.width; | 
 |   window_changes.height=(int) windows->icon.height; | 
 |   (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen, | 
 |     (unsigned int) (CWWidth | CWHeight),&window_changes); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   return(status != 0 ? MagickTrue : MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X C r o p I m a g e                                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XCropImage() allows the user to select a region of the image and crop, copy, | 
 | %  or cut it.  For copy or cut, the image can subsequently be composited onto | 
 | %  the image with XPasteImage. | 
 | % | 
 | %  The format of the XCropImage method is: | 
 | % | 
 | %      MagickBooleanType XCropImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        const ClipboardMode mode,ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | %    o mode: This unsigned value specified whether the image should be | 
 | %      cropped, copied, or cut. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XCropImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   const ClipboardMode mode,ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *CropModeMenu[] = | 
 |     { | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }, | 
 |     *RectifyModeMenu[] = | 
 |     { | 
 |       "Crop", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static const ModeType | 
 |     CropCommands[] = | 
 |     { | 
 |       CropHelpCommand, | 
 |       CropDismissCommand | 
 |     }, | 
 |     RectifyCommands[] = | 
 |     { | 
 |       RectifyCopyCommand, | 
 |       RectifyHelpCommand, | 
 |       RectifyDismissCommand | 
 |     }; | 
 |  | 
 |   CacheView | 
 |     *image_view; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   int | 
 |     id, | 
 |     x, | 
 |     y; | 
 |  | 
 |   KeySym | 
 |     key_symbol; | 
 |  | 
 |   Image | 
 |     *crop_image; | 
 |  | 
 |   MagickRealType | 
 |     scale_factor; | 
 |  | 
 |   RectangleInfo | 
 |     crop_info, | 
 |     highlight_info; | 
 |  | 
 |   register Quantum | 
 |     *q; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   switch (mode) | 
 |   { | 
 |     case CopyMode: | 
 |     { | 
 |       (void) CloneString(&windows->command.name,"Copy"); | 
 |       break; | 
 |     } | 
 |     case CropMode: | 
 |     { | 
 |       (void) CloneString(&windows->command.name,"Crop"); | 
 |       break; | 
 |     } | 
 |     case CutMode: | 
 |     { | 
 |       (void) CloneString(&windows->command.name,"Cut"); | 
 |       break; | 
 |     } | 
 |   } | 
 |   RectifyModeMenu[0]=windows->command.name; | 
 |   windows->command.data=0; | 
 |   (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   crop_info.x=(ssize_t) windows->image.x+x; | 
 |   crop_info.y=(ssize_t) windows->image.y+y; | 
 |   crop_info.width=0; | 
 |   crop_info.height=0; | 
 |   cursor=XCreateFontCursor(display,XC_fleur); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ", | 
 |           (long) crop_info.x,(long) crop_info.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,CropModeMenu,&event); | 
 |         if (id < 0) | 
 |           continue; | 
 |         switch (CropCommands[id]) | 
 |         { | 
 |           case CropHelpCommand: | 
 |           { | 
 |             switch (mode) | 
 |             { | 
 |               case CopyMode: | 
 |               { | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Copy",ImageCopyHelp); | 
 |                 break; | 
 |               } | 
 |               case CropMode: | 
 |               { | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Crop",ImageCropHelp); | 
 |                 break; | 
 |               } | 
 |               case CutMode: | 
 |               { | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Cut",ImageCutHelp); | 
 |                 break; | 
 |               } | 
 |             } | 
 |             break; | 
 |           } | 
 |           case CropDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Note first corner of cropping rectangle-- exit loop. | 
 |         */ | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         crop_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |         crop_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |         state|=ExitState; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |         break; | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             switch (mode) | 
 |             { | 
 |               case CopyMode: | 
 |               { | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Copy",ImageCopyHelp); | 
 |                 break; | 
 |               } | 
 |               case CropMode: | 
 |               { | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Crop",ImageCropHelp); | 
 |                 break; | 
 |               } | 
 |               case CutMode: | 
 |               { | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Cut",ImageCutHelp); | 
 |                 break; | 
 |               } | 
 |             } | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         if (event.xmotion.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Map and unmap Info widget as text cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |         crop_info.x=(ssize_t) windows->image.x+x; | 
 |         crop_info.y=(ssize_t) windows->image.y+y; | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   if ((state & EscapeState) != 0) | 
 |     { | 
 |       /* | 
 |         User want to exit without cropping. | 
 |       */ | 
 |       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       (void) XFreeCursor(display,cursor); | 
 |       return(MagickTrue); | 
 |     } | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |   do | 
 |   { | 
 |     /* | 
 |       Size rectangle as pointer moves until the mouse button is released. | 
 |     */ | 
 |     x=(int) crop_info.x; | 
 |     y=(int) crop_info.y; | 
 |     crop_info.width=0; | 
 |     crop_info.height=0; | 
 |     state=DefaultState; | 
 |     do | 
 |     { | 
 |       highlight_info=crop_info; | 
 |       highlight_info.x=crop_info.x-windows->image.x; | 
 |       highlight_info.y=crop_info.y-windows->image.y; | 
 |       if ((highlight_info.width > 3) && (highlight_info.height > 3)) | 
 |         { | 
 |           /* | 
 |             Display info and draw cropping rectangle. | 
 |           */ | 
 |           if (windows->info.mapped == MagickFalse) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |           (void) FormatLocaleString(text,MaxTextExtent, | 
 |             " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double) | 
 |             crop_info.height,(double) crop_info.x,(double) crop_info.y); | 
 |           XInfoWidget(display,windows,text); | 
 |           XHighlightRectangle(display,windows->image.id, | 
 |             windows->image.highlight_context,&highlight_info); | 
 |         } | 
 |       else | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       /* | 
 |         Wait for next event. | 
 |       */ | 
 |       XScreenEvent(display,windows,&event,exception); | 
 |       if ((highlight_info.width > 3) && (highlight_info.height > 3)) | 
 |         XHighlightRectangle(display,windows->image.id, | 
 |           windows->image.highlight_context,&highlight_info); | 
 |       switch (event.type) | 
 |       { | 
 |         case ButtonPress: | 
 |         { | 
 |           crop_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |           crop_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |           break; | 
 |         } | 
 |         case ButtonRelease: | 
 |         { | 
 |           /* | 
 |             User has committed to cropping rectangle. | 
 |           */ | 
 |           crop_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |           crop_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |           XSetCursorState(display,windows,MagickFalse); | 
 |           state|=ExitState; | 
 |           windows->command.data=0; | 
 |           (void) XCommandWidget(display,windows,RectifyModeMenu, | 
 |             (XEvent *) NULL); | 
 |           break; | 
 |         } | 
 |         case Expose: | 
 |           break; | 
 |         case MotionNotify: | 
 |         { | 
 |           crop_info.x=(ssize_t) windows->image.x+event.xmotion.x; | 
 |           crop_info.y=(ssize_t) windows->image.y+event.xmotion.y; | 
 |         } | 
 |         default: | 
 |           break; | 
 |       } | 
 |       if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) || | 
 |           ((state & ExitState) != 0)) | 
 |         { | 
 |           /* | 
 |             Check boundary conditions. | 
 |           */ | 
 |           if (crop_info.x < 0) | 
 |             crop_info.x=0; | 
 |           else | 
 |             if (crop_info.x > (ssize_t) windows->image.ximage->width) | 
 |               crop_info.x=(ssize_t) windows->image.ximage->width; | 
 |           if ((int) crop_info.x < x) | 
 |             crop_info.width=(unsigned int) (x-crop_info.x); | 
 |           else | 
 |             { | 
 |               crop_info.width=(unsigned int) (crop_info.x-x); | 
 |               crop_info.x=(ssize_t) x; | 
 |             } | 
 |           if (crop_info.y < 0) | 
 |             crop_info.y=0; | 
 |           else | 
 |             if (crop_info.y > (ssize_t) windows->image.ximage->height) | 
 |               crop_info.y=(ssize_t) windows->image.ximage->height; | 
 |           if ((int) crop_info.y < y) | 
 |             crop_info.height=(unsigned int) (y-crop_info.y); | 
 |           else | 
 |             { | 
 |               crop_info.height=(unsigned int) (crop_info.y-y); | 
 |               crop_info.y=(ssize_t) y; | 
 |             } | 
 |         } | 
 |     } while ((state & ExitState) == 0); | 
 |     /* | 
 |       Wait for user to grab a corner of the rectangle or press return. | 
 |     */ | 
 |     state=DefaultState; | 
 |     (void) XMapWindow(display,windows->info.id); | 
 |     do | 
 |     { | 
 |       if (windows->info.mapped != MagickFalse) | 
 |         { | 
 |           /* | 
 |             Display pointer position. | 
 |           */ | 
 |           (void) FormatLocaleString(text,MaxTextExtent, | 
 |             " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double) | 
 |             crop_info.height,(double) crop_info.x,(double) crop_info.y); | 
 |           XInfoWidget(display,windows,text); | 
 |         } | 
 |       highlight_info=crop_info; | 
 |       highlight_info.x=crop_info.x-windows->image.x; | 
 |       highlight_info.y=crop_info.y-windows->image.y; | 
 |       if ((highlight_info.width <= 3) || (highlight_info.height <= 3)) | 
 |         { | 
 |           state|=EscapeState; | 
 |           state|=ExitState; | 
 |           break; | 
 |         } | 
 |       XHighlightRectangle(display,windows->image.id, | 
 |         windows->image.highlight_context,&highlight_info); | 
 |       XScreenEvent(display,windows,&event,exception); | 
 |       if (event.xany.window == windows->command.id) | 
 |         { | 
 |           /* | 
 |             Select a command from the Command widget. | 
 |           */ | 
 |           (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |           id=XCommandWidget(display,windows,RectifyModeMenu,&event); | 
 |           (void) XSetFunction(display,windows->image.highlight_context, | 
 |             GXinvert); | 
 |           XHighlightRectangle(display,windows->image.id, | 
 |             windows->image.highlight_context,&highlight_info); | 
 |           if (id >= 0) | 
 |             switch (RectifyCommands[id]) | 
 |             { | 
 |               case RectifyCopyCommand: | 
 |               { | 
 |                 state|=ExitState; | 
 |                 break; | 
 |               } | 
 |               case RectifyHelpCommand: | 
 |               { | 
 |                 (void) XSetFunction(display,windows->image.highlight_context, | 
 |                   GXcopy); | 
 |                 switch (mode) | 
 |                 { | 
 |                   case CopyMode: | 
 |                   { | 
 |                     XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                       "Help Viewer - Image Copy",ImageCopyHelp); | 
 |                     break; | 
 |                   } | 
 |                   case CropMode: | 
 |                   { | 
 |                     XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                       "Help Viewer - Image Crop",ImageCropHelp); | 
 |                     break; | 
 |                   } | 
 |                   case CutMode: | 
 |                   { | 
 |                     XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                       "Help Viewer - Image Cut",ImageCutHelp); | 
 |                     break; | 
 |                   } | 
 |                 } | 
 |                 (void) XSetFunction(display,windows->image.highlight_context, | 
 |                   GXinvert); | 
 |                 break; | 
 |               } | 
 |               case RectifyDismissCommand: | 
 |               { | 
 |                 /* | 
 |                   Prematurely exit. | 
 |                 */ | 
 |                 state|=EscapeState; | 
 |                 state|=ExitState; | 
 |                 break; | 
 |               } | 
 |               default: | 
 |                 break; | 
 |             } | 
 |           continue; | 
 |         } | 
 |       XHighlightRectangle(display,windows->image.id, | 
 |         windows->image.highlight_context,&highlight_info); | 
 |       switch (event.type) | 
 |       { | 
 |         case ButtonPress: | 
 |         { | 
 |           if (event.xbutton.button != Button1) | 
 |             break; | 
 |           if (event.xbutton.window != windows->image.id) | 
 |             break; | 
 |           x=windows->image.x+event.xbutton.x; | 
 |           y=windows->image.y+event.xbutton.y; | 
 |           if ((x < (int) (crop_info.x+RoiDelta)) && | 
 |               (x > (int) (crop_info.x-RoiDelta)) && | 
 |               (y < (int) (crop_info.y+RoiDelta)) && | 
 |               (y > (int) (crop_info.y-RoiDelta))) | 
 |             { | 
 |               crop_info.x=(ssize_t) (crop_info.x+crop_info.width); | 
 |               crop_info.y=(ssize_t) (crop_info.y+crop_info.height); | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |           if ((x < (int) (crop_info.x+RoiDelta)) && | 
 |               (x > (int) (crop_info.x-RoiDelta)) && | 
 |               (y < (int) (crop_info.y+crop_info.height+RoiDelta)) && | 
 |               (y > (int) (crop_info.y+crop_info.height-RoiDelta))) | 
 |             { | 
 |               crop_info.x=(ssize_t) (crop_info.x+crop_info.width); | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |           if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) && | 
 |               (x > (int) (crop_info.x+crop_info.width-RoiDelta)) && | 
 |               (y < (int) (crop_info.y+RoiDelta)) && | 
 |               (y > (int) (crop_info.y-RoiDelta))) | 
 |             { | 
 |               crop_info.y=(ssize_t) (crop_info.y+crop_info.height); | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |           if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) && | 
 |               (x > (int) (crop_info.x+crop_info.width-RoiDelta)) && | 
 |               (y < (int) (crop_info.y+crop_info.height+RoiDelta)) && | 
 |               (y > (int) (crop_info.y+crop_info.height-RoiDelta))) | 
 |             { | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |         } | 
 |         case ButtonRelease: | 
 |         { | 
 |           if (event.xbutton.window == windows->pan.id) | 
 |             if ((highlight_info.x != crop_info.x-windows->image.x) || | 
 |                 (highlight_info.y != crop_info.y-windows->image.y)) | 
 |               XHighlightRectangle(display,windows->image.id, | 
 |                 windows->image.highlight_context,&highlight_info); | 
 |           (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id, | 
 |             event.xbutton.time); | 
 |           break; | 
 |         } | 
 |         case Expose: | 
 |         { | 
 |           if (event.xexpose.window == windows->image.id) | 
 |             if (event.xexpose.count == 0) | 
 |               { | 
 |                 event.xexpose.x=(int) highlight_info.x; | 
 |                 event.xexpose.y=(int) highlight_info.y; | 
 |                 event.xexpose.width=(int) highlight_info.width; | 
 |                 event.xexpose.height=(int) highlight_info.height; | 
 |                 XRefreshWindow(display,&windows->image,&event); | 
 |               } | 
 |           if (event.xexpose.window == windows->info.id) | 
 |             if (event.xexpose.count == 0) | 
 |               XInfoWidget(display,windows,text); | 
 |           break; | 
 |         } | 
 |         case KeyPress: | 
 |         { | 
 |           if (event.xkey.window != windows->image.id) | 
 |             break; | 
 |           /* | 
 |             Respond to a user key press. | 
 |           */ | 
 |           (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |             sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |           switch ((int) key_symbol) | 
 |           { | 
 |             case XK_Escape: | 
 |             case XK_F20: | 
 |               state|=EscapeState; | 
 |             case XK_Return: | 
 |             { | 
 |               state|=ExitState; | 
 |               break; | 
 |             } | 
 |             case XK_Home: | 
 |             case XK_KP_Home: | 
 |             { | 
 |               crop_info.x=(ssize_t) (windows->image.width/2L- | 
 |                 crop_info.width/2L); | 
 |               crop_info.y=(ssize_t) (windows->image.height/2L- | 
 |                 crop_info.height/2L); | 
 |               break; | 
 |             } | 
 |             case XK_Left: | 
 |             case XK_KP_Left: | 
 |             { | 
 |               crop_info.x--; | 
 |               break; | 
 |             } | 
 |             case XK_Up: | 
 |             case XK_KP_Up: | 
 |             case XK_Next: | 
 |             { | 
 |               crop_info.y--; | 
 |               break; | 
 |             } | 
 |             case XK_Right: | 
 |             case XK_KP_Right: | 
 |             { | 
 |               crop_info.x++; | 
 |               break; | 
 |             } | 
 |             case XK_Prior: | 
 |             case XK_Down: | 
 |             case XK_KP_Down: | 
 |             { | 
 |               crop_info.y++; | 
 |               break; | 
 |             } | 
 |             case XK_F1: | 
 |             case XK_Help: | 
 |             { | 
 |               (void) XSetFunction(display,windows->image.highlight_context, | 
 |                 GXcopy); | 
 |               switch (mode) | 
 |               { | 
 |                 case CopyMode: | 
 |                 { | 
 |                   XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                     "Help Viewer - Image Copy",ImageCopyHelp); | 
 |                   break; | 
 |                 } | 
 |                 case CropMode: | 
 |                 { | 
 |                   XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                     "Help Viewer - Image Cropg",ImageCropHelp); | 
 |                   break; | 
 |                 } | 
 |                 case CutMode: | 
 |                 { | 
 |                   XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                     "Help Viewer - Image Cutg",ImageCutHelp); | 
 |                   break; | 
 |                 } | 
 |               } | 
 |               (void) XSetFunction(display,windows->image.highlight_context, | 
 |                 GXinvert); | 
 |               break; | 
 |             } | 
 |             default: | 
 |             { | 
 |               (void) XBell(display,0); | 
 |               break; | 
 |             } | 
 |           } | 
 |           (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id, | 
 |             event.xkey.time); | 
 |           break; | 
 |         } | 
 |         case KeyRelease: | 
 |           break; | 
 |         case MotionNotify: | 
 |         { | 
 |           if (event.xmotion.window != windows->image.id) | 
 |             break; | 
 |           /* | 
 |             Map and unmap Info widget as text cursor crosses its boundaries. | 
 |           */ | 
 |           x=event.xmotion.x; | 
 |           y=event.xmotion.y; | 
 |           if (windows->info.mapped != MagickFalse) | 
 |             { | 
 |               if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                   (y < (int) (windows->info.y+windows->info.height))) | 
 |                 (void) XWithdrawWindow(display,windows->info.id, | 
 |                   windows->info.screen); | 
 |             } | 
 |           else | 
 |             if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |                 (y > (int) (windows->info.y+windows->info.height))) | 
 |               (void) XMapWindow(display,windows->info.id); | 
 |           crop_info.x=(ssize_t) windows->image.x+event.xmotion.x; | 
 |           crop_info.y=(ssize_t) windows->image.y+event.xmotion.y; | 
 |           break; | 
 |         } | 
 |         case SelectionRequest: | 
 |         { | 
 |           XSelectionEvent | 
 |             notify; | 
 |  | 
 |           XSelectionRequestEvent | 
 |             *request; | 
 |  | 
 |           /* | 
 |             Set primary selection. | 
 |           */ | 
 |           (void) FormatLocaleString(text,MaxTextExtent, | 
 |             "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double) | 
 |             crop_info.height,(double) crop_info.x,(double) crop_info.y); | 
 |           request=(&(event.xselectionrequest)); | 
 |           (void) XChangeProperty(request->display,request->requestor, | 
 |             request->property,request->target,8,PropModeReplace, | 
 |             (unsigned char *) text,(int) strlen(text)); | 
 |           notify.type=SelectionNotify; | 
 |           notify.display=request->display; | 
 |           notify.requestor=request->requestor; | 
 |           notify.selection=request->selection; | 
 |           notify.target=request->target; | 
 |           notify.time=request->time; | 
 |           if (request->property == None) | 
 |             notify.property=request->target; | 
 |           else | 
 |             notify.property=request->property; | 
 |           (void) XSendEvent(request->display,request->requestor,False,0, | 
 |             (XEvent *) ¬ify); | 
 |         } | 
 |         default: | 
 |           break; | 
 |       } | 
 |       if ((state & UpdateConfigurationState) != 0) | 
 |         { | 
 |           (void) XPutBackEvent(display,&event); | 
 |           (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |           break; | 
 |         } | 
 |     } while ((state & ExitState) == 0); | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if ((state & EscapeState) != 0) | 
 |     return(MagickTrue); | 
 |   if (mode == CropMode) | 
 |     if (((int) crop_info.width != windows->image.ximage->width) || | 
 |         ((int) crop_info.height != windows->image.ximage->height)) | 
 |       { | 
 |         /* | 
 |           Reconfigure Image window as defined by cropping rectangle. | 
 |         */ | 
 |         XSetCropGeometry(display,windows,&crop_info,image); | 
 |         windows->image.window_changes.width=(int) crop_info.width; | 
 |         windows->image.window_changes.height=(int) crop_info.height; | 
 |         (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |         return(MagickTrue); | 
 |       } | 
 |   /* | 
 |     Copy image before applying image transforms. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   width=(unsigned int) image->columns; | 
 |   height=(unsigned int) image->rows; | 
 |   x=0; | 
 |   y=0; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |   scale_factor=(MagickRealType) width/windows->image.ximage->width; | 
 |   crop_info.x+=x; | 
 |   crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5); | 
 |   crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5); | 
 |   scale_factor=(MagickRealType) height/windows->image.ximage->height; | 
 |   crop_info.y+=y; | 
 |   crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5); | 
 |   crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5); | 
 |   crop_image=CropImage(image,&crop_info,exception); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if (crop_image == (Image *) NULL) | 
 |     return(MagickFalse); | 
 |   if (resource_info->copy_image != (Image *) NULL) | 
 |     resource_info->copy_image=DestroyImage(resource_info->copy_image); | 
 |   resource_info->copy_image=crop_image; | 
 |   if (mode == CopyMode) | 
 |     { | 
 |       (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |       return(MagickTrue); | 
 |     } | 
 |   /* | 
 |     Cut image. | 
 |   */ | 
 |   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) | 
 |     return(MagickFalse); | 
 |   image->matte=MagickTrue; | 
 |   image_view=AcquireCacheView(image); | 
 |   for (y=0; y < (int) crop_info.height; y++) | 
 |   { | 
 |     q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y, | 
 |       crop_info.width,1,exception); | 
 |     if (q == (Quantum *) NULL) | 
 |       break; | 
 |     for (x=0; x < (int) crop_info.width; x++) | 
 |     { | 
 |       SetPixelAlpha(image,TransparentAlpha,q); | 
 |       q+=GetPixelChannels(image); | 
 |     } | 
 |     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) | 
 |       break; | 
 |   } | 
 |   image_view=DestroyCacheView(image_view); | 
 |   /* | 
 |     Update image configuration. | 
 |   */ | 
 |   XConfigureImageColormap(display,resource_info,windows,image,exception); | 
 |   (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X D r a w I m a g e                                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on | 
 | %  the image. | 
 | % | 
 | %  The format of the XDrawEditImage method is: | 
 | % | 
 | %      MagickBooleanType XDrawEditImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XDrawEditImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *DrawMenu[] = | 
 |     { | 
 |       "Element", | 
 |       "Color", | 
 |       "Stipple", | 
 |       "Width", | 
 |       "Undo", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static ElementType | 
 |     element = PointElement; | 
 |  | 
 |   static const ModeType | 
 |     DrawCommands[] = | 
 |     { | 
 |       DrawElementCommand, | 
 |       DrawColorCommand, | 
 |       DrawStippleCommand, | 
 |       DrawWidthCommand, | 
 |       DrawUndoCommand, | 
 |       DrawHelpCommand, | 
 |       DrawDismissCommand | 
 |     }; | 
 |  | 
 |   static Pixmap | 
 |     stipple = (Pixmap) NULL; | 
 |  | 
 |   static unsigned int | 
 |     pen_id = 0, | 
 |     line_width = 1; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   int | 
 |     entry, | 
 |     id, | 
 |     number_coordinates, | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     degrees; | 
 |  | 
 |   MagickStatusType | 
 |     status; | 
 |  | 
 |   RectangleInfo | 
 |     rectangle_info; | 
 |  | 
 |   register int | 
 |     i; | 
 |  | 
 |   unsigned int | 
 |     distance, | 
 |     height, | 
 |     max_coordinates, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   Window | 
 |     root_window; | 
 |  | 
 |   XDrawInfo | 
 |     draw_info; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   XPoint | 
 |     *coordinate_info; | 
 |  | 
 |   XSegment | 
 |     line_info; | 
 |  | 
 |   /* | 
 |     Allocate polygon info. | 
 |   */ | 
 |   max_coordinates=2048; | 
 |   coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates, | 
 |     sizeof(*coordinate_info)); | 
 |   if (coordinate_info == (XPoint *) NULL) | 
 |     { | 
 |       (void) ThrowMagickException(exception,GetMagickModule(), | 
 |         ResourceLimitError,"MemoryAllocationFailed","`%s'","..."); | 
 |       return(MagickFalse); | 
 |     } | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Draw"); | 
 |   windows->command.data=4; | 
 |   (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Wait for first button press. | 
 |   */ | 
 |   root_window=XRootWindow(display,XDefaultScreen(display)); | 
 |   draw_info.stencil=OpaqueStencil; | 
 |   status=MagickTrue; | 
 |   cursor=XCreateFontCursor(display,XC_tcross); | 
 |   for ( ; ; ) | 
 |   { | 
 |     XQueryPosition(display,windows->image.id,&x,&y); | 
 |     (void) XSelectInput(display,windows->image.id, | 
 |       windows->image.attributes.event_mask | PointerMotionMask); | 
 |     (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |     state=DefaultState; | 
 |     do | 
 |     { | 
 |       if (windows->info.mapped != MagickFalse) | 
 |         { | 
 |           /* | 
 |             Display pointer position. | 
 |           */ | 
 |           (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ", | 
 |             x+windows->image.x,y+windows->image.y); | 
 |           XInfoWidget(display,windows,text); | 
 |         } | 
 |       /* | 
 |         Wait for next event. | 
 |       */ | 
 |       XScreenEvent(display,windows,&event,exception); | 
 |       if (event.xany.window == windows->command.id) | 
 |         { | 
 |           /* | 
 |             Select a command from the Command widget. | 
 |           */ | 
 |           id=XCommandWidget(display,windows,DrawMenu,&event); | 
 |           if (id < 0) | 
 |             continue; | 
 |           switch (DrawCommands[id]) | 
 |           { | 
 |             case DrawElementCommand: | 
 |             { | 
 |               static const char | 
 |                 *Elements[] = | 
 |                 { | 
 |                   "point", | 
 |                   "line", | 
 |                   "rectangle", | 
 |                   "fill rectangle", | 
 |                   "circle", | 
 |                   "fill circle", | 
 |                   "ellipse", | 
 |                   "fill ellipse", | 
 |                   "polygon", | 
 |                   "fill polygon", | 
 |                   (char *) NULL, | 
 |                 }; | 
 |  | 
 |               /* | 
 |                 Select a command from the pop-up menu. | 
 |               */ | 
 |               element=(ElementType) (XMenuWidget(display,windows, | 
 |                 DrawMenu[id],Elements,command)+1); | 
 |               break; | 
 |             } | 
 |             case DrawColorCommand: | 
 |             { | 
 |               const char | 
 |                 *ColorMenu[MaxNumberPens+1]; | 
 |  | 
 |               int | 
 |                 pen_number; | 
 |  | 
 |               MagickBooleanType | 
 |                 transparent; | 
 |  | 
 |               XColor | 
 |                 color; | 
 |  | 
 |               /* | 
 |                 Initialize menu selections. | 
 |               */ | 
 |               for (i=0; i < (int) (MaxNumberPens-2); i++) | 
 |                 ColorMenu[i]=resource_info->pen_colors[i]; | 
 |               ColorMenu[MaxNumberPens-2]="transparent"; | 
 |               ColorMenu[MaxNumberPens-1]="Browser..."; | 
 |               ColorMenu[MaxNumberPens]=(char *) NULL; | 
 |               /* | 
 |                 Select a pen color from the pop-up menu. | 
 |               */ | 
 |               pen_number=XMenuWidget(display,windows,DrawMenu[id], | 
 |                 (const char **) ColorMenu,command); | 
 |               if (pen_number < 0) | 
 |                 break; | 
 |               transparent=pen_number == (MaxNumberPens-2) ? MagickTrue : | 
 |                 MagickFalse; | 
 |               if (transparent != MagickFalse) | 
 |                 { | 
 |                   draw_info.stencil=TransparentStencil; | 
 |                   break; | 
 |                 } | 
 |               if (pen_number == (MaxNumberPens-1)) | 
 |                 { | 
 |                   static char | 
 |                     color_name[MaxTextExtent] = "gray"; | 
 |  | 
 |                   /* | 
 |                     Select a pen color from a dialog. | 
 |                   */ | 
 |                   resource_info->pen_colors[pen_number]=color_name; | 
 |                   XColorBrowserWidget(display,windows,"Select",color_name); | 
 |                   if (*color_name == '\0') | 
 |                     break; | 
 |                 } | 
 |               /* | 
 |                 Set pen color. | 
 |               */ | 
 |               (void) XParseColor(display,windows->map_info->colormap, | 
 |                 resource_info->pen_colors[pen_number],&color); | 
 |               XBestPixel(display,windows->map_info->colormap,(XColor *) NULL, | 
 |                 (unsigned int) MaxColors,&color); | 
 |               windows->pixel_info->pen_colors[pen_number]=color; | 
 |               pen_id=(unsigned int) pen_number; | 
 |               draw_info.stencil=OpaqueStencil; | 
 |               break; | 
 |             } | 
 |             case DrawStippleCommand: | 
 |             { | 
 |               Image | 
 |                 *stipple_image; | 
 |  | 
 |               ImageInfo | 
 |                 *image_info; | 
 |  | 
 |               int | 
 |                 status; | 
 |  | 
 |               static char | 
 |                 filename[MaxTextExtent] = "\0"; | 
 |  | 
 |               static const char | 
 |                 *StipplesMenu[] = | 
 |                 { | 
 |                   "Brick", | 
 |                   "Diagonal", | 
 |                   "Scales", | 
 |                   "Vertical", | 
 |                   "Wavy", | 
 |                   "Translucent", | 
 |                   "Opaque", | 
 |                   (char *) NULL, | 
 |                   (char *) NULL, | 
 |                 }; | 
 |  | 
 |               /* | 
 |                 Select a command from the pop-up menu. | 
 |               */ | 
 |               StipplesMenu[7]="Open..."; | 
 |               entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu, | 
 |                 command); | 
 |               if (entry < 0) | 
 |                 break; | 
 |               if (stipple != (Pixmap) NULL) | 
 |                 (void) XFreePixmap(display,stipple); | 
 |               stipple=(Pixmap) NULL; | 
 |               if (entry != 7) | 
 |                 { | 
 |                   switch (entry) | 
 |                   { | 
 |                     case 0: | 
 |                     { | 
 |                       stipple=XCreateBitmapFromData(display,root_window, | 
 |                         (char *) BricksBitmap,BricksWidth,BricksHeight); | 
 |                       break; | 
 |                     } | 
 |                     case 1: | 
 |                     { | 
 |                       stipple=XCreateBitmapFromData(display,root_window, | 
 |                         (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight); | 
 |                       break; | 
 |                     } | 
 |                     case 2: | 
 |                     { | 
 |                       stipple=XCreateBitmapFromData(display,root_window, | 
 |                         (char *) ScalesBitmap,ScalesWidth,ScalesHeight); | 
 |                       break; | 
 |                     } | 
 |                     case 3: | 
 |                     { | 
 |                       stipple=XCreateBitmapFromData(display,root_window, | 
 |                         (char *) VerticalBitmap,VerticalWidth,VerticalHeight); | 
 |                       break; | 
 |                     } | 
 |                     case 4: | 
 |                     { | 
 |                       stipple=XCreateBitmapFromData(display,root_window, | 
 |                         (char *) WavyBitmap,WavyWidth,WavyHeight); | 
 |                       break; | 
 |                     } | 
 |                     case 5: | 
 |                     { | 
 |                       stipple=XCreateBitmapFromData(display,root_window, | 
 |                         (char *) HighlightBitmap,HighlightWidth, | 
 |                         HighlightHeight); | 
 |                       break; | 
 |                     } | 
 |                     case 6: | 
 |                     default: | 
 |                     { | 
 |                       stipple=XCreateBitmapFromData(display,root_window, | 
 |                         (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight); | 
 |                       break; | 
 |                     } | 
 |                   } | 
 |                   break; | 
 |                 } | 
 |               XFileBrowserWidget(display,windows,"Stipple",filename); | 
 |               if (*filename == '\0') | 
 |                 break; | 
 |               /* | 
 |                 Read image. | 
 |               */ | 
 |               XSetCursorState(display,windows,MagickTrue); | 
 |               XCheckRefreshWindows(display,windows); | 
 |               image_info=AcquireImageInfo(); | 
 |               (void) CopyMagickString(image_info->filename,filename, | 
 |                 MaxTextExtent); | 
 |               stipple_image=ReadImage(image_info,exception); | 
 |               CatchException(exception); | 
 |               XSetCursorState(display,windows,MagickFalse); | 
 |               if (stipple_image == (Image *) NULL) | 
 |                 break; | 
 |               (void) AcquireUniqueFileResource(filename); | 
 |               (void) FormatLocaleString(stipple_image->filename,MaxTextExtent, | 
 |                 "xbm:%s",filename); | 
 |               (void) WriteImage(image_info,stipple_image,exception); | 
 |               stipple_image=DestroyImage(stipple_image); | 
 |               image_info=DestroyImageInfo(image_info); | 
 |               status=XReadBitmapFile(display,root_window,filename,&width, | 
 |                 &height,&stipple,&x,&y); | 
 |               (void) RelinquishUniqueFileResource(filename); | 
 |               if ((status != BitmapSuccess) != 0) | 
 |                 XNoticeWidget(display,windows,"Unable to read X bitmap image:", | 
 |                   filename); | 
 |               break; | 
 |             } | 
 |             case DrawWidthCommand: | 
 |             { | 
 |               static char | 
 |                 width[MaxTextExtent] = "0"; | 
 |  | 
 |               static const char | 
 |                 *WidthsMenu[] = | 
 |                 { | 
 |                   "1", | 
 |                   "2", | 
 |                   "4", | 
 |                   "8", | 
 |                   "16", | 
 |                   "Dialog...", | 
 |                   (char *) NULL, | 
 |                 }; | 
 |  | 
 |               /* | 
 |                 Select a command from the pop-up menu. | 
 |               */ | 
 |               entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu, | 
 |                 command); | 
 |               if (entry < 0) | 
 |                 break; | 
 |               if (entry != 5) | 
 |                 { | 
 |                   line_width=(unsigned int) StringToUnsignedLong( | 
 |                     WidthsMenu[entry]); | 
 |                   break; | 
 |                 } | 
 |               (void) XDialogWidget(display,windows,"Ok","Enter line width:", | 
 |                 width); | 
 |               if (*width == '\0') | 
 |                 break; | 
 |               line_width=(unsigned int) StringToUnsignedLong(width); | 
 |               break; | 
 |             } | 
 |             case DrawUndoCommand: | 
 |             { | 
 |               (void) XMagickCommand(display,resource_info,windows,UndoCommand, | 
 |                 image,exception); | 
 |               break; | 
 |             } | 
 |             case DrawHelpCommand: | 
 |             { | 
 |               XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                 "Help Viewer - Image Rotation",ImageDrawHelp); | 
 |               (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |               break; | 
 |             } | 
 |             case DrawDismissCommand: | 
 |             { | 
 |               /* | 
 |                 Prematurely exit. | 
 |               */ | 
 |               state|=EscapeState; | 
 |               state|=ExitState; | 
 |               break; | 
 |             } | 
 |             default: | 
 |               break; | 
 |           } | 
 |           (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |           continue; | 
 |         } | 
 |       switch (event.type) | 
 |       { | 
 |         case ButtonPress: | 
 |         { | 
 |           if (event.xbutton.button != Button1) | 
 |             break; | 
 |           if (event.xbutton.window != windows->image.id) | 
 |             break; | 
 |           /* | 
 |             exit loop. | 
 |           */ | 
 |           x=event.xbutton.x; | 
 |           y=event.xbutton.y; | 
 |           state|=ExitState; | 
 |           break; | 
 |         } | 
 |         case ButtonRelease: | 
 |           break; | 
 |         case Expose: | 
 |           break; | 
 |         case KeyPress: | 
 |         { | 
 |           KeySym | 
 |             key_symbol; | 
 |  | 
 |           if (event.xkey.window != windows->image.id) | 
 |             break; | 
 |           /* | 
 |             Respond to a user key press. | 
 |           */ | 
 |           (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |             sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |           switch ((int) key_symbol) | 
 |           { | 
 |             case XK_Escape: | 
 |             case XK_F20: | 
 |             { | 
 |               /* | 
 |                 Prematurely exit. | 
 |               */ | 
 |               state|=EscapeState; | 
 |               state|=ExitState; | 
 |               break; | 
 |             } | 
 |             case XK_F1: | 
 |             case XK_Help: | 
 |             { | 
 |               XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                 "Help Viewer - Image Rotation",ImageDrawHelp); | 
 |               break; | 
 |             } | 
 |             default: | 
 |             { | 
 |               (void) XBell(display,0); | 
 |               break; | 
 |             } | 
 |           } | 
 |           break; | 
 |         } | 
 |         case MotionNotify: | 
 |         { | 
 |           /* | 
 |             Map and unmap Info widget as text cursor crosses its boundaries. | 
 |           */ | 
 |           x=event.xmotion.x; | 
 |           y=event.xmotion.y; | 
 |           if (windows->info.mapped != MagickFalse) | 
 |             { | 
 |               if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                   (y < (int) (windows->info.y+windows->info.height))) | 
 |                 (void) XWithdrawWindow(display,windows->info.id, | 
 |                   windows->info.screen); | 
 |             } | 
 |           else | 
 |             if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |                 (y > (int) (windows->info.y+windows->info.height))) | 
 |               (void) XMapWindow(display,windows->info.id); | 
 |           break; | 
 |         } | 
 |       } | 
 |     } while ((state & ExitState) == 0); | 
 |     (void) XSelectInput(display,windows->image.id, | 
 |       windows->image.attributes.event_mask); | 
 |     (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |     if ((state & EscapeState) != 0) | 
 |       break; | 
 |     /* | 
 |       Draw element as pointer moves until the button is released. | 
 |     */ | 
 |     distance=0; | 
 |     degrees=0.0; | 
 |     line_info.x1=x; | 
 |     line_info.y1=y; | 
 |     line_info.x2=x; | 
 |     line_info.y2=y; | 
 |     rectangle_info.x=(ssize_t) x; | 
 |     rectangle_info.y=(ssize_t) y; | 
 |     rectangle_info.width=0; | 
 |     rectangle_info.height=0; | 
 |     number_coordinates=1; | 
 |     coordinate_info->x=x; | 
 |     coordinate_info->y=y; | 
 |     (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |     state=DefaultState; | 
 |     do | 
 |     { | 
 |       switch (element) | 
 |       { | 
 |         case PointElement: | 
 |         default: | 
 |         { | 
 |           if (number_coordinates > 1) | 
 |             { | 
 |               (void) XDrawLines(display,windows->image.id, | 
 |                 windows->image.highlight_context,coordinate_info, | 
 |                 number_coordinates,CoordModeOrigin); | 
 |               (void) FormatLocaleString(text,MaxTextExtent," %+d%+d", | 
 |                 coordinate_info[number_coordinates-1].x, | 
 |                 coordinate_info[number_coordinates-1].y); | 
 |               XInfoWidget(display,windows,text); | 
 |             } | 
 |           break; | 
 |         } | 
 |         case LineElement: | 
 |         { | 
 |           if (distance > 9) | 
 |             { | 
 |               /* | 
 |                 Display angle of the line. | 
 |               */ | 
 |               degrees=RadiansToDegrees(-atan2((double) (line_info.y2- | 
 |                 line_info.y1),(double) (line_info.x2-line_info.x1))); | 
 |               (void) FormatLocaleString(text,MaxTextExtent," %g", | 
 |                 (double) degrees); | 
 |               XInfoWidget(display,windows,text); | 
 |               XHighlightLine(display,windows->image.id, | 
 |                 windows->image.highlight_context,&line_info); | 
 |             } | 
 |           else | 
 |             if (windows->info.mapped != MagickFalse) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           break; | 
 |         } | 
 |         case RectangleElement: | 
 |         case FillRectangleElement: | 
 |         { | 
 |           if ((rectangle_info.width > 3) && (rectangle_info.height > 3)) | 
 |             { | 
 |               /* | 
 |                 Display info and draw drawing rectangle. | 
 |               */ | 
 |               (void) FormatLocaleString(text,MaxTextExtent, | 
 |                 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width, | 
 |                 (double) rectangle_info.height,(double) rectangle_info.x, | 
 |                 (double) rectangle_info.y); | 
 |               XInfoWidget(display,windows,text); | 
 |               XHighlightRectangle(display,windows->image.id, | 
 |                 windows->image.highlight_context,&rectangle_info); | 
 |             } | 
 |           else | 
 |             if (windows->info.mapped != MagickFalse) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           break; | 
 |         } | 
 |         case CircleElement: | 
 |         case FillCircleElement: | 
 |         case EllipseElement: | 
 |         case FillEllipseElement: | 
 |         { | 
 |           if ((rectangle_info.width > 3) && (rectangle_info.height > 3)) | 
 |             { | 
 |               /* | 
 |                 Display info and draw drawing rectangle. | 
 |               */ | 
 |               (void) FormatLocaleString(text,MaxTextExtent, | 
 |                 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width, | 
 |                 (double) rectangle_info.height,(double) rectangle_info.x, | 
 |                 (double) rectangle_info.y); | 
 |               XInfoWidget(display,windows,text); | 
 |               XHighlightEllipse(display,windows->image.id, | 
 |                 windows->image.highlight_context,&rectangle_info); | 
 |             } | 
 |           else | 
 |             if (windows->info.mapped != MagickFalse) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           break; | 
 |         } | 
 |         case PolygonElement: | 
 |         case FillPolygonElement: | 
 |         { | 
 |           if (number_coordinates > 1) | 
 |             (void) XDrawLines(display,windows->image.id, | 
 |               windows->image.highlight_context,coordinate_info, | 
 |               number_coordinates,CoordModeOrigin); | 
 |           if (distance > 9) | 
 |             { | 
 |               /* | 
 |                 Display angle of the line. | 
 |               */ | 
 |               degrees=RadiansToDegrees(-atan2((double) (line_info.y2- | 
 |                 line_info.y1),(double) (line_info.x2-line_info.x1))); | 
 |               (void) FormatLocaleString(text,MaxTextExtent," %g", | 
 |                 (double) degrees); | 
 |               XInfoWidget(display,windows,text); | 
 |               XHighlightLine(display,windows->image.id, | 
 |                 windows->image.highlight_context,&line_info); | 
 |             } | 
 |           else | 
 |             if (windows->info.mapped != MagickFalse) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           break; | 
 |         } | 
 |       } | 
 |       /* | 
 |         Wait for next event. | 
 |       */ | 
 |       XScreenEvent(display,windows,&event,exception); | 
 |       switch (element) | 
 |       { | 
 |         case PointElement: | 
 |         default: | 
 |         { | 
 |           if (number_coordinates > 1) | 
 |             (void) XDrawLines(display,windows->image.id, | 
 |               windows->image.highlight_context,coordinate_info, | 
 |               number_coordinates,CoordModeOrigin); | 
 |           break; | 
 |         } | 
 |         case LineElement: | 
 |         { | 
 |           if (distance > 9) | 
 |             XHighlightLine(display,windows->image.id, | 
 |               windows->image.highlight_context,&line_info); | 
 |           break; | 
 |         } | 
 |         case RectangleElement: | 
 |         case FillRectangleElement: | 
 |         { | 
 |           if ((rectangle_info.width > 3) && (rectangle_info.height > 3)) | 
 |             XHighlightRectangle(display,windows->image.id, | 
 |               windows->image.highlight_context,&rectangle_info); | 
 |           break; | 
 |         } | 
 |         case CircleElement: | 
 |         case FillCircleElement: | 
 |         case EllipseElement: | 
 |         case FillEllipseElement: | 
 |         { | 
 |           if ((rectangle_info.width > 3) && (rectangle_info.height > 3)) | 
 |             XHighlightEllipse(display,windows->image.id, | 
 |               windows->image.highlight_context,&rectangle_info); | 
 |           break; | 
 |         } | 
 |         case PolygonElement: | 
 |         case FillPolygonElement: | 
 |         { | 
 |           if (number_coordinates > 1) | 
 |             (void) XDrawLines(display,windows->image.id, | 
 |               windows->image.highlight_context,coordinate_info, | 
 |               number_coordinates,CoordModeOrigin); | 
 |           if (distance > 9) | 
 |             XHighlightLine(display,windows->image.id, | 
 |               windows->image.highlight_context,&line_info); | 
 |           break; | 
 |         } | 
 |       } | 
 |       switch (event.type) | 
 |       { | 
 |         case ButtonPress: | 
 |           break; | 
 |         case ButtonRelease: | 
 |         { | 
 |           /* | 
 |             User has committed to element. | 
 |           */ | 
 |           line_info.x2=event.xbutton.x; | 
 |           line_info.y2=event.xbutton.y; | 
 |           rectangle_info.x=(ssize_t) event.xbutton.x; | 
 |           rectangle_info.y=(ssize_t) event.xbutton.y; | 
 |           coordinate_info[number_coordinates].x=event.xbutton.x; | 
 |           coordinate_info[number_coordinates].y=event.xbutton.y; | 
 |           if (((element != PolygonElement) && | 
 |                (element != FillPolygonElement)) || (distance <= 9)) | 
 |             { | 
 |               state|=ExitState; | 
 |               break; | 
 |             } | 
 |           number_coordinates++; | 
 |           if (number_coordinates < (int) max_coordinates) | 
 |             { | 
 |               line_info.x1=event.xbutton.x; | 
 |               line_info.y1=event.xbutton.y; | 
 |               break; | 
 |             } | 
 |           max_coordinates<<=1; | 
 |           coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info, | 
 |             max_coordinates,sizeof(*coordinate_info)); | 
 |           if (coordinate_info == (XPoint *) NULL) | 
 |             (void) ThrowMagickException(exception,GetMagickModule(), | 
 |               ResourceLimitError,"MemoryAllocationFailed","`%s'","..."); | 
 |           break; | 
 |         } | 
 |         case Expose: | 
 |           break; | 
 |         case MotionNotify: | 
 |         { | 
 |           if (event.xmotion.window != windows->image.id) | 
 |             break; | 
 |           if (element != PointElement) | 
 |             { | 
 |               line_info.x2=event.xmotion.x; | 
 |               line_info.y2=event.xmotion.y; | 
 |               rectangle_info.x=(ssize_t) event.xmotion.x; | 
 |               rectangle_info.y=(ssize_t) event.xmotion.y; | 
 |               break; | 
 |             } | 
 |           coordinate_info[number_coordinates].x=event.xbutton.x; | 
 |           coordinate_info[number_coordinates].y=event.xbutton.y; | 
 |           number_coordinates++; | 
 |           if (number_coordinates < (int) max_coordinates) | 
 |             break; | 
 |           max_coordinates<<=1; | 
 |           coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info, | 
 |             max_coordinates,sizeof(*coordinate_info)); | 
 |           if (coordinate_info == (XPoint *) NULL) | 
 |             (void) ThrowMagickException(exception,GetMagickModule(), | 
 |               ResourceLimitError,"MemoryAllocationFailed","`%s'","..."); | 
 |           break; | 
 |         } | 
 |         default: | 
 |           break; | 
 |       } | 
 |       /* | 
 |         Check boundary conditions. | 
 |       */ | 
 |       if (line_info.x2 < 0) | 
 |         line_info.x2=0; | 
 |       else | 
 |         if (line_info.x2 > (int) windows->image.width) | 
 |           line_info.x2=(short) windows->image.width; | 
 |       if (line_info.y2 < 0) | 
 |         line_info.y2=0; | 
 |       else | 
 |         if (line_info.y2 > (int) windows->image.height) | 
 |           line_info.y2=(short) windows->image.height; | 
 |       distance=(unsigned int) | 
 |         (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+ | 
 |          ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1))); | 
 |       if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) || | 
 |           ((state & ExitState) != 0)) | 
 |         { | 
 |           if (rectangle_info.x < 0) | 
 |             rectangle_info.x=0; | 
 |           else | 
 |             if (rectangle_info.x > (ssize_t) windows->image.width) | 
 |               rectangle_info.x=(ssize_t) windows->image.width; | 
 |           if ((int) rectangle_info.x < x) | 
 |             rectangle_info.width=(unsigned int) (x-rectangle_info.x); | 
 |           else | 
 |             { | 
 |               rectangle_info.width=(unsigned int) (rectangle_info.x-x); | 
 |               rectangle_info.x=(ssize_t) x; | 
 |             } | 
 |           if (rectangle_info.y < 0) | 
 |             rectangle_info.y=0; | 
 |           else | 
 |             if (rectangle_info.y > (ssize_t) windows->image.height) | 
 |               rectangle_info.y=(ssize_t) windows->image.height; | 
 |           if ((int) rectangle_info.y < y) | 
 |             rectangle_info.height=(unsigned int) (y-rectangle_info.y); | 
 |           else | 
 |             { | 
 |               rectangle_info.height=(unsigned int) (rectangle_info.y-y); | 
 |               rectangle_info.y=(ssize_t) y; | 
 |             } | 
 |         } | 
 |     } while ((state & ExitState) == 0); | 
 |     (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |     if ((element == PointElement) || (element == PolygonElement) || | 
 |         (element == FillPolygonElement)) | 
 |       { | 
 |         /* | 
 |           Determine polygon bounding box. | 
 |         */ | 
 |         rectangle_info.x=(ssize_t) coordinate_info->x; | 
 |         rectangle_info.y=(ssize_t) coordinate_info->y; | 
 |         x=coordinate_info->x; | 
 |         y=coordinate_info->y; | 
 |         for (i=1; i < number_coordinates; i++) | 
 |         { | 
 |           if (coordinate_info[i].x > x) | 
 |             x=coordinate_info[i].x; | 
 |           if (coordinate_info[i].y > y) | 
 |             y=coordinate_info[i].y; | 
 |           if ((ssize_t) coordinate_info[i].x < rectangle_info.x) | 
 |             rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0); | 
 |           if ((ssize_t) coordinate_info[i].y < rectangle_info.y) | 
 |             rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0); | 
 |         } | 
 |         rectangle_info.width=(size_t) (x-rectangle_info.x); | 
 |         rectangle_info.height=(size_t) (y-rectangle_info.y); | 
 |         for (i=0; i < number_coordinates; i++) | 
 |         { | 
 |           coordinate_info[i].x-=rectangle_info.x; | 
 |           coordinate_info[i].y-=rectangle_info.y; | 
 |         } | 
 |       } | 
 |     else | 
 |       if (distance <= 9) | 
 |         continue; | 
 |       else | 
 |         if ((element == RectangleElement) || | 
 |             (element == CircleElement) || (element == EllipseElement)) | 
 |           { | 
 |             rectangle_info.width--; | 
 |             rectangle_info.height--; | 
 |           } | 
 |     /* | 
 |       Drawing is relative to image configuration. | 
 |     */ | 
 |     draw_info.x=(int) rectangle_info.x; | 
 |     draw_info.y=(int) rectangle_info.y; | 
 |     (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand, | 
 |       image,exception); | 
 |     width=(unsigned int) (*image)->columns; | 
 |     height=(unsigned int) (*image)->rows; | 
 |     x=0; | 
 |     y=0; | 
 |     if (windows->image.crop_geometry != (char *) NULL) | 
 |       (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |     draw_info.x+=windows->image.x-(line_width/2); | 
 |     if (draw_info.x < 0) | 
 |       draw_info.x=0; | 
 |     draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width); | 
 |     draw_info.y+=windows->image.y-(line_width/2); | 
 |     if (draw_info.y < 0) | 
 |       draw_info.y=0; | 
 |     draw_info.y=(int) height*draw_info.y/windows->image.ximage->height; | 
 |     draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1); | 
 |     if (draw_info.width > (unsigned int) (*image)->columns) | 
 |       draw_info.width=(unsigned int) (*image)->columns; | 
 |     draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1); | 
 |     if (draw_info.height > (unsigned int) (*image)->rows) | 
 |       draw_info.height=(unsigned int) (*image)->rows; | 
 |     (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d", | 
 |       width*draw_info.width/windows->image.ximage->width, | 
 |       height*draw_info.height/windows->image.ximage->height, | 
 |       draw_info.x+x,draw_info.y+y); | 
 |     /* | 
 |       Initialize drawing attributes. | 
 |     */ | 
 |     draw_info.degrees=0.0; | 
 |     draw_info.element=element; | 
 |     draw_info.stipple=stipple; | 
 |     draw_info.line_width=line_width; | 
 |     draw_info.line_info=line_info; | 
 |     if (line_info.x1 > (int) (line_width/2)) | 
 |       draw_info.line_info.x1=(short) line_width/2; | 
 |     if (line_info.y1 > (int) (line_width/2)) | 
 |       draw_info.line_info.y1=(short) line_width/2; | 
 |     draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2)); | 
 |     draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2)); | 
 |     if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0)) | 
 |       { | 
 |         draw_info.line_info.x2=(-draw_info.line_info.x2); | 
 |         draw_info.line_info.y2=(-draw_info.line_info.y2); | 
 |       } | 
 |     if (draw_info.line_info.x2 < 0) | 
 |       { | 
 |         draw_info.line_info.x2=(-draw_info.line_info.x2); | 
 |         Swap(draw_info.line_info.x1,draw_info.line_info.x2); | 
 |       } | 
 |     if (draw_info.line_info.y2 < 0) | 
 |       { | 
 |         draw_info.line_info.y2=(-draw_info.line_info.y2); | 
 |         Swap(draw_info.line_info.y1,draw_info.line_info.y2); | 
 |       } | 
 |     draw_info.rectangle_info=rectangle_info; | 
 |     if (draw_info.rectangle_info.x > (ssize_t) (line_width/2)) | 
 |       draw_info.rectangle_info.x=(ssize_t) line_width/2; | 
 |     if (draw_info.rectangle_info.y > (ssize_t) (line_width/2)) | 
 |       draw_info.rectangle_info.y=(ssize_t) line_width/2; | 
 |     draw_info.number_coordinates=(unsigned int) number_coordinates; | 
 |     draw_info.coordinate_info=coordinate_info; | 
 |     windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id]; | 
 |     /* | 
 |       Draw element on image. | 
 |     */ | 
 |     XSetCursorState(display,windows,MagickTrue); | 
 |     XCheckRefreshWindows(display,windows); | 
 |     status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception); | 
 |     XSetCursorState(display,windows,MagickFalse); | 
 |     /* | 
 |       Update image colormap and return to image drawing. | 
 |     */ | 
 |     XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |     (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |   } | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info); | 
 |   return(status != 0 ? MagickTrue : MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X D r a w P a n R e c t a n g l e                                         % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XDrawPanRectangle() draws a rectangle in the pan window.  The pan window | 
 | %  displays a zoom image and the rectangle shows which portion of the image is | 
 | %  displayed in the Image window. | 
 | % | 
 | %  The format of the XDrawPanRectangle method is: | 
 | % | 
 | %      XDrawPanRectangle(Display *display,XWindows *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 XWindows structure. | 
 | % | 
 | */ | 
 | static void XDrawPanRectangle(Display *display,XWindows *windows) | 
 | { | 
 |   MagickRealType | 
 |     scale_factor; | 
 |  | 
 |   RectangleInfo | 
 |     highlight_info; | 
 |  | 
 |   /* | 
 |     Determine dimensions of the panning rectangle. | 
 |   */ | 
 |   scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width; | 
 |   highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5); | 
 |   highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5); | 
 |   scale_factor=(MagickRealType) | 
 |     windows->pan.height/windows->image.ximage->height; | 
 |   highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5); | 
 |   highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5); | 
 |   /* | 
 |     Display the panning rectangle. | 
 |   */ | 
 |   (void) XClearWindow(display,windows->pan.id); | 
 |   XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context, | 
 |     &highlight_info); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X I m a g e C a c h e                                                     % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XImageCache() handles the creation, manipulation, and destruction of the | 
 | %  image cache (undo and redo buffers). | 
 | % | 
 | %  The format of the XImageCache method is: | 
 | % | 
 | %      void XImageCache(Display *display,XResourceInfo *resource_info, | 
 | %        XWindows *windows,const CommandType command,Image **image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o command: Specifies a command to perform. | 
 | % | 
 | %    o image: the image;  XImageCache may transform the image and return a new | 
 | %      image pointer. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static void XImageCache(Display *display,XResourceInfo *resource_info, | 
 |   XWindows *windows,const CommandType command,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   Image | 
 |     *cache_image; | 
 |  | 
 |   static Image | 
 |     *redo_image = (Image *) NULL, | 
 |     *undo_image = (Image *) NULL; | 
 |  | 
 |   switch (command) | 
 |   { | 
 |     case FreeBuffersCommand: | 
 |     { | 
 |       /* | 
 |         Free memory from the undo and redo cache. | 
 |       */ | 
 |       while (undo_image != (Image *) NULL) | 
 |       { | 
 |         cache_image=undo_image; | 
 |         undo_image=GetPreviousImageInList(undo_image); | 
 |         cache_image->list=DestroyImage(cache_image->list); | 
 |         cache_image=DestroyImage(cache_image); | 
 |       } | 
 |       undo_image=NewImageList(); | 
 |       if (redo_image != (Image *) NULL) | 
 |         redo_image=DestroyImage(redo_image); | 
 |       redo_image=NewImageList(); | 
 |       return; | 
 |     } | 
 |     case UndoCommand: | 
 |     { | 
 |       char | 
 |         image_geometry[MaxTextExtent]; | 
 |  | 
 |       /* | 
 |         Undo the last image transformation. | 
 |       */ | 
 |       if (undo_image == (Image *) NULL) | 
 |         { | 
 |           (void) XBell(display,0); | 
 |           return; | 
 |         } | 
 |       cache_image=undo_image; | 
 |       undo_image=GetPreviousImageInList(undo_image); | 
 |       windows->image.window_changes.width=(int) cache_image->columns; | 
 |       windows->image.window_changes.height=(int) cache_image->rows; | 
 |       (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!", | 
 |         windows->image.ximage->width,windows->image.ximage->height); | 
 |       (void) TransformImage(image,windows->image.crop_geometry,image_geometry, | 
 |         exception); | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         windows->image.crop_geometry=(char *) RelinquishMagickMemory( | 
 |           windows->image.crop_geometry); | 
 |       windows->image.crop_geometry=cache_image->geometry; | 
 |       if (redo_image != (Image *) NULL) | 
 |         redo_image=DestroyImage(redo_image); | 
 |       redo_image=(*image); | 
 |       *image=cache_image->list; | 
 |       cache_image=DestroyImage(cache_image); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         return; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       return; | 
 |     } | 
 |     case CutCommand: | 
 |     case PasteCommand: | 
 |     case ApplyCommand: | 
 |     case HalfSizeCommand: | 
 |     case OriginalSizeCommand: | 
 |     case DoubleSizeCommand: | 
 |     case ResizeCommand: | 
 |     case TrimCommand: | 
 |     case CropCommand: | 
 |     case ChopCommand: | 
 |     case FlipCommand: | 
 |     case FlopCommand: | 
 |     case RotateRightCommand: | 
 |     case RotateLeftCommand: | 
 |     case RotateCommand: | 
 |     case ShearCommand: | 
 |     case RollCommand: | 
 |     case NegateCommand: | 
 |     case ContrastStretchCommand: | 
 |     case SigmoidalContrastCommand: | 
 |     case NormalizeCommand: | 
 |     case EqualizeCommand: | 
 |     case HueCommand: | 
 |     case SaturationCommand: | 
 |     case BrightnessCommand: | 
 |     case GammaCommand: | 
 |     case SpiffCommand: | 
 |     case DullCommand: | 
 |     case GrayscaleCommand: | 
 |     case MapCommand: | 
 |     case QuantizeCommand: | 
 |     case DespeckleCommand: | 
 |     case EmbossCommand: | 
 |     case ReduceNoiseCommand: | 
 |     case AddNoiseCommand: | 
 |     case SharpenCommand: | 
 |     case BlurCommand: | 
 |     case ThresholdCommand: | 
 |     case EdgeDetectCommand: | 
 |     case SpreadCommand: | 
 |     case ShadeCommand: | 
 |     case RaiseCommand: | 
 |     case SegmentCommand: | 
 |     case SolarizeCommand: | 
 |     case SepiaToneCommand: | 
 |     case SwirlCommand: | 
 |     case ImplodeCommand: | 
 |     case VignetteCommand: | 
 |     case WaveCommand: | 
 |     case OilPaintCommand: | 
 |     case CharcoalDrawCommand: | 
 |     case AnnotateCommand: | 
 |     case AddBorderCommand: | 
 |     case AddFrameCommand: | 
 |     case CompositeCommand: | 
 |     case CommentCommand: | 
 |     case LaunchCommand: | 
 |     case RegionofInterestCommand: | 
 |     case SaveToUndoBufferCommand: | 
 |     case RedoCommand: | 
 |     { | 
 |       Image | 
 |         *previous_image; | 
 |  | 
 |       ssize_t | 
 |         bytes; | 
 |  | 
 |       bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo)); | 
 |       if (undo_image != (Image *) NULL) | 
 |         { | 
 |           /* | 
 |             Ensure the undo cache has enough memory available. | 
 |           */ | 
 |           previous_image=undo_image; | 
 |           while (previous_image != (Image *) NULL) | 
 |           { | 
 |             bytes+=previous_image->list->columns*previous_image->list->rows* | 
 |               sizeof(PixelInfo); | 
 |             if (bytes <= (ssize_t) (resource_info->undo_cache << 20)) | 
 |               { | 
 |                 previous_image=GetPreviousImageInList(previous_image); | 
 |                 continue; | 
 |               } | 
 |             bytes-=previous_image->list->columns*previous_image->list->rows* | 
 |               sizeof(PixelInfo); | 
 |             if (previous_image == undo_image) | 
 |               undo_image=NewImageList(); | 
 |             else | 
 |               previous_image->next->previous=NewImageList(); | 
 |             break; | 
 |           } | 
 |           while (previous_image != (Image *) NULL) | 
 |           { | 
 |             /* | 
 |               Delete any excess memory from undo cache. | 
 |             */ | 
 |             cache_image=previous_image; | 
 |             previous_image=GetPreviousImageInList(previous_image); | 
 |             cache_image->list=DestroyImage(cache_image->list); | 
 |             cache_image=DestroyImage(cache_image); | 
 |           } | 
 |         } | 
 |       if (bytes > (ssize_t) (resource_info->undo_cache << 20)) | 
 |         break; | 
 |       /* | 
 |         Save image before transformations are applied. | 
 |       */ | 
 |       cache_image=AcquireImage((ImageInfo *) NULL,exception); | 
 |       if (cache_image == (Image *) NULL) | 
 |         break; | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       cache_image->list=CloneImage(*image,0,0,MagickTrue,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (cache_image->list == (Image *) NULL) | 
 |         { | 
 |           cache_image=DestroyImage(cache_image); | 
 |           break; | 
 |         } | 
 |       cache_image->columns=(size_t) windows->image.ximage->width; | 
 |       cache_image->rows=(size_t) windows->image.ximage->height; | 
 |       cache_image->geometry=windows->image.crop_geometry; | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         { | 
 |           cache_image->geometry=AcquireString((char *) NULL); | 
 |           (void) CopyMagickString(cache_image->geometry, | 
 |             windows->image.crop_geometry,MaxTextExtent); | 
 |         } | 
 |       if (undo_image == (Image *) NULL) | 
 |         { | 
 |           undo_image=cache_image; | 
 |           break; | 
 |         } | 
 |       undo_image->next=cache_image; | 
 |       undo_image->next->previous=undo_image; | 
 |       undo_image=undo_image->next; | 
 |       break; | 
 |     } | 
 |     default: | 
 |       break; | 
 |   } | 
 |   if (command == RedoCommand) | 
 |     { | 
 |       /* | 
 |         Redo the last image transformation. | 
 |       */ | 
 |       if (redo_image == (Image *) NULL) | 
 |         { | 
 |           (void) XBell(display,0); | 
 |           return; | 
 |         } | 
 |       windows->image.window_changes.width=(int) redo_image->columns; | 
 |       windows->image.window_changes.height=(int) redo_image->rows; | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         windows->image.crop_geometry=(char *) | 
 |           RelinquishMagickMemory(windows->image.crop_geometry); | 
 |       windows->image.crop_geometry=redo_image->geometry; | 
 |       *image=DestroyImage(*image); | 
 |       *image=redo_image; | 
 |       redo_image=NewImageList(); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         return; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       return; | 
 |     } | 
 |   if (command != InfoCommand) | 
 |     return; | 
 |   /* | 
 |     Display image info. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X I m a g e W i n d o w C o m m a n d                                     % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XImageWindowCommand() makes a transform to the image or Image window as | 
 | %  specified by a user menu button or keyboard command. | 
 | % | 
 | %  The format of the XImageWindowCommand method is: | 
 | % | 
 | %      CommandType XImageWindowCommand(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows, | 
 | %        const MagickStatusType state,KeySym key_symbol,Image **image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o nexus:  Method XImageWindowCommand returns an image when the | 
 | %      user chooses 'Open Image' from the command menu.  Otherwise a null | 
 | %      image is returned. | 
 | % | 
 | %    o display: Specifies a connection to an X server; returned from | 
 | %      XOpenDisplay. | 
 | % | 
 | %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure. | 
 | % | 
 | %    o windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o state: key mask. | 
 | % | 
 | %    o key_symbol: Specifies a command to perform. | 
 | % | 
 | %    o image: the image;  XImageWIndowCommand may transform the image and | 
 | %      return a new image pointer. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static CommandType XImageWindowCommand(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state, | 
 |   KeySym key_symbol,Image **image,ExceptionInfo *exception) | 
 | { | 
 |   static char | 
 |     delta[MaxTextExtent] = ""; | 
 |  | 
 |   static const char | 
 |     Digits[] = "01234567890"; | 
 |  | 
 |   static KeySym | 
 |     last_symbol = XK_0; | 
 |  | 
 |   if ((key_symbol >= XK_0) && (key_symbol <= XK_9)) | 
 |     { | 
 |       if (((last_symbol < XK_0) || (last_symbol > XK_9))) | 
 |         { | 
 |           *delta='\0'; | 
 |           resource_info->quantum=1; | 
 |         } | 
 |       last_symbol=key_symbol; | 
 |       delta[strlen(delta)+1]='\0'; | 
 |       delta[strlen(delta)]=Digits[key_symbol-XK_0]; | 
 |       resource_info->quantum=StringToLong(delta); | 
 |       return(NullCommand); | 
 |     } | 
 |   last_symbol=key_symbol; | 
 |   if (resource_info->immutable) | 
 |     { | 
 |       /* | 
 |         Virtual image window has a restricted command set. | 
 |       */ | 
 |       switch (key_symbol) | 
 |       { | 
 |         case XK_question: | 
 |           return(InfoCommand); | 
 |         case XK_p: | 
 |         case XK_Print: | 
 |           return(PrintCommand); | 
 |         case XK_space: | 
 |           return(NextCommand); | 
 |         case XK_q: | 
 |         case XK_Escape: | 
 |           return(QuitCommand); | 
 |         default: | 
 |           break; | 
 |       } | 
 |       return(NullCommand); | 
 |     } | 
 |   switch ((int) key_symbol) | 
 |   { | 
 |     case XK_o: | 
 |     { | 
 |       if ((state & ControlMask) == 0) | 
 |         break; | 
 |       return(OpenCommand); | 
 |     } | 
 |     case XK_space: | 
 |       return(NextCommand); | 
 |     case XK_BackSpace: | 
 |       return(FormerCommand); | 
 |     case XK_s: | 
 |     { | 
 |       if ((state & Mod1Mask) != 0) | 
 |         return(SwirlCommand); | 
 |       if ((state & ControlMask) == 0) | 
 |         return(ShearCommand); | 
 |       return(SaveCommand); | 
 |     } | 
 |     case XK_p: | 
 |     case XK_Print: | 
 |     { | 
 |       if ((state & Mod1Mask) != 0) | 
 |         return(OilPaintCommand); | 
 |       if ((state & Mod4Mask) != 0) | 
 |         return(ColorCommand); | 
 |       if ((state & ControlMask) == 0) | 
 |         return(NullCommand); | 
 |       return(PrintCommand); | 
 |     } | 
 |     case XK_d: | 
 |     { | 
 |       if ((state & Mod4Mask) != 0) | 
 |         return(DrawCommand); | 
 |       if ((state & ControlMask) == 0) | 
 |         return(NullCommand); | 
 |       return(DeleteCommand); | 
 |     } | 
 |     case XK_Select: | 
 |     { | 
 |       if ((state & ControlMask) == 0) | 
 |         return(NullCommand); | 
 |       return(SelectCommand); | 
 |     } | 
 |     case XK_n: | 
 |     { | 
 |       if ((state & ControlMask) == 0) | 
 |         return(NullCommand); | 
 |       return(NewCommand); | 
 |     } | 
 |     case XK_q: | 
 |     case XK_Escape: | 
 |       return(QuitCommand); | 
 |     case XK_z: | 
 |     case XK_Undo: | 
 |     { | 
 |       if ((state & ControlMask) == 0) | 
 |         return(NullCommand); | 
 |       return(UndoCommand); | 
 |     } | 
 |     case XK_r: | 
 |     case XK_Redo: | 
 |     { | 
 |       if ((state & ControlMask) == 0) | 
 |         return(RollCommand); | 
 |       return(RedoCommand); | 
 |     } | 
 |     case XK_x: | 
 |     { | 
 |       if ((state & ControlMask) == 0) | 
 |         return(NullCommand); | 
 |       return(CutCommand); | 
 |     } | 
 |     case XK_c: | 
 |     { | 
 |       if ((state & Mod1Mask) != 0) | 
 |         return(CharcoalDrawCommand); | 
 |       if ((state & ControlMask) == 0) | 
 |         return(CropCommand); | 
 |       return(CopyCommand); | 
 |     } | 
 |     case XK_v: | 
 |     case XK_Insert: | 
 |     { | 
 |       if ((state & Mod4Mask) != 0) | 
 |         return(CompositeCommand); | 
 |       if ((state & ControlMask) == 0) | 
 |         return(FlipCommand); | 
 |       return(PasteCommand); | 
 |     } | 
 |     case XK_less: | 
 |       return(HalfSizeCommand); | 
 |     case XK_minus: | 
 |       return(OriginalSizeCommand); | 
 |     case XK_greater: | 
 |       return(DoubleSizeCommand); | 
 |     case XK_percent: | 
 |       return(ResizeCommand); | 
 |     case XK_at: | 
 |       return(RefreshCommand); | 
 |     case XK_bracketleft: | 
 |       return(ChopCommand); | 
 |     case XK_h: | 
 |       return(FlopCommand); | 
 |     case XK_slash: | 
 |       return(RotateRightCommand); | 
 |     case XK_backslash: | 
 |       return(RotateLeftCommand); | 
 |     case XK_asterisk: | 
 |       return(RotateCommand); | 
 |     case XK_t: | 
 |       return(TrimCommand); | 
 |     case XK_H: | 
 |       return(HueCommand); | 
 |     case XK_S: | 
 |       return(SaturationCommand); | 
 |     case XK_L: | 
 |       return(BrightnessCommand); | 
 |     case XK_G: | 
 |       return(GammaCommand); | 
 |     case XK_C: | 
 |       return(SpiffCommand); | 
 |     case XK_Z: | 
 |       return(DullCommand); | 
 |     case XK_N: | 
 |       return(NormalizeCommand); | 
 |     case XK_equal: | 
 |       return(EqualizeCommand); | 
 |     case XK_asciitilde: | 
 |       return(NegateCommand); | 
 |     case XK_period: | 
 |       return(GrayscaleCommand); | 
 |     case XK_numbersign: | 
 |       return(QuantizeCommand); | 
 |     case XK_F2: | 
 |       return(DespeckleCommand); | 
 |     case XK_F3: | 
 |       return(EmbossCommand); | 
 |     case XK_F4: | 
 |       return(ReduceNoiseCommand); | 
 |     case XK_F5: | 
 |       return(AddNoiseCommand); | 
 |     case XK_F6: | 
 |       return(SharpenCommand); | 
 |     case XK_F7: | 
 |       return(BlurCommand); | 
 |     case XK_F8: | 
 |       return(ThresholdCommand); | 
 |     case XK_F9: | 
 |       return(EdgeDetectCommand); | 
 |     case XK_F10: | 
 |       return(SpreadCommand); | 
 |     case XK_F11: | 
 |       return(ShadeCommand); | 
 |     case XK_F12: | 
 |       return(RaiseCommand); | 
 |     case XK_F13: | 
 |       return(SegmentCommand); | 
 |     case XK_i: | 
 |     { | 
 |       if ((state & Mod1Mask) == 0) | 
 |         return(NullCommand); | 
 |       return(ImplodeCommand); | 
 |     } | 
 |     case XK_w: | 
 |     { | 
 |       if ((state & Mod1Mask) == 0) | 
 |         return(NullCommand); | 
 |       return(WaveCommand); | 
 |     } | 
 |     case XK_m: | 
 |     { | 
 |       if ((state & Mod4Mask) == 0) | 
 |         return(NullCommand); | 
 |       return(MatteCommand); | 
 |     } | 
 |     case XK_b: | 
 |     { | 
 |       if ((state & Mod4Mask) == 0) | 
 |         return(NullCommand); | 
 |       return(AddBorderCommand); | 
 |     } | 
 |     case XK_f: | 
 |     { | 
 |       if ((state & Mod4Mask) == 0) | 
 |         return(NullCommand); | 
 |       return(AddFrameCommand); | 
 |     } | 
 |     case XK_exclam: | 
 |     { | 
 |       if ((state & Mod4Mask) == 0) | 
 |         return(NullCommand); | 
 |       return(CommentCommand); | 
 |     } | 
 |     case XK_a: | 
 |     { | 
 |       if ((state & Mod1Mask) != 0) | 
 |         return(ApplyCommand); | 
 |       if ((state & Mod4Mask) != 0) | 
 |         return(AnnotateCommand); | 
 |       if ((state & ControlMask) == 0) | 
 |         return(NullCommand); | 
 |       return(RegionofInterestCommand); | 
 |     } | 
 |     case XK_question: | 
 |       return(InfoCommand); | 
 |     case XK_plus: | 
 |       return(ZoomCommand); | 
 |     case XK_P: | 
 |     { | 
 |       if ((state & ShiftMask) == 0) | 
 |         return(NullCommand); | 
 |       return(ShowPreviewCommand); | 
 |     } | 
 |     case XK_Execute: | 
 |       return(LaunchCommand); | 
 |     case XK_F1: | 
 |       return(HelpCommand); | 
 |     case XK_Find: | 
 |       return(BrowseDocumentationCommand); | 
 |     case XK_Menu: | 
 |     { | 
 |       (void) XMapRaised(display,windows->command.id); | 
 |       return(NullCommand); | 
 |     } | 
 |     case XK_Next: | 
 |     case XK_Prior: | 
 |     case XK_Home: | 
 |     case XK_KP_Home: | 
 |     { | 
 |       XTranslateImage(display,windows,*image,key_symbol); | 
 |       return(NullCommand); | 
 |     } | 
 |     case XK_Up: | 
 |     case XK_KP_Up: | 
 |     case XK_Down: | 
 |     case XK_KP_Down: | 
 |     case XK_Left: | 
 |     case XK_KP_Left: | 
 |     case XK_Right: | 
 |     case XK_KP_Right: | 
 |     { | 
 |       if ((state & Mod1Mask) != 0) | 
 |         { | 
 |           RectangleInfo | 
 |             crop_info; | 
 |  | 
 |           /* | 
 |             Trim one pixel from edge of image. | 
 |           */ | 
 |           crop_info.x=0; | 
 |           crop_info.y=0; | 
 |           crop_info.width=(size_t) windows->image.ximage->width; | 
 |           crop_info.height=(size_t) windows->image.ximage->height; | 
 |           if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up)) | 
 |             { | 
 |               if (resource_info->quantum >= (int) crop_info.height) | 
 |                 resource_info->quantum=(int) crop_info.height-1; | 
 |               crop_info.height-=resource_info->quantum; | 
 |             } | 
 |           if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down)) | 
 |             { | 
 |               if (resource_info->quantum >= (int) (crop_info.height-crop_info.y)) | 
 |                 resource_info->quantum=(int) (crop_info.height-crop_info.y-1); | 
 |               crop_info.y+=resource_info->quantum; | 
 |               crop_info.height-=resource_info->quantum; | 
 |             } | 
 |           if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left)) | 
 |             { | 
 |               if (resource_info->quantum >= (int) crop_info.width) | 
 |                 resource_info->quantum=(int) crop_info.width-1; | 
 |               crop_info.width-=resource_info->quantum; | 
 |             } | 
 |           if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right)) | 
 |             { | 
 |               if (resource_info->quantum >= (int) (crop_info.width-crop_info.x)) | 
 |                 resource_info->quantum=(int) (crop_info.width-crop_info.x-1); | 
 |               crop_info.x+=resource_info->quantum; | 
 |               crop_info.width-=resource_info->quantum; | 
 |             } | 
 |           if ((int) (windows->image.x+windows->image.width) > | 
 |               (int) crop_info.width) | 
 |             windows->image.x=(int) (crop_info.width-windows->image.width); | 
 |           if ((int) (windows->image.y+windows->image.height) > | 
 |               (int) crop_info.height) | 
 |             windows->image.y=(int) (crop_info.height-windows->image.height); | 
 |           XSetCropGeometry(display,windows,&crop_info,*image); | 
 |           windows->image.window_changes.width=(int) crop_info.width; | 
 |           windows->image.window_changes.height=(int) crop_info.height; | 
 |           (void) XSetWindowBackgroundPixmap(display,windows->image.id,None); | 
 |           (void) XConfigureImage(display,resource_info,windows,*image, | 
 |             exception); | 
 |           return(NullCommand); | 
 |         } | 
 |       XTranslateImage(display,windows,*image,key_symbol); | 
 |       return(NullCommand); | 
 |     } | 
 |     default: | 
 |       return(NullCommand); | 
 |   } | 
 |   return(NullCommand); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X M a g i c k C o m m a n d                                               % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XMagickCommand() makes a transform to the image or Image window as | 
 | %  specified by a user menu button or keyboard command. | 
 | % | 
 | %  The format of the XMagickCommand method is: | 
 | % | 
 | %      Image *XMagickCommand(Display *display,XResourceInfo *resource_info, | 
 | %        XWindows *windows,const CommandType command,Image **image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o command: Specifies a command to perform. | 
 | % | 
 | %    o image: the image;  XMagickCommand may transform the image and return a | 
 | %      new image pointer. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static Image *XMagickCommand(Display *display,XResourceInfo *resource_info, | 
 |   XWindows *windows,const CommandType command,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     filename[MaxTextExtent], | 
 |     geometry[MaxTextExtent], | 
 |     modulate_factors[MaxTextExtent]; | 
 |  | 
 |   GeometryInfo | 
 |     geometry_info; | 
 |  | 
 |   Image | 
 |     *nexus; | 
 |  | 
 |   ImageInfo | 
 |     *image_info; | 
 |  | 
 |   int | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickStatusType | 
 |     flags, | 
 |     status; | 
 |  | 
 |   QuantizeInfo | 
 |     quantize_info; | 
 |  | 
 |   RectangleInfo | 
 |     page_geometry; | 
 |  | 
 |   register int | 
 |     i; | 
 |  | 
 |   static char | 
 |     color[MaxTextExtent] = "gray"; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   /* | 
 |     Process user command. | 
 |   */ | 
 |   XCheckRefreshWindows(display,windows); | 
 |   XImageCache(display,resource_info,windows,command,image,exception); | 
 |   nexus=NewImageList(); | 
 |   windows->image.window_changes.width=windows->image.ximage->width; | 
 |   windows->image.window_changes.height=windows->image.ximage->height; | 
 |   image_info=CloneImageInfo(resource_info->image_info); | 
 |   SetGeometryInfo(&geometry_info); | 
 |   GetQuantizeInfo(&quantize_info); | 
 |   switch (command) | 
 |   { | 
 |     case OpenCommand: | 
 |     { | 
 |       /* | 
 |         Load image. | 
 |       */ | 
 |       nexus=XOpenImage(display,resource_info,windows,MagickFalse); | 
 |       break; | 
 |     } | 
 |     case NextCommand: | 
 |     { | 
 |       /* | 
 |         Display next image. | 
 |       */ | 
 |       for (i=0; i < resource_info->quantum; i++) | 
 |         XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |           windows->im_next_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case FormerCommand: | 
 |     { | 
 |       /* | 
 |         Display former image. | 
 |       */ | 
 |       for (i=0; i < resource_info->quantum; i++) | 
 |         XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |           windows->im_former_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case SelectCommand: | 
 |     { | 
 |       int | 
 |         status; | 
 |  | 
 |       /* | 
 |         Select image. | 
 |       */ | 
 |       status=chdir(resource_info->home_directory); | 
 |       if (status == -1) | 
 |         (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError, | 
 |           "UnableToOpenFile","%s",resource_info->home_directory); | 
 |       nexus=XOpenImage(display,resource_info,windows,MagickTrue); | 
 |       break; | 
 |     } | 
 |     case SaveCommand: | 
 |     { | 
 |       /* | 
 |         Save image. | 
 |       */ | 
 |       status=XSaveImage(display,resource_info,windows,*image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           char | 
 |             message[MaxTextExtent]; | 
 |  | 
 |           (void) FormatLocaleString(message,MaxTextExtent,"%s:%s", | 
 |             exception->reason != (char *) NULL ? exception->reason : "", | 
 |             exception->description != (char *) NULL ? exception->description : | 
 |             ""); | 
 |           XNoticeWidget(display,windows,"Unable to save file:",message); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case PrintCommand: | 
 |     { | 
 |       /* | 
 |         Print image. | 
 |       */ | 
 |       status=XPrintImage(display,resource_info,windows,*image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           char | 
 |             message[MaxTextExtent]; | 
 |  | 
 |           (void) FormatLocaleString(message,MaxTextExtent,"%s:%s", | 
 |             exception->reason != (char *) NULL ? exception->reason : "", | 
 |             exception->description != (char *) NULL ? exception->description : | 
 |             ""); | 
 |           XNoticeWidget(display,windows,"Unable to print file:",message); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case DeleteCommand: | 
 |     { | 
 |       static char | 
 |         filename[MaxTextExtent] = "\0"; | 
 |  | 
 |       /* | 
 |         Delete image file. | 
 |       */ | 
 |       XFileBrowserWidget(display,windows,"Delete",filename); | 
 |       if (*filename == '\0') | 
 |         break; | 
 |       status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse; | 
 |       if (status != MagickFalse) | 
 |         XNoticeWidget(display,windows,"Unable to delete image file:",filename); | 
 |       break; | 
 |     } | 
 |     case NewCommand: | 
 |     { | 
 |       int | 
 |         status; | 
 |  | 
 |       static char | 
 |         color[MaxTextExtent] = "gray", | 
 |         geometry[MaxTextExtent] = "640x480"; | 
 |  | 
 |       static const char | 
 |         *format = "gradient"; | 
 |  | 
 |       /* | 
 |         Query user for canvas geometry. | 
 |       */ | 
 |       status=XDialogWidget(display,windows,"New","Enter image geometry:", | 
 |         geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       if (status == 0) | 
 |         format="xc"; | 
 |       XColorBrowserWidget(display,windows,"Select",color); | 
 |       if (*color == '\0') | 
 |         break; | 
 |       /* | 
 |         Create canvas. | 
 |       */ | 
 |       (void) FormatLocaleString(image_info->filename,MaxTextExtent, | 
 |         "%s:%s",format,color); | 
 |       (void) CloneString(&image_info->size,geometry); | 
 |       nexus=ReadImage(image_info,exception); | 
 |       CatchException(exception); | 
 |       XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |         windows->im_next_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case VisualDirectoryCommand: | 
 |     { | 
 |       /* | 
 |         Visual Image directory. | 
 |       */ | 
 |       nexus=XVisualDirectoryImage(display,resource_info,windows,exception); | 
 |       break; | 
 |     } | 
 |     case QuitCommand: | 
 |     { | 
 |       /* | 
 |         exit program. | 
 |       */ | 
 |       if (resource_info->confirm_exit == MagickFalse) | 
 |         XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |           windows->im_exit,CurrentTime); | 
 |       else | 
 |         { | 
 |           int | 
 |             status; | 
 |  | 
 |           /* | 
 |             Confirm program exit. | 
 |           */ | 
 |           status=XConfirmWidget(display,windows,"Do you really want to exit", | 
 |             resource_info->client_name); | 
 |           if (status > 0) | 
 |             XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |               windows->im_exit,CurrentTime); | 
 |         } | 
 |       break; | 
 |     } | 
 |     case CutCommand: | 
 |     { | 
 |       /* | 
 |         Cut image. | 
 |       */ | 
 |       (void) XCropImage(display,resource_info,windows,*image,CutMode,exception); | 
 |       break; | 
 |     } | 
 |     case CopyCommand: | 
 |     { | 
 |       /* | 
 |         Copy image. | 
 |       */ | 
 |       (void) XCropImage(display,resource_info,windows,*image,CopyMode, | 
 |         exception); | 
 |       break; | 
 |     } | 
 |     case PasteCommand: | 
 |     { | 
 |       /* | 
 |         Paste image. | 
 |       */ | 
 |       status=XPasteImage(display,resource_info,windows,*image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to paste X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case HalfSizeCommand: | 
 |     { | 
 |       /* | 
 |         Half image size. | 
 |       */ | 
 |       windows->image.window_changes.width=windows->image.ximage->width/2; | 
 |       windows->image.window_changes.height=windows->image.ximage->height/2; | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case OriginalSizeCommand: | 
 |     { | 
 |       /* | 
 |         Original image size. | 
 |       */ | 
 |       windows->image.window_changes.width=(int) (*image)->columns; | 
 |       windows->image.window_changes.height=(int) (*image)->rows; | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case DoubleSizeCommand: | 
 |     { | 
 |       /* | 
 |         Double the image size. | 
 |       */ | 
 |       windows->image.window_changes.width=windows->image.ximage->width << 1; | 
 |       windows->image.window_changes.height=windows->image.ximage->height << 1; | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case ResizeCommand: | 
 |     { | 
 |       int | 
 |         status; | 
 |  | 
 |       size_t | 
 |         height, | 
 |         width; | 
 |  | 
 |       ssize_t | 
 |         x, | 
 |         y; | 
 |  | 
 |       /* | 
 |         Resize image. | 
 |       */ | 
 |       width=(size_t) windows->image.ximage->width; | 
 |       height=(size_t) windows->image.ximage->height; | 
 |       x=0; | 
 |       y=0; | 
 |       (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0", | 
 |         (double) width,(double) height); | 
 |       status=XDialogWidget(display,windows,"Resize", | 
 |         "Enter resize geometry (e.g. 640x480, 200%):",geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       if (status == 0) | 
 |         (void) ConcatenateMagickString(geometry,"!",MaxTextExtent); | 
 |       (void) ParseMetaGeometry(geometry,&x,&y,&width,&height); | 
 |       windows->image.window_changes.width=(int) width; | 
 |       windows->image.window_changes.height=(int) height; | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case ApplyCommand: | 
 |     { | 
 |       char | 
 |         image_geometry[MaxTextExtent]; | 
 |  | 
 |       if ((windows->image.crop_geometry == (char *) NULL) && | 
 |           ((int) (*image)->columns == windows->image.ximage->width) && | 
 |           ((int) (*image)->rows == windows->image.ximage->height)) | 
 |         break; | 
 |       /* | 
 |         Apply size transforms to image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       /* | 
 |         Crop and/or scale displayed image. | 
 |       */ | 
 |       (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!", | 
 |         windows->image.ximage->width,windows->image.ximage->height); | 
 |       (void) TransformImage(image,windows->image.crop_geometry,image_geometry, | 
 |         exception); | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         windows->image.crop_geometry=(char *) RelinquishMagickMemory( | 
 |           windows->image.crop_geometry); | 
 |       windows->image.x=0; | 
 |       windows->image.y=0; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case RefreshCommand: | 
 |     { | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case RestoreCommand: | 
 |     { | 
 |       /* | 
 |         Restore Image window to its original size. | 
 |       */ | 
 |       if ((windows->image.width == (unsigned int) (*image)->columns) && | 
 |           (windows->image.height == (unsigned int) (*image)->rows) && | 
 |           (windows->image.crop_geometry == (char *) NULL)) | 
 |         { | 
 |           (void) XBell(display,0); | 
 |           break; | 
 |         } | 
 |       windows->image.window_changes.width=(int) (*image)->columns; | 
 |       windows->image.window_changes.height=(int) (*image)->rows; | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         { | 
 |           windows->image.crop_geometry=(char *) | 
 |             RelinquishMagickMemory(windows->image.crop_geometry); | 
 |           windows->image.crop_geometry=(char *) NULL; | 
 |           windows->image.x=0; | 
 |           windows->image.y=0; | 
 |         } | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case CropCommand: | 
 |     { | 
 |       /* | 
 |         Crop image. | 
 |       */ | 
 |       (void) XCropImage(display,resource_info,windows,*image,CropMode, | 
 |         exception); | 
 |       break; | 
 |     } | 
 |     case ChopCommand: | 
 |     { | 
 |       /* | 
 |         Chop image. | 
 |       */ | 
 |       status=XChopImage(display,resource_info,windows,image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to cut X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case FlopCommand: | 
 |     { | 
 |       Image | 
 |         *flop_image; | 
 |  | 
 |       /* | 
 |         Flop image scanlines. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flop_image=FlopImage(*image,exception); | 
 |       if (flop_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=flop_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         { | 
 |           /* | 
 |             Flop crop geometry. | 
 |           */ | 
 |           width=(unsigned int) (*image)->columns; | 
 |           height=(unsigned int) (*image)->rows; | 
 |           (void) XParseGeometry(windows->image.crop_geometry,&x,&y, | 
 |             &width,&height); | 
 |           (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent, | 
 |             "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y); | 
 |         } | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case FlipCommand: | 
 |     { | 
 |       Image | 
 |         *flip_image; | 
 |  | 
 |       /* | 
 |         Flip image scanlines. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flip_image=FlipImage(*image,exception); | 
 |       if (flip_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=flip_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         { | 
 |           /* | 
 |             Flip crop geometry. | 
 |           */ | 
 |           width=(unsigned int) (*image)->columns; | 
 |           height=(unsigned int) (*image)->rows; | 
 |           (void) XParseGeometry(windows->image.crop_geometry,&x,&y, | 
 |             &width,&height); | 
 |           (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent, | 
 |             "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y); | 
 |         } | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case RotateRightCommand: | 
 |     { | 
 |       /* | 
 |         Rotate image 90 degrees clockwise. | 
 |       */ | 
 |       status=XRotateImage(display,resource_info,windows,90.0,image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to rotate X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case RotateLeftCommand: | 
 |     { | 
 |       /* | 
 |         Rotate image 90 degrees counter-clockwise. | 
 |       */ | 
 |       status=XRotateImage(display,resource_info,windows,-90.0,image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to rotate X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case RotateCommand: | 
 |     { | 
 |       /* | 
 |         Rotate image. | 
 |       */ | 
 |       status=XRotateImage(display,resource_info,windows,0.0,image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to rotate X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case ShearCommand: | 
 |     { | 
 |       Image | 
 |         *shear_image; | 
 |  | 
 |       static char | 
 |         geometry[MaxTextExtent] = "45.0x45.0"; | 
 |  | 
 |       /* | 
 |         Query user for shear color and geometry. | 
 |       */ | 
 |       XColorBrowserWidget(display,windows,"Select",color); | 
 |       if (*color == '\0') | 
 |         break; | 
 |       (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:", | 
 |         geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       /* | 
 |         Shear image. | 
 |       */ | 
 |       (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |         exception); | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) QueryColorCompliance(color,AllCompliance, | 
 |         &(*image)->background_color,exception); | 
 |       flags=ParseGeometry(geometry,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=geometry_info.rho; | 
 |       shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         exception); | 
 |       if (shear_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=shear_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       windows->image.window_changes.width=(int) (*image)->columns; | 
 |       windows->image.window_changes.height=(int) (*image)->rows; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case RollCommand: | 
 |     { | 
 |       Image | 
 |         *roll_image; | 
 |  | 
 |       static char | 
 |         geometry[MaxTextExtent] = "+2+2"; | 
 |  | 
 |       /* | 
 |         Query user for the roll geometry. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:", | 
 |         geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       /* | 
 |         Roll image. | 
 |       */ | 
 |       (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |         exception); | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) ParsePageGeometry(*image,geometry,&page_geometry, | 
 |         exception); | 
 |       roll_image=RollImage(*image,page_geometry.x,page_geometry.y, | 
 |         exception); | 
 |       if (roll_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=roll_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       windows->image.window_changes.width=(int) (*image)->columns; | 
 |       windows->image.window_changes.height=(int) (*image)->rows; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case TrimCommand: | 
 |     { | 
 |       static char | 
 |         fuzz[MaxTextExtent]; | 
 |  | 
 |       /* | 
 |         Query user for the fuzz factor. | 
 |       */ | 
 |       (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0* | 
 |         (*image)->fuzz/(QuantumRange+1.0)); | 
 |       (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz); | 
 |       if (*fuzz == '\0') | 
 |         break; | 
 |       (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0); | 
 |       /* | 
 |         Trim image. | 
 |       */ | 
 |       status=XTrimImage(display,resource_info,windows,*image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to trim X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case HueCommand: | 
 |     { | 
 |       static char | 
 |         hue_percent[MaxTextExtent] = "110"; | 
 |  | 
 |       /* | 
 |         Query user for percent hue change. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Apply", | 
 |         "Enter percent change in image hue (0-200):",hue_percent); | 
 |       if (*hue_percent == '\0') | 
 |         break; | 
 |       /* | 
 |         Vary the image hue. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent); | 
 |       (void) ConcatenateMagickString(modulate_factors,hue_percent, | 
 |         MaxTextExtent); | 
 |       (void) ModulateImage(*image,modulate_factors,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SaturationCommand: | 
 |     { | 
 |       static char | 
 |         saturation_percent[MaxTextExtent] = "110"; | 
 |  | 
 |       /* | 
 |         Query user for percent saturation change. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Apply", | 
 |         "Enter percent change in color saturation (0-200):",saturation_percent); | 
 |       if (*saturation_percent == '\0') | 
 |         break; | 
 |       /* | 
 |         Vary color saturation. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent); | 
 |       (void) ConcatenateMagickString(modulate_factors,saturation_percent, | 
 |         MaxTextExtent); | 
 |       (void) ModulateImage(*image,modulate_factors,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case BrightnessCommand: | 
 |     { | 
 |       static char | 
 |         brightness_percent[MaxTextExtent] = "110"; | 
 |  | 
 |       /* | 
 |         Query user for percent brightness change. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Apply", | 
 |         "Enter percent change in color brightness (0-200):",brightness_percent); | 
 |       if (*brightness_percent == '\0') | 
 |         break; | 
 |       /* | 
 |         Vary the color brightness. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) CopyMagickString(modulate_factors,brightness_percent, | 
 |         MaxTextExtent); | 
 |       (void) ModulateImage(*image,modulate_factors,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case GammaCommand: | 
 |     { | 
 |       static char | 
 |         factor[MaxTextExtent] = "1.6"; | 
 |  | 
 |       /* | 
 |         Query user for gamma value. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Gamma", | 
 |         "Enter gamma value (e.g. 1.2):",factor); | 
 |       if (*factor == '\0') | 
 |         break; | 
 |       /* | 
 |         Gamma correct image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) GammaImage(*image,atof(factor),exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SpiffCommand: | 
 |     { | 
 |       /* | 
 |         Sharpen the image contrast. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) ContrastImage(*image,MagickTrue,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case DullCommand: | 
 |     { | 
 |       /* | 
 |         Dull the image contrast. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) ContrastImage(*image,MagickFalse,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case ContrastStretchCommand: | 
 |     { | 
 |       double | 
 |         black_point, | 
 |         white_point; | 
 |  | 
 |       static char | 
 |         levels[MaxTextExtent] = "1%"; | 
 |  | 
 |       /* | 
 |         Query user for gamma value. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Contrast Stretch", | 
 |         "Enter black and white points:",levels); | 
 |       if (*levels == '\0') | 
 |         break; | 
 |       /* | 
 |         Contrast stretch image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(levels,&geometry_info); | 
 |       black_point=geometry_info.rho; | 
 |       white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point; | 
 |       if ((flags & PercentValue) != 0) | 
 |         { | 
 |           black_point*=(double) (*image)->columns*(*image)->rows/100.0; | 
 |           white_point*=(double) (*image)->columns*(*image)->rows/100.0; | 
 |         } | 
 |       white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point; | 
 |       (void) ContrastStretchImage(*image,black_point,white_point, | 
 |         exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SigmoidalContrastCommand: | 
 |     { | 
 |       GeometryInfo | 
 |         geometry_info; | 
 |  | 
 |       MagickStatusType | 
 |         flags; | 
 |  | 
 |       static char | 
 |         levels[MaxTextExtent] = "3x50%"; | 
 |  | 
 |       /* | 
 |         Query user for gamma value. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Sigmoidal Contrast", | 
 |         "Enter contrast and midpoint:",levels); | 
 |       if (*levels == '\0') | 
 |         break; | 
 |       /* | 
 |         Contrast stretch image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(levels,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=1.0*QuantumRange/2.0; | 
 |       if ((flags & PercentValue) != 0) | 
 |         geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0; | 
 |       (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho, | 
 |         geometry_info.sigma,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case NormalizeCommand: | 
 |     { | 
 |       /* | 
 |         Perform histogram normalization on the image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) NormalizeImage(*image,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case EqualizeCommand: | 
 |     { | 
 |       /* | 
 |         Perform histogram equalization on the image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) EqualizeImage(*image,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case NegateCommand: | 
 |     { | 
 |       /* | 
 |         Negate colors in image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) NegateImage(*image,MagickFalse,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case GrayscaleCommand: | 
 |     { | 
 |       /* | 
 |         Convert image to grayscale. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) SetImageType(*image,(*image)->matte == MagickFalse ? | 
 |         GrayscaleType : GrayscaleMatteType,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case MapCommand: | 
 |     { | 
 |       Image | 
 |         *affinity_image; | 
 |  | 
 |       static char | 
 |         filename[MaxTextExtent] = "\0"; | 
 |  | 
 |       /* | 
 |         Request image file name from user. | 
 |       */ | 
 |       XFileBrowserWidget(display,windows,"Map",filename); | 
 |       if (*filename == '\0') | 
 |         break; | 
 |       /* | 
 |         Map image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); | 
 |       affinity_image=ReadImage(image_info,exception); | 
 |       if (affinity_image != (Image *) NULL) | 
 |         { | 
 |           (void) RemapImage(&quantize_info,*image,affinity_image,exception); | 
 |           affinity_image=DestroyImage(affinity_image); | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case QuantizeCommand: | 
 |     { | 
 |       int | 
 |         status; | 
 |  | 
 |       static char | 
 |         colors[MaxTextExtent] = "256"; | 
 |  | 
 |       /* | 
 |         Query user for maximum number of colors. | 
 |       */ | 
 |       status=XDialogWidget(display,windows,"Quantize", | 
 |         "Maximum number of colors:",colors); | 
 |       if (*colors == '\0') | 
 |         break; | 
 |       /* | 
 |         Color reduce the image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       quantize_info.number_colors=StringToUnsignedLong(colors); | 
 |       quantize_info.dither=status != 0 ? MagickTrue : MagickFalse; | 
 |       (void) QuantizeImage(&quantize_info,*image,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case DespeckleCommand: | 
 |     { | 
 |       Image | 
 |         *despeckle_image; | 
 |  | 
 |       /* | 
 |         Despeckle image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       despeckle_image=DespeckleImage(*image,exception); | 
 |       if (despeckle_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=despeckle_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case EmbossCommand: | 
 |     { | 
 |       Image | 
 |         *emboss_image; | 
 |  | 
 |       static char | 
 |         radius[MaxTextExtent] = "0.0x1.0"; | 
 |  | 
 |       /* | 
 |         Query user for emboss radius. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Emboss", | 
 |         "Enter the emboss radius and standard deviation:",radius); | 
 |       if (*radius == '\0') | 
 |         break; | 
 |       /* | 
 |         Reduce noise in the image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(radius,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=1.0; | 
 |       emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         exception); | 
 |       if (emboss_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=emboss_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case ReduceNoiseCommand: | 
 |     { | 
 |       Image | 
 |         *noise_image; | 
 |  | 
 |       static char | 
 |         radius[MaxTextExtent] = "0"; | 
 |  | 
 |       /* | 
 |         Query user for noise radius. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Reduce Noise", | 
 |         "Enter the noise radius:",radius); | 
 |       if (*radius == '\0') | 
 |         break; | 
 |       /* | 
 |         Reduce noise in the image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(radius,&geometry_info); | 
 |       noise_image=StatisticImage(*image,NonpeakStatistic,(size_t) | 
 |         geometry_info.rho,(size_t) geometry_info.rho,exception); | 
 |       if (noise_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=noise_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case AddNoiseCommand: | 
 |     { | 
 |       char | 
 |         **noises; | 
 |  | 
 |       Image | 
 |         *noise_image; | 
 |  | 
 |       static char | 
 |         noise_type[MaxTextExtent] = "Gaussian"; | 
 |  | 
 |       /* | 
 |         Add noise to the image. | 
 |       */ | 
 |       noises=GetCommandOptions(MagickNoiseOptions); | 
 |       if (noises == (char **) NULL) | 
 |         break; | 
 |       XListBrowserWidget(display,windows,&windows->widget, | 
 |         (const char **) noises,"Add Noise", | 
 |         "Select a type of noise to add to your image:",noise_type); | 
 |       noises=DestroyStringList(noises); | 
 |       if (*noise_type == '\0') | 
 |         break; | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption( | 
 |         MagickNoiseOptions,MagickFalse,noise_type),1.0,exception); | 
 |       if (noise_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=noise_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SharpenCommand: | 
 |     { | 
 |       Image | 
 |         *sharp_image; | 
 |  | 
 |       static char | 
 |         radius[MaxTextExtent] = "0.0x1.0"; | 
 |  | 
 |       /* | 
 |         Query user for sharpen radius. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Sharpen", | 
 |         "Enter the sharpen radius and standard deviation:",radius); | 
 |       if (*radius == '\0') | 
 |         break; | 
 |       /* | 
 |         Sharpen image scanlines. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(radius,&geometry_info); | 
 |       sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         geometry_info.xi,exception); | 
 |       if (sharp_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=sharp_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case BlurCommand: | 
 |     { | 
 |       Image | 
 |         *blur_image; | 
 |  | 
 |       static char | 
 |         radius[MaxTextExtent] = "0.0x1.0"; | 
 |  | 
 |       /* | 
 |         Query user for blur radius. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Blur", | 
 |         "Enter the blur radius and standard deviation:",radius); | 
 |       if (*radius == '\0') | 
 |         break; | 
 |       /* | 
 |         Blur an image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(radius,&geometry_info); | 
 |       blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         geometry_info.xi,exception); | 
 |       if (blur_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=blur_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case ThresholdCommand: | 
 |     { | 
 |       double | 
 |         threshold; | 
 |  | 
 |       static char | 
 |         factor[MaxTextExtent] = "128"; | 
 |  | 
 |       /* | 
 |         Query user for threshold value. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Threshold", | 
 |         "Enter threshold value:",factor); | 
 |       if (*factor == '\0') | 
 |         break; | 
 |       /* | 
 |         Gamma correct image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       threshold=SiPrefixToDouble(factor,QuantumRange); | 
 |       (void) BilevelImage(*image,threshold,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case EdgeDetectCommand: | 
 |     { | 
 |       Image | 
 |         *edge_image; | 
 |  | 
 |       static char | 
 |         radius[MaxTextExtent] = "0"; | 
 |  | 
 |       /* | 
 |         Query user for edge factor. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Detect Edges", | 
 |         "Enter the edge detect radius:",radius); | 
 |       if (*radius == '\0') | 
 |         break; | 
 |       /* | 
 |         Detect edge in image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(radius,&geometry_info); | 
 |       edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         exception); | 
 |       if (edge_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=edge_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SpreadCommand: | 
 |     { | 
 |       Image | 
 |         *spread_image; | 
 |  | 
 |       static char | 
 |         amount[MaxTextExtent] = "2"; | 
 |  | 
 |       /* | 
 |         Query user for spread amount. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Spread", | 
 |         "Enter the displacement amount:",amount); | 
 |       if (*amount == '\0') | 
 |         break; | 
 |       /* | 
 |         Displace image pixels by a random amount. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(amount,&geometry_info); | 
 |       spread_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         exception); | 
 |       if (spread_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=spread_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case ShadeCommand: | 
 |     { | 
 |       Image | 
 |         *shade_image; | 
 |  | 
 |       int | 
 |         status; | 
 |  | 
 |       static char | 
 |         geometry[MaxTextExtent] = "30x30"; | 
 |  | 
 |       /* | 
 |         Query user for the shade geometry. | 
 |       */ | 
 |       status=XDialogWidget(display,windows,"Shade", | 
 |         "Enter the azimuth and elevation of the light source:",geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       /* | 
 |         Shade image pixels. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(geometry,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=1.0; | 
 |       shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue, | 
 |         geometry_info.rho,geometry_info.sigma,exception); | 
 |       if (shade_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=shade_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case RaiseCommand: | 
 |     { | 
 |       static char | 
 |         bevel_width[MaxTextExtent] = "10"; | 
 |  | 
 |       /* | 
 |         Query user for bevel width. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width); | 
 |       if (*bevel_width == '\0') | 
 |         break; | 
 |       /* | 
 |         Raise an image. | 
 |       */ | 
 |       (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |         exception); | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) ParsePageGeometry(*image,bevel_width,&page_geometry, | 
 |         exception); | 
 |       (void) RaiseImage(*image,&page_geometry,MagickTrue,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SegmentCommand: | 
 |     { | 
 |       static char | 
 |         threshold[MaxTextExtent] = "1.0x1.5"; | 
 |  | 
 |       /* | 
 |         Query user for smoothing threshold. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Segment","Smooth threshold:", | 
 |         threshold); | 
 |       if (*threshold == '\0') | 
 |         break; | 
 |       /* | 
 |         Segment an image. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(threshold,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=1.0; | 
 |       (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho, | 
 |         geometry_info.sigma,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SepiaToneCommand: | 
 |     { | 
 |       double | 
 |         threshold; | 
 |  | 
 |       Image | 
 |         *sepia_image; | 
 |  | 
 |       static char | 
 |         factor[MaxTextExtent] = "80%"; | 
 |  | 
 |       /* | 
 |         Query user for sepia-tone factor. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Sepia Tone", | 
 |         "Enter the sepia tone factor (0 - 99.9%):",factor); | 
 |       if (*factor == '\0') | 
 |         break; | 
 |       /* | 
 |         Sepia tone image pixels. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       threshold=SiPrefixToDouble(factor,QuantumRange); | 
 |       sepia_image=SepiaToneImage(*image,threshold,exception); | 
 |       if (sepia_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=sepia_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SolarizeCommand: | 
 |     { | 
 |       double | 
 |         threshold; | 
 |  | 
 |       static char | 
 |         factor[MaxTextExtent] = "60%"; | 
 |  | 
 |       /* | 
 |         Query user for solarize factor. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Solarize", | 
 |         "Enter the solarize factor (0 - 99.9%):",factor); | 
 |       if (*factor == '\0') | 
 |         break; | 
 |       /* | 
 |         Solarize image pixels. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       threshold=SiPrefixToDouble(factor,QuantumRange); | 
 |       (void) SolarizeImage(*image,threshold,exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case SwirlCommand: | 
 |     { | 
 |       Image | 
 |         *swirl_image; | 
 |  | 
 |       static char | 
 |         degrees[MaxTextExtent] = "60"; | 
 |  | 
 |       /* | 
 |         Query user for swirl angle. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:", | 
 |         degrees); | 
 |       if (*degrees == '\0') | 
 |         break; | 
 |       /* | 
 |         Swirl image pixels about the center. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(degrees,&geometry_info); | 
 |       swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate, | 
 |         exception); | 
 |       if (swirl_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=swirl_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case ImplodeCommand: | 
 |     { | 
 |       Image | 
 |         *implode_image; | 
 |  | 
 |       static char | 
 |         factor[MaxTextExtent] = "0.3"; | 
 |  | 
 |       /* | 
 |         Query user for implode factor. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Implode", | 
 |         "Enter the implosion/explosion factor (-1.0 - 1.0):",factor); | 
 |       if (*factor == '\0') | 
 |         break; | 
 |       /* | 
 |         Implode image pixels about the center. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(factor,&geometry_info); | 
 |       implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate, | 
 |         exception); | 
 |       if (implode_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=implode_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case VignetteCommand: | 
 |     { | 
 |       Image | 
 |         *vignette_image; | 
 |  | 
 |       static char | 
 |         geometry[MaxTextExtent] = "0x20"; | 
 |  | 
 |       /* | 
 |         Query user for the vignette geometry. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Vignette", | 
 |         "Enter the radius, sigma, and x and y offsets:",geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       /* | 
 |         Soften the edges of the image in vignette style | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(geometry,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=1.0; | 
 |       if ((flags & XiValue) == 0) | 
 |         geometry_info.xi=0.1*(*image)->columns; | 
 |       if ((flags & PsiValue) == 0) | 
 |         geometry_info.psi=0.1*(*image)->rows; | 
 |       vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi- | 
 |         0.5),exception); | 
 |       if (vignette_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=vignette_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case WaveCommand: | 
 |     { | 
 |       Image | 
 |         *wave_image; | 
 |  | 
 |       static char | 
 |         geometry[MaxTextExtent] = "25x150"; | 
 |  | 
 |       /* | 
 |         Query user for the wave geometry. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Wave", | 
 |         "Enter the amplitude and length of the wave:",geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       /* | 
 |         Alter an image along a sine wave. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(geometry,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=1.0; | 
 |       wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         (*image)->interpolate,exception); | 
 |       if (wave_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=wave_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case OilPaintCommand: | 
 |     { | 
 |       Image | 
 |         *paint_image; | 
 |  | 
 |       static char | 
 |         radius[MaxTextExtent] = "0"; | 
 |  | 
 |       /* | 
 |         Query user for circular neighborhood radius. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Oil Paint", | 
 |         "Enter the mask radius:",radius); | 
 |       if (*radius == '\0') | 
 |         break; | 
 |       /* | 
 |         OilPaint image scanlines. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(radius,&geometry_info); | 
 |       paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         exception); | 
 |       if (paint_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=paint_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case CharcoalDrawCommand: | 
 |     { | 
 |       Image | 
 |         *charcoal_image; | 
 |  | 
 |       static char | 
 |         radius[MaxTextExtent] = "0x1"; | 
 |  | 
 |       /* | 
 |         Query user for charcoal radius. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Charcoal Draw", | 
 |         "Enter the charcoal radius and sigma:",radius); | 
 |       if (*radius == '\0') | 
 |         break; | 
 |       /* | 
 |         Charcoal the image. | 
 |       */ | 
 |       (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |         exception); | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       flags=ParseGeometry(radius,&geometry_info); | 
 |       if ((flags & SigmaValue) == 0) | 
 |         geometry_info.sigma=geometry_info.rho; | 
 |       charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma, | 
 |         geometry_info.xi,exception); | 
 |       if (charcoal_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=charcoal_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case AnnotateCommand: | 
 |     { | 
 |       /* | 
 |         Annotate the image with text. | 
 |       */ | 
 |       status=XAnnotateEditImage(display,resource_info,windows,*image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to annotate X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case DrawCommand: | 
 |     { | 
 |       /* | 
 |         Draw image. | 
 |       */ | 
 |       status=XDrawEditImage(display,resource_info,windows,image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to draw on the X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case ColorCommand: | 
 |     { | 
 |       /* | 
 |         Color edit. | 
 |       */ | 
 |       status=XColorEditImage(display,resource_info,windows,image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to pixel edit X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case MatteCommand: | 
 |     { | 
 |       /* | 
 |         Matte edit. | 
 |       */ | 
 |       status=XMatteEditImage(display,resource_info,windows,image,exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to matte edit X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case CompositeCommand: | 
 |     { | 
 |       /* | 
 |         Composite image. | 
 |       */ | 
 |       status=XCompositeImage(display,resource_info,windows,*image, | 
 |         exception); | 
 |       if (status == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to composite X image", | 
 |             (*image)->filename); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case AddBorderCommand: | 
 |     { | 
 |       Image | 
 |         *border_image; | 
 |  | 
 |       static char | 
 |         geometry[MaxTextExtent] = "6x6"; | 
 |  | 
 |       /* | 
 |         Query user for border color and geometry. | 
 |       */ | 
 |       XColorBrowserWidget(display,windows,"Select",color); | 
 |       if (*color == '\0') | 
 |         break; | 
 |       (void) XDialogWidget(display,windows,"Add Border", | 
 |         "Enter border geometry:",geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       /* | 
 |         Add a border to the image. | 
 |       */ | 
 |       (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |         exception); | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color, | 
 |         exception); | 
 |       (void) ParsePageGeometry(*image,geometry,&page_geometry, | 
 |         exception); | 
 |       border_image=BorderImage(*image,&page_geometry,(*image)->compose, | 
 |         exception); | 
 |       if (border_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=border_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       windows->image.window_changes.width=(int) (*image)->columns; | 
 |       windows->image.window_changes.height=(int) (*image)->rows; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case AddFrameCommand: | 
 |     { | 
 |       FrameInfo | 
 |         frame_info; | 
 |  | 
 |       Image | 
 |         *frame_image; | 
 |  | 
 |       static char | 
 |         geometry[MaxTextExtent] = "6x6"; | 
 |  | 
 |       /* | 
 |         Query user for frame color and geometry. | 
 |       */ | 
 |       XColorBrowserWidget(display,windows,"Select",color); | 
 |       if (*color == '\0') | 
 |         break; | 
 |       (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:", | 
 |         geometry); | 
 |       if (*geometry == '\0') | 
 |         break; | 
 |       /* | 
 |         Surround image with an ornamental border. | 
 |       */ | 
 |       (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |         exception); | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color, | 
 |         exception); | 
 |       (void) ParsePageGeometry(*image,geometry,&page_geometry, | 
 |         exception); | 
 |       frame_info.width=page_geometry.width; | 
 |       frame_info.height=page_geometry.height; | 
 |       frame_info.outer_bevel=page_geometry.x; | 
 |       frame_info.inner_bevel=page_geometry.y; | 
 |       frame_info.x=(ssize_t) frame_info.width; | 
 |       frame_info.y=(ssize_t) frame_info.height; | 
 |       frame_info.width=(*image)->columns+2*frame_info.width; | 
 |       frame_info.height=(*image)->rows+2*frame_info.height; | 
 |       frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception); | 
 |       if (frame_image != (Image *) NULL) | 
 |         { | 
 |           *image=DestroyImage(*image); | 
 |           *image=frame_image; | 
 |         } | 
 |       CatchException(exception); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       if (windows->image.orphan != MagickFalse) | 
 |         break; | 
 |       windows->image.window_changes.width=(int) (*image)->columns; | 
 |       windows->image.window_changes.height=(int) (*image)->rows; | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |       break; | 
 |     } | 
 |     case CommentCommand: | 
 |     { | 
 |       const char | 
 |         *value; | 
 |  | 
 |       FILE | 
 |         *file; | 
 |  | 
 |       int | 
 |         unique_file; | 
 |  | 
 |       /* | 
 |         Edit image comment. | 
 |       */ | 
 |       unique_file=AcquireUniqueFileResource(image_info->filename); | 
 |       if (unique_file == -1) | 
 |         XNoticeWidget(display,windows,"Unable to edit image comment", | 
 |           image_info->filename); | 
 |       value=GetImageProperty(*image,"comment",exception); | 
 |       if (value == (char *) NULL) | 
 |         unique_file=close(unique_file)-1; | 
 |       else | 
 |         { | 
 |           register const char | 
 |             *p; | 
 |  | 
 |           file=fdopen(unique_file,"w"); | 
 |           if (file == (FILE *) NULL) | 
 |             { | 
 |               XNoticeWidget(display,windows,"Unable to edit image comment", | 
 |                 image_info->filename); | 
 |               break; | 
 |             } | 
 |           for (p=value; *p != '\0'; p++) | 
 |             (void) fputc((int) *p,file); | 
 |           (void) fputc('\n',file); | 
 |           (void) fclose(file); | 
 |         } | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       status=InvokeDelegate(image_info,*image,"edit",(char *) NULL, | 
 |         exception); | 
 |       if (status == MagickFalse) | 
 |         XNoticeWidget(display,windows,"Unable to edit image comment", | 
 |           (char *) NULL); | 
 |       else | 
 |         { | 
 |           char | 
 |             *comment; | 
 |  | 
 |           comment=FileToString(image_info->filename,~0UL,exception); | 
 |           if (comment != (char *) NULL) | 
 |             { | 
 |               (void) SetImageProperty(*image,"comment",comment,exception); | 
 |               (*image)->taint=MagickTrue; | 
 |             } | 
 |         } | 
 |       (void) RelinquishUniqueFileResource(image_info->filename); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       break; | 
 |     } | 
 |     case LaunchCommand: | 
 |     { | 
 |       /* | 
 |         Launch program. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) AcquireUniqueFilename(filename); | 
 |       (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s", | 
 |         filename); | 
 |       status=WriteImage(image_info,*image,exception); | 
 |       if (status == MagickFalse) | 
 |         XNoticeWidget(display,windows,"Unable to launch image editor", | 
 |           (char *) NULL); | 
 |       else | 
 |         { | 
 |           nexus=ReadImage(resource_info->image_info,exception); | 
 |           CatchException(exception); | 
 |           XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |             windows->im_next_image,CurrentTime); | 
 |         } | 
 |       (void) RelinquishUniqueFileResource(filename); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       break; | 
 |     } | 
 |     case RegionofInterestCommand: | 
 |     { | 
 |       /* | 
 |         Apply an image processing technique to a region of interest. | 
 |       */ | 
 |       (void) XROIImage(display,resource_info,windows,image,exception); | 
 |       break; | 
 |     } | 
 |     case InfoCommand: | 
 |       break; | 
 |     case ZoomCommand: | 
 |     { | 
 |       /* | 
 |         Zoom image. | 
 |       */ | 
 |       if (windows->magnify.mapped != MagickFalse) | 
 |         (void) XRaiseWindow(display,windows->magnify.id); | 
 |       else | 
 |         { | 
 |           /* | 
 |             Make magnify image. | 
 |           */ | 
 |           XSetCursorState(display,windows,MagickTrue); | 
 |           (void) XMapRaised(display,windows->magnify.id); | 
 |           XSetCursorState(display,windows,MagickFalse); | 
 |         } | 
 |       break; | 
 |     } | 
 |     case ShowPreviewCommand: | 
 |     { | 
 |       char | 
 |         **previews; | 
 |  | 
 |       Image | 
 |         *preview_image; | 
 |  | 
 |       static char | 
 |         preview_type[MaxTextExtent] = "Gamma"; | 
 |  | 
 |       /* | 
 |         Select preview type from menu. | 
 |       */ | 
 |       previews=GetCommandOptions(MagickPreviewOptions); | 
 |       if (previews == (char **) NULL) | 
 |         break; | 
 |       XListBrowserWidget(display,windows,&windows->widget, | 
 |         (const char **) previews,"Preview", | 
 |         "Select an enhancement, effect, or F/X:",preview_type); | 
 |       previews=DestroyStringList(previews); | 
 |       if (*preview_type == '\0') | 
 |         break; | 
 |       /* | 
 |         Show image preview. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       image_info->preview_type=(PreviewType) | 
 |         ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type); | 
 |       image_info->group=(ssize_t) windows->image.id; | 
 |       (void) DeleteImageProperty(*image,"label"); | 
 |       (void) SetImageProperty(*image,"label","Preview",exception); | 
 |       (void) AcquireUniqueFilename(filename); | 
 |       (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s", | 
 |         filename); | 
 |       status=WriteImage(image_info,*image,exception); | 
 |       (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); | 
 |       preview_image=ReadImage(image_info,exception); | 
 |       (void) RelinquishUniqueFileResource(filename); | 
 |       if (preview_image == (Image *) NULL) | 
 |         break; | 
 |       (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s", | 
 |         filename); | 
 |       status=WriteImage(image_info,preview_image,exception); | 
 |       preview_image=DestroyImage(preview_image); | 
 |       if (status == MagickFalse) | 
 |         XNoticeWidget(display,windows,"Unable to show image preview", | 
 |           (*image)->filename); | 
 |       XDelay(display,1500); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       break; | 
 |     } | 
 |     case ShowHistogramCommand: | 
 |     { | 
 |       Image | 
 |         *histogram_image; | 
 |  | 
 |       /* | 
 |         Show image histogram. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       image_info->group=(ssize_t) windows->image.id; | 
 |       (void) DeleteImageProperty(*image,"label"); | 
 |       (void) SetImageProperty(*image,"label","Histogram",exception); | 
 |       (void) AcquireUniqueFilename(filename); | 
 |       (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s", | 
 |         filename); | 
 |       status=WriteImage(image_info,*image,exception); | 
 |       (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); | 
 |       histogram_image=ReadImage(image_info,exception); | 
 |       (void) RelinquishUniqueFileResource(filename); | 
 |       if (histogram_image == (Image *) NULL) | 
 |         break; | 
 |       (void) FormatLocaleString(histogram_image->filename,MaxTextExtent, | 
 |         "show:%s",filename); | 
 |       status=WriteImage(image_info,histogram_image,exception); | 
 |       histogram_image=DestroyImage(histogram_image); | 
 |       if (status == MagickFalse) | 
 |         XNoticeWidget(display,windows,"Unable to show histogram", | 
 |           (*image)->filename); | 
 |       XDelay(display,1500); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       break; | 
 |     } | 
 |     case ShowMatteCommand: | 
 |     { | 
 |       Image | 
 |         *matte_image; | 
 |  | 
 |       if ((*image)->matte == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows, | 
 |             "Image does not have any matte information",(*image)->filename); | 
 |           break; | 
 |         } | 
 |       /* | 
 |         Show image matte. | 
 |       */ | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       image_info->group=(ssize_t) windows->image.id; | 
 |       (void) DeleteImageProperty(*image,"label"); | 
 |       (void) SetImageProperty(*image,"label","Matte",exception); | 
 |       (void) AcquireUniqueFilename(filename); | 
 |       (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s", | 
 |         filename); | 
 |       status=WriteImage(image_info,*image,exception); | 
 |       (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); | 
 |       matte_image=ReadImage(image_info,exception); | 
 |       (void) RelinquishUniqueFileResource(filename); | 
 |       if (matte_image == (Image *) NULL) | 
 |         break; | 
 |       (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s", | 
 |         filename); | 
 |       status=WriteImage(image_info,matte_image,exception); | 
 |       matte_image=DestroyImage(matte_image); | 
 |       if (status == MagickFalse) | 
 |         XNoticeWidget(display,windows,"Unable to show matte", | 
 |           (*image)->filename); | 
 |       XDelay(display,1500); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       break; | 
 |     } | 
 |     case BackgroundCommand: | 
 |     { | 
 |       /* | 
 |         Background image. | 
 |       */ | 
 |       status=XBackgroundImage(display,resource_info,windows,image,exception); | 
 |       if (status == MagickFalse) | 
 |         break; | 
 |       nexus=CloneImage(*image,0,0,MagickTrue,exception); | 
 |       if (nexus != (Image *) NULL) | 
 |         XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |           windows->im_next_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case SlideShowCommand: | 
 |     { | 
 |       static char | 
 |         delay[MaxTextExtent] = "5"; | 
 |  | 
 |       /* | 
 |         Display next image after pausing. | 
 |       */ | 
 |       (void) XDialogWidget(display,windows,"Slide Show", | 
 |         "Pause how many 1/100ths of a second between images:",delay); | 
 |       if (*delay == '\0') | 
 |         break; | 
 |       resource_info->delay=StringToUnsignedLong(delay); | 
 |       XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |         windows->im_next_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case PreferencesCommand: | 
 |     { | 
 |       /* | 
 |         Set user preferences. | 
 |       */ | 
 |       status=XPreferencesWidget(display,resource_info,windows); | 
 |       if (status == MagickFalse) | 
 |         break; | 
 |       nexus=CloneImage(*image,0,0,MagickTrue,exception); | 
 |       if (nexus != (Image *) NULL) | 
 |         XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |           windows->im_next_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case HelpCommand: | 
 |     { | 
 |       /* | 
 |         User requested help. | 
 |       */ | 
 |       XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |         "Help Viewer - Display",DisplayHelp); | 
 |       break; | 
 |     } | 
 |     case BrowseDocumentationCommand: | 
 |     { | 
 |       Atom | 
 |         mozilla_atom; | 
 |  | 
 |       Window | 
 |         mozilla_window, | 
 |         root_window; | 
 |  | 
 |       /* | 
 |         Browse the ImageMagick documentation. | 
 |       */ | 
 |       root_window=XRootWindow(display,XDefaultScreen(display)); | 
 |       mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse); | 
 |       mozilla_window=XWindowByProperty(display,root_window,mozilla_atom); | 
 |       if (mozilla_window != (Window) NULL) | 
 |         { | 
 |           char | 
 |             command[MaxTextExtent], | 
 |             *url; | 
 |  | 
 |           /* | 
 |             Display documentation using Netscape remote control. | 
 |           */ | 
 |           url=GetMagickHomeURL(); | 
 |           (void) FormatLocaleString(command,MaxTextExtent, | 
 |             "openurl(%s,new-tab)",url); | 
 |           url=DestroyString(url); | 
 |           mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse); | 
 |           (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING, | 
 |             8,PropModeReplace,(unsigned char *) command,(int) strlen(command)); | 
 |           XSetCursorState(display,windows,MagickFalse); | 
 |           break; | 
 |         } | 
 |       XSetCursorState(display,windows,MagickTrue); | 
 |       XCheckRefreshWindows(display,windows); | 
 |       status=InvokeDelegate(image_info,*image,"browse",(char *) NULL, | 
 |         exception); | 
 |       if (status == MagickFalse) | 
 |         XNoticeWidget(display,windows,"Unable to browse documentation", | 
 |           (char *) NULL); | 
 |       XDelay(display,1500); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       break; | 
 |     } | 
 |     case VersionCommand: | 
 |     { | 
 |       XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL), | 
 |         GetMagickCopyright()); | 
 |       break; | 
 |     } | 
 |     case SaveToUndoBufferCommand: | 
 |       break; | 
 |     default: | 
 |     { | 
 |       (void) XBell(display,0); | 
 |       break; | 
 |     } | 
 |   } | 
 |   image_info=DestroyImageInfo(image_info); | 
 |   return(nexus); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X M a g n i f y I m a g e                                                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XMagnifyImage() magnifies portions of the image as indicated by the pointer. | 
 | %  The magnified portion is displayed in a separate window. | 
 | % | 
 | %  The format of the XMagnifyImage method is: | 
 | % | 
 | %      void XMagnifyImage(Display *display,XWindows *windows,XEvent *event, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 XWindows structure. | 
 | % | 
 | %    o event: Specifies a pointer to a XEvent structure.  If it is NULL, | 
 | %      the entire image is refreshed. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   register int | 
 |     x, | 
 |     y; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   /* | 
 |     Update magnified image until the mouse button is released. | 
 |   */ | 
 |   (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor); | 
 |   state=DefaultState; | 
 |   x=event->xbutton.x; | 
 |   y=event->xbutton.y; | 
 |   windows->magnify.x=(int) windows->image.x+x; | 
 |   windows->magnify.y=(int) windows->image.y+y; | 
 |   do | 
 |   { | 
 |     /* | 
 |       Map and unmap Info widget as text cursor crosses its boundaries. | 
 |     */ | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |             (y < (int) (windows->info.y+windows->info.height))) | 
 |           (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       } | 
 |     else | 
 |       if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |           (y > (int) (windows->info.y+windows->info.height))) | 
 |         (void) XMapWindow(display,windows->info.id); | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ", | 
 |           windows->magnify.x,windows->magnify.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,event,exception); | 
 |     switch (event->type) | 
 |     { | 
 |       case ButtonPress: | 
 |         break; | 
 |       case ButtonRelease: | 
 |       { | 
 |         /* | 
 |           User has finished magnifying image. | 
 |         */ | 
 |         x=event->xbutton.x; | 
 |         y=event->xbutton.y; | 
 |         state|=ExitState; | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |         break; | 
 |       case MotionNotify: | 
 |       { | 
 |         x=event->xmotion.x; | 
 |         y=event->xmotion.y; | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |     /* | 
 |       Check boundary conditions. | 
 |     */ | 
 |     if (x < 0) | 
 |       x=0; | 
 |     else | 
 |       if (x >= (int) windows->image.width) | 
 |         x=(int) windows->image.width-1; | 
 |     if (y < 0) | 
 |       y=0; | 
 |     else | 
 |      if (y >= (int) windows->image.height) | 
 |        y=(int) windows->image.height-1; | 
 |   } while ((state & ExitState) == 0); | 
 |   /* | 
 |     Display magnified image. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X M a g n i f y W i n d o w C o m m a n d                                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XMagnifyWindowCommand() moves the image within an Magnify window by one | 
 | %  pixel as specified by the key symbol. | 
 | % | 
 | %  The format of the XMagnifyWindowCommand method is: | 
 | % | 
 | %      void XMagnifyWindowCommand(Display *display,XWindows *windows, | 
 | %        const MagickStatusType state,const KeySym key_symbol, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 XWindows structure. | 
 | % | 
 | %    o state: key mask. | 
 | % | 
 | %    o key_symbol: Specifies a KeySym which indicates which side of the image | 
 | %      to trim. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static void XMagnifyWindowCommand(Display *display,XWindows *windows, | 
 |   const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception) | 
 | { | 
 |   unsigned int | 
 |     quantum; | 
 |  | 
 |   /* | 
 |     User specified a magnify factor or position. | 
 |   */ | 
 |   quantum=1; | 
 |   if ((state & Mod1Mask) != 0) | 
 |     quantum=10; | 
 |   switch ((int) key_symbol) | 
 |   { | 
 |     case QuitCommand: | 
 |     { | 
 |       (void) XWithdrawWindow(display,windows->magnify.id, | 
 |         windows->magnify.screen); | 
 |       break; | 
 |     } | 
 |     case XK_Home: | 
 |     case XK_KP_Home: | 
 |     { | 
 |       windows->magnify.x=(int) windows->image.width/2; | 
 |       windows->magnify.y=(int) windows->image.height/2; | 
 |       break; | 
 |     } | 
 |     case XK_Left: | 
 |     case XK_KP_Left: | 
 |     { | 
 |       if (windows->magnify.x > 0) | 
 |         windows->magnify.x-=quantum; | 
 |       break; | 
 |     } | 
 |     case XK_Up: | 
 |     case XK_KP_Up: | 
 |     { | 
 |       if (windows->magnify.y > 0) | 
 |         windows->magnify.y-=quantum; | 
 |       break; | 
 |     } | 
 |     case XK_Right: | 
 |     case XK_KP_Right: | 
 |     { | 
 |       if (windows->magnify.x < (int) (windows->image.ximage->width-1)) | 
 |         windows->magnify.x+=quantum; | 
 |       break; | 
 |     } | 
 |     case XK_Down: | 
 |     case XK_KP_Down: | 
 |     { | 
 |       if (windows->magnify.y < (int) (windows->image.ximage->height-1)) | 
 |         windows->magnify.y+=quantum; | 
 |       break; | 
 |     } | 
 |     case XK_0: | 
 |     case XK_1: | 
 |     case XK_2: | 
 |     case XK_3: | 
 |     case XK_4: | 
 |     case XK_5: | 
 |     case XK_6: | 
 |     case XK_7: | 
 |     case XK_8: | 
 |     case XK_9: | 
 |     { | 
 |       windows->magnify.data=(key_symbol-XK_0); | 
 |       break; | 
 |     } | 
 |     case XK_KP_0: | 
 |     case XK_KP_1: | 
 |     case XK_KP_2: | 
 |     case XK_KP_3: | 
 |     case XK_KP_4: | 
 |     case XK_KP_5: | 
 |     case XK_KP_6: | 
 |     case XK_KP_7: | 
 |     case XK_KP_8: | 
 |     case XK_KP_9: | 
 |     { | 
 |       windows->magnify.data=(key_symbol-XK_KP_0); | 
 |       break; | 
 |     } | 
 |     default: | 
 |       break; | 
 |   } | 
 |   XMakeMagnifyImage(display,windows,exception); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X M a k e P a n I m a g e                                                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XMakePanImage() creates a thumbnail of the image and displays it in the Pan | 
 | %  icon window. | 
 | % | 
 | %  The format of the XMakePanImage method is: | 
 | % | 
 | %        void XMakePanImage(Display *display,XResourceInfo *resource_info, | 
 | %          XWindows *windows,Image *image,ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static void XMakePanImage(Display *display,XResourceInfo *resource_info, | 
 |   XWindows *windows,Image *image,ExceptionInfo *exception) | 
 | { | 
 |   MagickStatusType | 
 |     status; | 
 |  | 
 |   /* | 
 |     Create and display image for panning icon. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   windows->pan.x=(int) windows->image.x; | 
 |   windows->pan.y=(int) windows->image.y; | 
 |   status=XMakeImage(display,resource_info,&windows->pan,image, | 
 |     windows->pan.width,windows->pan.height,exception); | 
 |   if (status == MagickFalse) | 
 |     ThrowXWindowFatalException(ResourceLimitError, | 
 |      "MemoryAllocationFailed",image->filename); | 
 |   (void) XSetWindowBackgroundPixmap(display,windows->pan.id, | 
 |     windows->pan.pixmap); | 
 |   (void) XClearWindow(display,windows->pan.id); | 
 |   XDrawPanRectangle(display,windows); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X M a t t a E d i t I m a g e                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XMatteEditImage() allows the user to interactively change the Matte channel | 
 | %  of an image.  If the image is PseudoClass it is promoted to DirectClass | 
 | %  before the matte information is stored. | 
 | % | 
 | %  The format of the XMatteEditImage method is: | 
 | % | 
 | %      MagickBooleanType XMatteEditImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XMatteEditImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static char | 
 |     matte[MaxTextExtent] = "0"; | 
 |  | 
 |   static const char | 
 |     *MatteEditMenu[] = | 
 |     { | 
 |       "Method", | 
 |       "Border Color", | 
 |       "Fuzz", | 
 |       "Matte Value", | 
 |       "Undo", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static const ModeType | 
 |     MatteEditCommands[] = | 
 |     { | 
 |       MatteEditMethod, | 
 |       MatteEditBorderCommand, | 
 |       MatteEditFuzzCommand, | 
 |       MatteEditValueCommand, | 
 |       MatteEditUndoCommand, | 
 |       MatteEditHelpCommand, | 
 |       MatteEditDismissCommand | 
 |     }; | 
 |  | 
 |   static PaintMethod | 
 |     method = PointMethod; | 
 |  | 
 |   static XColor | 
 |     border_color = { 0, 0, 0, 0, 0, 0 }; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   int | 
 |     entry, | 
 |     id, | 
 |     x, | 
 |     x_offset, | 
 |     y, | 
 |     y_offset; | 
 |  | 
 |   register int | 
 |     i; | 
 |  | 
 |   register Quantum | 
 |     *q; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Matte Edit"); | 
 |   windows->command.data=4; | 
 |   (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Make cursor. | 
 |   */ | 
 |   cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap, | 
 |     resource_info->background_color,resource_info->foreground_color); | 
 |   (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ", | 
 |           x+windows->image.x,y+windows->image.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,MatteEditMenu,&event); | 
 |         if (id < 0) | 
 |           { | 
 |             (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |             continue; | 
 |           } | 
 |         switch (MatteEditCommands[id]) | 
 |         { | 
 |           case MatteEditMethod: | 
 |           { | 
 |             char | 
 |               **methods; | 
 |  | 
 |             /* | 
 |               Select a method from the pop-up menu. | 
 |             */ | 
 |             methods=GetCommandOptions(MagickMethodOptions); | 
 |             if (methods == (char **) NULL) | 
 |               break; | 
 |             entry=XMenuWidget(display,windows,MatteEditMenu[id], | 
 |               (const char **) methods,command); | 
 |             if (entry >= 0) | 
 |               method=(PaintMethod) ParseCommandOption(MagickMethodOptions, | 
 |                 MagickFalse,methods[entry]); | 
 |             methods=DestroyStringList(methods); | 
 |             break; | 
 |           } | 
 |           case MatteEditBorderCommand: | 
 |           { | 
 |             const char | 
 |               *ColorMenu[MaxNumberPens]; | 
 |  | 
 |             int | 
 |               pen_number; | 
 |  | 
 |             /* | 
 |               Initialize menu selections. | 
 |             */ | 
 |             for (i=0; i < (int) (MaxNumberPens-2); i++) | 
 |               ColorMenu[i]=resource_info->pen_colors[i]; | 
 |             ColorMenu[MaxNumberPens-2]="Browser..."; | 
 |             ColorMenu[MaxNumberPens-1]=(const char *) NULL; | 
 |             /* | 
 |               Select a pen color from the pop-up menu. | 
 |             */ | 
 |             pen_number=XMenuWidget(display,windows,MatteEditMenu[id], | 
 |               (const char **) ColorMenu,command); | 
 |             if (pen_number < 0) | 
 |               break; | 
 |             if (pen_number == (MaxNumberPens-2)) | 
 |               { | 
 |                 static char | 
 |                   color_name[MaxTextExtent] = "gray"; | 
 |  | 
 |                 /* | 
 |                   Select a pen color from a dialog. | 
 |                 */ | 
 |                 resource_info->pen_colors[pen_number]=color_name; | 
 |                 XColorBrowserWidget(display,windows,"Select",color_name); | 
 |                 if (*color_name == '\0') | 
 |                   break; | 
 |               } | 
 |             /* | 
 |               Set border color. | 
 |             */ | 
 |             (void) XParseColor(display,windows->map_info->colormap, | 
 |               resource_info->pen_colors[pen_number],&border_color); | 
 |             break; | 
 |           } | 
 |           case MatteEditFuzzCommand: | 
 |           { | 
 |             static char | 
 |               fuzz[MaxTextExtent]; | 
 |  | 
 |             static const char | 
 |               *FuzzMenu[] = | 
 |               { | 
 |                 "0%", | 
 |                 "2%", | 
 |                 "5%", | 
 |                 "10%", | 
 |                 "15%", | 
 |                 "Dialog...", | 
 |                 (char *) NULL, | 
 |               }; | 
 |  | 
 |             /* | 
 |               Select a command from the pop-up menu. | 
 |             */ | 
 |             entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu, | 
 |               command); | 
 |             if (entry < 0) | 
 |               break; | 
 |             if (entry != 5) | 
 |               { | 
 |                 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],(double) | 
 |                   QuantumRange+1.0); | 
 |                 break; | 
 |               } | 
 |             (void) CopyMagickString(fuzz,"20%",MaxTextExtent); | 
 |             (void) XDialogWidget(display,windows,"Ok", | 
 |               "Enter fuzz factor (0.0 - 99.9%):",fuzz); | 
 |             if (*fuzz == '\0') | 
 |               break; | 
 |             (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent); | 
 |             (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0); | 
 |             break; | 
 |           } | 
 |           case MatteEditValueCommand: | 
 |           { | 
 |             static char | 
 |               message[MaxTextExtent]; | 
 |  | 
 |             static const char | 
 |               *MatteMenu[] = | 
 |               { | 
 |                 "Opaque", | 
 |                 "Transparent", | 
 |                 "Dialog...", | 
 |                 (char *) NULL, | 
 |               }; | 
 |  | 
 |             /* | 
 |               Select a command from the pop-up menu. | 
 |             */ | 
 |             entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu, | 
 |               command); | 
 |             if (entry < 0) | 
 |               break; | 
 |             if (entry != 2) | 
 |               { | 
 |                 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat, | 
 |                   OpaqueAlpha); | 
 |                 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0) | 
 |                   (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat, | 
 |                     (Quantum) TransparentAlpha); | 
 |                 break; | 
 |               } | 
 |             (void) FormatLocaleString(message,MaxTextExtent, | 
 |               "Enter matte value (0 - " QuantumFormat "):",(Quantum) | 
 |               QuantumRange); | 
 |             (void) XDialogWidget(display,windows,"Matte",message,matte); | 
 |             if (*matte == '\0') | 
 |               break; | 
 |             break; | 
 |           } | 
 |           case MatteEditUndoCommand: | 
 |           { | 
 |             (void) XMagickCommand(display,resource_info,windows,UndoCommand, | 
 |               image,exception); | 
 |             break; | 
 |           } | 
 |           case MatteEditHelpCommand: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Matte Edit",ImageMatteEditHelp); | 
 |             break; | 
 |           } | 
 |           case MatteEditDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if ((event.xbutton.window != windows->image.id) && | 
 |             (event.xbutton.window != windows->magnify.id)) | 
 |           break; | 
 |         /* | 
 |           Update matte data. | 
 |         */ | 
 |         x=event.xbutton.x; | 
 |         y=event.xbutton.y; | 
 |         (void) XMagickCommand(display,resource_info,windows, | 
 |           SaveToUndoBufferCommand,image,exception); | 
 |         state|=UpdateConfigurationState; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if ((event.xbutton.window != windows->image.id) && | 
 |             (event.xbutton.window != windows->magnify.id)) | 
 |           break; | 
 |         /* | 
 |           Update colormap information. | 
 |         */ | 
 |         x=event.xbutton.x; | 
 |         y=event.xbutton.y; | 
 |         XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |         (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |         XInfoWidget(display,windows,text); | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         state&=(~UpdateConfigurationState); | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         char | 
 |           command[MaxTextExtent]; | 
 |  | 
 |         KeySym | 
 |           key_symbol; | 
 |  | 
 |         if (event.xkey.window == windows->magnify.id) | 
 |           { | 
 |             Window | 
 |               window; | 
 |  | 
 |             window=windows->magnify.id; | 
 |             while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ; | 
 |           } | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Matte Edit",ImageMatteEditHelp); | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         /* | 
 |           Map and unmap Info widget as cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |     if (event.xany.window == windows->magnify.id) | 
 |       { | 
 |         x=windows->magnify.x-windows->image.x; | 
 |         y=windows->magnify.y-windows->image.y; | 
 |       } | 
 |     x_offset=x; | 
 |     y_offset=y; | 
 |     if ((state & UpdateConfigurationState) != 0) | 
 |       { | 
 |         CacheView | 
 |           *image_view; | 
 |  | 
 |         int | 
 |           x, | 
 |           y; | 
 |  | 
 |         /* | 
 |           Matte edit is relative to image configuration. | 
 |         */ | 
 |         (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1, | 
 |           MagickTrue); | 
 |         XPutPixel(windows->image.ximage,x_offset,y_offset, | 
 |           windows->pixel_info->background_color.pixel); | 
 |         width=(unsigned int) (*image)->columns; | 
 |         height=(unsigned int) (*image)->rows; | 
 |         x=0; | 
 |         y=0; | 
 |         if (windows->image.crop_geometry != (char *) NULL) | 
 |           (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width, | 
 |             &height); | 
 |         x_offset=(int) (width*(windows->image.x+x_offset)/ | 
 |           windows->image.ximage->width+x); | 
 |         y_offset=(int) (height*(windows->image.y+y_offset)/ | 
 |           windows->image.ximage->height+y); | 
 |         if ((x_offset < 0) || (y_offset < 0)) | 
 |           continue; | 
 |         if ((x_offset >= (int) (*image)->columns) || | 
 |             (y_offset >= (int) (*image)->rows)) | 
 |           continue; | 
 |         if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse) | 
 |           return(MagickFalse); | 
 |         (*image)->matte=MagickTrue; | 
 |         image_view=AcquireCacheView(*image); | 
 |         switch (method) | 
 |         { | 
 |           case PointMethod: | 
 |           default: | 
 |           { | 
 |             /* | 
 |               Update matte information using point algorithm. | 
 |             */ | 
 |             q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset, | 
 |               (ssize_t) y_offset,1,1,exception); | 
 |             if (q == (Quantum *) NULL) | 
 |               break; | 
 |             SetPixelAlpha(*image,(Quantum) StringToLong(matte),q); | 
 |             (void) SyncCacheViewAuthenticPixels(image_view,exception); | 
 |             break; | 
 |           } | 
 |           case ReplaceMethod: | 
 |           { | 
 |             PixelInfo | 
 |               pixel, | 
 |               target; | 
 |  | 
 |             Quantum | 
 |               virtual_pixel[CompositePixelChannel]; | 
 |  | 
 |             /* | 
 |               Update matte information using replace algorithm. | 
 |             */ | 
 |             (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset, | 
 |               (ssize_t) y_offset,virtual_pixel,exception); | 
 |             target.red=virtual_pixel[RedPixelChannel]; | 
 |             target.green=virtual_pixel[GreenPixelChannel]; | 
 |             target.blue=virtual_pixel[BluePixelChannel]; | 
 |             target.alpha=virtual_pixel[AlphaPixelChannel]; | 
 |             for (y=0; y < (int) (*image)->rows; y++) | 
 |             { | 
 |               q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y, | 
 |                 (*image)->columns,1,exception); | 
 |               if (q == (Quantum *) NULL) | 
 |                 break; | 
 |               for (x=0; x < (int) (*image)->columns; x++) | 
 |               { | 
 |                 GetPixelInfoPixel(*image,q,&pixel); | 
 |                 if (IsFuzzyEquivalencePixelInfo(&pixel,&target)) | 
 |                   SetPixelAlpha(*image,(Quantum) StringToLong(matte),q); | 
 |                 q+=GetPixelChannels(*image); | 
 |               } | 
 |               if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) | 
 |                 break; | 
 |             } | 
 |             break; | 
 |           } | 
 |           case FloodfillMethod: | 
 |           case FillToBorderMethod: | 
 |           { | 
 |             ChannelType | 
 |               channel_mask; | 
 |  | 
 |             DrawInfo | 
 |               *draw_info; | 
 |  | 
 |             PixelInfo | 
 |               target; | 
 |  | 
 |             /* | 
 |               Update matte information using floodfill algorithm. | 
 |             */ | 
 |             (void) GetOneVirtualMagickPixel(*image, | 
 |               GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t) | 
 |               y_offset,&target,exception); | 
 |             if (method == FillToBorderMethod) | 
 |               { | 
 |                 target.red=(MagickRealType) ScaleShortToQuantum( | 
 |                   border_color.red); | 
 |                 target.green=(MagickRealType) ScaleShortToQuantum( | 
 |                   border_color.green); | 
 |                 target.blue=(MagickRealType) ScaleShortToQuantum( | 
 |                   border_color.blue); | 
 |               } | 
 |             draw_info=CloneDrawInfo(resource_info->image_info, | 
 |               (DrawInfo *) NULL); | 
 |             draw_info->fill.alpha=ClampToQuantum(InterpretLocaleValue(matte, | 
 |               (char **) NULL)); | 
 |             channel_mask=SetPixelChannelMask(*image,AlphaChannel);  | 
 |             (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t) | 
 |               x_offset,(ssize_t) y_offset,method == FloodfillMethod ? | 
 |               MagickFalse : MagickTrue,exception); | 
 |             (void) SetPixelChannelMap(*image,channel_mask); | 
 |             draw_info=DestroyDrawInfo(draw_info); | 
 |             break; | 
 |           } | 
 |           case ResetMethod: | 
 |           { | 
 |             /* | 
 |               Update matte information using reset algorithm. | 
 |             */ | 
 |             if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse) | 
 |               return(MagickFalse); | 
 |             for (y=0; y < (int) (*image)->rows; y++) | 
 |             { | 
 |               q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y, | 
 |                 (*image)->columns,1,exception); | 
 |               if (q == (Quantum *) NULL) | 
 |                 break; | 
 |               for (x=0; x < (int) (*image)->columns; x++) | 
 |               { | 
 |                 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q); | 
 |                 q+=GetPixelChannels(*image); | 
 |               } | 
 |               if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) | 
 |                 break; | 
 |             } | 
 |             if (StringToLong(matte) == (long) OpaqueAlpha) | 
 |               (*image)->matte=MagickFalse; | 
 |             break; | 
 |           } | 
 |         } | 
 |         image_view=DestroyCacheView(image_view); | 
 |         state&=(~UpdateConfigurationState); | 
 |       } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   (void) XFreeCursor(display,cursor); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X O p e n I m a g e                                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XOpenImage() loads an image from a file. | 
 | % | 
 | %  The format of the XOpenImage method is: | 
 | % | 
 | %     Image *XOpenImage(Display *display,XResourceInfo *resource_info, | 
 | %       XWindows *windows,const unsigned int command) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o command: A value other than zero indicates that the file is selected | 
 | %      from the command line argument list. | 
 | % | 
 | */ | 
 | static Image *XOpenImage(Display *display,XResourceInfo *resource_info, | 
 |   XWindows *windows,const MagickBooleanType command) | 
 | { | 
 |   const MagickInfo | 
 |     *magick_info; | 
 |  | 
 |   ExceptionInfo | 
 |     *exception; | 
 |  | 
 |   Image | 
 |     *nexus; | 
 |  | 
 |   ImageInfo | 
 |     *image_info; | 
 |  | 
 |   static char | 
 |     filename[MaxTextExtent] = "\0"; | 
 |  | 
 |   /* | 
 |     Request file name from user. | 
 |   */ | 
 |   if (command == MagickFalse) | 
 |     XFileBrowserWidget(display,windows,"Open",filename); | 
 |   else | 
 |     { | 
 |       char | 
 |         **filelist, | 
 |         **files; | 
 |  | 
 |       int | 
 |         count, | 
 |         status; | 
 |  | 
 |       register int | 
 |         i, | 
 |         j; | 
 |  | 
 |       /* | 
 |         Select next image from the command line. | 
 |       */ | 
 |       status=XGetCommand(display,windows->image.id,&files,&count); | 
 |       if (status == 0) | 
 |         { | 
 |           ThrowXWindowFatalException(XServerError,"UnableToGetProperty","..."); | 
 |           return((Image *) NULL); | 
 |         } | 
 |       filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist)); | 
 |       if (filelist == (char **) NULL) | 
 |         { | 
 |           ThrowXWindowFatalException(ResourceLimitError, | 
 |             "MemoryAllocationFailed","..."); | 
 |           (void) XFreeStringList(files); | 
 |           return((Image *) NULL); | 
 |         } | 
 |       j=0; | 
 |       for (i=1; i < count; i++) | 
 |         if (*files[i] != '-') | 
 |           filelist[j++]=files[i]; | 
 |       filelist[j]=(char *) NULL; | 
 |       XListBrowserWidget(display,windows,&windows->widget, | 
 |         (const char **) filelist,"Load","Select Image to Load:",filename); | 
 |       filelist=(char **) RelinquishMagickMemory(filelist); | 
 |       (void) XFreeStringList(files); | 
 |     } | 
 |   if (*filename == '\0') | 
 |     return((Image *) NULL); | 
 |   image_info=CloneImageInfo(resource_info->image_info); | 
 |   (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL, | 
 |     (void *) NULL); | 
 |   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); | 
 |   exception=AcquireExceptionInfo(); | 
 |   (void) SetImageInfo(image_info,0,exception); | 
 |   if (LocaleCompare(image_info->magick,"X") == 0) | 
 |     { | 
 |       char | 
 |         seconds[MaxTextExtent]; | 
 |  | 
 |       /* | 
 |         User may want to delay the X server screen grab. | 
 |       */ | 
 |       (void) CopyMagickString(seconds,"0",MaxTextExtent); | 
 |       (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:", | 
 |         seconds); | 
 |       if (*seconds == '\0') | 
 |         return((Image *) NULL); | 
 |       XDelay(display,(size_t) (1000*StringToLong(seconds))); | 
 |     } | 
 |   magick_info=GetMagickInfo(image_info->magick,exception); | 
 |   if ((magick_info != (const MagickInfo *) NULL) && | 
 |       (magick_info->raw != MagickFalse)) | 
 |     { | 
 |       char | 
 |         geometry[MaxTextExtent]; | 
 |  | 
 |       /* | 
 |         Request image size from the user. | 
 |       */ | 
 |       (void) CopyMagickString(geometry,"512x512",MaxTextExtent); | 
 |       if (image_info->size != (char *) NULL) | 
 |         (void) CopyMagickString(geometry,image_info->size,MaxTextExtent); | 
 |       (void) XDialogWidget(display,windows,"Load","Enter the image geometry:", | 
 |         geometry); | 
 |       (void) CloneString(&image_info->size,geometry); | 
 |     } | 
 |   /* | 
 |     Load the image. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); | 
 |   nexus=ReadImage(image_info,exception); | 
 |   CatchException(exception); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if (nexus != (Image *) NULL) | 
 |     XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |       windows->im_next_image,CurrentTime); | 
 |   else | 
 |     { | 
 |       char | 
 |         *text, | 
 |         **textlist; | 
 |  | 
 |       /* | 
 |         Unknown image format. | 
 |       */ | 
 |       text=FileToString(filename,~0,exception); | 
 |       if (text == (char *) NULL) | 
 |         return((Image *) NULL); | 
 |       textlist=StringToList(text); | 
 |       if (textlist != (char **) NULL) | 
 |         { | 
 |           char | 
 |             title[MaxTextExtent]; | 
 |  | 
 |           register int | 
 |             i; | 
 |  | 
 |           (void) FormatLocaleString(title,MaxTextExtent, | 
 |             "Unknown format: %s",filename); | 
 |           XTextViewWidget(display,resource_info,windows,MagickTrue,title, | 
 |             (const char **) textlist); | 
 |           for (i=0; textlist[i] != (char *) NULL; i++) | 
 |             textlist[i]=DestroyString(textlist[i]); | 
 |           textlist=(char **) RelinquishMagickMemory(textlist); | 
 |         } | 
 |       text=DestroyString(text); | 
 |     } | 
 |   exception=DestroyExceptionInfo(exception); | 
 |   image_info=DestroyImageInfo(image_info); | 
 |   return(nexus); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X P a n I m a g e                                                         % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XPanImage() pans the image until the mouse button is released. | 
 | % | 
 | %  The format of the XPanImage method is: | 
 | % | 
 | %      void XPanImage(Display *display,XWindows *windows,XEvent *event, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 XWindows structure. | 
 | % | 
 | %    o event: Specifies a pointer to a XEvent structure.  If it is NULL, | 
 | %      the entire image is refreshed. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static void XPanImage(Display *display,XWindows *windows,XEvent *event, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   MagickRealType | 
 |     x_factor, | 
 |     y_factor; | 
 |  | 
 |   RectangleInfo | 
 |     pan_info; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   /* | 
 |     Define cursor. | 
 |   */ | 
 |   if ((windows->image.ximage->width > (int) windows->image.width) && | 
 |       (windows->image.ximage->height > (int) windows->image.height)) | 
 |     cursor=XCreateFontCursor(display,XC_fleur); | 
 |   else | 
 |     if (windows->image.ximage->width > (int) windows->image.width) | 
 |       cursor=XCreateFontCursor(display,XC_sb_h_double_arrow); | 
 |     else | 
 |       if (windows->image.ximage->height > (int) windows->image.height) | 
 |         cursor=XCreateFontCursor(display,XC_sb_v_double_arrow); | 
 |       else | 
 |         cursor=XCreateFontCursor(display,XC_arrow); | 
 |   (void) XCheckDefineCursor(display,windows->pan.id,cursor); | 
 |   /* | 
 |     Pan image as pointer moves until the mouse button is released. | 
 |   */ | 
 |   x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width; | 
 |   y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height; | 
 |   pan_info.width=windows->pan.width*windows->image.width/ | 
 |     windows->image.ximage->width; | 
 |   pan_info.height=windows->pan.height*windows->image.height/ | 
 |     windows->image.ximage->height; | 
 |   pan_info.x=0; | 
 |   pan_info.y=0; | 
 |   state=UpdateConfigurationState; | 
 |   do | 
 |   { | 
 |     switch (event->type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         /* | 
 |           User choose an initial pan location. | 
 |         */ | 
 |         pan_info.x=(ssize_t) event->xbutton.x; | 
 |         pan_info.y=(ssize_t) event->xbutton.y; | 
 |         state|=UpdateConfigurationState; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |       { | 
 |         /* | 
 |           User has finished panning the image. | 
 |         */ | 
 |         pan_info.x=(ssize_t) event->xbutton.x; | 
 |         pan_info.y=(ssize_t) event->xbutton.y; | 
 |         state|=UpdateConfigurationState | ExitState; | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         pan_info.x=(ssize_t) event->xmotion.x; | 
 |         pan_info.y=(ssize_t) event->xmotion.y; | 
 |         state|=UpdateConfigurationState; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |     if ((state & UpdateConfigurationState) != 0) | 
 |       { | 
 |         /* | 
 |           Check boundary conditions. | 
 |         */ | 
 |         if (pan_info.x < (ssize_t) (pan_info.width/2)) | 
 |           pan_info.x=0; | 
 |         else | 
 |           pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2))); | 
 |         if (pan_info.x < 0) | 
 |           pan_info.x=0; | 
 |         else | 
 |           if ((int) (pan_info.x+windows->image.width) > | 
 |               windows->image.ximage->width) | 
 |             pan_info.x=(ssize_t) | 
 |               (windows->image.ximage->width-windows->image.width); | 
 |         if (pan_info.y < (ssize_t) (pan_info.height/2)) | 
 |           pan_info.y=0; | 
 |         else | 
 |           pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2))); | 
 |         if (pan_info.y < 0) | 
 |           pan_info.y=0; | 
 |         else | 
 |           if ((int) (pan_info.y+windows->image.height) > | 
 |               windows->image.ximage->height) | 
 |             pan_info.y=(ssize_t) | 
 |               (windows->image.ximage->height-windows->image.height); | 
 |         if ((windows->image.x != (int) pan_info.x) || | 
 |             (windows->image.y != (int) pan_info.y)) | 
 |           { | 
 |             /* | 
 |               Display image pan offset. | 
 |             */ | 
 |             windows->image.x=(int) pan_info.x; | 
 |             windows->image.y=(int) pan_info.y; | 
 |             (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ", | 
 |               windows->image.width,windows->image.height,windows->image.x, | 
 |               windows->image.y); | 
 |             XInfoWidget(display,windows,text); | 
 |             /* | 
 |               Refresh Image window. | 
 |             */ | 
 |             XDrawPanRectangle(display,windows); | 
 |             XRefreshWindow(display,&windows->image,(XEvent *) NULL); | 
 |           } | 
 |         state&=(~UpdateConfigurationState); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     if ((state & ExitState) == 0) | 
 |       XScreenEvent(display,windows,event,exception); | 
 |   } while ((state & ExitState) == 0); | 
 |   /* | 
 |     Restore cursor. | 
 |   */ | 
 |   (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor); | 
 |   (void) XFreeCursor(display,cursor); | 
 |   (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X P a s t e I m a g e                                                     % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XPasteImage() pastes an image previously saved with XCropImage in the X | 
 | %  window image at a location the user chooses with the pointer. | 
 | % | 
 | %  The format of the XPasteImage method is: | 
 | % | 
 | %      MagickBooleanType XPasteImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XPasteImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *PasteMenu[] = | 
 |     { | 
 |       "Operator", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static const ModeType | 
 |     PasteCommands[] = | 
 |     { | 
 |       PasteOperatorsCommand, | 
 |       PasteHelpCommand, | 
 |       PasteDismissCommand | 
 |     }; | 
 |  | 
 |   static CompositeOperator | 
 |     compose = CopyCompositeOp; | 
 |  | 
 |   char | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   Image | 
 |     *paste_image; | 
 |  | 
 |   int | 
 |     entry, | 
 |     id, | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     scale_factor; | 
 |  | 
 |   RectangleInfo | 
 |     highlight_info, | 
 |     paste_info; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   /* | 
 |     Copy image. | 
 |   */ | 
 |   if (resource_info->copy_image == (Image *) NULL) | 
 |     return(MagickFalse); | 
 |   paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception); | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"Paste"); | 
 |   windows->command.data=1; | 
 |   (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   paste_info.x=(ssize_t) windows->image.x+x; | 
 |   paste_info.y=(ssize_t) windows->image.y+y; | 
 |   paste_info.width=0; | 
 |   paste_info.height=0; | 
 |   cursor=XCreateFontCursor(display,XC_ul_angle); | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ", | 
 |           (long) paste_info.x,(long) paste_info.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     highlight_info=paste_info; | 
 |     highlight_info.x=paste_info.x-windows->image.x; | 
 |     highlight_info.y=paste_info.y-windows->image.y; | 
 |     XHighlightRectangle(display,windows->image.id, | 
 |       windows->image.highlight_context,&highlight_info); | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     XHighlightRectangle(display,windows->image.id, | 
 |       windows->image.highlight_context,&highlight_info); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,PasteMenu,&event); | 
 |         if (id < 0) | 
 |           continue; | 
 |         switch (PasteCommands[id]) | 
 |         { | 
 |           case PasteOperatorsCommand: | 
 |           { | 
 |             char | 
 |               command[MaxTextExtent], | 
 |               **operators; | 
 |  | 
 |             /* | 
 |               Select a command from the pop-up menu. | 
 |             */ | 
 |             operators=GetCommandOptions(MagickComposeOptions); | 
 |             if (operators == (char **) NULL) | 
 |               break; | 
 |             entry=XMenuWidget(display,windows,PasteMenu[id], | 
 |               (const char **) operators,command); | 
 |             if (entry >= 0) | 
 |               compose=(CompositeOperator) ParseCommandOption( | 
 |                 MagickComposeOptions,MagickFalse,operators[entry]); | 
 |             operators=DestroyStringList(operators); | 
 |             break; | 
 |           } | 
 |           case PasteHelpCommand: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Composite",ImagePasteHelp); | 
 |             break; | 
 |           } | 
 |           case PasteDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Button Press: 0x%lx %u +%d+%d",event.xbutton.window, | 
 |             event.xbutton.button,event.xbutton.x,event.xbutton.y); | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Paste rectangle is relative to image configuration. | 
 |         */ | 
 |         width=(unsigned int) image->columns; | 
 |         height=(unsigned int) image->rows; | 
 |         x=0; | 
 |         y=0; | 
 |         if (windows->image.crop_geometry != (char *) NULL) | 
 |           (void) XParseGeometry(windows->image.crop_geometry,&x,&y, | 
 |             &width,&height); | 
 |         scale_factor=(MagickRealType) windows->image.ximage->width/width; | 
 |         paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5); | 
 |         scale_factor=(MagickRealType) windows->image.ximage->height/height; | 
 |         paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5); | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         paste_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |         paste_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |       { | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Button Release: 0x%lx %u +%d+%d",event.xbutton.window, | 
 |             event.xbutton.button,event.xbutton.x,event.xbutton.y); | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         if ((paste_info.width != 0) && (paste_info.height != 0)) | 
 |           { | 
 |             /* | 
 |               User has selected the location of the paste image. | 
 |             */ | 
 |             paste_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |             paste_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |             state|=ExitState; | 
 |           } | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         char | 
 |           command[MaxTextExtent]; | 
 |  | 
 |         KeySym | 
 |           key_symbol; | 
 |  | 
 |         int | 
 |           length; | 
 |  | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         length=XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         *(command+length)='\0'; | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Key press: 0x%lx (%s)",(long) key_symbol,command); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             paste_image=DestroyImage(paste_image); | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Image Composite",ImagePasteHelp); | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXinvert); | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         /* | 
 |           Map and unmap Info widget as text cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |         paste_info.x=(ssize_t) windows->image.x+x; | 
 |         paste_info.y=(ssize_t) windows->image.y+y; | 
 |         break; | 
 |       } | 
 |       default: | 
 |       { | 
 |         if (image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d", | 
 |             event.type); | 
 |         break; | 
 |       } | 
 |     } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   (void) XFreeCursor(display,cursor); | 
 |   if ((state & EscapeState) != 0) | 
 |     return(MagickTrue); | 
 |   /* | 
 |     Image pasting is relative to image configuration. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   width=(unsigned int) image->columns; | 
 |   height=(unsigned int) image->rows; | 
 |   x=0; | 
 |   y=0; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |   scale_factor=(MagickRealType) width/windows->image.ximage->width; | 
 |   paste_info.x+=x; | 
 |   paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5); | 
 |   paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5); | 
 |   scale_factor=(MagickRealType) height/windows->image.ximage->height; | 
 |   paste_info.y+=y; | 
 |   paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5); | 
 |   paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5); | 
 |   /* | 
 |     Paste image with X Image window. | 
 |   */ | 
 |   (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y, | 
 |     exception); | 
 |   paste_image=DestroyImage(paste_image); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   /* | 
 |     Update image colormap. | 
 |   */ | 
 |   XConfigureImageColormap(display,resource_info,windows,image,exception); | 
 |   (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X P r i n t I m a g e                                                     % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XPrintImage() prints an image to a Postscript printer. | 
 | % | 
 | %  The format of the XPrintImage method is: | 
 | % | 
 | %      MagickBooleanType XPrintImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XPrintImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     filename[MaxTextExtent], | 
 |     geometry[MaxTextExtent]; | 
 |  | 
 |   Image | 
 |     *print_image; | 
 |  | 
 |   ImageInfo | 
 |     *image_info; | 
 |  | 
 |   MagickStatusType | 
 |     status; | 
 |  | 
 |   /* | 
 |     Request Postscript page geometry from user. | 
 |   */ | 
 |   image_info=CloneImageInfo(resource_info->image_info); | 
 |   (void) FormatLocaleString(geometry,MaxTextExtent,"Letter"); | 
 |   if (image_info->page != (char *) NULL) | 
 |     (void) CopyMagickString(geometry,image_info->page,MaxTextExtent); | 
 |   XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select", | 
 |     "Select Postscript Page Geometry:",geometry); | 
 |   if (*geometry == '\0') | 
 |     return(MagickTrue); | 
 |   image_info->page=GetPageGeometry(geometry); | 
 |   /* | 
 |     Apply image transforms. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   print_image=CloneImage(image,0,0,MagickTrue,exception); | 
 |   if (print_image == (Image *) NULL) | 
 |     return(MagickFalse); | 
 |   (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!", | 
 |     windows->image.ximage->width,windows->image.ximage->height); | 
 |   (void) TransformImage(&print_image,windows->image.crop_geometry,geometry, | 
 |     exception); | 
 |   /* | 
 |     Print image. | 
 |   */ | 
 |   (void) AcquireUniqueFilename(filename); | 
 |   (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s", | 
 |     filename); | 
 |   status=WriteImage(image_info,print_image,exception); | 
 |   (void) RelinquishUniqueFileResource(filename); | 
 |   print_image=DestroyImage(print_image); | 
 |   image_info=DestroyImageInfo(image_info); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   return(status != 0 ? MagickTrue : MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X R O I I m a g e                                                         % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XROIImage() applies an image processing technique to a region of interest. | 
 | % | 
 | %  The format of the XROIImage method is: | 
 | % | 
 | %      MagickBooleanType XROIImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XROIImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 | #define ApplyMenus  7 | 
 |  | 
 |   static const char | 
 |     *ROIMenu[] = | 
 |     { | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }, | 
 |     *ApplyMenu[] = | 
 |     { | 
 |       "File", | 
 |       "Edit", | 
 |       "Transform", | 
 |       "Enhance", | 
 |       "Effects", | 
 |       "F/X", | 
 |       "Miscellany", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }, | 
 |     *FileMenu[] = | 
 |     { | 
 |       "Save...", | 
 |       "Print...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *EditMenu[] = | 
 |     { | 
 |       "Undo", | 
 |       "Redo", | 
 |       (char *) NULL | 
 |     }, | 
 |     *TransformMenu[] = | 
 |     { | 
 |       "Flop", | 
 |       "Flip", | 
 |       "Rotate Right", | 
 |       "Rotate Left", | 
 |       (char *) NULL | 
 |     }, | 
 |     *EnhanceMenu[] = | 
 |     { | 
 |       "Hue...", | 
 |       "Saturation...", | 
 |       "Brightness...", | 
 |       "Gamma...", | 
 |       "Spiff", | 
 |       "Dull", | 
 |       "Contrast Stretch...", | 
 |       "Sigmoidal Contrast...", | 
 |       "Normalize", | 
 |       "Equalize", | 
 |       "Negate", | 
 |       "Grayscale", | 
 |       "Map...", | 
 |       "Quantize...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *EffectsMenu[] = | 
 |     { | 
 |       "Despeckle", | 
 |       "Emboss", | 
 |       "Reduce Noise", | 
 |       "Add Noise", | 
 |       "Sharpen...", | 
 |       "Blur...", | 
 |       "Threshold...", | 
 |       "Edge Detect...", | 
 |       "Spread...", | 
 |       "Shade...", | 
 |       "Raise...", | 
 |       "Segment...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *FXMenu[] = | 
 |     { | 
 |       "Solarize...", | 
 |       "Sepia Tone...", | 
 |       "Swirl...", | 
 |       "Implode...", | 
 |       "Vignette...", | 
 |       "Wave...", | 
 |       "Oil Paint...", | 
 |       "Charcoal Draw...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *MiscellanyMenu[] = | 
 |     { | 
 |       "Image Info", | 
 |       "Zoom Image", | 
 |       "Show Preview...", | 
 |       "Show Histogram", | 
 |       "Show Matte", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static const char | 
 |     **Menus[ApplyMenus] = | 
 |     { | 
 |       FileMenu, | 
 |       EditMenu, | 
 |       TransformMenu, | 
 |       EnhanceMenu, | 
 |       EffectsMenu, | 
 |       FXMenu, | 
 |       MiscellanyMenu | 
 |     }; | 
 |  | 
 |   static const CommandType | 
 |     ApplyCommands[] = | 
 |     { | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       HelpCommand, | 
 |       QuitCommand | 
 |     }, | 
 |     FileCommands[] = | 
 |     { | 
 |       SaveCommand, | 
 |       PrintCommand | 
 |     }, | 
 |     EditCommands[] = | 
 |     { | 
 |       UndoCommand, | 
 |       RedoCommand | 
 |     }, | 
 |     TransformCommands[] = | 
 |     { | 
 |       FlopCommand, | 
 |       FlipCommand, | 
 |       RotateRightCommand, | 
 |       RotateLeftCommand | 
 |     }, | 
 |     EnhanceCommands[] = | 
 |     { | 
 |       HueCommand, | 
 |       SaturationCommand, | 
 |       BrightnessCommand, | 
 |       GammaCommand, | 
 |       SpiffCommand, | 
 |       DullCommand, | 
 |       ContrastStretchCommand, | 
 |       SigmoidalContrastCommand, | 
 |       NormalizeCommand, | 
 |       EqualizeCommand, | 
 |       NegateCommand, | 
 |       GrayscaleCommand, | 
 |       MapCommand, | 
 |       QuantizeCommand | 
 |     }, | 
 |     EffectsCommands[] = | 
 |     { | 
 |       DespeckleCommand, | 
 |       EmbossCommand, | 
 |       ReduceNoiseCommand, | 
 |       AddNoiseCommand, | 
 |       SharpenCommand, | 
 |       BlurCommand, | 
 |       EdgeDetectCommand, | 
 |       SpreadCommand, | 
 |       ShadeCommand, | 
 |       RaiseCommand, | 
 |       SegmentCommand | 
 |     }, | 
 |     FXCommands[] = | 
 |     { | 
 |       SolarizeCommand, | 
 |       SepiaToneCommand, | 
 |       SwirlCommand, | 
 |       ImplodeCommand, | 
 |       VignetteCommand, | 
 |       WaveCommand, | 
 |       OilPaintCommand, | 
 |       CharcoalDrawCommand | 
 |     }, | 
 |     MiscellanyCommands[] = | 
 |     { | 
 |       InfoCommand, | 
 |       ZoomCommand, | 
 |       ShowPreviewCommand, | 
 |       ShowHistogramCommand, | 
 |       ShowMatteCommand | 
 |     }, | 
 |     ROICommands[] = | 
 |     { | 
 |       ROIHelpCommand, | 
 |       ROIDismissCommand | 
 |     }; | 
 |  | 
 |   static const CommandType | 
 |     *Commands[ApplyMenus] = | 
 |     { | 
 |       FileCommands, | 
 |       EditCommands, | 
 |       TransformCommands, | 
 |       EnhanceCommands, | 
 |       EffectsCommands, | 
 |       FXCommands, | 
 |       MiscellanyCommands | 
 |     }; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   CommandType | 
 |     command_type; | 
 |  | 
 |   Cursor | 
 |     cursor; | 
 |  | 
 |   Image | 
 |     *roi_image; | 
 |  | 
 |   int | 
 |     entry, | 
 |     id, | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     scale_factor; | 
 |  | 
 |   MagickProgressMonitor | 
 |     progress_monitor; | 
 |  | 
 |   RectangleInfo | 
 |     crop_info, | 
 |     highlight_info, | 
 |     roi_info; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     state; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   /* | 
 |     Map Command widget. | 
 |   */ | 
 |   (void) CloneString(&windows->command.name,"ROI"); | 
 |   windows->command.data=0; | 
 |   (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL); | 
 |   (void) XMapRaised(display,windows->command.id); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_update_widget,CurrentTime); | 
 |   /* | 
 |     Track pointer until button 1 is pressed. | 
 |   */ | 
 |   XQueryPosition(display,windows->image.id,&x,&y); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask | PointerMotionMask); | 
 |   roi_info.x=(ssize_t) windows->image.x+x; | 
 |   roi_info.y=(ssize_t) windows->image.y+y; | 
 |   roi_info.width=0; | 
 |   roi_info.height=0; | 
 |   cursor=XCreateFontCursor(display,XC_fleur); | 
 |   state=DefaultState; | 
 |   do | 
 |   { | 
 |     if (windows->info.mapped != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Display pointer position. | 
 |         */ | 
 |         (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ", | 
 |           (long) roi_info.x,(long) roi_info.y); | 
 |         XInfoWidget(display,windows,text); | 
 |       } | 
 |     /* | 
 |       Wait for next event. | 
 |     */ | 
 |     XScreenEvent(display,windows,&event,exception); | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,ROIMenu,&event); | 
 |         if (id < 0) | 
 |           continue; | 
 |         switch (ROICommands[id]) | 
 |         { | 
 |           case ROIHelpCommand: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Region of Interest",ImageROIHelp); | 
 |             break; | 
 |           } | 
 |           case ROIDismissCommand: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (event.xbutton.button != Button1) | 
 |           break; | 
 |         if (event.xbutton.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Note first corner of region of interest rectangle-- exit loop. | 
 |         */ | 
 |         (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |         roi_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |         roi_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |         state|=ExitState; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |         break; | 
 |       case Expose: | 
 |         break; | 
 |       case KeyPress: | 
 |       { | 
 |         KeySym | 
 |           key_symbol; | 
 |  | 
 |         if (event.xkey.window != windows->image.id) | 
 |           break; | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         switch ((int) key_symbol) | 
 |         { | 
 |           case XK_Escape: | 
 |           case XK_F20: | 
 |           { | 
 |             /* | 
 |               Prematurely exit. | 
 |             */ | 
 |             state|=EscapeState; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case XK_F1: | 
 |           case XK_Help: | 
 |           { | 
 |             XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |               "Help Viewer - Region of Interest",ImageROIHelp); | 
 |             break; | 
 |           } | 
 |           default: | 
 |           { | 
 |             (void) XBell(display,0); | 
 |             break; | 
 |           } | 
 |         } | 
 |         break; | 
 |       } | 
 |       case MotionNotify: | 
 |       { | 
 |         /* | 
 |           Map and unmap Info widget as text cursor crosses its boundaries. | 
 |         */ | 
 |         x=event.xmotion.x; | 
 |         y=event.xmotion.y; | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           { | 
 |             if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                 (y < (int) (windows->info.y+windows->info.height))) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |           } | 
 |         else | 
 |           if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |               (y > (int) (windows->info.y+windows->info.height))) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |         roi_info.x=(ssize_t) windows->image.x+x; | 
 |         roi_info.y=(ssize_t) windows->image.y+y; | 
 |         break; | 
 |       } | 
 |       default: | 
 |         break; | 
 |     } | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSelectInput(display,windows->image.id, | 
 |     windows->image.attributes.event_mask); | 
 |   if ((state & EscapeState) != 0) | 
 |     { | 
 |       /* | 
 |         User want to exit without region of interest. | 
 |       */ | 
 |       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       (void) XFreeCursor(display,cursor); | 
 |       return(MagickTrue); | 
 |     } | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |   do | 
 |   { | 
 |     /* | 
 |       Size rectangle as pointer moves until the mouse button is released. | 
 |     */ | 
 |     x=(int) roi_info.x; | 
 |     y=(int) roi_info.y; | 
 |     roi_info.width=0; | 
 |     roi_info.height=0; | 
 |     state=DefaultState; | 
 |     do | 
 |     { | 
 |       highlight_info=roi_info; | 
 |       highlight_info.x=roi_info.x-windows->image.x; | 
 |       highlight_info.y=roi_info.y-windows->image.y; | 
 |       if ((highlight_info.width > 3) && (highlight_info.height > 3)) | 
 |         { | 
 |           /* | 
 |             Display info and draw region of interest rectangle. | 
 |           */ | 
 |           if (windows->info.mapped == MagickFalse) | 
 |             (void) XMapWindow(display,windows->info.id); | 
 |           (void) FormatLocaleString(text,MaxTextExtent, | 
 |             " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double) | 
 |             roi_info.height,(double) roi_info.x,(double) roi_info.y); | 
 |           XInfoWidget(display,windows,text); | 
 |           XHighlightRectangle(display,windows->image.id, | 
 |             windows->image.highlight_context,&highlight_info); | 
 |         } | 
 |       else | 
 |         if (windows->info.mapped != MagickFalse) | 
 |           (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       /* | 
 |         Wait for next event. | 
 |       */ | 
 |       XScreenEvent(display,windows,&event,exception); | 
 |       if ((highlight_info.width > 3) && (highlight_info.height > 3)) | 
 |         XHighlightRectangle(display,windows->image.id, | 
 |           windows->image.highlight_context,&highlight_info); | 
 |       switch (event.type) | 
 |       { | 
 |         case ButtonPress: | 
 |         { | 
 |           roi_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |           roi_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |           break; | 
 |         } | 
 |         case ButtonRelease: | 
 |         { | 
 |           /* | 
 |             User has committed to region of interest rectangle. | 
 |           */ | 
 |           roi_info.x=(ssize_t) windows->image.x+event.xbutton.x; | 
 |           roi_info.y=(ssize_t) windows->image.y+event.xbutton.y; | 
 |           XSetCursorState(display,windows,MagickFalse); | 
 |           state|=ExitState; | 
 |           if (LocaleCompare(windows->command.name,"Apply") == 0) | 
 |             break; | 
 |           (void) CloneString(&windows->command.name,"Apply"); | 
 |           windows->command.data=ApplyMenus; | 
 |           (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL); | 
 |           break; | 
 |         } | 
 |         case Expose: | 
 |           break; | 
 |         case MotionNotify: | 
 |         { | 
 |           roi_info.x=(ssize_t) windows->image.x+event.xmotion.x; | 
 |           roi_info.y=(ssize_t) windows->image.y+event.xmotion.y; | 
 |         } | 
 |         default: | 
 |           break; | 
 |       } | 
 |       if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) || | 
 |           ((state & ExitState) != 0)) | 
 |         { | 
 |           /* | 
 |             Check boundary conditions. | 
 |           */ | 
 |           if (roi_info.x < 0) | 
 |             roi_info.x=0; | 
 |           else | 
 |             if (roi_info.x > (ssize_t) windows->image.ximage->width) | 
 |               roi_info.x=(ssize_t) windows->image.ximage->width; | 
 |           if ((int) roi_info.x < x) | 
 |             roi_info.width=(unsigned int) (x-roi_info.x); | 
 |           else | 
 |             { | 
 |               roi_info.width=(unsigned int) (roi_info.x-x); | 
 |               roi_info.x=(ssize_t) x; | 
 |             } | 
 |           if (roi_info.y < 0) | 
 |             roi_info.y=0; | 
 |           else | 
 |             if (roi_info.y > (ssize_t) windows->image.ximage->height) | 
 |               roi_info.y=(ssize_t) windows->image.ximage->height; | 
 |           if ((int) roi_info.y < y) | 
 |             roi_info.height=(unsigned int) (y-roi_info.y); | 
 |           else | 
 |             { | 
 |               roi_info.height=(unsigned int) (roi_info.y-y); | 
 |               roi_info.y=(ssize_t) y; | 
 |             } | 
 |         } | 
 |     } while ((state & ExitState) == 0); | 
 |     /* | 
 |       Wait for user to grab a corner of the rectangle or press return. | 
 |     */ | 
 |     state=DefaultState; | 
 |     command_type=NullCommand; | 
 |     (void) XMapWindow(display,windows->info.id); | 
 |     do | 
 |     { | 
 |       if (windows->info.mapped != MagickFalse) | 
 |         { | 
 |           /* | 
 |             Display pointer position. | 
 |           */ | 
 |           (void) FormatLocaleString(text,MaxTextExtent, | 
 |             " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double) | 
 |             roi_info.height,(double) roi_info.x,(double) roi_info.y); | 
 |           XInfoWidget(display,windows,text); | 
 |         } | 
 |       highlight_info=roi_info; | 
 |       highlight_info.x=roi_info.x-windows->image.x; | 
 |       highlight_info.y=roi_info.y-windows->image.y; | 
 |       if ((highlight_info.width <= 3) || (highlight_info.height <= 3)) | 
 |         { | 
 |           state|=EscapeState; | 
 |           state|=ExitState; | 
 |           break; | 
 |         } | 
 |       if ((state & UpdateRegionState) != 0) | 
 |         { | 
 |           (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |           switch (command_type) | 
 |           { | 
 |             case UndoCommand: | 
 |             case RedoCommand: | 
 |             { | 
 |               (void) XMagickCommand(display,resource_info,windows,command_type, | 
 |                 image,exception); | 
 |               break; | 
 |             } | 
 |             default: | 
 |             { | 
 |               /* | 
 |                 Region of interest is relative to image configuration. | 
 |               */ | 
 |               progress_monitor=SetImageProgressMonitor(*image, | 
 |                 (MagickProgressMonitor) NULL,(*image)->client_data); | 
 |               crop_info=roi_info; | 
 |               width=(unsigned int) (*image)->columns; | 
 |               height=(unsigned int) (*image)->rows; | 
 |               x=0; | 
 |               y=0; | 
 |               if (windows->image.crop_geometry != (char *) NULL) | 
 |                 (void) XParseGeometry(windows->image.crop_geometry,&x,&y, | 
 |                   &width,&height); | 
 |               scale_factor=(MagickRealType) width/windows->image.ximage->width; | 
 |               crop_info.x+=x; | 
 |               crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5); | 
 |               crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5); | 
 |               scale_factor=(MagickRealType) | 
 |                 height/windows->image.ximage->height; | 
 |               crop_info.y+=y; | 
 |               crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5); | 
 |               crop_info.height=(unsigned int) | 
 |                 (scale_factor*crop_info.height+0.5); | 
 |               roi_image=CropImage(*image,&crop_info,exception); | 
 |               (void) SetImageProgressMonitor(*image,progress_monitor, | 
 |                 (*image)->client_data); | 
 |               if (roi_image == (Image *) NULL) | 
 |                 continue; | 
 |               /* | 
 |                 Apply image processing technique to the region of interest. | 
 |               */ | 
 |               windows->image.orphan=MagickTrue; | 
 |               (void) XMagickCommand(display,resource_info,windows,command_type, | 
 |                 &roi_image,exception); | 
 |               progress_monitor=SetImageProgressMonitor(*image, | 
 |                 (MagickProgressMonitor) NULL,(*image)->client_data); | 
 |               (void) XMagickCommand(display,resource_info,windows, | 
 |                 SaveToUndoBufferCommand,image,exception); | 
 |               windows->image.orphan=MagickFalse; | 
 |               (void) CompositeImage(*image,CopyCompositeOp,roi_image, | 
 |                 crop_info.x,crop_info.y,exception); | 
 |               roi_image=DestroyImage(roi_image); | 
 |               (void) SetImageProgressMonitor(*image,progress_monitor, | 
 |                 (*image)->client_data); | 
 |               break; | 
 |             } | 
 |           } | 
 |           if (command_type != InfoCommand) | 
 |             { | 
 |               XConfigureImageColormap(display,resource_info,windows,*image, | 
 |                 exception); | 
 |               (void) XConfigureImage(display,resource_info,windows,*image, | 
 |                 exception); | 
 |             } | 
 |           XCheckRefreshWindows(display,windows); | 
 |           XInfoWidget(display,windows,text); | 
 |           (void) XSetFunction(display,windows->image.highlight_context, | 
 |             GXinvert); | 
 |           state&=(~UpdateRegionState); | 
 |         } | 
 |       XHighlightRectangle(display,windows->image.id, | 
 |         windows->image.highlight_context,&highlight_info); | 
 |       XScreenEvent(display,windows,&event,exception); | 
 |       if (event.xany.window == windows->command.id) | 
 |         { | 
 |           /* | 
 |             Select a command from the Command widget. | 
 |           */ | 
 |           (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |           command_type=NullCommand; | 
 |           id=XCommandWidget(display,windows,ApplyMenu,&event); | 
 |           if (id >= 0) | 
 |             { | 
 |               (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent); | 
 |               command_type=ApplyCommands[id]; | 
 |               if (id < ApplyMenus) | 
 |                 { | 
 |                   /* | 
 |                     Select a command from a pop-up menu. | 
 |                   */ | 
 |                   entry=XMenuWidget(display,windows,ApplyMenu[id], | 
 |                     (const char **) Menus[id],command); | 
 |                   if (entry >= 0) | 
 |                     { | 
 |                       (void) CopyMagickString(command,Menus[id][entry], | 
 |                         MaxTextExtent); | 
 |                       command_type=Commands[id][entry]; | 
 |                     } | 
 |                 } | 
 |             } | 
 |           (void) XSetFunction(display,windows->image.highlight_context, | 
 |             GXinvert); | 
 |           XHighlightRectangle(display,windows->image.id, | 
 |             windows->image.highlight_context,&highlight_info); | 
 |           if (command_type == HelpCommand) | 
 |             { | 
 |               (void) XSetFunction(display,windows->image.highlight_context, | 
 |                 GXcopy); | 
 |               XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                 "Help Viewer - Region of Interest",ImageROIHelp); | 
 |               (void) XSetFunction(display,windows->image.highlight_context, | 
 |                 GXinvert); | 
 |               continue; | 
 |             } | 
 |           if (command_type == QuitCommand) | 
 |             { | 
 |               /* | 
 |                 exit. | 
 |               */ | 
 |               state|=EscapeState; | 
 |               state|=ExitState; | 
 |               continue; | 
 |             } | 
 |           if (command_type != NullCommand) | 
 |             state|=UpdateRegionState; | 
 |           continue; | 
 |         } | 
 |       XHighlightRectangle(display,windows->image.id, | 
 |         windows->image.highlight_context,&highlight_info); | 
 |       switch (event.type) | 
 |       { | 
 |         case ButtonPress: | 
 |         { | 
 |           x=windows->image.x; | 
 |           y=windows->image.y; | 
 |           if (event.xbutton.button != Button1) | 
 |             break; | 
 |           if (event.xbutton.window != windows->image.id) | 
 |             break; | 
 |           x=windows->image.x+event.xbutton.x; | 
 |           y=windows->image.y+event.xbutton.y; | 
 |           if ((x < (int) (roi_info.x+RoiDelta)) && | 
 |               (x > (int) (roi_info.x-RoiDelta)) && | 
 |               (y < (int) (roi_info.y+RoiDelta)) && | 
 |               (y > (int) (roi_info.y-RoiDelta))) | 
 |             { | 
 |               roi_info.x=(ssize_t) (roi_info.x+roi_info.width); | 
 |               roi_info.y=(ssize_t) (roi_info.y+roi_info.height); | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |           if ((x < (int) (roi_info.x+RoiDelta)) && | 
 |               (x > (int) (roi_info.x-RoiDelta)) && | 
 |               (y < (int) (roi_info.y+roi_info.height+RoiDelta)) && | 
 |               (y > (int) (roi_info.y+roi_info.height-RoiDelta))) | 
 |             { | 
 |               roi_info.x=(ssize_t) (roi_info.x+roi_info.width); | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |           if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) && | 
 |               (x > (int) (roi_info.x+roi_info.width-RoiDelta)) && | 
 |               (y < (int) (roi_info.y+RoiDelta)) && | 
 |               (y > (int) (roi_info.y-RoiDelta))) | 
 |             { | 
 |               roi_info.y=(ssize_t) (roi_info.y+roi_info.height); | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |           if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) && | 
 |               (x > (int) (roi_info.x+roi_info.width-RoiDelta)) && | 
 |               (y < (int) (roi_info.y+roi_info.height+RoiDelta)) && | 
 |               (y > (int) (roi_info.y+roi_info.height-RoiDelta))) | 
 |             { | 
 |               state|=UpdateConfigurationState; | 
 |               break; | 
 |             } | 
 |         } | 
 |         case ButtonRelease: | 
 |         { | 
 |           if (event.xbutton.window == windows->pan.id) | 
 |             if ((highlight_info.x != crop_info.x-windows->image.x) || | 
 |                 (highlight_info.y != crop_info.y-windows->image.y)) | 
 |               XHighlightRectangle(display,windows->image.id, | 
 |                 windows->image.highlight_context,&highlight_info); | 
 |           (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id, | 
 |             event.xbutton.time); | 
 |           break; | 
 |         } | 
 |         case Expose: | 
 |         { | 
 |           if (event.xexpose.window == windows->image.id) | 
 |             if (event.xexpose.count == 0) | 
 |               { | 
 |                 event.xexpose.x=(int) highlight_info.x; | 
 |                 event.xexpose.y=(int) highlight_info.y; | 
 |                 event.xexpose.width=(int) highlight_info.width; | 
 |                 event.xexpose.height=(int) highlight_info.height; | 
 |                 XRefreshWindow(display,&windows->image,&event); | 
 |               } | 
 |           if (event.xexpose.window == windows->info.id) | 
 |             if (event.xexpose.count == 0) | 
 |               XInfoWidget(display,windows,text); | 
 |           break; | 
 |         } | 
 |         case KeyPress: | 
 |         { | 
 |           KeySym | 
 |             key_symbol; | 
 |  | 
 |           if (event.xkey.window != windows->image.id) | 
 |             break; | 
 |           /* | 
 |             Respond to a user key press. | 
 |           */ | 
 |           (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |             sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |           switch ((int) key_symbol) | 
 |           { | 
 |             case XK_Shift_L: | 
 |             case XK_Shift_R: | 
 |               break; | 
 |             case XK_Escape: | 
 |             case XK_F20: | 
 |               state|=EscapeState; | 
 |             case XK_Return: | 
 |             { | 
 |               state|=ExitState; | 
 |               break; | 
 |             } | 
 |             case XK_Home: | 
 |             case XK_KP_Home: | 
 |             { | 
 |               roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L); | 
 |               roi_info.y=(ssize_t) (windows->image.height/2L- | 
 |                 roi_info.height/2L); | 
 |               break; | 
 |             } | 
 |             case XK_Left: | 
 |             case XK_KP_Left: | 
 |             { | 
 |               roi_info.x--; | 
 |               break; | 
 |             } | 
 |             case XK_Up: | 
 |             case XK_KP_Up: | 
 |             case XK_Next: | 
 |             { | 
 |               roi_info.y--; | 
 |               break; | 
 |             } | 
 |             case XK_Right: | 
 |             case XK_KP_Right: | 
 |             { | 
 |               roi_info.x++; | 
 |               break; | 
 |             } | 
 |             case XK_Prior: | 
 |             case XK_Down: | 
 |             case XK_KP_Down: | 
 |             { | 
 |               roi_info.y++; | 
 |               break; | 
 |             } | 
 |             case XK_F1: | 
 |             case XK_Help: | 
 |             { | 
 |               (void) XSetFunction(display,windows->image.highlight_context, | 
 |                 GXcopy); | 
 |               XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                 "Help Viewer - Region of Interest",ImageROIHelp); | 
 |               (void) XSetFunction(display,windows->image.highlight_context, | 
 |                 GXinvert); | 
 |               break; | 
 |             } | 
 |             default: | 
 |             { | 
 |               command_type=XImageWindowCommand(display,resource_info,windows, | 
 |                 event.xkey.state,key_symbol,image,exception); | 
 |               if (command_type != NullCommand) | 
 |                 state|=UpdateRegionState; | 
 |               break; | 
 |             } | 
 |           } | 
 |           (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id, | 
 |             event.xkey.time); | 
 |           break; | 
 |         } | 
 |         case KeyRelease: | 
 |           break; | 
 |         case MotionNotify: | 
 |         { | 
 |           if (event.xbutton.window != windows->image.id) | 
 |             break; | 
 |           /* | 
 |             Map and unmap Info widget as text cursor crosses its boundaries. | 
 |           */ | 
 |           x=event.xmotion.x; | 
 |           y=event.xmotion.y; | 
 |           if (windows->info.mapped != MagickFalse) | 
 |             { | 
 |               if ((x < (int) (windows->info.x+windows->info.width)) && | 
 |                   (y < (int) (windows->info.y+windows->info.height))) | 
 |                 (void) XWithdrawWindow(display,windows->info.id, | 
 |                   windows->info.screen); | 
 |             } | 
 |           else | 
 |             if ((x > (int) (windows->info.x+windows->info.width)) || | 
 |                 (y > (int) (windows->info.y+windows->info.height))) | 
 |               (void) XMapWindow(display,windows->info.id); | 
 |           roi_info.x=(ssize_t) windows->image.x+event.xmotion.x; | 
 |           roi_info.y=(ssize_t) windows->image.y+event.xmotion.y; | 
 |           break; | 
 |         } | 
 |         case SelectionRequest: | 
 |         { | 
 |           XSelectionEvent | 
 |             notify; | 
 |  | 
 |           XSelectionRequestEvent | 
 |             *request; | 
 |  | 
 |           /* | 
 |             Set primary selection. | 
 |           */ | 
 |           (void) FormatLocaleString(text,MaxTextExtent, | 
 |             "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double) | 
 |             roi_info.height,(double) roi_info.x,(double) roi_info.y); | 
 |           request=(&(event.xselectionrequest)); | 
 |           (void) XChangeProperty(request->display,request->requestor, | 
 |             request->property,request->target,8,PropModeReplace, | 
 |             (unsigned char *) text,(int) strlen(text)); | 
 |           notify.type=SelectionNotify; | 
 |           notify.display=request->display; | 
 |           notify.requestor=request->requestor; | 
 |           notify.selection=request->selection; | 
 |           notify.target=request->target; | 
 |           notify.time=request->time; | 
 |           if (request->property == None) | 
 |             notify.property=request->target; | 
 |           else | 
 |             notify.property=request->property; | 
 |           (void) XSendEvent(request->display,request->requestor,False,0, | 
 |             (XEvent *) ¬ify); | 
 |         } | 
 |         default: | 
 |           break; | 
 |       } | 
 |       if ((state & UpdateConfigurationState) != 0) | 
 |         { | 
 |           (void) XPutBackEvent(display,&event); | 
 |           (void) XCheckDefineCursor(display,windows->image.id,cursor); | 
 |           break; | 
 |         } | 
 |     } while ((state & ExitState) == 0); | 
 |   } while ((state & ExitState) == 0); | 
 |   (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if ((state & EscapeState) != 0) | 
 |     return(MagickTrue); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X R o t a t e I m a g e                                                   % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XRotateImage() rotates the X image.  If the degrees parameter if zero, the | 
 | %  rotation angle is computed from the slope of a line drawn by the user. | 
 | % | 
 | %  The format of the XRotateImage method is: | 
 | % | 
 | %      MagickBooleanType XRotateImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,double degrees, | 
 | %        Image **image,ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o degrees: Specifies the number of degrees to rotate the image. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XRotateImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *RotateMenu[] = | 
 |     { | 
 |       "Pixel Color", | 
 |       "Direction", | 
 |       "Help", | 
 |       "Dismiss", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static ModeType | 
 |     direction = HorizontalRotateCommand; | 
 |  | 
 |   static const ModeType | 
 |     DirectionCommands[] = | 
 |     { | 
 |       HorizontalRotateCommand, | 
 |       VerticalRotateCommand | 
 |     }, | 
 |     RotateCommands[] = | 
 |     { | 
 |       RotateColorCommand, | 
 |       RotateDirectionCommand, | 
 |       RotateHelpCommand, | 
 |       RotateDismissCommand | 
 |     }; | 
 |  | 
 |   static unsigned int | 
 |     pen_id = 0; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   Image | 
 |     *rotate_image; | 
 |  | 
 |   int | 
 |     id, | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     normalized_degrees; | 
 |  | 
 |   register int | 
 |     i; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     rotations, | 
 |     width; | 
 |  | 
 |   if (degrees == 0.0) | 
 |     { | 
 |       unsigned int | 
 |         distance; | 
 |  | 
 |       size_t | 
 |         state; | 
 |  | 
 |       XEvent | 
 |         event; | 
 |  | 
 |       XSegment | 
 |         rotate_info; | 
 |  | 
 |       /* | 
 |         Map Command widget. | 
 |       */ | 
 |       (void) CloneString(&windows->command.name,"Rotate"); | 
 |       windows->command.data=2; | 
 |       (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL); | 
 |       (void) XMapRaised(display,windows->command.id); | 
 |       XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |         windows->im_update_widget,CurrentTime); | 
 |       /* | 
 |         Wait for first button press. | 
 |       */ | 
 |       (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |       XQueryPosition(display,windows->image.id,&x,&y); | 
 |       rotate_info.x1=x; | 
 |       rotate_info.y1=y; | 
 |       rotate_info.x2=x; | 
 |       rotate_info.y2=y; | 
 |       state=DefaultState; | 
 |       do | 
 |       { | 
 |         XHighlightLine(display,windows->image.id, | 
 |           windows->image.highlight_context,&rotate_info); | 
 |         /* | 
 |           Wait for next event. | 
 |         */ | 
 |         XScreenEvent(display,windows,&event,exception); | 
 |         XHighlightLine(display,windows->image.id, | 
 |           windows->image.highlight_context,&rotate_info); | 
 |         if (event.xany.window == windows->command.id) | 
 |           { | 
 |             /* | 
 |               Select a command from the Command widget. | 
 |             */ | 
 |             id=XCommandWidget(display,windows,RotateMenu,&event); | 
 |             if (id < 0) | 
 |               continue; | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             switch (RotateCommands[id]) | 
 |             { | 
 |               case RotateColorCommand: | 
 |               { | 
 |                 const char | 
 |                   *ColorMenu[MaxNumberPens]; | 
 |  | 
 |                 int | 
 |                   pen_number; | 
 |  | 
 |                 XColor | 
 |                   color; | 
 |  | 
 |                 /* | 
 |                   Initialize menu selections. | 
 |                 */ | 
 |                 for (i=0; i < (int) (MaxNumberPens-2); i++) | 
 |                   ColorMenu[i]=resource_info->pen_colors[i]; | 
 |                 ColorMenu[MaxNumberPens-2]="Browser..."; | 
 |                 ColorMenu[MaxNumberPens-1]=(const char *) NULL; | 
 |                 /* | 
 |                   Select a pen color from the pop-up menu. | 
 |                 */ | 
 |                 pen_number=XMenuWidget(display,windows,RotateMenu[id], | 
 |                   (const char **) ColorMenu,command); | 
 |                 if (pen_number < 0) | 
 |                   break; | 
 |                 if (pen_number == (MaxNumberPens-2)) | 
 |                   { | 
 |                     static char | 
 |                       color_name[MaxTextExtent] = "gray"; | 
 |  | 
 |                     /* | 
 |                       Select a pen color from a dialog. | 
 |                     */ | 
 |                     resource_info->pen_colors[pen_number]=color_name; | 
 |                     XColorBrowserWidget(display,windows,"Select",color_name); | 
 |                     if (*color_name == '\0') | 
 |                       break; | 
 |                   } | 
 |                 /* | 
 |                   Set pen color. | 
 |                 */ | 
 |                 (void) XParseColor(display,windows->map_info->colormap, | 
 |                   resource_info->pen_colors[pen_number],&color); | 
 |                 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL, | 
 |                   (unsigned int) MaxColors,&color); | 
 |                 windows->pixel_info->pen_colors[pen_number]=color; | 
 |                 pen_id=(unsigned int) pen_number; | 
 |                 break; | 
 |               } | 
 |               case RotateDirectionCommand: | 
 |               { | 
 |                 static const char | 
 |                   *Directions[] = | 
 |                   { | 
 |                     "horizontal", | 
 |                     "vertical", | 
 |                     (char *) NULL, | 
 |                   }; | 
 |  | 
 |                 /* | 
 |                   Select a command from the pop-up menu. | 
 |                 */ | 
 |                 id=XMenuWidget(display,windows,RotateMenu[id], | 
 |                   Directions,command); | 
 |                 if (id >= 0) | 
 |                   direction=DirectionCommands[id]; | 
 |                 break; | 
 |               } | 
 |               case RotateHelpCommand: | 
 |               { | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Rotation",ImageRotateHelp); | 
 |                 break; | 
 |               } | 
 |               case RotateDismissCommand: | 
 |               { | 
 |                 /* | 
 |                   Prematurely exit. | 
 |                 */ | 
 |                 state|=EscapeState; | 
 |                 state|=ExitState; | 
 |                 break; | 
 |               } | 
 |               default: | 
 |                 break; | 
 |             } | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXinvert); | 
 |             continue; | 
 |           } | 
 |         switch (event.type) | 
 |         { | 
 |           case ButtonPress: | 
 |           { | 
 |             if (event.xbutton.button != Button1) | 
 |               break; | 
 |             if (event.xbutton.window != windows->image.id) | 
 |               break; | 
 |             /* | 
 |               exit loop. | 
 |             */ | 
 |             (void) XSetFunction(display,windows->image.highlight_context, | 
 |               GXcopy); | 
 |             rotate_info.x1=event.xbutton.x; | 
 |             rotate_info.y1=event.xbutton.y; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case ButtonRelease: | 
 |             break; | 
 |           case Expose: | 
 |             break; | 
 |           case KeyPress: | 
 |           { | 
 |             char | 
 |               command[MaxTextExtent]; | 
 |  | 
 |             KeySym | 
 |               key_symbol; | 
 |  | 
 |             if (event.xkey.window != windows->image.id) | 
 |               break; | 
 |             /* | 
 |               Respond to a user key press. | 
 |             */ | 
 |             (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |               sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |             switch ((int) key_symbol) | 
 |             { | 
 |               case XK_Escape: | 
 |               case XK_F20: | 
 |               { | 
 |                 /* | 
 |                   Prematurely exit. | 
 |                 */ | 
 |                 state|=EscapeState; | 
 |                 state|=ExitState; | 
 |                 break; | 
 |               } | 
 |               case XK_F1: | 
 |               case XK_Help: | 
 |               { | 
 |                 (void) XSetFunction(display,windows->image.highlight_context, | 
 |                   GXcopy); | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Rotation",ImageRotateHelp); | 
 |                 (void) XSetFunction(display,windows->image.highlight_context, | 
 |                   GXinvert); | 
 |                 break; | 
 |               } | 
 |               default: | 
 |               { | 
 |                 (void) XBell(display,0); | 
 |                 break; | 
 |               } | 
 |             } | 
 |             break; | 
 |           } | 
 |           case MotionNotify: | 
 |           { | 
 |             rotate_info.x1=event.xmotion.x; | 
 |             rotate_info.y1=event.xmotion.y; | 
 |           } | 
 |         } | 
 |         rotate_info.x2=rotate_info.x1; | 
 |         rotate_info.y2=rotate_info.y1; | 
 |         if (direction == HorizontalRotateCommand) | 
 |           rotate_info.x2+=32; | 
 |         else | 
 |           rotate_info.y2-=32; | 
 |       } while ((state & ExitState) == 0); | 
 |       (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       if ((state & EscapeState) != 0) | 
 |         return(MagickTrue); | 
 |       /* | 
 |         Draw line as pointer moves until the mouse button is released. | 
 |       */ | 
 |       distance=0; | 
 |       (void) XSetFunction(display,windows->image.highlight_context,GXinvert); | 
 |       state=DefaultState; | 
 |       do | 
 |       { | 
 |         if (distance > 9) | 
 |           { | 
 |             /* | 
 |               Display info and draw rotation line. | 
 |             */ | 
 |             if (windows->info.mapped == MagickFalse) | 
 |               (void) XMapWindow(display,windows->info.id); | 
 |             (void) FormatLocaleString(text,MaxTextExtent," %g", | 
 |               direction == VerticalRotateCommand ? degrees-90.0 : degrees); | 
 |             XInfoWidget(display,windows,text); | 
 |             XHighlightLine(display,windows->image.id, | 
 |               windows->image.highlight_context,&rotate_info); | 
 |           } | 
 |         else | 
 |           if (windows->info.mapped != MagickFalse) | 
 |             (void) XWithdrawWindow(display,windows->info.id, | 
 |               windows->info.screen); | 
 |         /* | 
 |           Wait for next event. | 
 |         */ | 
 |         XScreenEvent(display,windows,&event,exception); | 
 |         if (distance > 9) | 
 |           XHighlightLine(display,windows->image.id, | 
 |             windows->image.highlight_context,&rotate_info); | 
 |         switch (event.type) | 
 |         { | 
 |           case ButtonPress: | 
 |             break; | 
 |           case ButtonRelease: | 
 |           { | 
 |             /* | 
 |               User has committed to rotation line. | 
 |             */ | 
 |             rotate_info.x2=event.xbutton.x; | 
 |             rotate_info.y2=event.xbutton.y; | 
 |             state|=ExitState; | 
 |             break; | 
 |           } | 
 |           case Expose: | 
 |             break; | 
 |           case MotionNotify: | 
 |           { | 
 |             rotate_info.x2=event.xmotion.x; | 
 |             rotate_info.y2=event.xmotion.y; | 
 |           } | 
 |           default: | 
 |             break; | 
 |         } | 
 |         /* | 
 |           Check boundary conditions. | 
 |         */ | 
 |         if (rotate_info.x2 < 0) | 
 |           rotate_info.x2=0; | 
 |         else | 
 |           if (rotate_info.x2 > (int) windows->image.width) | 
 |             rotate_info.x2=(short) windows->image.width; | 
 |         if (rotate_info.y2 < 0) | 
 |           rotate_info.y2=0; | 
 |         else | 
 |           if (rotate_info.y2 > (int) windows->image.height) | 
 |             rotate_info.y2=(short) windows->image.height; | 
 |         /* | 
 |           Compute rotation angle from the slope of the line. | 
 |         */ | 
 |         degrees=0.0; | 
 |         distance=(unsigned int) | 
 |           ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+ | 
 |           ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1)); | 
 |         if (distance > 9) | 
 |           degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2- | 
 |             rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1))); | 
 |       } while ((state & ExitState) == 0); | 
 |       (void) XSetFunction(display,windows->image.highlight_context,GXcopy); | 
 |       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       if (distance <= 9) | 
 |         return(MagickTrue); | 
 |     } | 
 |   if (direction == VerticalRotateCommand) | 
 |     degrees-=90.0; | 
 |   if (degrees == 0.0) | 
 |     return(MagickTrue); | 
 |   /* | 
 |     Rotate image. | 
 |   */ | 
 |   normalized_degrees=degrees; | 
 |   while (normalized_degrees < -45.0) | 
 |     normalized_degrees+=360.0; | 
 |   for (rotations=0; normalized_degrees > 45.0; rotations++) | 
 |     normalized_degrees-=90.0; | 
 |   if (normalized_degrees != 0.0) | 
 |     (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image, | 
 |       exception); | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   (*image)->background_color.red=ScaleShortToQuantum( | 
 |     windows->pixel_info->pen_colors[pen_id].red); | 
 |   (*image)->background_color.green=ScaleShortToQuantum( | 
 |     windows->pixel_info->pen_colors[pen_id].green); | 
 |   (*image)->background_color.blue=ScaleShortToQuantum( | 
 |     windows->pixel_info->pen_colors[pen_id].blue); | 
 |   rotate_image=RotateImage(*image,degrees,exception); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if (rotate_image == (Image *) NULL) | 
 |     return(MagickFalse); | 
 |   *image=DestroyImage(*image); | 
 |   *image=rotate_image; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     { | 
 |       /* | 
 |         Rotate crop geometry. | 
 |       */ | 
 |       width=(unsigned int) (*image)->columns; | 
 |       height=(unsigned int) (*image)->rows; | 
 |       (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |       switch (rotations % 4) | 
 |       { | 
 |         default: | 
 |         case 0: | 
 |           break; | 
 |         case 1: | 
 |         { | 
 |           /* | 
 |             Rotate 90 degrees. | 
 |           */ | 
 |           (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent, | 
 |             "%ux%u%+d%+d",height,width,(int) (*image)->columns- | 
 |             (int) height-y,x); | 
 |           break; | 
 |         } | 
 |         case 2: | 
 |         { | 
 |           /* | 
 |             Rotate 180 degrees. | 
 |           */ | 
 |           (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent, | 
 |             "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y); | 
 |           break; | 
 |         } | 
 |         case 3: | 
 |         { | 
 |           /* | 
 |             Rotate 270 degrees. | 
 |           */ | 
 |           (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent, | 
 |             "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x); | 
 |           break; | 
 |         } | 
 |       } | 
 |     } | 
 |   if (windows->image.orphan != MagickFalse) | 
 |     return(MagickTrue); | 
 |   if (normalized_degrees != 0.0) | 
 |     { | 
 |       /* | 
 |         Update image colormap. | 
 |       */ | 
 |       windows->image.window_changes.width=(int) (*image)->columns; | 
 |       windows->image.window_changes.height=(int) (*image)->rows; | 
 |       if (windows->image.crop_geometry != (char *) NULL) | 
 |         { | 
 |           /* | 
 |             Obtain dimensions of image from crop geometry. | 
 |           */ | 
 |           (void) XParseGeometry(windows->image.crop_geometry,&x,&y, | 
 |             &width,&height); | 
 |           windows->image.window_changes.width=(int) width; | 
 |           windows->image.window_changes.height=(int) height; | 
 |         } | 
 |       XConfigureImageColormap(display,resource_info,windows,*image,exception); | 
 |     } | 
 |   else | 
 |     if (((rotations % 4) == 1) || ((rotations % 4) == 3)) | 
 |       { | 
 |         windows->image.window_changes.width=windows->image.ximage->height; | 
 |         windows->image.window_changes.height=windows->image.ximage->width; | 
 |       } | 
 |   /* | 
 |     Update image configuration. | 
 |   */ | 
 |   (void) XConfigureImage(display,resource_info,windows,*image,exception); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X S a v e I m a g e                                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XSaveImage() saves an image to a file. | 
 | % | 
 | %  The format of the XSaveImage method is: | 
 | % | 
 | %      MagickBooleanType XSaveImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XSaveImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     filename[MaxTextExtent], | 
 |     geometry[MaxTextExtent]; | 
 |  | 
 |   Image | 
 |     *save_image; | 
 |  | 
 |   ImageInfo | 
 |     *image_info; | 
 |  | 
 |   MagickStatusType | 
 |     status; | 
 |  | 
 |   /* | 
 |     Request file name from user. | 
 |   */ | 
 |   if (resource_info->write_filename != (char *) NULL) | 
 |     (void) CopyMagickString(filename,resource_info->write_filename, | 
 |       MaxTextExtent); | 
 |   else | 
 |     { | 
 |       char | 
 |         path[MaxTextExtent]; | 
 |  | 
 |       int | 
 |         status; | 
 |  | 
 |       GetPathComponent(image->filename,HeadPath,path); | 
 |       GetPathComponent(image->filename,TailPath,filename); | 
 |       if (*path != '\0') | 
 |         { | 
 |           status=chdir(path); | 
 |           if (status == -1) | 
 |             (void) ThrowMagickException(exception,GetMagickModule(), | 
 |               FileOpenError,"UnableToOpenFile","%s",path); | 
 |         } | 
 |     } | 
 |   XFileBrowserWidget(display,windows,"Save",filename); | 
 |   if (*filename == '\0') | 
 |     return(MagickTrue); | 
 |   if (IsPathAccessible(filename) != MagickFalse) | 
 |     { | 
 |       int | 
 |         status; | 
 |  | 
 |       /* | 
 |         File exists-- seek user's permission before overwriting. | 
 |       */ | 
 |       status=XConfirmWidget(display,windows,"Overwrite",filename); | 
 |       if (status <= 0) | 
 |         return(MagickTrue); | 
 |     } | 
 |   image_info=CloneImageInfo(resource_info->image_info); | 
 |   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent); | 
 |   (void) SetImageInfo(image_info,1,exception); | 
 |   if ((LocaleCompare(image_info->magick,"JPEG") == 0) || | 
 |       (LocaleCompare(image_info->magick,"JPG") == 0)) | 
 |     { | 
 |       char | 
 |         quality[MaxTextExtent]; | 
 |  | 
 |       int | 
 |         status; | 
 |  | 
 |       /* | 
 |         Request JPEG quality from user. | 
 |       */ | 
 |       (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double) | 
 |         image->quality); | 
 |       status=XDialogWidget(display,windows,"Save","Enter JPEG quality:", | 
 |         quality); | 
 |       if (*quality == '\0') | 
 |         return(MagickTrue); | 
 |       image->quality=StringToUnsignedLong(quality); | 
 |       image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace; | 
 |     } | 
 |   if ((LocaleCompare(image_info->magick,"EPS") == 0) || | 
 |       (LocaleCompare(image_info->magick,"PDF") == 0) || | 
 |       (LocaleCompare(image_info->magick,"PS") == 0) || | 
 |       (LocaleCompare(image_info->magick,"PS2") == 0)) | 
 |     { | 
 |       char | 
 |         geometry[MaxTextExtent]; | 
 |  | 
 |       /* | 
 |         Request page geometry from user. | 
 |       */ | 
 |       (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent); | 
 |       if (LocaleCompare(image_info->magick,"PDF") == 0) | 
 |         (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent); | 
 |       if (image_info->page != (char *) NULL) | 
 |         (void) CopyMagickString(geometry,image_info->page,MaxTextExtent); | 
 |       XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select", | 
 |         "Select page geometry:",geometry); | 
 |       if (*geometry != '\0') | 
 |         image_info->page=GetPageGeometry(geometry); | 
 |     } | 
 |   /* | 
 |     Apply image transforms. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   save_image=CloneImage(image,0,0,MagickTrue,exception); | 
 |   if (save_image == (Image *) NULL) | 
 |     return(MagickFalse); | 
 |   (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!", | 
 |     windows->image.ximage->width,windows->image.ximage->height); | 
 |   (void) TransformImage(&save_image,windows->image.crop_geometry,geometry, | 
 |     exception); | 
 |   /* | 
 |     Write image. | 
 |   */ | 
 |   (void) CopyMagickString(save_image->filename,filename,MaxTextExtent); | 
 |   status=WriteImage(image_info,save_image,exception); | 
 |   if (status != MagickFalse) | 
 |     image->taint=MagickFalse; | 
 |   save_image=DestroyImage(save_image); | 
 |   image_info=DestroyImageInfo(image_info); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   return(status != 0 ? MagickTrue : MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X S c r e e n E v e n t                                                   % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XScreenEvent() handles global events associated with the Pan and Magnify | 
 | %  windows. | 
 | % | 
 | %  The format of the XScreenEvent function is: | 
 | % | 
 | %      void XScreenEvent(Display *display,XWindows *windows,XEvent *event, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o display: Specifies a pointer to the Display structure;  returned from | 
 | %      XOpenDisplay. | 
 | % | 
 | %    o windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o event: Specifies a pointer to a X11 XEvent structure. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 |  | 
 | #if defined(__cplusplus) || defined(c_plusplus) | 
 | extern "C" { | 
 | #endif | 
 |  | 
 | static int XPredicate(Display *magick_unused(display),XEvent *event,char *data) | 
 | { | 
 |   register XWindows | 
 |     *windows; | 
 |  | 
 |   windows=(XWindows *) data; | 
 |   if ((event->type == ClientMessage) && | 
 |       (event->xclient.window == windows->image.id)) | 
 |     return(MagickFalse); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | #if defined(__cplusplus) || defined(c_plusplus) | 
 | } | 
 | #endif | 
 |  | 
 | static void XScreenEvent(Display *display,XWindows *windows,XEvent *event, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   register int | 
 |     x, | 
 |     y; | 
 |  | 
 |   (void) XIfEvent(display,event,XPredicate,(char *) windows); | 
 |   if (event->xany.window == windows->command.id) | 
 |     return; | 
 |   switch (event->type) | 
 |   { | 
 |     case ButtonPress: | 
 |     case ButtonRelease: | 
 |     { | 
 |       if ((event->xbutton.button == Button3) && | 
 |           (event->xbutton.state & Mod1Mask)) | 
 |         { | 
 |           /* | 
 |             Convert Alt-Button3 to Button2. | 
 |           */ | 
 |           event->xbutton.button=Button2; | 
 |           event->xbutton.state&=(~Mod1Mask); | 
 |         } | 
 |       if (event->xbutton.window == windows->backdrop.id) | 
 |         { | 
 |           (void) XSetInputFocus(display,event->xbutton.window,RevertToParent, | 
 |             event->xbutton.time); | 
 |           break; | 
 |         } | 
 |       if (event->xbutton.window == windows->pan.id) | 
 |         { | 
 |           XPanImage(display,windows,event,exception); | 
 |           break; | 
 |         } | 
 |       if (event->xbutton.window == windows->image.id) | 
 |         if (event->xbutton.button == Button2) | 
 |           { | 
 |             /* | 
 |               Update magnified image. | 
 |             */ | 
 |             x=event->xbutton.x; | 
 |             y=event->xbutton.y; | 
 |             if (x < 0) | 
 |               x=0; | 
 |             else | 
 |               if (x >= (int) windows->image.width) | 
 |                 x=(int) (windows->image.width-1); | 
 |             windows->magnify.x=(int) windows->image.x+x; | 
 |             if (y < 0) | 
 |               y=0; | 
 |             else | 
 |              if (y >= (int) windows->image.height) | 
 |                y=(int) (windows->image.height-1); | 
 |             windows->magnify.y=windows->image.y+y; | 
 |             if (windows->magnify.mapped == MagickFalse) | 
 |               (void) XMapRaised(display,windows->magnify.id); | 
 |             XMakeMagnifyImage(display,windows,exception); | 
 |             if (event->type == ButtonRelease) | 
 |               (void) XWithdrawWindow(display,windows->info.id, | 
 |                 windows->info.screen); | 
 |             break; | 
 |           } | 
 |       break; | 
 |     } | 
 |     case ClientMessage: | 
 |     { | 
 |       /* | 
 |         If client window delete message, exit. | 
 |       */ | 
 |       if (event->xclient.message_type != windows->wm_protocols) | 
 |         break; | 
 |       if (*event->xclient.data.l != (long) windows->wm_delete_window) | 
 |         break; | 
 |       if (event->xclient.window == windows->magnify.id) | 
 |         { | 
 |           (void) XWithdrawWindow(display,windows->magnify.id, | 
 |             windows->magnify.screen); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case ConfigureNotify: | 
 |     { | 
 |       if (event->xconfigure.window == windows->magnify.id) | 
 |         { | 
 |           unsigned int | 
 |             magnify; | 
 |  | 
 |           /* | 
 |             Magnify window has a new configuration. | 
 |           */ | 
 |           windows->magnify.width=(unsigned int) event->xconfigure.width; | 
 |           windows->magnify.height=(unsigned int) event->xconfigure.height; | 
 |           if (windows->magnify.mapped == MagickFalse) | 
 |             break; | 
 |           magnify=1; | 
 |           while ((int) magnify <= event->xconfigure.width) | 
 |             magnify<<=1; | 
 |           while ((int) magnify <= event->xconfigure.height) | 
 |             magnify<<=1; | 
 |           magnify>>=1; | 
 |           if (((int) magnify != event->xconfigure.width) || | 
 |               ((int) magnify != event->xconfigure.height)) | 
 |             { | 
 |               XWindowChanges | 
 |                 window_changes; | 
 |  | 
 |               window_changes.width=(int) magnify; | 
 |               window_changes.height=(int) magnify; | 
 |               (void) XReconfigureWMWindow(display,windows->magnify.id, | 
 |                 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight), | 
 |                 &window_changes); | 
 |               break; | 
 |             } | 
 |           XMakeMagnifyImage(display,windows,exception); | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case Expose: | 
 |     { | 
 |       if (event->xexpose.window == windows->image.id) | 
 |         { | 
 |           XRefreshWindow(display,&windows->image,event); | 
 |           break; | 
 |         } | 
 |       if (event->xexpose.window == windows->pan.id) | 
 |         if (event->xexpose.count == 0) | 
 |           { | 
 |             XDrawPanRectangle(display,windows); | 
 |             break; | 
 |           } | 
 |       if (event->xexpose.window == windows->magnify.id) | 
 |         if (event->xexpose.count == 0) | 
 |           { | 
 |             XMakeMagnifyImage(display,windows,exception); | 
 |             break; | 
 |           } | 
 |       break; | 
 |     } | 
 |     case KeyPress: | 
 |     { | 
 |       char | 
 |         command[MaxTextExtent]; | 
 |  | 
 |       KeySym | 
 |         key_symbol; | 
 |  | 
 |       if (event->xkey.window != windows->magnify.id) | 
 |         break; | 
 |       /* | 
 |         Respond to a user key press. | 
 |       */ | 
 |       (void) XLookupString((XKeyEvent *) &event->xkey,command,(int) | 
 |         sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |       XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol, | 
 |         exception); | 
 |       break; | 
 |     } | 
 |     case MapNotify: | 
 |     { | 
 |       if (event->xmap.window == windows->magnify.id) | 
 |         { | 
 |           windows->magnify.mapped=MagickTrue; | 
 |           (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |           break; | 
 |         } | 
 |       if (event->xmap.window == windows->info.id) | 
 |         { | 
 |           windows->info.mapped=MagickTrue; | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     case MotionNotify: | 
 |     { | 
 |       while (XCheckMaskEvent(display,ButtonMotionMask,event)) ; | 
 |       if (event->xmotion.window == windows->image.id) | 
 |         if (windows->magnify.mapped != MagickFalse) | 
 |           { | 
 |             /* | 
 |               Update magnified image. | 
 |             */ | 
 |             x=event->xmotion.x; | 
 |             y=event->xmotion.y; | 
 |             if (x < 0) | 
 |               x=0; | 
 |             else | 
 |               if (x >= (int) windows->image.width) | 
 |                 x=(int) (windows->image.width-1); | 
 |             windows->magnify.x=(int) windows->image.x+x; | 
 |             if (y < 0) | 
 |               y=0; | 
 |             else | 
 |              if (y >= (int) windows->image.height) | 
 |                y=(int) (windows->image.height-1); | 
 |             windows->magnify.y=windows->image.y+y; | 
 |             XMakeMagnifyImage(display,windows,exception); | 
 |           } | 
 |       break; | 
 |     } | 
 |     case UnmapNotify: | 
 |     { | 
 |       if (event->xunmap.window == windows->magnify.id) | 
 |         { | 
 |           windows->magnify.mapped=MagickFalse; | 
 |           break; | 
 |         } | 
 |       if (event->xunmap.window == windows->info.id) | 
 |         { | 
 |           windows->info.mapped=MagickFalse; | 
 |           break; | 
 |         } | 
 |       break; | 
 |     } | 
 |     default: | 
 |       break; | 
 |   } | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X S e t C r o p G e o m e t r y                                           % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XSetCropGeometry() accepts a cropping geometry relative to the Image window | 
 | %  and translates it to a cropping geometry relative to the image. | 
 | % | 
 | %  The format of the XSetCropGeometry method is: | 
 | % | 
 | %      void XSetCropGeometry(Display *display,XWindows *windows, | 
 | %        RectangleInfo *crop_info,Image *image) | 
 | % | 
 | %  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 XWindows structure. | 
 | % | 
 | %    o crop_info:  A pointer to a RectangleInfo that defines a region of the | 
 | %      Image window to crop. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | */ | 
 | static void XSetCropGeometry(Display *display,XWindows *windows, | 
 |   RectangleInfo *crop_info,Image *image) | 
 | { | 
 |   char | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   int | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     scale_factor; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   if (windows->info.mapped != MagickFalse) | 
 |     { | 
 |       /* | 
 |         Display info on cropping rectangle. | 
 |       */ | 
 |       (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g", | 
 |         (double) crop_info->width,(double) crop_info->height,(double) | 
 |         crop_info->x,(double) crop_info->y); | 
 |       XInfoWidget(display,windows,text); | 
 |     } | 
 |   /* | 
 |     Cropping geometry is relative to any previous crop geometry. | 
 |   */ | 
 |   x=0; | 
 |   y=0; | 
 |   width=(unsigned int) image->columns; | 
 |   height=(unsigned int) image->rows; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |   else | 
 |     windows->image.crop_geometry=AcquireString((char *) NULL); | 
 |   /* | 
 |     Define the crop geometry string from the cropping rectangle. | 
 |   */ | 
 |   scale_factor=(MagickRealType) width/windows->image.ximage->width; | 
 |   if (crop_info->x > 0) | 
 |     x+=(int) (scale_factor*crop_info->x+0.5); | 
 |   width=(unsigned int) (scale_factor*crop_info->width+0.5); | 
 |   if (width == 0) | 
 |     width=1; | 
 |   scale_factor=(MagickRealType) height/windows->image.ximage->height; | 
 |   if (crop_info->y > 0) | 
 |     y+=(int) (scale_factor*crop_info->y+0.5); | 
 |   height=(unsigned int) (scale_factor*crop_info->height+0.5); | 
 |   if (height == 0) | 
 |     height=1; | 
 |   (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent, | 
 |     "%ux%u%+d%+d",width,height,x,y); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X T i l e I m a g e                                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XTileImage() loads or deletes a selected tile from a visual image directory. | 
 | %  The load or delete command is chosen from a menu. | 
 | % | 
 | %  The format of the XTileImage method is: | 
 | % | 
 | %      Image *XTileImage(Display *display,XResourceInfo *resource_info, | 
 | %        XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o tile_image:  XTileImage reads or deletes the tile image | 
 | %      and returns it.  A null image is returned if an error occurs. | 
 | % | 
 | %    o display: Specifies a connection to an X server;  returned from | 
 | %      XOpenDisplay. | 
 | % | 
 | %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure. | 
 | % | 
 | %    o windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image; returned from ReadImage. | 
 | % | 
 | %    o event: Specifies a pointer to a XEvent structure.  If it is NULL, | 
 | %      the entire image is refreshed. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static Image *XTileImage(Display *display,XResourceInfo *resource_info, | 
 |   XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception) | 
 | { | 
 |   static const char | 
 |     *VerbMenu[] = | 
 |     { | 
 |       "Load", | 
 |       "Next", | 
 |       "Former", | 
 |       "Delete", | 
 |       "Update", | 
 |       (char *) NULL, | 
 |     }; | 
 |  | 
 |   static const ModeType | 
 |     TileCommands[] = | 
 |     { | 
 |       TileLoadCommand, | 
 |       TileNextCommand, | 
 |       TileFormerCommand, | 
 |       TileDeleteCommand, | 
 |       TileUpdateCommand | 
 |     }; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     filename[MaxTextExtent]; | 
 |  | 
 |   Image | 
 |     *tile_image; | 
 |  | 
 |   int | 
 |     id, | 
 |     status, | 
 |     tile, | 
 |     x, | 
 |     y; | 
 |  | 
 |   MagickRealType | 
 |     scale_factor; | 
 |  | 
 |   register char | 
 |     *p, | 
 |     *q; | 
 |  | 
 |   register int | 
 |     i; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   /* | 
 |     Tile image is relative to montage image configuration. | 
 |   */ | 
 |   x=0; | 
 |   y=0; | 
 |   width=(unsigned int) image->columns; | 
 |   height=(unsigned int) image->rows; | 
 |   if (windows->image.crop_geometry != (char *) NULL) | 
 |     (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height); | 
 |   scale_factor=(MagickRealType) width/windows->image.ximage->width; | 
 |   event->xbutton.x+=windows->image.x; | 
 |   event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5); | 
 |   scale_factor=(MagickRealType) height/windows->image.ximage->height; | 
 |   event->xbutton.y+=windows->image.y; | 
 |   event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5); | 
 |   /* | 
 |     Determine size and location of each tile in the visual image directory. | 
 |   */ | 
 |   width=(unsigned int) image->columns; | 
 |   height=(unsigned int) image->rows; | 
 |   x=0; | 
 |   y=0; | 
 |   (void) XParseGeometry(image->montage,&x,&y,&width,&height); | 
 |   tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+ | 
 |     (event->xbutton.x-x)/width; | 
 |   if (tile < 0) | 
 |     { | 
 |       /* | 
 |         Button press is outside any tile. | 
 |       */ | 
 |       (void) XBell(display,0); | 
 |       return((Image *) NULL); | 
 |     } | 
 |   /* | 
 |     Determine file name from the tile directory. | 
 |   */ | 
 |   p=image->directory; | 
 |   for (i=tile; (i != 0) && (*p != '\0'); ) | 
 |   { | 
 |     if (*p == '\n') | 
 |       i--; | 
 |     p++; | 
 |   } | 
 |   if (*p == '\0') | 
 |     { | 
 |       /* | 
 |         Button press is outside any tile. | 
 |       */ | 
 |       (void) XBell(display,0); | 
 |       return((Image *) NULL); | 
 |     } | 
 |   /* | 
 |     Select a command from the pop-up menu. | 
 |   */ | 
 |   id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command); | 
 |   if (id < 0) | 
 |     return((Image *) NULL); | 
 |   q=p; | 
 |   while ((*q != '\n') && (*q != '\0')) | 
 |     q++; | 
 |   (void) CopyMagickString(filename,p,(size_t) (q-p+1)); | 
 |   /* | 
 |     Perform command for the selected tile. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   tile_image=NewImageList(); | 
 |   switch (TileCommands[id]) | 
 |   { | 
 |     case TileLoadCommand: | 
 |     { | 
 |       /* | 
 |         Load tile image. | 
 |       */ | 
 |       XCheckRefreshWindows(display,windows); | 
 |       (void) CopyMagickString(resource_info->image_info->magick,"MIFF", | 
 |         MaxTextExtent); | 
 |       (void) CopyMagickString(resource_info->image_info->filename,filename, | 
 |         MaxTextExtent); | 
 |       tile_image=ReadImage(resource_info->image_info,exception); | 
 |       CatchException(exception); | 
 |       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       break; | 
 |     } | 
 |     case TileNextCommand: | 
 |     { | 
 |       /* | 
 |         Display next image. | 
 |       */ | 
 |       XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |         windows->im_next_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case TileFormerCommand: | 
 |     { | 
 |       /* | 
 |         Display former image. | 
 |       */ | 
 |       XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |         windows->im_former_image,CurrentTime); | 
 |       break; | 
 |     } | 
 |     case TileDeleteCommand: | 
 |     { | 
 |       /* | 
 |         Delete tile image. | 
 |       */ | 
 |       if (IsPathAccessible(filename) == MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Image file does not exist:",filename); | 
 |           break; | 
 |         } | 
 |       status=XConfirmWidget(display,windows,"Really delete tile",filename); | 
 |       if (status <= 0) | 
 |         break; | 
 |       status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse; | 
 |       if (status != MagickFalse) | 
 |         { | 
 |           XNoticeWidget(display,windows,"Unable to delete image file:", | 
 |             filename); | 
 |           break; | 
 |         } | 
 |     } | 
 |     case TileUpdateCommand: | 
 |     { | 
 |       int | 
 |         x_offset, | 
 |         y_offset; | 
 |  | 
 |       PixelInfo | 
 |         pixel; | 
 |  | 
 |       Quantum | 
 |         virtual_pixel[CompositePixelChannel]; | 
 |  | 
 |       register int | 
 |         j; | 
 |  | 
 |       register Quantum | 
 |         *s; | 
 |  | 
 |       /* | 
 |         Ensure all the images exist. | 
 |       */ | 
 |       tile=0; | 
 |       GetPixelInfo(image,&pixel); | 
 |       for (p=image->directory; *p != '\0'; p++) | 
 |       { | 
 |         CacheView | 
 |           *image_view; | 
 |  | 
 |         q=p; | 
 |         while ((*q != '\n') && (*q != '\0')) | 
 |           q++; | 
 |         (void) CopyMagickString(filename,p,(size_t) (q-p+1)); | 
 |         p=q; | 
 |         if (IsPathAccessible(filename) != MagickFalse) | 
 |           { | 
 |             tile++; | 
 |             continue; | 
 |           } | 
 |         /* | 
 |           Overwrite tile with background color. | 
 |         */ | 
 |         x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x); | 
 |         y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y); | 
 |         image_view=AcquireCacheView(image); | 
 |         (void) GetOneCacheViewVirtualPixel(image_view,0,0,virtual_pixel, | 
 |           exception); | 
 |         pixel.red=virtual_pixel[RedPixelChannel]; | 
 |         pixel.green=virtual_pixel[GreenPixelChannel]; | 
 |         pixel.blue=virtual_pixel[BluePixelChannel]; | 
 |         pixel.alpha=virtual_pixel[AlphaPixelChannel]; | 
 |         for (i=0; i < (int) height; i++) | 
 |         { | 
 |           s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t) | 
 |             y_offset+i,width,1,exception); | 
 |           if (s == (Quantum *) NULL) | 
 |             break; | 
 |           for (j=0; j < (int) width; j++) | 
 |           { | 
 |             SetPixelPixelInfo(image,&pixel,s); | 
 |             s+=GetPixelChannels(image); | 
 |           } | 
 |           if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) | 
 |             break; | 
 |         } | 
 |         image_view=DestroyCacheView(image_view); | 
 |         tile++; | 
 |       } | 
 |       windows->image.window_changes.width=(int) image->columns; | 
 |       windows->image.window_changes.height=(int) image->rows; | 
 |       XConfigureImageColormap(display,resource_info,windows,image,exception); | 
 |       (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |       break; | 
 |     } | 
 |     default: | 
 |       break; | 
 |   } | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   return(tile_image); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X T r a n s l a t e I m a g e                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XTranslateImage() translates the image within an Image window by one pixel | 
 | %  as specified by the key symbol.  If the image has a `montage string the | 
 | %  translation is respect to the width and height contained within the string. | 
 | % | 
 | %  The format of the XTranslateImage method is: | 
 | % | 
 | %      void XTranslateImage(Display *display,XWindows *windows, | 
 | %        Image *image,const KeySym key_symbol) | 
 | % | 
 | %  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 XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o key_symbol: Specifies a KeySym which indicates which side of the image | 
 | %      to trim. | 
 | % | 
 | */ | 
 | static void XTranslateImage(Display *display,XWindows *windows, | 
 |   Image *image,const KeySym key_symbol) | 
 | { | 
 |   char | 
 |     text[MaxTextExtent]; | 
 |  | 
 |   int | 
 |     x, | 
 |     y; | 
 |  | 
 |   unsigned int | 
 |     x_offset, | 
 |     y_offset; | 
 |  | 
 |   /* | 
 |     User specified a pan position offset. | 
 |   */ | 
 |   x_offset=windows->image.width; | 
 |   y_offset=windows->image.height; | 
 |   if (image->montage != (char *) NULL) | 
 |     (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset); | 
 |   switch ((int) key_symbol) | 
 |   { | 
 |     case XK_Home: | 
 |     case XK_KP_Home: | 
 |     { | 
 |       windows->image.x=(int) windows->image.width/2; | 
 |       windows->image.y=(int) windows->image.height/2; | 
 |       break; | 
 |     } | 
 |     case XK_Left: | 
 |     case XK_KP_Left: | 
 |     { | 
 |       windows->image.x-=x_offset; | 
 |       break; | 
 |     } | 
 |     case XK_Next: | 
 |     case XK_Up: | 
 |     case XK_KP_Up: | 
 |     { | 
 |       windows->image.y-=y_offset; | 
 |       break; | 
 |     } | 
 |     case XK_Right: | 
 |     case XK_KP_Right: | 
 |     { | 
 |       windows->image.x+=x_offset; | 
 |       break; | 
 |     } | 
 |     case XK_Prior: | 
 |     case XK_Down: | 
 |     case XK_KP_Down: | 
 |     { | 
 |       windows->image.y+=y_offset; | 
 |       break; | 
 |     } | 
 |     default: | 
 |       return; | 
 |   } | 
 |   /* | 
 |     Check boundary conditions. | 
 |   */ | 
 |   if (windows->image.x < 0) | 
 |     windows->image.x=0; | 
 |   else | 
 |     if ((int) (windows->image.x+windows->image.width) > | 
 |         windows->image.ximage->width) | 
 |       windows->image.x=(int) windows->image.ximage->width-windows->image.width; | 
 |   if (windows->image.y < 0) | 
 |     windows->image.y=0; | 
 |   else | 
 |     if ((int) (windows->image.y+windows->image.height) > | 
 |         windows->image.ximage->height) | 
 |       windows->image.y=(int) windows->image.ximage->height-windows->image.height; | 
 |   /* | 
 |     Refresh Image window. | 
 |   */ | 
 |   (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ", | 
 |     windows->image.width,windows->image.height,windows->image.x, | 
 |     windows->image.y); | 
 |   XInfoWidget(display,windows,text); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   XDrawPanRectangle(display,windows); | 
 |   XRefreshWindow(display,&windows->image,(XEvent *) NULL); | 
 |   (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X T r i m I m a g e                                                       % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XTrimImage() trims the edges from the Image window. | 
 | % | 
 | %  The format of the XTrimImage method is: | 
 | % | 
 | %      MagickBooleanType XTrimImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static MagickBooleanType XTrimImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,Image *image, | 
 |   ExceptionInfo *exception) | 
 | { | 
 |   RectangleInfo | 
 |     trim_info; | 
 |  | 
 |   register int | 
 |     x, | 
 |     y; | 
 |  | 
 |   size_t | 
 |     background, | 
 |     pixel; | 
 |  | 
 |   /* | 
 |     Trim edges from image. | 
 |   */ | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   /* | 
 |     Crop the left edge. | 
 |   */ | 
 |   background=XGetPixel(windows->image.ximage,0,0); | 
 |   trim_info.width=(size_t) windows->image.ximage->width; | 
 |   for (x=0; x < windows->image.ximage->width; x++) | 
 |   { | 
 |     for (y=0; y < windows->image.ximage->height; y++) | 
 |     { | 
 |       pixel=XGetPixel(windows->image.ximage,x,y); | 
 |       if (pixel != background) | 
 |         break; | 
 |     } | 
 |     if (y < windows->image.ximage->height) | 
 |       break; | 
 |   } | 
 |   trim_info.x=(ssize_t) x; | 
 |   if (trim_info.x == (ssize_t) windows->image.ximage->width) | 
 |     { | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       return(MagickFalse); | 
 |     } | 
 |   /* | 
 |     Crop the right edge. | 
 |   */ | 
 |   background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0); | 
 |   for (x=windows->image.ximage->width-1; x != 0; x--) | 
 |   { | 
 |     for (y=0; y < windows->image.ximage->height; y++) | 
 |     { | 
 |       pixel=XGetPixel(windows->image.ximage,x,y); | 
 |       if (pixel != background) | 
 |         break; | 
 |     } | 
 |     if (y < windows->image.ximage->height) | 
 |       break; | 
 |   } | 
 |   trim_info.width=(size_t) (x-trim_info.x+1); | 
 |   /* | 
 |     Crop the top edge. | 
 |   */ | 
 |   background=XGetPixel(windows->image.ximage,0,0); | 
 |   trim_info.height=(size_t) windows->image.ximage->height; | 
 |   for (y=0; y < windows->image.ximage->height; y++) | 
 |   { | 
 |     for (x=0; x < windows->image.ximage->width; x++) | 
 |     { | 
 |       pixel=XGetPixel(windows->image.ximage,x,y); | 
 |       if (pixel != background) | 
 |         break; | 
 |     } | 
 |     if (x < windows->image.ximage->width) | 
 |       break; | 
 |   } | 
 |   trim_info.y=(ssize_t) y; | 
 |   /* | 
 |     Crop the bottom edge. | 
 |   */ | 
 |   background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1); | 
 |   for (y=windows->image.ximage->height-1; y != 0; y--) | 
 |   { | 
 |     for (x=0; x < windows->image.ximage->width; x++) | 
 |     { | 
 |       pixel=XGetPixel(windows->image.ximage,x,y); | 
 |       if (pixel != background) | 
 |         break; | 
 |     } | 
 |     if (x < windows->image.ximage->width) | 
 |       break; | 
 |   } | 
 |   trim_info.height=(size_t) y-trim_info.y+1; | 
 |   if (((unsigned int) trim_info.width != windows->image.width) || | 
 |       ((unsigned int) trim_info.height != windows->image.height)) | 
 |     { | 
 |       /* | 
 |         Reconfigure Image window as defined by the trimming rectangle. | 
 |       */ | 
 |       XSetCropGeometry(display,windows,&trim_info,image); | 
 |       windows->image.window_changes.width=(int) trim_info.width; | 
 |       windows->image.window_changes.height=(int) trim_info.height; | 
 |       (void) XConfigureImage(display,resource_info,windows,image,exception); | 
 |     } | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   return(MagickTrue); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X V i s u a l D i r e c t o r y I m a g e                                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XVisualDirectoryImage() creates a Visual Image Directory. | 
 | % | 
 | %  The format of the XVisualDirectoryImage method is: | 
 | % | 
 | %      Image *XVisualDirectoryImage(Display *display, | 
 | %        XResourceInfo *resource_info,XWindows *windows, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  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 windows: Specifies a pointer to a XWindows structure. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | static Image *XVisualDirectoryImage(Display *display, | 
 |   XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception) | 
 | { | 
 | #define TileImageTag  "Scale/Image" | 
 | #define XClientName  "montage" | 
 |  | 
 |   char | 
 |     **filelist; | 
 |  | 
 |   Image | 
 |     *images, | 
 |     *montage_image, | 
 |     *next_image, | 
 |     *thumbnail_image; | 
 |  | 
 |   ImageInfo | 
 |     *read_info; | 
 |  | 
 |   int | 
 |     number_files; | 
 |  | 
 |   MagickBooleanType | 
 |     backdrop; | 
 |  | 
 |   MagickStatusType | 
 |     status; | 
 |  | 
 |   MontageInfo | 
 |     *montage_info; | 
 |  | 
 |   RectangleInfo | 
 |     geometry; | 
 |  | 
 |   register int | 
 |     i; | 
 |  | 
 |   static char | 
 |     filename[MaxTextExtent] = "\0", | 
 |     filenames[MaxTextExtent] = "*"; | 
 |  | 
 |   XResourceInfo | 
 |     background_resources; | 
 |  | 
 |   /* | 
 |     Request file name from user. | 
 |   */ | 
 |   XFileBrowserWidget(display,windows,"Directory",filenames); | 
 |   if (*filenames == '\0') | 
 |     return((Image *) NULL); | 
 |   /* | 
 |     Expand the filenames. | 
 |   */ | 
 |   filelist=(char **) AcquireMagickMemory(sizeof(*filelist)); | 
 |   if (filelist == (char **) NULL) | 
 |     { | 
 |       ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed", | 
 |         filenames); | 
 |       return((Image *) NULL); | 
 |     } | 
 |   number_files=1; | 
 |   filelist[0]=filenames; | 
 |   status=ExpandFilenames(&number_files,&filelist); | 
 |   if ((status == MagickFalse) || (number_files == 0)) | 
 |     { | 
 |       if (number_files == 0) | 
 |         ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames) | 
 |       else | 
 |         ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed", | 
 |           filenames); | 
 |       return((Image *) NULL); | 
 |     } | 
 |   /* | 
 |     Set image background resources. | 
 |   */ | 
 |   background_resources=(*resource_info); | 
 |   background_resources.window_id=AcquireString(""); | 
 |   (void) FormatLocaleString(background_resources.window_id,MaxTextExtent, | 
 |     "0x%lx",windows->image.id); | 
 |   background_resources.backdrop=MagickTrue; | 
 |   /* | 
 |     Read each image and convert them to a tile. | 
 |   */ | 
 |   backdrop=(windows->visual_info->klass == TrueColor) || | 
 |     (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse; | 
 |   read_info=CloneImageInfo(resource_info->image_info); | 
 |   (void) SetImageOption(read_info,"jpeg:size","120x120"); | 
 |   (void) CloneString(&read_info->size,DefaultTileGeometry); | 
 |   (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL, | 
 |     (void *) NULL); | 
 |   images=NewImageList(); | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   for (i=0; i < (int) number_files; i++) | 
 |   { | 
 |     (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent); | 
 |     filelist[i]=DestroyString(filelist[i]); | 
 |     *read_info->magick='\0'; | 
 |     next_image=ReadImage(read_info,exception); | 
 |     CatchException(exception); | 
 |     if (next_image != (Image *) NULL) | 
 |       { | 
 |         (void) DeleteImageProperty(next_image,"label"); | 
 |         (void) SetImageProperty(next_image,"label",InterpretImageProperties( | 
 |           read_info,next_image,DefaultTileLabel,exception),exception); | 
 |         (void) ParseRegionGeometry(next_image,read_info->size,&geometry, | 
 |           exception); | 
 |         thumbnail_image=ThumbnailImage(next_image,geometry.width, | 
 |           geometry.height,exception); | 
 |         if (thumbnail_image != (Image *) NULL) | 
 |           { | 
 |             next_image=DestroyImage(next_image); | 
 |             next_image=thumbnail_image; | 
 |           } | 
 |         if (backdrop) | 
 |           { | 
 |             (void) XDisplayBackgroundImage(display,&background_resources, | 
 |               next_image,exception); | 
 |             XSetCursorState(display,windows,MagickTrue); | 
 |           } | 
 |         AppendImageToList(&images,next_image); | 
 |         if (images->progress_monitor != (MagickProgressMonitor) NULL) | 
 |           { | 
 |             MagickBooleanType | 
 |               proceed; | 
 |  | 
 |             proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i, | 
 |               (MagickSizeType) number_files); | 
 |             if (proceed == MagickFalse) | 
 |               break; | 
 |           } | 
 |       } | 
 |   } | 
 |   filelist=(char **) RelinquishMagickMemory(filelist); | 
 |   if (images == (Image *) NULL) | 
 |     { | 
 |       read_info=DestroyImageInfo(read_info); | 
 |       XSetCursorState(display,windows,MagickFalse); | 
 |       ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames); | 
 |       return((Image *) NULL); | 
 |     } | 
 |   /* | 
 |     Create the Visual Image Directory. | 
 |   */ | 
 |   montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL); | 
 |   montage_info->pointsize=10; | 
 |   if (resource_info->font != (char *) NULL) | 
 |     (void) CloneString(&montage_info->font,resource_info->font); | 
 |   (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent); | 
 |   montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList( | 
 |     images),exception); | 
 |   images=DestroyImageList(images); | 
 |   montage_info=DestroyMontageInfo(montage_info); | 
 |   read_info=DestroyImageInfo(read_info); | 
 |   XSetCursorState(display,windows,MagickFalse); | 
 |   if (montage_image == (Image *) NULL) | 
 |     return(montage_image); | 
 |   XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |     windows->im_next_image,CurrentTime); | 
 |   return(montage_image); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %   X D i s p l a y B a c k g r o u n d I m a g e                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XDisplayBackgroundImage() displays an image in the background of a window. | 
 | % | 
 | %  The format of the XDisplayBackgroundImage method is: | 
 | % | 
 | %      MagickBooleanType XDisplayBackgroundImage(Display *display, | 
 | %        XResourceInfo *resource_info,Image *image,ExceptionInfo *exception) | 
 | % | 
 | %  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: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display, | 
 |   XResourceInfo *resource_info,Image *image,ExceptionInfo *exception) | 
 | { | 
 |   char | 
 |     geometry[MaxTextExtent], | 
 |     visual_type[MaxTextExtent]; | 
 |  | 
 |   int | 
 |     height, | 
 |     status, | 
 |     width; | 
 |  | 
 |   RectangleInfo | 
 |     geometry_info; | 
 |  | 
 |   static XPixelInfo | 
 |     pixel; | 
 |  | 
 |   static XStandardColormap | 
 |     *map_info; | 
 |  | 
 |   static XVisualInfo | 
 |     *visual_info = (XVisualInfo *) NULL; | 
 |  | 
 |   static XWindowInfo | 
 |     window_info; | 
 |  | 
 |   size_t | 
 |     delay; | 
 |  | 
 |   Window | 
 |     root_window; | 
 |  | 
 |   XGCValues | 
 |     context_values; | 
 |  | 
 |   XResourceInfo | 
 |     resources; | 
 |  | 
 |   XWindowAttributes | 
 |     window_attributes; | 
 |  | 
 |   /* | 
 |     Determine target window. | 
 |   */ | 
 |   assert(image != (Image *) NULL); | 
 |   assert(image->signature == MagickSignature); | 
 |   if (image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); | 
 |   resources=(*resource_info); | 
 |   window_info.id=(Window) NULL; | 
 |   root_window=XRootWindow(display,XDefaultScreen(display)); | 
 |   if (LocaleCompare(resources.window_id,"root") == 0) | 
 |     window_info.id=root_window; | 
 |   else | 
 |     { | 
 |       if (isdigit((unsigned char) *resources.window_id) != 0) | 
 |         window_info.id=XWindowByID(display,root_window, | 
 |           (Window) strtol((char *) resources.window_id,(char **) NULL,0)); | 
 |       if (window_info.id == (Window) NULL) | 
 |         window_info.id=XWindowByName(display,root_window,resources.window_id); | 
 |     } | 
 |   if (window_info.id == (Window) NULL) | 
 |     { | 
 |       ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists", | 
 |         resources.window_id); | 
 |       return(MagickFalse); | 
 |     } | 
 |   /* | 
 |     Determine window visual id. | 
 |   */ | 
 |   window_attributes.width=XDisplayWidth(display,XDefaultScreen(display)); | 
 |   window_attributes.height=XDisplayHeight(display,XDefaultScreen(display)); | 
 |   (void) CopyMagickString(visual_type,"default",MaxTextExtent); | 
 |   status=XGetWindowAttributes(display,window_info.id,&window_attributes); | 
 |   if (status != 0) | 
 |     (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx", | 
 |       XVisualIDFromVisual(window_attributes.visual)); | 
 |   if (visual_info == (XVisualInfo *) NULL) | 
 |     { | 
 |       /* | 
 |         Allocate standard colormap. | 
 |       */ | 
 |       map_info=XAllocStandardColormap(); | 
 |       if (map_info == (XStandardColormap *) NULL) | 
 |         ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed", | 
 |           image->filename); | 
 |       map_info->colormap=(Colormap) NULL; | 
 |       pixel.pixels=(unsigned long *) NULL; | 
 |       /* | 
 |         Initialize visual info. | 
 |       */ | 
 |       resources.map_type=(char *) NULL; | 
 |       resources.visual_type=visual_type; | 
 |       visual_info=XBestVisualInfo(display,map_info,&resources); | 
 |       if (visual_info == (XVisualInfo *) NULL) | 
 |         ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual", | 
 |           resources.visual_type); | 
 |       /* | 
 |         Initialize window info. | 
 |       */ | 
 |       window_info.ximage=(XImage *) NULL; | 
 |       window_info.matte_image=(XImage *) NULL; | 
 |       window_info.pixmap=(Pixmap) NULL; | 
 |       window_info.matte_pixmap=(Pixmap) NULL; | 
 |     } | 
 |   /* | 
 |     Free previous root colors. | 
 |   */ | 
 |   if (window_info.id == root_window) | 
 |     (void) XDestroyWindowColors(display,root_window); | 
 |   /* | 
 |     Initialize Standard Colormap. | 
 |   */ | 
 |   resources.colormap=SharedColormap; | 
 |   XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel, | 
 |     exception); | 
 |   /* | 
 |     Graphic context superclass. | 
 |   */ | 
 |   context_values.background=pixel.background_color.pixel; | 
 |   context_values.foreground=pixel.foreground_color.pixel; | 
 |   pixel.annotate_context=XCreateGC(display,window_info.id, | 
 |     (size_t) (GCBackground | GCForeground),&context_values); | 
 |   if (pixel.annotate_context == (GC) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", | 
 |       image->filename); | 
 |   /* | 
 |     Initialize Image window attributes. | 
 |   */ | 
 |   window_info.name=AcquireString("\0"); | 
 |   window_info.icon_name=AcquireString("\0"); | 
 |   XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL, | 
 |     &resources,&window_info); | 
 |   /* | 
 |     Create the X image. | 
 |   */ | 
 |   window_info.width=(unsigned int) image->columns; | 
 |   window_info.height=(unsigned int) image->rows; | 
 |   if ((image->columns != window_info.width) || | 
 |       (image->rows != window_info.height)) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", | 
 |       image->filename); | 
 |   (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>", | 
 |     window_attributes.width,window_attributes.height); | 
 |   geometry_info.width=window_info.width; | 
 |   geometry_info.height=window_info.height; | 
 |   geometry_info.x=(ssize_t) window_info.x; | 
 |   geometry_info.y=(ssize_t) window_info.y; | 
 |   (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y, | 
 |     &geometry_info.width,&geometry_info.height); | 
 |   window_info.width=(unsigned int) geometry_info.width; | 
 |   window_info.height=(unsigned int) geometry_info.height; | 
 |   window_info.x=(int) geometry_info.x; | 
 |   window_info.y=(int) geometry_info.y; | 
 |   status=XMakeImage(display,&resources,&window_info,image,window_info.width, | 
 |     window_info.height,exception); | 
 |   if (status == MagickFalse) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", | 
 |       image->filename); | 
 |   window_info.x=0; | 
 |   window_info.y=0; | 
 |   if (image->debug != MagickFalse) | 
 |     { | 
 |       (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |         "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene, | 
 |         (double) image->columns,(double) image->rows); | 
 |       if (image->colors != 0) | 
 |         (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double) | 
 |           image->colors); | 
 |       (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick); | 
 |     } | 
 |   /* | 
 |     Adjust image dimensions as specified by backdrop or geometry options. | 
 |   */ | 
 |   width=(int) window_info.width; | 
 |   height=(int) window_info.height; | 
 |   if (resources.backdrop != MagickFalse) | 
 |     { | 
 |       /* | 
 |         Center image on window. | 
 |       */ | 
 |       window_info.x=(window_attributes.width/2)- | 
 |         (window_info.ximage->width/2); | 
 |       window_info.y=(window_attributes.height/2)- | 
 |         (window_info.ximage->height/2); | 
 |       width=window_attributes.width; | 
 |       height=window_attributes.height; | 
 |     } | 
 |   if ((resources.image_geometry != (char *) NULL) && | 
 |       (*resources.image_geometry != '\0')) | 
 |     { | 
 |       char | 
 |         default_geometry[MaxTextExtent]; | 
 |  | 
 |       int | 
 |         flags, | 
 |         gravity; | 
 |  | 
 |       XSizeHints | 
 |         *size_hints; | 
 |  | 
 |       /* | 
 |         User specified geometry. | 
 |       */ | 
 |       size_hints=XAllocSizeHints(); | 
 |       if (size_hints == (XSizeHints *) NULL) | 
 |         ThrowXWindowFatalException(ResourceLimitFatalError, | 
 |           "MemoryAllocationFailed",image->filename); | 
 |       size_hints->flags=0L; | 
 |       (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d", | 
 |         width,height); | 
 |       flags=XWMGeometry(display,visual_info->screen,resources.image_geometry, | 
 |         default_geometry,window_info.border_width,size_hints,&window_info.x, | 
 |         &window_info.y,&width,&height,&gravity); | 
 |       if (flags & (XValue | YValue)) | 
 |         { | 
 |           width=window_attributes.width; | 
 |           height=window_attributes.height; | 
 |         } | 
 |       (void) XFree((void *) size_hints); | 
 |     } | 
 |   /* | 
 |     Create the X pixmap. | 
 |   */ | 
 |   window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width, | 
 |     (unsigned int) height,window_info.depth); | 
 |   if (window_info.pixmap == (Pixmap) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap", | 
 |       image->filename); | 
 |   /* | 
 |     Display pixmap on the window. | 
 |   */ | 
 |   if (((unsigned int) width > window_info.width) || | 
 |       ((unsigned int) height > window_info.height)) | 
 |     (void) XFillRectangle(display,window_info.pixmap, | 
 |       window_info.annotate_context,0,0,(unsigned int) width, | 
 |       (unsigned int) height); | 
 |   (void) XPutImage(display,window_info.pixmap,window_info.annotate_context, | 
 |     window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int) | 
 |     window_info.width,(unsigned int) window_info.height); | 
 |   (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap); | 
 |   (void) XClearWindow(display,window_info.id); | 
 |   delay=1000*image->delay/MagickMax(image->ticks_per_second,1L); | 
 |   XDelay(display,delay == 0UL ? 10UL : delay); | 
 |   (void) XSync(display,MagickFalse); | 
 |   return(window_info.id == root_window ? MagickTrue : MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   X D i s p l a y I m a g e                                                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  XDisplayImage() displays an image via X11.  A new image is created and | 
 | %  returned if the user interactively transforms the displayed image. | 
 | % | 
 | %  The format of the XDisplayImage method is: | 
 | % | 
 | %      Image *XDisplayImage(Display *display,XResourceInfo *resource_info, | 
 | %        char **argv,int argc,Image **image,size_t *state, | 
 | %        ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o nexus:  Method XDisplayImage returns an image when the | 
 | %      user chooses 'Open Image' from the command menu or picks a tile | 
 | %      from the image directory.  Otherwise a null image is returned. | 
 | % | 
 | %    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 an address to an address of an Image structure; | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info, | 
 |   char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception) | 
 | { | 
 | #define MagnifySize  256  /* must be a power of 2 */ | 
 | #define MagickMenus  10 | 
 | #define MagickTitle  "Commands" | 
 |  | 
 |   static const char | 
 |     *CommandMenu[] = | 
 |     { | 
 |       "File", | 
 |       "Edit", | 
 |       "View", | 
 |       "Transform", | 
 |       "Enhance", | 
 |       "Effects", | 
 |       "F/X", | 
 |       "Image Edit", | 
 |       "Miscellany", | 
 |       "Help", | 
 |       (char *) NULL | 
 |     }, | 
 |     *FileMenu[] = | 
 |     { | 
 |       "Open...", | 
 |       "Next", | 
 |       "Former", | 
 |       "Select...", | 
 |       "Save...", | 
 |       "Print...", | 
 |       "Delete...", | 
 |       "New...", | 
 |       "Visual Directory...", | 
 |       "Quit", | 
 |       (char *) NULL | 
 |     }, | 
 |     *EditMenu[] = | 
 |     { | 
 |       "Undo", | 
 |       "Redo", | 
 |       "Cut", | 
 |       "Copy", | 
 |       "Paste", | 
 |       (char *) NULL | 
 |     }, | 
 |     *ViewMenu[] = | 
 |     { | 
 |       "Half Size", | 
 |       "Original Size", | 
 |       "Double Size", | 
 |       "Resize...", | 
 |       "Apply", | 
 |       "Refresh", | 
 |       "Restore", | 
 |       (char *) NULL | 
 |     }, | 
 |     *TransformMenu[] = | 
 |     { | 
 |       "Crop", | 
 |       "Chop", | 
 |       "Flop", | 
 |       "Flip", | 
 |       "Rotate Right", | 
 |       "Rotate Left", | 
 |       "Rotate...", | 
 |       "Shear...", | 
 |       "Roll...", | 
 |       "Trim Edges", | 
 |       (char *) NULL | 
 |     }, | 
 |     *EnhanceMenu[] = | 
 |     { | 
 |       "Hue...", | 
 |       "Saturation...", | 
 |       "Brightness...", | 
 |       "Gamma...", | 
 |       "Spiff", | 
 |       "Dull", | 
 |       "Contrast Stretch...", | 
 |       "Sigmoidal Contrast...", | 
 |       "Normalize", | 
 |       "Equalize", | 
 |       "Negate", | 
 |       "Grayscale", | 
 |       "Map...", | 
 |       "Quantize...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *EffectsMenu[] = | 
 |     { | 
 |       "Despeckle", | 
 |       "Emboss", | 
 |       "Reduce Noise", | 
 |       "Add Noise...", | 
 |       "Sharpen...", | 
 |       "Blur...", | 
 |       "Threshold...", | 
 |       "Edge Detect...", | 
 |       "Spread...", | 
 |       "Shade...", | 
 |       "Raise...", | 
 |       "Segment...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *FXMenu[] = | 
 |     { | 
 |       "Solarize...", | 
 |       "Sepia Tone...", | 
 |       "Swirl...", | 
 |       "Implode...", | 
 |       "Vignette...", | 
 |       "Wave...", | 
 |       "Oil Paint...", | 
 |       "Charcoal Draw...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *ImageEditMenu[] = | 
 |     { | 
 |       "Annotate...", | 
 |       "Draw...", | 
 |       "Color...", | 
 |       "Matte...", | 
 |       "Composite...", | 
 |       "Add Border...", | 
 |       "Add Frame...", | 
 |       "Comment...", | 
 |       "Launch...", | 
 |       "Region of Interest...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *MiscellanyMenu[] = | 
 |     { | 
 |       "Image Info", | 
 |       "Zoom Image", | 
 |       "Show Preview...", | 
 |       "Show Histogram", | 
 |       "Show Matte", | 
 |       "Background...", | 
 |       "Slide Show...", | 
 |       "Preferences...", | 
 |       (char *) NULL | 
 |     }, | 
 |     *HelpMenu[] = | 
 |     { | 
 |       "Overview", | 
 |       "Browse Documentation", | 
 |       "About Display", | 
 |       (char *) NULL | 
 |     }, | 
 |     *ShortCutsMenu[] = | 
 |     { | 
 |       "Next", | 
 |       "Former", | 
 |       "Open...", | 
 |       "Save...", | 
 |       "Print...", | 
 |       "Undo", | 
 |       "Restore", | 
 |       "Image Info", | 
 |       "Quit", | 
 |       (char *) NULL | 
 |     }, | 
 |     *VirtualMenu[] = | 
 |     { | 
 |       "Image Info", | 
 |       "Print", | 
 |       "Next", | 
 |       "Quit", | 
 |       (char *) NULL | 
 |     }; | 
 |  | 
 |   static const char | 
 |     **Menus[MagickMenus] = | 
 |     { | 
 |       FileMenu, | 
 |       EditMenu, | 
 |       ViewMenu, | 
 |       TransformMenu, | 
 |       EnhanceMenu, | 
 |       EffectsMenu, | 
 |       FXMenu, | 
 |       ImageEditMenu, | 
 |       MiscellanyMenu, | 
 |       HelpMenu | 
 |     }; | 
 |  | 
 |   static CommandType | 
 |     CommandMenus[] = | 
 |     { | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |       NullCommand, | 
 |     }, | 
 |     FileCommands[] = | 
 |     { | 
 |       OpenCommand, | 
 |       NextCommand, | 
 |       FormerCommand, | 
 |       SelectCommand, | 
 |       SaveCommand, | 
 |       PrintCommand, | 
 |       DeleteCommand, | 
 |       NewCommand, | 
 |       VisualDirectoryCommand, | 
 |       QuitCommand | 
 |     }, | 
 |     EditCommands[] = | 
 |     { | 
 |       UndoCommand, | 
 |       RedoCommand, | 
 |       CutCommand, | 
 |       CopyCommand, | 
 |       PasteCommand | 
 |     }, | 
 |     ViewCommands[] = | 
 |     { | 
 |       HalfSizeCommand, | 
 |       OriginalSizeCommand, | 
 |       DoubleSizeCommand, | 
 |       ResizeCommand, | 
 |       ApplyCommand, | 
 |       RefreshCommand, | 
 |       RestoreCommand | 
 |     }, | 
 |     TransformCommands[] = | 
 |     { | 
 |       CropCommand, | 
 |       ChopCommand, | 
 |       FlopCommand, | 
 |       FlipCommand, | 
 |       RotateRightCommand, | 
 |       RotateLeftCommand, | 
 |       RotateCommand, | 
 |       ShearCommand, | 
 |       RollCommand, | 
 |       TrimCommand | 
 |     }, | 
 |     EnhanceCommands[] = | 
 |     { | 
 |       HueCommand, | 
 |       SaturationCommand, | 
 |       BrightnessCommand, | 
 |       GammaCommand, | 
 |       SpiffCommand, | 
 |       DullCommand, | 
 |       ContrastStretchCommand, | 
 |       SigmoidalContrastCommand, | 
 |       NormalizeCommand, | 
 |       EqualizeCommand, | 
 |       NegateCommand, | 
 |       GrayscaleCommand, | 
 |       MapCommand, | 
 |       QuantizeCommand | 
 |     }, | 
 |     EffectsCommands[] = | 
 |     { | 
 |       DespeckleCommand, | 
 |       EmbossCommand, | 
 |       ReduceNoiseCommand, | 
 |       AddNoiseCommand, | 
 |       SharpenCommand, | 
 |       BlurCommand, | 
 |       ThresholdCommand, | 
 |       EdgeDetectCommand, | 
 |       SpreadCommand, | 
 |       ShadeCommand, | 
 |       RaiseCommand, | 
 |       SegmentCommand | 
 |     }, | 
 |     FXCommands[] = | 
 |     { | 
 |       SolarizeCommand, | 
 |       SepiaToneCommand, | 
 |       SwirlCommand, | 
 |       ImplodeCommand, | 
 |       VignetteCommand, | 
 |       WaveCommand, | 
 |       OilPaintCommand, | 
 |       CharcoalDrawCommand | 
 |     }, | 
 |     ImageEditCommands[] = | 
 |     { | 
 |       AnnotateCommand, | 
 |       DrawCommand, | 
 |       ColorCommand, | 
 |       MatteCommand, | 
 |       CompositeCommand, | 
 |       AddBorderCommand, | 
 |       AddFrameCommand, | 
 |       CommentCommand, | 
 |       LaunchCommand, | 
 |       RegionofInterestCommand | 
 |     }, | 
 |     MiscellanyCommands[] = | 
 |     { | 
 |       InfoCommand, | 
 |       ZoomCommand, | 
 |       ShowPreviewCommand, | 
 |       ShowHistogramCommand, | 
 |       ShowMatteCommand, | 
 |       BackgroundCommand, | 
 |       SlideShowCommand, | 
 |       PreferencesCommand | 
 |     }, | 
 |     HelpCommands[] = | 
 |     { | 
 |       HelpCommand, | 
 |       BrowseDocumentationCommand, | 
 |       VersionCommand | 
 |     }, | 
 |     ShortCutsCommands[] = | 
 |     { | 
 |       NextCommand, | 
 |       FormerCommand, | 
 |       OpenCommand, | 
 |       SaveCommand, | 
 |       PrintCommand, | 
 |       UndoCommand, | 
 |       RestoreCommand, | 
 |       InfoCommand, | 
 |       QuitCommand | 
 |     }, | 
 |     VirtualCommands[] = | 
 |     { | 
 |       InfoCommand, | 
 |       PrintCommand, | 
 |       NextCommand, | 
 |       QuitCommand | 
 |     }; | 
 |  | 
 |   static CommandType | 
 |     *Commands[MagickMenus] = | 
 |     { | 
 |       FileCommands, | 
 |       EditCommands, | 
 |       ViewCommands, | 
 |       TransformCommands, | 
 |       EnhanceCommands, | 
 |       EffectsCommands, | 
 |       FXCommands, | 
 |       ImageEditCommands, | 
 |       MiscellanyCommands, | 
 |       HelpCommands | 
 |     }; | 
 |  | 
 |   char | 
 |     command[MaxTextExtent], | 
 |     *directory, | 
 |     geometry[MaxTextExtent], | 
 |     resource_name[MaxTextExtent]; | 
 |  | 
 |   CommandType | 
 |     command_type; | 
 |  | 
 |   Image | 
 |     *display_image, | 
 |     *nexus; | 
 |  | 
 |   int | 
 |     entry, | 
 |     id; | 
 |  | 
 |   KeySym | 
 |     key_symbol; | 
 |  | 
 |   MagickStatusType | 
 |     context_mask, | 
 |     status; | 
 |  | 
 |   RectangleInfo | 
 |     geometry_info; | 
 |  | 
 |   register int | 
 |     i; | 
 |  | 
 |   static char | 
 |     working_directory[MaxTextExtent]; | 
 |  | 
 |   static XPoint | 
 |     vid_info; | 
 |  | 
 |   static XWindowInfo | 
 |     *magick_windows[MaxXWindows]; | 
 |  | 
 |   static unsigned int | 
 |     number_windows; | 
 |  | 
 |   struct stat | 
 |     attributes; | 
 |  | 
 |   time_t | 
 |     timer, | 
 |     timestamp, | 
 |     update_time; | 
 |  | 
 |   unsigned int | 
 |     height, | 
 |     width; | 
 |  | 
 |   size_t | 
 |     delay; | 
 |  | 
 |   WarningHandler | 
 |     warning_handler; | 
 |  | 
 |   Window | 
 |     root_window; | 
 |  | 
 |   XClassHint | 
 |     *class_hints; | 
 |  | 
 |   XEvent | 
 |     event; | 
 |  | 
 |   XFontStruct | 
 |     *font_info; | 
 |  | 
 |   XGCValues | 
 |     context_values; | 
 |  | 
 |   XPixelInfo | 
 |     *icon_pixel, | 
 |     *pixel; | 
 |  | 
 |   XResourceInfo | 
 |     *icon_resources; | 
 |  | 
 |   XStandardColormap | 
 |     *icon_map, | 
 |     *map_info; | 
 |  | 
 |   XVisualInfo | 
 |     *icon_visual, | 
 |     *visual_info; | 
 |  | 
 |   XWindowChanges | 
 |     window_changes; | 
 |  | 
 |   XWindows | 
 |     *windows; | 
 |  | 
 |   XWMHints | 
 |     *manager_hints; | 
 |  | 
 |   assert(image != (Image **) NULL); | 
 |   assert((*image)->signature == MagickSignature); | 
 |   if ((*image)->debug != MagickFalse) | 
 |     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename); | 
 |   display_image=(*image); | 
 |   warning_handler=(WarningHandler) NULL; | 
 |   windows=XSetWindows((XWindows *) ~0); | 
 |   if (windows != (XWindows *) NULL) | 
 |     { | 
 |       int | 
 |         status; | 
 |  | 
 |       status=chdir(working_directory); | 
 |       if (status == -1) | 
 |         (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError, | 
 |           "UnableToOpenFile","%s",working_directory); | 
 |       warning_handler=resource_info->display_warnings ? | 
 |         SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL); | 
 |       warning_handler=resource_info->display_warnings ? | 
 |         SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL); | 
 |     } | 
 |   else | 
 |     { | 
 |       /* | 
 |         Allocate windows structure. | 
 |       */ | 
 |       resource_info->colors=display_image->colors; | 
 |       windows=XSetWindows(XInitializeWindows(display,resource_info)); | 
 |       if (windows == (XWindows *) NULL) | 
 |         ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow", | 
 |           (*image)->filename); | 
 |       /* | 
 |         Initialize window id's. | 
 |       */ | 
 |       number_windows=0; | 
 |       magick_windows[number_windows++]=(&windows->icon); | 
 |       magick_windows[number_windows++]=(&windows->backdrop); | 
 |       magick_windows[number_windows++]=(&windows->image); | 
 |       magick_windows[number_windows++]=(&windows->info); | 
 |       magick_windows[number_windows++]=(&windows->command); | 
 |       magick_windows[number_windows++]=(&windows->widget); | 
 |       magick_windows[number_windows++]=(&windows->popup); | 
 |       magick_windows[number_windows++]=(&windows->magnify); | 
 |       magick_windows[number_windows++]=(&windows->pan); | 
 |       for (i=0; i < (int) number_windows; i++) | 
 |         magick_windows[i]->id=(Window) NULL; | 
 |       vid_info.x=0; | 
 |       vid_info.y=0; | 
 |     } | 
 |   /* | 
 |     Initialize font info. | 
 |   */ | 
 |   if (windows->font_info != (XFontStruct *) NULL) | 
 |     (void) XFreeFont(display,windows->font_info); | 
 |   windows->font_info=XBestFont(display,resource_info,MagickFalse); | 
 |   if (windows->font_info == (XFontStruct *) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont", | 
 |       resource_info->font); | 
 |   /* | 
 |     Initialize Standard Colormap. | 
 |   */ | 
 |   map_info=windows->map_info; | 
 |   icon_map=windows->icon_map; | 
 |   visual_info=windows->visual_info; | 
 |   icon_visual=windows->icon_visual; | 
 |   pixel=windows->pixel_info; | 
 |   icon_pixel=windows->icon_pixel; | 
 |   font_info=windows->font_info; | 
 |   icon_resources=windows->icon_resources; | 
 |   class_hints=windows->class_hints; | 
 |   manager_hints=windows->manager_hints; | 
 |   root_window=XRootWindow(display,visual_info->screen); | 
 |   nexus=NewImageList(); | 
 |   if (display_image->debug != MagickFalse) | 
 |     { | 
 |       (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |         "Image: %s[%.20g] %.20gx%.20g ",display_image->filename, | 
 |         (double) display_image->scene,(double) display_image->columns, | 
 |         (double) display_image->rows); | 
 |       if (display_image->colors != 0) | 
 |         (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double) | 
 |           display_image->colors); | 
 |       (void) LogMagickEvent(X11Event,GetMagickModule(),"%s", | 
 |         display_image->magick); | 
 |     } | 
 |   XMakeStandardColormap(display,visual_info,resource_info,display_image, | 
 |     map_info,pixel,exception); | 
 |   display_image->taint=MagickFalse; | 
 |   /* | 
 |     Initialize graphic context. | 
 |   */ | 
 |   windows->context.id=(Window) NULL; | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info, | 
 |     resource_info,&windows->context); | 
 |   (void) CloneString(&class_hints->res_name,resource_info->client_name); | 
 |   (void) CloneString(&class_hints->res_class,resource_info->client_name); | 
 |   class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]); | 
 |   manager_hints->flags=InputHint | StateHint; | 
 |   manager_hints->input=MagickFalse; | 
 |   manager_hints->initial_state=WithdrawnState; | 
 |   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |     &windows->context); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |       "Window id: 0x%lx (context)",windows->context.id); | 
 |   context_values.background=pixel->background_color.pixel; | 
 |   context_values.font=font_info->fid; | 
 |   context_values.foreground=pixel->foreground_color.pixel; | 
 |   context_values.graphics_exposures=MagickFalse; | 
 |   context_mask=(MagickStatusType) | 
 |     (GCBackground | GCFont | GCForeground | GCGraphicsExposures); | 
 |   if (pixel->annotate_context != (GC) NULL) | 
 |     (void) XFreeGC(display,pixel->annotate_context); | 
 |   pixel->annotate_context=XCreateGC(display,windows->context.id, | 
 |     context_mask,&context_values); | 
 |   if (pixel->annotate_context == (GC) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", | 
 |       display_image->filename); | 
 |   context_values.background=pixel->depth_color.pixel; | 
 |   if (pixel->widget_context != (GC) NULL) | 
 |     (void) XFreeGC(display,pixel->widget_context); | 
 |   pixel->widget_context=XCreateGC(display,windows->context.id,context_mask, | 
 |     &context_values); | 
 |   if (pixel->widget_context == (GC) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", | 
 |       display_image->filename); | 
 |   context_values.background=pixel->foreground_color.pixel; | 
 |   context_values.foreground=pixel->background_color.pixel; | 
 |   context_values.plane_mask=context_values.background ^ | 
 |     context_values.foreground; | 
 |   if (pixel->highlight_context != (GC) NULL) | 
 |     (void) XFreeGC(display,pixel->highlight_context); | 
 |   pixel->highlight_context=XCreateGC(display,windows->context.id, | 
 |     (size_t) (context_mask | GCPlaneMask),&context_values); | 
 |   if (pixel->highlight_context == (GC) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", | 
 |       display_image->filename); | 
 |   (void) XDestroyWindow(display,windows->context.id); | 
 |   /* | 
 |     Initialize icon window. | 
 |   */ | 
 |   XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL, | 
 |     icon_resources,&windows->icon); | 
 |   windows->icon.geometry=resource_info->icon_geometry; | 
 |   XBestIconSize(display,&windows->icon,display_image); | 
 |   windows->icon.attributes.colormap=XDefaultColormap(display, | 
 |     icon_visual->screen); | 
 |   windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask; | 
 |   manager_hints->flags=InputHint | StateHint; | 
 |   manager_hints->input=MagickFalse; | 
 |   manager_hints->initial_state=IconicState; | 
 |   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |     &windows->icon); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)", | 
 |       windows->icon.id); | 
 |   /* | 
 |     Initialize graphic context for icon window. | 
 |   */ | 
 |   if (icon_pixel->annotate_context != (GC) NULL) | 
 |     (void) XFreeGC(display,icon_pixel->annotate_context); | 
 |   context_values.background=icon_pixel->background_color.pixel; | 
 |   context_values.foreground=icon_pixel->foreground_color.pixel; | 
 |   icon_pixel->annotate_context=XCreateGC(display,windows->icon.id, | 
 |     (size_t) (GCBackground | GCForeground),&context_values); | 
 |   if (icon_pixel->annotate_context == (GC) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext", | 
 |       display_image->filename); | 
 |   windows->icon.annotate_context=icon_pixel->annotate_context; | 
 |   /* | 
 |     Initialize Image window. | 
 |   */ | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info, | 
 |     &windows->image); | 
 |   windows->image.shape=MagickTrue;  /* non-rectangular shape hint */ | 
 |   if (resource_info->use_shared_memory == MagickFalse) | 
 |     windows->image.shared_memory=MagickFalse; | 
 |   if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState)) | 
 |     { | 
 |       char | 
 |         *title; | 
 |  | 
 |       title=InterpretImageProperties(resource_info->image_info,display_image, | 
 |         resource_info->title,exception); | 
 |       (void) CopyMagickString(windows->image.name,title,MaxTextExtent); | 
 |       (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent); | 
 |       title=DestroyString(title); | 
 |     } | 
 |   else | 
 |     { | 
 |       char | 
 |         filename[MaxTextExtent]; | 
 |  | 
 |       /* | 
 |         Window name is the base of the filename. | 
 |       */ | 
 |       GetPathComponent(display_image->magick_filename,TailPath,filename); | 
 |       if (display_image->scene == 0) | 
 |         (void) FormatLocaleString(windows->image.name,MaxTextExtent, | 
 |           "%s: %s",MagickPackageName,filename); | 
 |       else | 
 |         (void) FormatLocaleString(windows->image.name,MaxTextExtent, | 
 |           "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename, | 
 |           (double) display_image->scene,(double) GetImageListLength( | 
 |           display_image)); | 
 |       (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent); | 
 |     } | 
 |   if (resource_info->immutable) | 
 |     windows->image.immutable=MagickTrue; | 
 |   windows->image.use_pixmap=resource_info->use_pixmap; | 
 |   windows->image.geometry=resource_info->image_geometry; | 
 |   (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!", | 
 |     XDisplayWidth(display,visual_info->screen), | 
 |     XDisplayHeight(display,visual_info->screen)); | 
 |   geometry_info.width=display_image->columns; | 
 |   geometry_info.height=display_image->rows; | 
 |   geometry_info.x=0; | 
 |   geometry_info.y=0; | 
 |   (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y, | 
 |     &geometry_info.width,&geometry_info.height); | 
 |   windows->image.width=(unsigned int) geometry_info.width; | 
 |   windows->image.height=(unsigned int) geometry_info.height; | 
 |   windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask | | 
 |     ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask | | 
 |     KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask | | 
 |     PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask; | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info, | 
 |     resource_info,&windows->backdrop); | 
 |   if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL)) | 
 |     { | 
 |       /* | 
 |         Initialize backdrop window. | 
 |       */ | 
 |       windows->backdrop.x=0; | 
 |       windows->backdrop.y=0; | 
 |       (void) CloneString(&windows->backdrop.name,"Backdrop"); | 
 |       windows->backdrop.flags=(size_t) (USSize | USPosition); | 
 |       windows->backdrop.width=(unsigned int) | 
 |         XDisplayWidth(display,visual_info->screen); | 
 |       windows->backdrop.height=(unsigned int) | 
 |         XDisplayHeight(display,visual_info->screen); | 
 |       windows->backdrop.border_width=0; | 
 |       windows->backdrop.immutable=MagickTrue; | 
 |       windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask | | 
 |         ButtonReleaseMask; | 
 |       windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask | | 
 |         StructureNotifyMask; | 
 |       manager_hints->flags=IconWindowHint | InputHint | StateHint; | 
 |       manager_hints->icon_window=windows->icon.id; | 
 |       manager_hints->input=MagickTrue; | 
 |       manager_hints->initial_state=resource_info->iconic ? IconicState : | 
 |         NormalState; | 
 |       XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |         &windows->backdrop); | 
 |       if (display_image->debug != MagickFalse) | 
 |         (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |           "Window id: 0x%lx (backdrop)",windows->backdrop.id); | 
 |       (void) XMapWindow(display,windows->backdrop.id); | 
 |       (void) XClearWindow(display,windows->backdrop.id); | 
 |       if (windows->image.id != (Window) NULL) | 
 |         { | 
 |           (void) XDestroyWindow(display,windows->image.id); | 
 |           windows->image.id=(Window) NULL; | 
 |         } | 
 |       /* | 
 |         Position image in the center the backdrop. | 
 |       */ | 
 |       windows->image.flags|=USPosition; | 
 |       windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)- | 
 |         (windows->image.width/2); | 
 |       windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)- | 
 |         (windows->image.height/2); | 
 |     } | 
 |   manager_hints->flags=IconWindowHint | InputHint | StateHint; | 
 |   manager_hints->icon_window=windows->icon.id; | 
 |   manager_hints->input=MagickTrue; | 
 |   manager_hints->initial_state=resource_info->iconic ? IconicState : | 
 |     NormalState; | 
 |   if (windows->group_leader.id != (Window) NULL) | 
 |     { | 
 |       /* | 
 |         Follow the leader. | 
 |       */ | 
 |       manager_hints->flags|=WindowGroupHint; | 
 |       manager_hints->window_group=windows->group_leader.id; | 
 |       (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask); | 
 |       if (display_image->debug != MagickFalse) | 
 |         (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |           "Window id: 0x%lx (group leader)",windows->group_leader.id); | 
 |     } | 
 |   XMakeWindow(display, | 
 |     (Window) (resource_info->backdrop ? windows->backdrop.id : root_window), | 
 |     argv,argc,class_hints,manager_hints,&windows->image); | 
 |   (void) XChangeProperty(display,windows->image.id,windows->im_protocols, | 
 |     XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0); | 
 |   if (windows->group_leader.id != (Window) NULL) | 
 |     (void) XSetTransientForHint(display,windows->image.id, | 
 |       windows->group_leader.id); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)", | 
 |       windows->image.id); | 
 |   /* | 
 |     Initialize Info widget. | 
 |   */ | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info, | 
 |     &windows->info); | 
 |   (void) CloneString(&windows->info.name,"Info"); | 
 |   (void) CloneString(&windows->info.icon_name,"Info"); | 
 |   windows->info.border_width=1; | 
 |   windows->info.x=2; | 
 |   windows->info.y=2; | 
 |   windows->info.flags|=PPosition; | 
 |   windows->info.attributes.win_gravity=UnmapGravity; | 
 |   windows->info.attributes.event_mask=ButtonPressMask | ExposureMask | | 
 |     StructureNotifyMask; | 
 |   manager_hints->flags=InputHint | StateHint | WindowGroupHint; | 
 |   manager_hints->input=MagickFalse; | 
 |   manager_hints->initial_state=NormalState; | 
 |   manager_hints->window_group=windows->image.id; | 
 |   XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints, | 
 |     &windows->info); | 
 |   windows->info.highlight_stipple=XCreateBitmapFromData(display, | 
 |     windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight); | 
 |   windows->info.shadow_stipple=XCreateBitmapFromData(display, | 
 |     windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); | 
 |   (void) XSetTransientForHint(display,windows->info.id,windows->image.id); | 
 |   if (windows->image.mapped != MagickFalse) | 
 |     (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)", | 
 |       windows->info.id); | 
 |   /* | 
 |     Initialize Command widget. | 
 |   */ | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info, | 
 |     resource_info,&windows->command); | 
 |   windows->command.data=MagickMenus; | 
 |   (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL); | 
 |   (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command", | 
 |     resource_info->client_name); | 
 |   windows->command.geometry=XGetResourceClass(resource_info->resource_database, | 
 |     resource_name,"geometry",(char *) NULL); | 
 |   (void) CloneString(&windows->command.name,MagickTitle); | 
 |   windows->command.border_width=0; | 
 |   windows->command.flags|=PPosition; | 
 |   windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask | | 
 |     ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask | | 
 |     OwnerGrabButtonMask | StructureNotifyMask; | 
 |   manager_hints->flags=InputHint | StateHint | WindowGroupHint; | 
 |   manager_hints->input=MagickTrue; | 
 |   manager_hints->initial_state=NormalState; | 
 |   manager_hints->window_group=windows->image.id; | 
 |   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |     &windows->command); | 
 |   windows->command.highlight_stipple=XCreateBitmapFromData(display, | 
 |     windows->command.id,(char *) HighlightBitmap,HighlightWidth, | 
 |     HighlightHeight); | 
 |   windows->command.shadow_stipple=XCreateBitmapFromData(display, | 
 |     windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); | 
 |   (void) XSetTransientForHint(display,windows->command.id,windows->image.id); | 
 |   if (windows->command.mapped != MagickFalse) | 
 |     (void) XMapRaised(display,windows->command.id); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |       "Window id: 0x%lx (command)",windows->command.id); | 
 |   /* | 
 |     Initialize Widget window. | 
 |   */ | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info, | 
 |     resource_info,&windows->widget); | 
 |   (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget", | 
 |     resource_info->client_name); | 
 |   windows->widget.geometry=XGetResourceClass(resource_info->resource_database, | 
 |     resource_name,"geometry",(char *) NULL); | 
 |   windows->widget.border_width=0; | 
 |   windows->widget.flags|=PPosition; | 
 |   windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask | | 
 |     ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask | | 
 |     KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask | | 
 |     StructureNotifyMask; | 
 |   manager_hints->flags=InputHint | StateHint | WindowGroupHint; | 
 |   manager_hints->input=MagickTrue; | 
 |   manager_hints->initial_state=NormalState; | 
 |   manager_hints->window_group=windows->image.id; | 
 |   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |     &windows->widget); | 
 |   windows->widget.highlight_stipple=XCreateBitmapFromData(display, | 
 |     windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight); | 
 |   windows->widget.shadow_stipple=XCreateBitmapFromData(display, | 
 |     windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); | 
 |   (void) XSetTransientForHint(display,windows->widget.id,windows->image.id); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |       "Window id: 0x%lx (widget)",windows->widget.id); | 
 |   /* | 
 |     Initialize popup window. | 
 |   */ | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info, | 
 |     resource_info,&windows->popup); | 
 |   windows->popup.border_width=0; | 
 |   windows->popup.flags|=PPosition; | 
 |   windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask | | 
 |     ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask | | 
 |     KeyReleaseMask | LeaveWindowMask | StructureNotifyMask; | 
 |   manager_hints->flags=InputHint | StateHint | WindowGroupHint; | 
 |   manager_hints->input=MagickTrue; | 
 |   manager_hints->initial_state=NormalState; | 
 |   manager_hints->window_group=windows->image.id; | 
 |   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |     &windows->popup); | 
 |   windows->popup.highlight_stipple=XCreateBitmapFromData(display, | 
 |     windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight); | 
 |   windows->popup.shadow_stipple=XCreateBitmapFromData(display, | 
 |     windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight); | 
 |   (void) XSetTransientForHint(display,windows->popup.id,windows->image.id); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |       "Window id: 0x%lx (pop up)",windows->popup.id); | 
 |   /* | 
 |     Initialize Magnify window and cursor. | 
 |   */ | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info, | 
 |     resource_info,&windows->magnify); | 
 |   if (resource_info->use_shared_memory == MagickFalse) | 
 |     windows->magnify.shared_memory=MagickFalse; | 
 |   (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify", | 
 |     resource_info->client_name); | 
 |   windows->magnify.geometry=XGetResourceClass(resource_info->resource_database, | 
 |     resource_name,"geometry",(char *) NULL); | 
 |   (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX", | 
 |     resource_info->magnify); | 
 |   if (windows->magnify.cursor != (Cursor) NULL) | 
 |     (void) XFreeCursor(display,windows->magnify.cursor); | 
 |   windows->magnify.cursor=XMakeCursor(display,windows->image.id, | 
 |     map_info->colormap,resource_info->background_color, | 
 |     resource_info->foreground_color); | 
 |   if (windows->magnify.cursor == (Cursor) NULL) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor", | 
 |       display_image->filename); | 
 |   windows->magnify.width=MagnifySize; | 
 |   windows->magnify.height=MagnifySize; | 
 |   windows->magnify.flags|=PPosition; | 
 |   windows->magnify.min_width=MagnifySize; | 
 |   windows->magnify.min_height=MagnifySize; | 
 |   windows->magnify.width_inc=MagnifySize; | 
 |   windows->magnify.height_inc=MagnifySize; | 
 |   windows->magnify.data=resource_info->magnify; | 
 |   windows->magnify.attributes.cursor=windows->magnify.cursor; | 
 |   windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask | | 
 |     ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask | | 
 |     StructureNotifyMask; | 
 |   manager_hints->flags=InputHint | StateHint | WindowGroupHint; | 
 |   manager_hints->input=MagickTrue; | 
 |   manager_hints->initial_state=NormalState; | 
 |   manager_hints->window_group=windows->image.id; | 
 |   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |     &windows->magnify); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |       "Window id: 0x%lx (magnify)",windows->magnify.id); | 
 |   (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id); | 
 |   /* | 
 |     Initialize panning window. | 
 |   */ | 
 |   XGetWindowInfo(display,visual_info,map_info,pixel,font_info, | 
 |     resource_info,&windows->pan); | 
 |   (void) CloneString(&windows->pan.name,"Pan Icon"); | 
 |   windows->pan.width=windows->icon.width; | 
 |   windows->pan.height=windows->icon.height; | 
 |   (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan", | 
 |     resource_info->client_name); | 
 |   windows->pan.geometry=XGetResourceClass(resource_info->resource_database, | 
 |     resource_name,"geometry",(char *) NULL); | 
 |   (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y, | 
 |     &windows->pan.width,&windows->pan.height); | 
 |   windows->pan.flags|=PPosition; | 
 |   windows->pan.immutable=MagickTrue; | 
 |   windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask | | 
 |     ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask | | 
 |     StructureNotifyMask; | 
 |   manager_hints->flags=InputHint | StateHint | WindowGroupHint; | 
 |   manager_hints->input=MagickFalse; | 
 |   manager_hints->initial_state=NormalState; | 
 |   manager_hints->window_group=windows->image.id; | 
 |   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints, | 
 |     &windows->pan); | 
 |   if (display_image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)", | 
 |       windows->pan.id); | 
 |   (void) XSetTransientForHint(display,windows->pan.id,windows->image.id); | 
 |   if (windows->info.mapped != MagickFalse) | 
 |     (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |   if ((windows->image.mapped == MagickFalse) || | 
 |       (windows->backdrop.id != (Window) NULL)) | 
 |     (void) XMapWindow(display,windows->image.id); | 
 |   /* | 
 |     Set our progress monitor and warning handlers. | 
 |   */ | 
 |   if (warning_handler == (WarningHandler) NULL) | 
 |     { | 
 |       warning_handler=resource_info->display_warnings ? | 
 |         SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL); | 
 |       warning_handler=resource_info->display_warnings ? | 
 |         SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL); | 
 |     } | 
 |   /* | 
 |     Initialize Image and Magnify X images. | 
 |   */ | 
 |   windows->image.x=0; | 
 |   windows->image.y=0; | 
 |   windows->magnify.shape=MagickFalse; | 
 |   width=(unsigned int) display_image->columns; | 
 |   height=(unsigned int) display_image->rows; | 
 |   if ((display_image->columns != width) || (display_image->rows != height)) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", | 
 |       display_image->filename); | 
 |   status=XMakeImage(display,resource_info,&windows->image,display_image, | 
 |     width,height,exception); | 
 |   if (status == MagickFalse) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", | 
 |       display_image->filename); | 
 |   status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL, | 
 |     windows->magnify.width,windows->magnify.height,exception); | 
 |   if (status == MagickFalse) | 
 |     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage", | 
 |       display_image->filename); | 
 |   if (windows->magnify.mapped != MagickFalse) | 
 |     (void) XMapRaised(display,windows->magnify.id); | 
 |   if (windows->pan.mapped != MagickFalse) | 
 |     (void) XMapRaised(display,windows->pan.id); | 
 |   windows->image.window_changes.width=(int) display_image->columns; | 
 |   windows->image.window_changes.height=(int) display_image->rows; | 
 |   (void) XConfigureImage(display,resource_info,windows,display_image,exception); | 
 |   (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |   (void) XSync(display,MagickFalse); | 
 |   /* | 
 |     Respond to events. | 
 |   */ | 
 |   delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L); | 
 |   timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1; | 
 |   update_time=0; | 
 |   if (resource_info->update != MagickFalse) | 
 |     { | 
 |       MagickBooleanType | 
 |         status; | 
 |  | 
 |       /* | 
 |         Determine when file data was last modified. | 
 |       */ | 
 |       status=GetPathAttributes(display_image->filename,&attributes); | 
 |       if (status != MagickFalse) | 
 |         update_time=attributes.st_mtime; | 
 |     } | 
 |   *state&=(~FormerImageState); | 
 |   *state&=(~MontageImageState); | 
 |   *state&=(~NextImageState); | 
 |   do | 
 |   { | 
 |     /* | 
 |       Handle a window event. | 
 |     */ | 
 |     if (windows->image.mapped != MagickFalse) | 
 |       if ((display_image->delay != 0) || (resource_info->update != 0)) | 
 |         { | 
 |           if (timer < time((time_t *) NULL)) | 
 |             { | 
 |               if (resource_info->update == MagickFalse) | 
 |                 *state|=NextImageState | ExitState; | 
 |               else | 
 |                 { | 
 |                   MagickBooleanType | 
 |                     status; | 
 |  | 
 |                   /* | 
 |                     Determine if image file was modified. | 
 |                   */ | 
 |                   status=GetPathAttributes(display_image->filename,&attributes); | 
 |                   if (status != MagickFalse) | 
 |                     if (update_time != attributes.st_mtime) | 
 |                       { | 
 |                         /* | 
 |                           Redisplay image. | 
 |                         */ | 
 |                         (void) FormatLocaleString( | 
 |                           resource_info->image_info->filename,MaxTextExtent, | 
 |                           "%s:%s",display_image->magick, | 
 |                           display_image->filename); | 
 |                         nexus=ReadImage(resource_info->image_info,exception); | 
 |                         if (nexus != (Image *) NULL) | 
 |                           { | 
 |                             nexus=DestroyImage(nexus); | 
 |                             *state|=NextImageState | ExitState; | 
 |                           } | 
 |                       } | 
 |                   delay=display_image->delay/MagickMax( | 
 |                     display_image->ticks_per_second,1L); | 
 |                   timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1; | 
 |                 } | 
 |             } | 
 |           if (XEventsQueued(display,QueuedAfterFlush) == 0) | 
 |             { | 
 |               /* | 
 |                 Do not block if delay > 0. | 
 |               */ | 
 |               XDelay(display,SuspendTime << 2); | 
 |               continue; | 
 |             } | 
 |         } | 
 |     timestamp=time((time_t *) NULL); | 
 |     (void) XNextEvent(display,&event); | 
 |     if (windows->image.stasis == MagickFalse) | 
 |       windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ? | 
 |         MagickTrue : MagickFalse; | 
 |     if (windows->magnify.stasis == MagickFalse) | 
 |       windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ? | 
 |         MagickTrue : MagickFalse; | 
 |     if (event.xany.window == windows->command.id) | 
 |       { | 
 |         /* | 
 |           Select a command from the Command widget. | 
 |         */ | 
 |         id=XCommandWidget(display,windows,CommandMenu,&event); | 
 |         if (id < 0) | 
 |           continue; | 
 |         (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent); | 
 |         command_type=CommandMenus[id]; | 
 |         if (id < MagickMenus) | 
 |           { | 
 |             /* | 
 |               Select a command from a pop-up menu. | 
 |             */ | 
 |             entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id], | 
 |               command); | 
 |             if (entry < 0) | 
 |               continue; | 
 |             (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent); | 
 |             command_type=Commands[id][entry]; | 
 |           } | 
 |         if (command_type != NullCommand) | 
 |           nexus=XMagickCommand(display,resource_info,windows,command_type, | 
 |             &display_image,exception); | 
 |         continue; | 
 |       } | 
 |     switch (event.type) | 
 |     { | 
 |       case ButtonPress: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Button Press: 0x%lx %u +%d+%d",event.xbutton.window, | 
 |             event.xbutton.button,event.xbutton.x,event.xbutton.y); | 
 |         if ((event.xbutton.button == Button3) && | 
 |             (event.xbutton.state & Mod1Mask)) | 
 |           { | 
 |             /* | 
 |               Convert Alt-Button3 to Button2. | 
 |             */ | 
 |             event.xbutton.button=Button2; | 
 |             event.xbutton.state&=(~Mod1Mask); | 
 |           } | 
 |         if (event.xbutton.window == windows->backdrop.id) | 
 |           { | 
 |             (void) XSetInputFocus(display,event.xbutton.window,RevertToParent, | 
 |               event.xbutton.time); | 
 |             break; | 
 |           } | 
 |         if (event.xbutton.window == windows->image.id) | 
 |           { | 
 |             switch (event.xbutton.button) | 
 |             { | 
 |               case Button1: | 
 |               { | 
 |                 if (resource_info->immutable) | 
 |                   { | 
 |                     /* | 
 |                       Select a command from the Virtual menu. | 
 |                     */ | 
 |                     entry=XMenuWidget(display,windows,"Commands",VirtualMenu, | 
 |                       command); | 
 |                     if (entry >= 0) | 
 |                       nexus=XMagickCommand(display,resource_info,windows, | 
 |                         VirtualCommands[entry],&display_image,exception); | 
 |                     break; | 
 |                   } | 
 |                 /* | 
 |                   Map/unmap Command widget. | 
 |                 */ | 
 |                 if (windows->command.mapped != MagickFalse) | 
 |                   (void) XWithdrawWindow(display,windows->command.id, | 
 |                     windows->command.screen); | 
 |                 else | 
 |                   { | 
 |                     (void) XCommandWidget(display,windows,CommandMenu, | 
 |                       (XEvent *) NULL); | 
 |                     (void) XMapRaised(display,windows->command.id); | 
 |                   } | 
 |                 break; | 
 |               } | 
 |               case Button2: | 
 |               { | 
 |                 /* | 
 |                   User pressed the image magnify button. | 
 |                 */ | 
 |                 (void) XMagickCommand(display,resource_info,windows,ZoomCommand, | 
 |                   &display_image,exception); | 
 |                 XMagnifyImage(display,windows,&event,exception); | 
 |                 break; | 
 |               } | 
 |               case Button3: | 
 |               { | 
 |                 if (resource_info->immutable) | 
 |                   { | 
 |                     /* | 
 |                       Select a command from the Virtual menu. | 
 |                     */ | 
 |                     entry=XMenuWidget(display,windows,"Commands",VirtualMenu, | 
 |                       command); | 
 |                     if (entry >= 0) | 
 |                       nexus=XMagickCommand(display,resource_info,windows, | 
 |                         VirtualCommands[entry],&display_image,exception); | 
 |                     break; | 
 |                   } | 
 |                 if (display_image->montage != (char *) NULL) | 
 |                   { | 
 |                     /* | 
 |                       Open or delete a tile from a visual image directory. | 
 |                     */ | 
 |                     nexus=XTileImage(display,resource_info,windows, | 
 |                       display_image,&event,exception); | 
 |                     if (nexus != (Image *) NULL) | 
 |                       *state|=MontageImageState | NextImageState | ExitState; | 
 |                     vid_info.x=(short int) windows->image.x; | 
 |                     vid_info.y=(short int) windows->image.y; | 
 |                     break; | 
 |                   } | 
 |                 /* | 
 |                   Select a command from the Short Cuts menu. | 
 |                 */ | 
 |                 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu, | 
 |                   command); | 
 |                 if (entry >= 0) | 
 |                   nexus=XMagickCommand(display,resource_info,windows, | 
 |                     ShortCutsCommands[entry],&display_image,exception); | 
 |                 break; | 
 |               } | 
 |               case Button4: | 
 |               { | 
 |                 /* | 
 |                   Wheel up. | 
 |                 */ | 
 |                 XTranslateImage(display,windows,*image,XK_Up); | 
 |                 break; | 
 |               } | 
 |               case Button5: | 
 |               { | 
 |                 /* | 
 |                   Wheel down. | 
 |                 */ | 
 |                 XTranslateImage(display,windows,*image,XK_Down); | 
 |                 break; | 
 |               } | 
 |               default: | 
 |                 break; | 
 |             } | 
 |             break; | 
 |           } | 
 |         if (event.xbutton.window == windows->magnify.id) | 
 |           { | 
 |             int | 
 |               factor; | 
 |  | 
 |             static const char | 
 |               *MagnifyMenu[] = | 
 |               { | 
 |                 "2", | 
 |                 "4", | 
 |                 "5", | 
 |                 "6", | 
 |                 "7", | 
 |                 "8", | 
 |                 "9", | 
 |                 "3", | 
 |                 (char *) NULL, | 
 |               }; | 
 |  | 
 |             static KeySym | 
 |               MagnifyCommands[] = | 
 |               { | 
 |                 XK_2, | 
 |                 XK_4, | 
 |                 XK_5, | 
 |                 XK_6, | 
 |                 XK_7, | 
 |                 XK_8, | 
 |                 XK_9, | 
 |                 XK_3 | 
 |               }; | 
 |  | 
 |             /* | 
 |               Select a magnify factor from the pop-up menu. | 
 |             */ | 
 |             factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command); | 
 |             if (factor >= 0) | 
 |               XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor], | 
 |                 exception); | 
 |             break; | 
 |           } | 
 |         if (event.xbutton.window == windows->pan.id) | 
 |           { | 
 |             switch (event.xbutton.button) | 
 |             { | 
 |               case Button4: | 
 |               { | 
 |                 /* | 
 |                   Wheel up. | 
 |                 */ | 
 |                 XTranslateImage(display,windows,*image,XK_Up); | 
 |                 break; | 
 |               } | 
 |               case Button5: | 
 |               { | 
 |                 /* | 
 |                   Wheel down. | 
 |                 */ | 
 |                 XTranslateImage(display,windows,*image,XK_Down); | 
 |                 break; | 
 |               } | 
 |               default: | 
 |               { | 
 |                 XPanImage(display,windows,&event,exception); | 
 |                 break; | 
 |               } | 
 |             } | 
 |             break; | 
 |           } | 
 |         delay=display_image->delay/MagickMax(display_image->ticks_per_second, | 
 |           1L); | 
 |         timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1; | 
 |         break; | 
 |       } | 
 |       case ButtonRelease: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Button Release: 0x%lx %u +%d+%d",event.xbutton.window, | 
 |             event.xbutton.button,event.xbutton.x,event.xbutton.y); | 
 |         break; | 
 |       } | 
 |       case ClientMessage: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window, | 
 |             event.xclient.message_type,event.xclient.format,(unsigned long) | 
 |             event.xclient.data.l[0]); | 
 |         if (event.xclient.message_type == windows->im_protocols) | 
 |           { | 
 |             if (*event.xclient.data.l == (long) windows->im_update_widget) | 
 |               { | 
 |                 (void) CloneString(&windows->command.name,MagickTitle); | 
 |                 windows->command.data=MagickMenus; | 
 |                 (void) XCommandWidget(display,windows,CommandMenu, | 
 |                   (XEvent *) NULL); | 
 |                 break; | 
 |               } | 
 |             if (*event.xclient.data.l == (long) windows->im_update_colormap) | 
 |               { | 
 |                 /* | 
 |                   Update graphic context and window colormap. | 
 |                 */ | 
 |                 for (i=0; i < (int) number_windows; i++) | 
 |                 { | 
 |                   if (magick_windows[i]->id == windows->icon.id) | 
 |                     continue; | 
 |                   context_values.background=pixel->background_color.pixel; | 
 |                   context_values.foreground=pixel->foreground_color.pixel; | 
 |                   (void) XChangeGC(display,magick_windows[i]->annotate_context, | 
 |                     context_mask,&context_values); | 
 |                   (void) XChangeGC(display,magick_windows[i]->widget_context, | 
 |                     context_mask,&context_values); | 
 |                   context_values.background=pixel->foreground_color.pixel; | 
 |                   context_values.foreground=pixel->background_color.pixel; | 
 |                   context_values.plane_mask=context_values.background ^ | 
 |                     context_values.foreground; | 
 |                   (void) XChangeGC(display,magick_windows[i]->highlight_context, | 
 |                     (size_t) (context_mask | GCPlaneMask), | 
 |                     &context_values); | 
 |                   magick_windows[i]->attributes.background_pixel= | 
 |                     pixel->background_color.pixel; | 
 |                   magick_windows[i]->attributes.border_pixel= | 
 |                     pixel->border_color.pixel; | 
 |                   magick_windows[i]->attributes.colormap=map_info->colormap; | 
 |                   (void) XChangeWindowAttributes(display,magick_windows[i]->id, | 
 |                     (unsigned long) magick_windows[i]->mask, | 
 |                     &magick_windows[i]->attributes); | 
 |                 } | 
 |                 if (windows->pan.mapped != MagickFalse) | 
 |                   { | 
 |                     (void) XSetWindowBackgroundPixmap(display,windows->pan.id, | 
 |                       windows->pan.pixmap); | 
 |                     (void) XClearWindow(display,windows->pan.id); | 
 |                     XDrawPanRectangle(display,windows); | 
 |                   } | 
 |                 if (windows->backdrop.id != (Window) NULL) | 
 |                   (void) XInstallColormap(display,map_info->colormap); | 
 |                 break; | 
 |               } | 
 |             if (*event.xclient.data.l == (long) windows->im_former_image) | 
 |               { | 
 |                 *state|=FormerImageState | ExitState; | 
 |                 break; | 
 |               } | 
 |             if (*event.xclient.data.l == (long) windows->im_next_image) | 
 |               { | 
 |                 *state|=NextImageState | ExitState; | 
 |                 break; | 
 |               } | 
 |             if (*event.xclient.data.l == (long) windows->im_retain_colors) | 
 |               { | 
 |                 *state|=RetainColorsState; | 
 |                 break; | 
 |               } | 
 |             if (*event.xclient.data.l == (long) windows->im_exit) | 
 |               { | 
 |                 *state|=ExitState; | 
 |                 break; | 
 |               } | 
 |             break; | 
 |           } | 
 |         if (event.xclient.message_type == windows->dnd_protocols) | 
 |           { | 
 |             Atom | 
 |               selection, | 
 |               type; | 
 |  | 
 |             int | 
 |               format, | 
 |               status; | 
 |  | 
 |             unsigned char | 
 |               *data; | 
 |  | 
 |             unsigned long | 
 |               after, | 
 |               length; | 
 |  | 
 |             /* | 
 |               Display image named by the Drag-and-Drop selection. | 
 |             */ | 
 |             if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128)) | 
 |               break; | 
 |             selection=XInternAtom(display,"DndSelection",MagickFalse); | 
 |             status=XGetWindowProperty(display,root_window,selection,0L,(long) | 
 |               MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format, | 
 |               &length,&after,&data); | 
 |             if ((status != Success) || (length == 0)) | 
 |               break; | 
 |             if (*event.xclient.data.l == 2) | 
 |               { | 
 |                 /* | 
 |                   Offix DND. | 
 |                 */ | 
 |                 (void) CopyMagickString(resource_info->image_info->filename, | 
 |                   (char *) data,MaxTextExtent); | 
 |               } | 
 |             else | 
 |               { | 
 |                 /* | 
 |                   XDND. | 
 |                 */ | 
 |                 if (strncmp((char *) data, "file:", 5) != 0) | 
 |                   { | 
 |                     (void) XFree((void *) data); | 
 |                     break; | 
 |                   } | 
 |                 (void) CopyMagickString(resource_info->image_info->filename, | 
 |                   ((char *) data)+5,MaxTextExtent); | 
 |               } | 
 |             nexus=ReadImage(resource_info->image_info,exception); | 
 |             CatchException(exception); | 
 |             if (nexus != (Image *) NULL) | 
 |               *state|=NextImageState | ExitState; | 
 |             (void) XFree((void *) data); | 
 |             break; | 
 |           } | 
 |         /* | 
 |           If client window delete message, exit. | 
 |         */ | 
 |         if (event.xclient.message_type != windows->wm_protocols) | 
 |           break; | 
 |         if (*event.xclient.data.l != (long) windows->wm_delete_window) | 
 |           break; | 
 |         (void) XWithdrawWindow(display,event.xclient.window, | 
 |           visual_info->screen); | 
 |         if (event.xclient.window == windows->image.id) | 
 |           { | 
 |             *state|=ExitState; | 
 |             break; | 
 |           } | 
 |         if (event.xclient.window == windows->pan.id) | 
 |           { | 
 |             /* | 
 |               Restore original image size when pan window is deleted. | 
 |             */ | 
 |             windows->image.window_changes.width=windows->image.ximage->width; | 
 |             windows->image.window_changes.height=windows->image.ximage->height; | 
 |             (void) XConfigureImage(display,resource_info,windows, | 
 |               display_image,exception); | 
 |           } | 
 |         break; | 
 |       } | 
 |       case ConfigureNotify: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window, | 
 |             event.xconfigure.width,event.xconfigure.height,event.xconfigure.x, | 
 |             event.xconfigure.y,event.xconfigure.send_event); | 
 |         if (event.xconfigure.window == windows->image.id) | 
 |           { | 
 |             /* | 
 |               Image window has a new configuration. | 
 |             */ | 
 |             if (event.xconfigure.send_event != 0) | 
 |               { | 
 |                 XWindowChanges | 
 |                   window_changes; | 
 |  | 
 |                 /* | 
 |                   Position the transient windows relative of the Image window. | 
 |                 */ | 
 |                 if (windows->command.geometry == (char *) NULL) | 
 |                   if (windows->command.mapped == MagickFalse) | 
 |                     { | 
 |                       windows->command.x=event.xconfigure.x- | 
 |                         windows->command.width-25; | 
 |                       windows->command.y=event.xconfigure.y; | 
 |                       XConstrainWindowPosition(display,&windows->command); | 
 |                       window_changes.x=windows->command.x; | 
 |                       window_changes.y=windows->command.y; | 
 |                       (void) XReconfigureWMWindow(display,windows->command.id, | 
 |                         windows->command.screen,(unsigned int) (CWX | CWY), | 
 |                         &window_changes); | 
 |                     } | 
 |                 if (windows->widget.geometry == (char *) NULL) | 
 |                   if (windows->widget.mapped == MagickFalse) | 
 |                     { | 
 |                       windows->widget.x=event.xconfigure.x+ | 
 |                         event.xconfigure.width/10; | 
 |                       windows->widget.y=event.xconfigure.y+ | 
 |                         event.xconfigure.height/10; | 
 |                       XConstrainWindowPosition(display,&windows->widget); | 
 |                       window_changes.x=windows->widget.x; | 
 |                       window_changes.y=windows->widget.y; | 
 |                       (void) XReconfigureWMWindow(display,windows->widget.id, | 
 |                         windows->widget.screen,(unsigned int) (CWX | CWY), | 
 |                         &window_changes); | 
 |                     } | 
 |                 if (windows->magnify.geometry == (char *) NULL) | 
 |                   if (windows->magnify.mapped == MagickFalse) | 
 |                     { | 
 |                       windows->magnify.x=event.xconfigure.x+ | 
 |                         event.xconfigure.width+25; | 
 |                       windows->magnify.y=event.xconfigure.y; | 
 |                       XConstrainWindowPosition(display,&windows->magnify); | 
 |                       window_changes.x=windows->magnify.x; | 
 |                       window_changes.y=windows->magnify.y; | 
 |                       (void) XReconfigureWMWindow(display,windows->magnify.id, | 
 |                         windows->magnify.screen,(unsigned int) (CWX | CWY), | 
 |                         &window_changes); | 
 |                     } | 
 |                 if (windows->pan.geometry == (char *) NULL) | 
 |                   if (windows->pan.mapped == MagickFalse) | 
 |                     { | 
 |                       windows->pan.x=event.xconfigure.x+ | 
 |                         event.xconfigure.width+25; | 
 |                       windows->pan.y=event.xconfigure.y+ | 
 |                         windows->magnify.height+50; | 
 |                       XConstrainWindowPosition(display,&windows->pan); | 
 |                       window_changes.x=windows->pan.x; | 
 |                       window_changes.y=windows->pan.y; | 
 |                       (void) XReconfigureWMWindow(display,windows->pan.id, | 
 |                         windows->pan.screen,(unsigned int) (CWX | CWY), | 
 |                         &window_changes); | 
 |                     } | 
 |               } | 
 |             if ((event.xconfigure.width == (int) windows->image.width) && | 
 |                 (event.xconfigure.height == (int) windows->image.height)) | 
 |               break; | 
 |             windows->image.width=(unsigned int) event.xconfigure.width; | 
 |             windows->image.height=(unsigned int) event.xconfigure.height; | 
 |             windows->image.x=0; | 
 |             windows->image.y=0; | 
 |             if (display_image->montage != (char *) NULL) | 
 |               { | 
 |                 windows->image.x=vid_info.x; | 
 |                 windows->image.y=vid_info.y; | 
 |               } | 
 |             if ((windows->image.mapped != MagickFalse) && | 
 |                 (windows->image.stasis != MagickFalse)) | 
 |               { | 
 |                 /* | 
 |                   Update image window configuration. | 
 |                 */ | 
 |                 windows->image.window_changes.width=event.xconfigure.width; | 
 |                 windows->image.window_changes.height=event.xconfigure.height; | 
 |                 (void) XConfigureImage(display,resource_info,windows, | 
 |                   display_image,exception); | 
 |               } | 
 |             /* | 
 |               Update pan window configuration. | 
 |             */ | 
 |             if ((event.xconfigure.width < windows->image.ximage->width) || | 
 |                 (event.xconfigure.height < windows->image.ximage->height)) | 
 |               { | 
 |                 (void) XMapRaised(display,windows->pan.id); | 
 |                 XDrawPanRectangle(display,windows); | 
 |               } | 
 |             else | 
 |               if (windows->pan.mapped != MagickFalse) | 
 |                 (void) XWithdrawWindow(display,windows->pan.id, | 
 |                   windows->pan.screen); | 
 |             break; | 
 |           } | 
 |         if (event.xconfigure.window == windows->magnify.id) | 
 |           { | 
 |             unsigned int | 
 |               magnify; | 
 |  | 
 |             /* | 
 |               Magnify window has a new configuration. | 
 |             */ | 
 |             windows->magnify.width=(unsigned int) event.xconfigure.width; | 
 |             windows->magnify.height=(unsigned int) event.xconfigure.height; | 
 |             if (windows->magnify.mapped == MagickFalse) | 
 |               break; | 
 |             magnify=1; | 
 |             while ((int) magnify <= event.xconfigure.width) | 
 |               magnify<<=1; | 
 |             while ((int) magnify <= event.xconfigure.height) | 
 |               magnify<<=1; | 
 |             magnify>>=1; | 
 |             if (((int) magnify != event.xconfigure.width) || | 
 |                 ((int) magnify != event.xconfigure.height)) | 
 |               { | 
 |                 window_changes.width=(int) magnify; | 
 |                 window_changes.height=(int) magnify; | 
 |                 (void) XReconfigureWMWindow(display,windows->magnify.id, | 
 |                   windows->magnify.screen,(unsigned int) (CWWidth | CWHeight), | 
 |                   &window_changes); | 
 |                 break; | 
 |               } | 
 |             if ((windows->magnify.mapped != MagickFalse) && | 
 |                 (windows->magnify.stasis != MagickFalse)) | 
 |               { | 
 |                 status=XMakeImage(display,resource_info,&windows->magnify, | 
 |                   display_image,windows->magnify.width,windows->magnify.height, | 
 |                   exception); | 
 |                 XMakeMagnifyImage(display,windows,exception); | 
 |               } | 
 |             break; | 
 |           } | 
 |         if ((windows->magnify.mapped != MagickFalse) && | 
 |             (event.xconfigure.window == windows->pan.id)) | 
 |           { | 
 |             /* | 
 |               Pan icon window has a new configuration. | 
 |             */ | 
 |             if (event.xconfigure.send_event != 0) | 
 |               { | 
 |                 windows->pan.x=event.xconfigure.x; | 
 |                 windows->pan.y=event.xconfigure.y; | 
 |               } | 
 |             windows->pan.width=(unsigned int) event.xconfigure.width; | 
 |             windows->pan.height=(unsigned int) event.xconfigure.height; | 
 |             break; | 
 |           } | 
 |         if (event.xconfigure.window == windows->icon.id) | 
 |           { | 
 |             /* | 
 |               Icon window has a new configuration. | 
 |             */ | 
 |             windows->icon.width=(unsigned int) event.xconfigure.width; | 
 |             windows->icon.height=(unsigned int) event.xconfigure.height; | 
 |             break; | 
 |           } | 
 |         break; | 
 |       } | 
 |       case DestroyNotify: | 
 |       { | 
 |         /* | 
 |           Group leader has exited. | 
 |         */ | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Destroy Notify: 0x%lx",event.xdestroywindow.window); | 
 |         if (event.xdestroywindow.window == windows->group_leader.id) | 
 |           { | 
 |             *state|=ExitState; | 
 |             break; | 
 |           } | 
 |         break; | 
 |       } | 
 |       case EnterNotify: | 
 |       { | 
 |         /* | 
 |           Selectively install colormap. | 
 |         */ | 
 |         if (map_info->colormap != XDefaultColormap(display,visual_info->screen)) | 
 |           if (event.xcrossing.mode != NotifyUngrab) | 
 |             XInstallColormap(display,map_info->colormap); | 
 |         break; | 
 |       } | 
 |       case Expose: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window, | 
 |             event.xexpose.width,event.xexpose.height,event.xexpose.x, | 
 |             event.xexpose.y); | 
 |         /* | 
 |           Refresh windows that are now exposed. | 
 |         */ | 
 |         if ((event.xexpose.window == windows->image.id) && | 
 |             (windows->image.mapped != MagickFalse)) | 
 |           { | 
 |             XRefreshWindow(display,&windows->image,&event); | 
 |             delay=display_image->delay/MagickMax( | 
 |               display_image->ticks_per_second,1L); | 
 |             timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1; | 
 |             break; | 
 |           } | 
 |         if ((event.xexpose.window == windows->magnify.id) && | 
 |             (windows->magnify.mapped != MagickFalse)) | 
 |           { | 
 |             XMakeMagnifyImage(display,windows,exception); | 
 |             break; | 
 |           } | 
 |         if (event.xexpose.window == windows->pan.id) | 
 |           { | 
 |             XDrawPanRectangle(display,windows); | 
 |             break; | 
 |           } | 
 |         if (event.xexpose.window == windows->icon.id) | 
 |           { | 
 |             XRefreshWindow(display,&windows->icon,&event); | 
 |             break; | 
 |           } | 
 |         break; | 
 |       } | 
 |       case KeyPress: | 
 |       { | 
 |         int | 
 |           length; | 
 |  | 
 |         /* | 
 |           Respond to a user key press. | 
 |         */ | 
 |         length=XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         *(command+length)='\0'; | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long) | 
 |             key_symbol,command); | 
 |         if (event.xkey.window == windows->image.id) | 
 |           { | 
 |             command_type=XImageWindowCommand(display,resource_info,windows, | 
 |               event.xkey.state,key_symbol,&display_image,exception); | 
 |             if (command_type != NullCommand) | 
 |               nexus=XMagickCommand(display,resource_info,windows,command_type, | 
 |                 &display_image,exception); | 
 |           } | 
 |         if (event.xkey.window == windows->magnify.id) | 
 |           XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol, | 
 |             exception); | 
 |         if (event.xkey.window == windows->pan.id) | 
 |           { | 
 |             if ((key_symbol == XK_q) || (key_symbol == XK_Escape)) | 
 |               (void) XWithdrawWindow(display,windows->pan.id, | 
 |                 windows->pan.screen); | 
 |             else | 
 |               if ((key_symbol == XK_F1) || (key_symbol == XK_Help)) | 
 |                 XTextViewWidget(display,resource_info,windows,MagickFalse, | 
 |                   "Help Viewer - Image Pan",ImagePanHelp); | 
 |               else | 
 |                 XTranslateImage(display,windows,*image,key_symbol); | 
 |           } | 
 |         delay=display_image->delay/MagickMax( | 
 |           display_image->ticks_per_second,1L); | 
 |         timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1; | 
 |         break; | 
 |       } | 
 |       case KeyRelease: | 
 |       { | 
 |         /* | 
 |           Respond to a user key release. | 
 |         */ | 
 |         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int) | 
 |           sizeof(command),&key_symbol,(XComposeStatus *) NULL); | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command); | 
 |         break; | 
 |       } | 
 |       case LeaveNotify: | 
 |       { | 
 |         /* | 
 |           Selectively uninstall colormap. | 
 |         */ | 
 |         if (map_info->colormap != XDefaultColormap(display,visual_info->screen)) | 
 |           if (event.xcrossing.mode != NotifyUngrab) | 
 |             XUninstallColormap(display,map_info->colormap); | 
 |         break; | 
 |       } | 
 |       case MapNotify: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx", | 
 |             event.xmap.window); | 
 |         if (event.xmap.window == windows->backdrop.id) | 
 |           { | 
 |             (void) XSetInputFocus(display,event.xmap.window,RevertToParent, | 
 |               CurrentTime); | 
 |             windows->backdrop.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->image.id) | 
 |           { | 
 |             if (windows->backdrop.id != (Window) NULL) | 
 |               (void) XInstallColormap(display,map_info->colormap); | 
 |             if (LocaleCompare(display_image->magick,"LOGO") == 0) | 
 |               { | 
 |                 if (LocaleCompare(display_image->filename,"LOGO") == 0) | 
 |                   nexus=XOpenImage(display,resource_info,windows,MagickFalse); | 
 |               } | 
 |             if (((int) windows->image.width < windows->image.ximage->width) || | 
 |                 ((int) windows->image.height < windows->image.ximage->height)) | 
 |               (void) XMapRaised(display,windows->pan.id); | 
 |             windows->image.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->magnify.id) | 
 |           { | 
 |             XMakeMagnifyImage(display,windows,exception); | 
 |             windows->magnify.mapped=MagickTrue; | 
 |             (void) XWithdrawWindow(display,windows->info.id, | 
 |               windows->info.screen); | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->pan.id) | 
 |           { | 
 |             XMakePanImage(display,resource_info,windows,display_image, | 
 |               exception); | 
 |             windows->pan.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->info.id) | 
 |           { | 
 |             windows->info.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->icon.id) | 
 |           { | 
 |             MagickBooleanType | 
 |               taint; | 
 |  | 
 |             /* | 
 |               Create an icon image. | 
 |             */ | 
 |             taint=display_image->taint; | 
 |             XMakeStandardColormap(display,icon_visual,icon_resources, | 
 |               display_image,icon_map,icon_pixel,exception); | 
 |             (void) XMakeImage(display,icon_resources,&windows->icon, | 
 |               display_image,windows->icon.width,windows->icon.height, | 
 |               exception); | 
 |             display_image->taint=taint; | 
 |             (void) XSetWindowBackgroundPixmap(display,windows->icon.id, | 
 |               windows->icon.pixmap); | 
 |             (void) XClearWindow(display,windows->icon.id); | 
 |             (void) XWithdrawWindow(display,windows->info.id, | 
 |               windows->info.screen); | 
 |             windows->icon.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->command.id) | 
 |           { | 
 |             windows->command.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->popup.id) | 
 |           { | 
 |             windows->popup.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         if (event.xmap.window == windows->widget.id) | 
 |           { | 
 |             windows->widget.mapped=MagickTrue; | 
 |             break; | 
 |           } | 
 |         break; | 
 |       } | 
 |       case MappingNotify: | 
 |       { | 
 |         (void) XRefreshKeyboardMapping(&event.xmapping); | 
 |         break; | 
 |       } | 
 |       case NoExpose: | 
 |         break; | 
 |       case PropertyNotify: | 
 |       { | 
 |         Atom | 
 |           type; | 
 |  | 
 |         int | 
 |           format, | 
 |           status; | 
 |  | 
 |         unsigned char | 
 |           *data; | 
 |  | 
 |         unsigned long | 
 |           after, | 
 |           length; | 
 |  | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window, | 
 |             event.xproperty.atom,event.xproperty.state); | 
 |         if (event.xproperty.atom != windows->im_remote_command) | 
 |           break; | 
 |         /* | 
 |           Display image named by the remote command protocol. | 
 |         */ | 
 |         status=XGetWindowProperty(display,event.xproperty.window, | 
 |           event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom) | 
 |           AnyPropertyType,&type,&format,&length,&after,&data); | 
 |         if ((status != Success) || (length == 0)) | 
 |           break; | 
 |         if (LocaleCompare((char *) data,"-quit") == 0) | 
 |           { | 
 |             XClientMessage(display,windows->image.id,windows->im_protocols, | 
 |               windows->im_exit,CurrentTime); | 
 |             (void) XFree((void *) data); | 
 |             break; | 
 |           } | 
 |         (void) CopyMagickString(resource_info->image_info->filename, | 
 |           (char *) data,MaxTextExtent); | 
 |         (void) XFree((void *) data); | 
 |         nexus=ReadImage(resource_info->image_info,exception); | 
 |         CatchException(exception); | 
 |         if (nexus != (Image *) NULL) | 
 |           *state|=NextImageState | ExitState; | 
 |         break; | 
 |       } | 
 |       case ReparentNotify: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent, | 
 |             event.xreparent.window); | 
 |         break; | 
 |       } | 
 |       case UnmapNotify: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(), | 
 |             "Unmap Notify: 0x%lx",event.xunmap.window); | 
 |         if (event.xunmap.window == windows->backdrop.id) | 
 |           { | 
 |             windows->backdrop.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->image.id) | 
 |           { | 
 |             windows->image.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->magnify.id) | 
 |           { | 
 |             windows->magnify.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->pan.id) | 
 |           { | 
 |             windows->pan.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->info.id) | 
 |           { | 
 |             windows->info.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->icon.id) | 
 |           { | 
 |             if (map_info->colormap == icon_map->colormap) | 
 |               XConfigureImageColormap(display,resource_info,windows, | 
 |                 display_image,exception); | 
 |             (void) XFreeStandardColormap(display,icon_visual,icon_map, | 
 |               icon_pixel); | 
 |             windows->icon.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->command.id) | 
 |           { | 
 |             windows->command.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->popup.id) | 
 |           { | 
 |             if (windows->backdrop.id != (Window) NULL) | 
 |               (void) XSetInputFocus(display,windows->image.id,RevertToParent, | 
 |                 CurrentTime); | 
 |             windows->popup.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         if (event.xunmap.window == windows->widget.id) | 
 |           { | 
 |             if (windows->backdrop.id != (Window) NULL) | 
 |               (void) XSetInputFocus(display,windows->image.id,RevertToParent, | 
 |                 CurrentTime); | 
 |             windows->widget.mapped=MagickFalse; | 
 |             break; | 
 |           } | 
 |         break; | 
 |       } | 
 |       default: | 
 |       { | 
 |         if (display_image->debug != MagickFalse) | 
 |           (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d", | 
 |             event.type); | 
 |         break; | 
 |       } | 
 |     } | 
 |   } while (!(*state & ExitState)); | 
 |   if ((*state & ExitState) == 0) | 
 |     (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand, | 
 |       &display_image,exception); | 
 |   else | 
 |     if (resource_info->confirm_edit != MagickFalse) | 
 |       { | 
 |         /* | 
 |           Query user if image has changed. | 
 |         */ | 
 |         if ((resource_info->immutable == MagickFalse) && | 
 |             (display_image->taint != MagickFalse)) | 
 |           { | 
 |             int | 
 |               status; | 
 |  | 
 |             status=XConfirmWidget(display,windows,"Your image changed.", | 
 |               "Do you want to save it"); | 
 |             if (status == 0) | 
 |               *state&=(~ExitState); | 
 |             else | 
 |               if (status > 0) | 
 |                 (void) XMagickCommand(display,resource_info,windows,SaveCommand, | 
 |                   &display_image,exception); | 
 |           } | 
 |       } | 
 |   if ((windows->visual_info->klass == GrayScale) || | 
 |       (windows->visual_info->klass == PseudoColor) || | 
 |       (windows->visual_info->klass == DirectColor)) | 
 |     { | 
 |       /* | 
 |         Withdraw pan and Magnify window. | 
 |       */ | 
 |       if (windows->info.mapped != MagickFalse) | 
 |         (void) XWithdrawWindow(display,windows->info.id,windows->info.screen); | 
 |       if (windows->magnify.mapped != MagickFalse) | 
 |         (void) XWithdrawWindow(display,windows->magnify.id, | 
 |           windows->magnify.screen); | 
 |       if (windows->command.mapped != MagickFalse) | 
 |         (void) XWithdrawWindow(display,windows->command.id, | 
 |           windows->command.screen); | 
 |     } | 
 |   if (windows->pan.mapped != MagickFalse) | 
 |     (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen); | 
 |   if (resource_info->backdrop == MagickFalse) | 
 |     if (windows->backdrop.mapped) | 
 |       { | 
 |         (void) XWithdrawWindow(display,windows->backdrop.id, | 
 |           windows->backdrop.screen); | 
 |         (void) XDestroyWindow(display,windows->backdrop.id); | 
 |         windows->backdrop.id=(Window) NULL; | 
 |         (void) XWithdrawWindow(display,windows->image.id, | 
 |           windows->image.screen); | 
 |         (void) XDestroyWindow(display,windows->image.id); | 
 |         windows->image.id=(Window) NULL; | 
 |       } | 
 |   XSetCursorState(display,windows,MagickTrue); | 
 |   XCheckRefreshWindows(display,windows); | 
 |   if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0)) | 
 |     *state&=(~ExitState); | 
 |   if (*state & ExitState) | 
 |     { | 
 |       /* | 
 |         Free Standard Colormap. | 
 |       */ | 
 |       (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel); | 
 |       if (resource_info->map_type == (char *) NULL) | 
 |         (void) XFreeStandardColormap(display,visual_info,map_info,pixel); | 
 |       /* | 
 |         Free X resources. | 
 |       */ | 
 |       if (resource_info->copy_image != (Image *) NULL) | 
 |         { | 
 |           resource_info->copy_image=DestroyImage(resource_info->copy_image); | 
 |           resource_info->copy_image=NewImageList(); | 
 |         } | 
 |       DestroyXResources(); | 
 |     } | 
 |   (void) XSync(display,MagickFalse); | 
 |   /* | 
 |     Restore our progress monitor and warning handlers. | 
 |   */ | 
 |   (void) SetErrorHandler(warning_handler); | 
 |   (void) SetWarningHandler(warning_handler); | 
 |   /* | 
 |     Change to home directory. | 
 |   */ | 
 |   directory=getcwd(working_directory,MaxTextExtent); | 
 |   (void) directory; | 
 |   { | 
 |     int | 
 |       status; | 
 |  | 
 |     status=chdir(resource_info->home_directory); | 
 |     if (status == -1) | 
 |       (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError, | 
 |         "UnableToOpenFile","%s",resource_info->home_directory); | 
 |   } | 
 |   *image=display_image; | 
 |   return(nexus); | 
 | } | 
 | #else | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   D i s p l a y I m a g e s                                                 % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  DisplayImages() displays an image sequence to any X window screen.  It | 
 | %  returns a value other than 0 if successful.  Check the exception member | 
 | %  of image to determine the reason for any failure. | 
 | % | 
 | %  The format of the DisplayImages method is: | 
 | % | 
 | %      MagickBooleanType DisplayImages(const ImageInfo *image_info, | 
 | %        Image *images,ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o image_info: the image info. | 
 | % | 
 | %    o image: the image. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info, | 
 |   Image *image,ExceptionInfo *exception) | 
 | { | 
 |   assert(image_info != (const ImageInfo *) NULL); | 
 |   assert(image_info->signature == MagickSignature); | 
 |   assert(image != (Image *) NULL); | 
 |   assert(image->signature == MagickSignature); | 
 |   if (image->debug != MagickFalse) | 
 |     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); | 
 |   (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, | 
 |     "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename); | 
 |   return(MagickFalse); | 
 | } | 
 |  | 
 | /* | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | +   R e m o t e D i s p l a y C o m m a n d                                   % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %                                                                             % | 
 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
 | % | 
 | %  RemoteDisplayCommand() encourages a remote display program to display the | 
 | %  specified image filename. | 
 | % | 
 | %  The format of the RemoteDisplayCommand method is: | 
 | % | 
 | %      MagickBooleanType RemoteDisplayCommand(const ImageInfo *image, | 
 | %        const char *window,const char *filename,ExceptionInfo *exception) | 
 | % | 
 | %  A description of each parameter follows: | 
 | % | 
 | %    o image_info: the image info. | 
 | % | 
 | %    o window: Specifies the name or id of an X window. | 
 | % | 
 | %    o filename: the name of the image filename to display. | 
 | % | 
 | %    o exception: return any errors or warnings in this structure. | 
 | % | 
 | */ | 
 | MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info, | 
 |   const char *window,const char *filename,ExceptionInfo *exception) | 
 | { | 
 |   assert(image_info != (const ImageInfo *) NULL); | 
 |   assert(image_info->signature == MagickSignature); | 
 |   assert(filename != (char *) NULL); | 
 |   (void) window; | 
 |   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); | 
 |   (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, | 
 |     "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename); | 
 |   return(MagickFalse); | 
 | } | 
 | #endif |