animate.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                AAA   N   N  IIIII  M   M   AAA   TTTTT  EEEEE               %
00007 %               A   A  NN  N    I    MM MM  A   A    T    E                   %
00008 %               AAAAA  N N N    I    M M M  AAAAA    T    EEE                 %
00009 %               A   A  N  NN    I    M   M  A   A    T    E                   %
00010 %               A   A  N   N  IIIII  M   M  A   A    T    EEEEE               %
00011 %                                                                             %
00012 %                                                                             %
00013 %              Methods to Interactively Animate an Image Sequence             %
00014 %                                                                             %
00015 %                             Software Design                                 %
00016 %                               John Cristy                                   %
00017 %                                July 1992                                    %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "magick/studio.h"
00043 #include "magick/animate.h"
00044 #include "magick/animate-private.h"
00045 #include "magick/client.h"
00046 #include "magick/color.h"
00047 #include "magick/color-private.h"
00048 #include "magick/colorspace.h"
00049 #include "magick/constitute.h"
00050 #include "magick/delegate.h"
00051 #include "magick/exception.h"
00052 #include "magick/exception-private.h"
00053 #include "magick/geometry.h"
00054 #include "magick/image-private.h"
00055 #include "magick/layer.h"
00056 #include "magick/list.h"
00057 #include "magick/log.h"
00058 #include "magick/image.h"
00059 #include "magick/memory_.h"
00060 #include "magick/monitor.h"
00061 #include "magick/monitor-private.h"
00062 #include "magick/option.h"
00063 #include "magick/property.h"
00064 #include "magick/resource_.h"
00065 #include "magick/string_.h"
00066 #include "magick/transform.h"
00067 #include "magick/utility.h"
00068 #include "magick/version.h"
00069 #include "magick/widget.h"
00070 #include "magick/xwindow-private.h"
00071 
00072 #if defined(MAGICKCORE_X11_DELEGATE)
00073 /*
00074   Animate state declarations.
00075 */
00076 #define AutoReverseAnimationState 0x0004
00077 #define ForwardAnimationState 0x0008
00078 #define HighlightState  0x0010
00079 #define PlayAnimationState 0x0020
00080 #define RepeatAnimationState 0x0040
00081 #define StepAnimationState 0x0080
00082 
00083 /*
00084   Static declarations.
00085 */
00086 static const char
00087   *AnimateHelp[]=
00088   {
00089     "BUTTONS",
00090     "",
00091     "  Press any button to map or unmap the Command widget.",
00092     "",
00093     "COMMAND WIDGET",
00094     "  The Command widget lists a number of sub-menus and commands.",
00095     "  They are",
00096     "",
00097     "    Animate",
00098     "      Open...",
00099     "      Save...",
00100     "      Play",
00101     "      Step",
00102     "      Repeat",
00103     "      Auto Reverse",
00104     "    Speed",
00105     "      Slower",
00106     "      Faster",
00107     "    Direction",
00108     "      Forward",
00109     "      Reverse",
00110     "      Help",
00111     "        Overview",
00112     "        Browse Documentation",
00113     "        About Animate",
00114     "    Image Info",
00115     "    Quit",
00116     "",
00117     "  Menu items with a indented triangle have a sub-menu.  They",
00118     "  are represented above as the indented items.  To access a",
00119     "  sub-menu item, move the pointer to the appropriate menu and",
00120     "  press a button and drag.  When you find the desired sub-menu",
00121     "  item, release the button and the command is executed.  Move",
00122     "  the pointer away from the sub-menu if you decide not to",
00123     "  execute a particular command.",
00124     "",
00125     "KEYBOARD ACCELERATORS",
00126     "  Accelerators are one or two key presses that effect a",
00127     "  particular command.  The keyboard accelerators that",
00128     "  animate(1) understands is:",
00129     "",
00130     "  Ctl+O  Press to open an image from a file.",
00131     "",
00132     "  space  Press to display the next image in the sequence.",
00133     "",
00134     "  <      Press to speed-up the display of the images.  Refer to",
00135     "         -delay for more information.",
00136     "",
00137     "  >      Press to slow the display of the images.  Refer to",
00138     "         -delay for more information.",
00139     "",
00140     "  F1     Press to display helpful information about animate(1).",
00141     "",
00142     "  Find   Press to browse documentation about ImageMagick.",
00143     "",
00144     "  ?      Press to display information about the image.  Press",
00145     "         any key or button to erase the information.",
00146     "",
00147     "         This information is printed: image name;  image size;",
00148     "         and the total number of unique colors in the image.",
00149     "",
00150     "  Ctl-q  Press to discard all images and exit program.",
00151     (char *) NULL
00152   };
00153 
00154 /*
00155   Constant declarations.
00156 */
00157 static const char
00158   *PageSizes[]=
00159   {
00160     "Letter",
00161     "Tabloid",
00162     "Ledger",
00163     "Legal",
00164     "Statement",
00165     "Executive",
00166     "A3",
00167     "A4",
00168     "A5",
00169     "B4",
00170     "B5",
00171     "Folio",
00172     "Quarto",
00173     "10x14",
00174     (char *) NULL
00175   };
00176 
00177 static const unsigned char
00178   HighlightBitmap[8] =
00179   {
00180     (unsigned char) 0xaa,
00181     (unsigned char) 0x55,
00182     (unsigned char) 0xaa,
00183     (unsigned char) 0x55,
00184     (unsigned char) 0xaa,
00185     (unsigned char) 0x55,
00186     (unsigned char) 0xaa,
00187     (unsigned char) 0x55
00188   },
00189   ShadowBitmap[8] =
00190   {
00191     (unsigned char) 0x00,
00192     (unsigned char) 0x00,
00193     (unsigned char) 0x00,
00194     (unsigned char) 0x00,
00195     (unsigned char) 0x00,
00196     (unsigned char) 0x00,
00197     (unsigned char) 0x00,
00198     (unsigned char) 0x00
00199   };
00200 
00201 /*
00202   Enumeration declarations.
00203 */
00204 typedef enum
00205 {
00206   OpenCommand,
00207   SaveCommand,
00208   PlayCommand,
00209   StepCommand,
00210   RepeatCommand,
00211   AutoReverseCommand,
00212   SlowerCommand,
00213   FasterCommand,
00214   ForwardCommand,
00215   ReverseCommand,
00216   HelpCommand,
00217   BrowseDocumentationCommand,
00218   VersionCommand,
00219   InfoCommand,
00220   QuitCommand,
00221   StepBackwardCommand,
00222   StepForwardCommand,
00223   NullCommand
00224 } CommandType;
00225 
00226 /*
00227   Stipples.
00228 */
00229 #define HighlightWidth  8
00230 #define HighlightHeight  8
00231 #define ShadowWidth  8
00232 #define ShadowHeight  8
00233 
00234 /*
00235   Forward declarations.
00236 */
00237 static Image
00238   *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
00239     Image **,MagickStatusType *);
00240 
00241 static MagickBooleanType
00242   XSaveImage(Display *,XResourceInfo *,XWindows *,Image *);
00243 
00244 /*
00245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00246 %                                                                             %
00247 %                                                                             %
00248 %                                                                             %
00249 %   A n i m a t e I m a g e s                                                 %
00250 %                                                                             %
00251 %                                                                             %
00252 %                                                                             %
00253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00254 %
00255 %  AnimateImages() repeatedly displays an image sequence to any X window
00256 %  screen.  It returns a value other than 0 if successful.  Check the
00257 %  exception member of image to determine the reason for any failure.
00258 %
00259 %  The format of the AnimateImages method is:
00260 %
00261 %      MagickBooleanType AnimateImages(const ImageInfo *image_info,
00262 %        Image *images)
00263 %
00264 %  A description of each parameter follows:
00265 %
00266 %    o image_info: the image info.
00267 %
00268 %    o image: the image.
00269 %
00270 */
00271 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
00272   Image *images)
00273 {
00274   char
00275     *argv[1];
00276 
00277   Display
00278     *display;
00279 
00280   MagickStatusType
00281     status;
00282 
00283   XrmDatabase
00284     resource_database;
00285 
00286   XResourceInfo
00287     resource_info;
00288 
00289   assert(image_info != (const ImageInfo *) NULL);
00290   assert(image_info->signature == MagickSignature);
00291   assert(images != (Image *) NULL);
00292   assert(images->signature == MagickSignature);
00293   if (images->debug != MagickFalse)
00294     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
00295   display=XOpenDisplay(image_info->server_name);
00296   if (display == (Display *) NULL)
00297     {
00298       (void) ThrowMagickException(&images->exception,GetMagickModule(),
00299         XServerError,"UnableToOpenXServer","`%s'",XDisplayName(
00300         image_info->server_name));
00301       return(MagickFalse);
00302     }
00303   if (images->exception.severity != UndefinedException)
00304     CatchException(&images->exception);
00305   (void) XSetErrorHandler(XError);
00306   resource_database=XGetResourceDatabase(display,GetClientName());
00307   (void) ResetMagickMemory(&resource_info,0,sizeof(XResourceInfo));
00308   XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
00309   if (image_info->page != (char *) NULL)
00310     resource_info.image_geometry=AcquireString(image_info->page);
00311   resource_info.immutable=MagickTrue;
00312   argv[0]=AcquireString(GetClientName());
00313   (void) XAnimateImages(display,&resource_info,argv,1,images);
00314   argv[0]=DestroyString(argv[0]);
00315   (void) XCloseDisplay(display);
00316   XDestroyResourceInfo(&resource_info);
00317   status=images->exception.severity == UndefinedException ?
00318     MagickTrue : MagickFalse;
00319   return(status != 0 ? MagickTrue : MagickFalse);
00320 }
00321 
00322 /*
00323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00324 %                                                                             %
00325 %                                                                             %
00326 %                                                                             %
00327 +   X M a g i c k C o m m a n d                                               %
00328 %                                                                             %
00329 %                                                                             %
00330 %                                                                             %
00331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00332 %
00333 %  XMagickCommand() makes a transform to the image or Image window as specified
00334 %  by a user menu button or keyboard command.
00335 %
00336 %  The format of the XMagickCommand method is:
00337 %
00338 %      Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
00339 %        XWindows *windows,const CommandType command_type,Image **image,
00340 %        MagickStatusType *state)
00341 %
00342 %  A description of each parameter follows:
00343 %
00344 %    o display: Specifies a connection to an X server; returned from
00345 %      XOpenDisplay.
00346 %
00347 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
00348 %
00349 %    o windows: Specifies a pointer to a XWindows structure.
00350 %
00351 %    o image: the image;  XMagickCommand
00352 %      may transform the image and return a new image pointer.
00353 %
00354 %    o state: Specifies a MagickStatusType;  XMagickCommand may return a
00355 %      modified state.
00356 %
00357 %
00358 */
00359 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
00360   XWindows *windows,const CommandType command_type,Image **image,
00361   MagickStatusType *state)
00362 {
00363   Image
00364     *nexus;
00365 
00366   MagickBooleanType
00367     proceed;
00368 
00369   MagickStatusType
00370     status;
00371 
00372   XTextProperty
00373     window_name;
00374 
00375   /*
00376     Process user command.
00377   */
00378   nexus=NewImageList();
00379   switch (command_type)
00380   {
00381     case OpenCommand:
00382     {
00383       char
00384         **filelist;
00385 
00386       ExceptionInfo
00387         *exception;
00388 
00389       Image
00390         *images,
00391         *next;
00392 
00393       ImageInfo
00394         *read_info;
00395 
00396       int
00397         number_files;
00398 
00399       register int
00400         i;
00401 
00402       static char
00403         filenames[MaxTextExtent] = "*";
00404 
00405       if (resource_info->immutable != MagickFalse)
00406         break;
00407       /*
00408         Request file name from user.
00409       */
00410       XFileBrowserWidget(display,windows,"Animate",filenames);
00411       if (*filenames == '\0')
00412         return((Image *) NULL);
00413       /*
00414         Expand the filenames.
00415       */
00416       filelist=(char **) AcquireMagickMemory(sizeof(char *));
00417       if (filelist == (char **) NULL)
00418         {
00419           ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
00420             filenames);
00421           return((Image *) NULL);
00422         }
00423       number_files=1;
00424       filelist[0]=filenames;
00425       status=ExpandFilenames(&number_files,&filelist);
00426       if ((status == MagickFalse) || (number_files == 0))
00427         {
00428           if (number_files == 0)
00429             {
00430               ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
00431              return((Image *) NULL);
00432             }
00433           ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
00434             filenames);
00435           return((Image *) NULL);
00436         }
00437       read_info=CloneImageInfo(resource_info->image_info);
00438       exception=AcquireExceptionInfo();
00439       images=NewImageList();
00440       XSetCursorState(display,windows,MagickTrue);
00441       XCheckRefreshWindows(display,windows);
00442       for (i=0; i < number_files; i++)
00443       {
00444         (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
00445         filelist[i]=DestroyString(filelist[i]);
00446         *read_info->magick='\0';
00447         next=ReadImage(read_info,exception);
00448         CatchException(exception);
00449         if (next != (Image *) NULL)
00450           AppendImageToList(&images,next);
00451         if (number_files <= 5)
00452           continue;
00453         proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
00454           number_files);
00455         if (proceed == MagickFalse)
00456           break;
00457       }
00458       filelist=(char **) RelinquishMagickMemory(filelist);
00459       exception=DestroyExceptionInfo(exception);
00460       read_info=DestroyImageInfo(read_info);
00461       if (images == (Image *) NULL)
00462         {
00463           XSetCursorState(display,windows,MagickFalse);
00464           ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
00465           return((Image *) NULL);
00466         }
00467       nexus=GetFirstImageInList(images);
00468       *state|=ExitState;
00469       break;
00470     }
00471     case PlayCommand:
00472     {
00473       char
00474         basename[MaxTextExtent];
00475 
00476       int
00477         status;
00478 
00479       /*
00480         Window name is the base of the filename.
00481       */
00482       *state|=PlayAnimationState;
00483       *state&=(~AutoReverseAnimationState);
00484       GetPathComponent((*image)->magick_filename,BasePath,basename);
00485       (void) FormatMagickString(windows->image.name,MaxTextExtent,
00486         "ImageMagick: %s",basename);
00487       if (resource_info->title != (char *) NULL)
00488         {
00489           char
00490             *title;
00491 
00492           title=InterpretImageProperties(resource_info->image_info,*image,
00493             resource_info->title);
00494           (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
00495           title=DestroyString(title);
00496         }
00497       status=XStringListToTextProperty(&windows->image.name,1,&window_name);
00498       if (status == 0)
00499         break;
00500       XSetWMName(display,windows->image.id,&window_name);
00501       (void) XFree((void *) window_name.value);
00502       break;
00503     }
00504     case StepCommand:
00505     case StepBackwardCommand:
00506     case StepForwardCommand:
00507     {
00508       *state|=StepAnimationState;
00509       *state&=(~PlayAnimationState);
00510       if (command_type == StepBackwardCommand)
00511         *state&=(~ForwardAnimationState);
00512       if (command_type == StepForwardCommand)
00513         *state|=ForwardAnimationState;
00514       if (resource_info->title != (char *) NULL)
00515         break;
00516       break;
00517     }
00518     case RepeatCommand:
00519     {
00520       *state|=RepeatAnimationState;
00521       *state&=(~AutoReverseAnimationState);
00522       *state|=PlayAnimationState;
00523       break;
00524     }
00525     case AutoReverseCommand:
00526     {
00527       *state|=AutoReverseAnimationState;
00528       *state&=(~RepeatAnimationState);
00529       *state|=PlayAnimationState;
00530       break;
00531     }
00532     case SaveCommand:
00533     {
00534       /*
00535         Save image.
00536       */
00537       status=XSaveImage(display,resource_info,windows,*image);
00538       if (status == MagickFalse)
00539         {
00540           XNoticeWidget(display,windows,"Unable to write X image:",
00541             (*image)->filename);
00542           break;
00543         }
00544       break;
00545     }
00546     case SlowerCommand:
00547     {
00548       resource_info->delay++;
00549       break;
00550     }
00551     case FasterCommand:
00552     {
00553       if (resource_info->delay == 0)
00554         break;
00555       resource_info->delay--;
00556       break;
00557     }
00558     case ForwardCommand:
00559     {
00560       *state=ForwardAnimationState;
00561       *state&=(~AutoReverseAnimationState);
00562       break;
00563     }
00564     case ReverseCommand:
00565     {
00566       *state&=(~ForwardAnimationState);
00567       *state&=(~AutoReverseAnimationState);
00568       break;
00569     }
00570     case InfoCommand:
00571     {
00572       XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image);
00573       break;
00574     }
00575     case HelpCommand:
00576     {
00577       /*
00578         User requested help.
00579       */
00580       XTextViewWidget(display,resource_info,windows,MagickFalse,
00581         "Help Viewer - Animate",AnimateHelp);
00582       break;
00583     }
00584     case BrowseDocumentationCommand:
00585     {
00586       Atom
00587         mozilla_atom;
00588 
00589       Window
00590         mozilla_window,
00591         root_window;
00592 
00593       /*
00594         Browse the ImageMagick documentation.
00595       */
00596       root_window=XRootWindow(display,XDefaultScreen(display));
00597       mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
00598       mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
00599       if (mozilla_window != (Window) NULL)
00600         {
00601           char
00602             command[MaxTextExtent],
00603             *url;
00604 
00605           /*
00606             Display documentation using Netscape remote control.
00607           */
00608           url=GetMagickHomeURL();
00609           (void) FormatMagickString(command,MaxTextExtent,
00610             "openurl(%s,new-tab)",url);
00611           url=DestroyString(url);
00612           mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
00613           (void) XChangeProperty(display,mozilla_window,mozilla_atom,
00614             XA_STRING,8,PropModeReplace,(unsigned char *) command,
00615             (int) strlen(command));
00616           XSetCursorState(display,windows,MagickFalse);
00617           break;
00618         }
00619       XSetCursorState(display,windows,MagickTrue);
00620       XCheckRefreshWindows(display,windows);
00621       status=InvokeDelegate(resource_info->image_info,*image,"browse",
00622         (char *) NULL,&(*image)->exception);
00623       if (status == MagickFalse)
00624         XNoticeWidget(display,windows,"Unable to browse documentation",
00625           (char *) NULL);
00626       XDelay(display,1500);
00627       XSetCursorState(display,windows,MagickFalse);
00628       break;
00629     }
00630     case VersionCommand:
00631     {
00632       XNoticeWidget(display,windows,GetMagickVersion((unsigned long *) NULL),
00633         GetMagickCopyright());
00634       break;
00635     }
00636     case QuitCommand:
00637     {
00638       /*
00639         exit program
00640       */
00641       if (resource_info->confirm_exit == MagickFalse)
00642         XClientMessage(display,windows->image.id,windows->im_protocols,
00643           windows->im_exit,CurrentTime);
00644       else
00645         {
00646           int
00647             status;
00648 
00649           /*
00650             Confirm program exit.
00651           */
00652           status=XConfirmWidget(display,windows,"Do you really want to exit",
00653             resource_info->client_name);
00654           if (status != 0)
00655             XClientMessage(display,windows->image.id,windows->im_protocols,
00656               windows->im_exit,CurrentTime);
00657         }
00658       break;
00659     }
00660     default:
00661       break;
00662   }
00663   return(nexus);
00664 }
00665 
00666 /*
00667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00668 %                                                                             %
00669 %                                                                             %
00670 %                                                                             %
00671 +   X A n i m a t e B a c k g r o u n d I m a g e                             %
00672 %                                                                             %
00673 %                                                                             %
00674 %                                                                             %
00675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00676 %
00677 %  XAnimateBackgroundImage() animates an image sequence in the background of
00678 %  a window.
00679 %
00680 %  The format of the XAnimateBackgroundImage method is:
00681 %
00682 %      void XAnimateBackgroundImage(Display *display,
00683 %        XResourceInfo *resource_info,Image *images)
00684 %
00685 %  A description of each parameter follows:
00686 %
00687 %    o display: Specifies a connection to an X server;  returned from
00688 %      XOpenDisplay.
00689 %
00690 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
00691 %
00692 %    o images: the image list.
00693 %
00694 */
00695 
00696 static inline long MagickMax(const long x,const long y)
00697 {
00698   if (x > y)
00699     return(x);
00700   return(y);
00701 }
00702 
00703 #if defined(__cplusplus) || defined(c_plusplus)
00704 extern "C" {
00705 #endif
00706 
00707 static int SceneCompare(const void *x,const void *y)
00708 {
00709   const Image
00710     **image_1,
00711     **image_2;
00712 
00713   image_1=(const Image **) x;
00714   image_2=(const Image **) y;
00715   return((int) ((*image_1)->scene-(*image_2)->scene));
00716 }
00717 
00718 #if defined(__cplusplus) || defined(c_plusplus)
00719 }
00720 #endif
00721 
00722 MagickExport void XAnimateBackgroundImage(Display *display,
00723   XResourceInfo *resource_info,Image *images)
00724 {
00725   char
00726     geometry[MaxTextExtent],
00727     visual_type[MaxTextExtent];
00728 
00729   Image
00730     *coalesce_image,
00731     *display_image,
00732     **image_list;
00733 
00734   int
00735     scene;
00736 
00737   MagickStatusType
00738     status;
00739 
00740   RectangleInfo
00741     geometry_info;
00742 
00743   register long
00744     i;
00745 
00746   size_t
00747     number_scenes;
00748 
00749   static XPixelInfo
00750     pixel;
00751 
00752   static XStandardColormap
00753     *map_info;
00754 
00755   static XVisualInfo
00756     *visual_info = (XVisualInfo *) NULL;
00757 
00758   static XWindowInfo
00759     window_info;
00760 
00761   unsigned int
00762     height,
00763     width;
00764 
00765   unsigned long
00766     delay;
00767 
00768   Window
00769     root_window;
00770 
00771   XEvent
00772     event;
00773 
00774   XGCValues
00775     context_values;
00776 
00777   XResourceInfo
00778     resources;
00779 
00780   XWindowAttributes
00781     window_attributes;
00782 
00783   /*
00784     Determine target window.
00785   */
00786   assert(images != (Image *) NULL);
00787   assert(images->signature == MagickSignature);
00788   if (images->debug != MagickFalse)
00789     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
00790   resources=(*resource_info);
00791   window_info.id=(Window) NULL;
00792   root_window=XRootWindow(display,XDefaultScreen(display));
00793   if (LocaleCompare(resources.window_id,"root") == 0)
00794     window_info.id=root_window;
00795   else
00796     {
00797       if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
00798         window_info.id=XWindowByID(display,root_window,
00799           (Window) strtol((char *) resources.window_id,(char **) NULL,0));
00800       if (window_info.id == (Window) NULL)
00801         window_info.id=
00802           XWindowByName(display,root_window,resources.window_id);
00803     }
00804   if (window_info.id == (Window) NULL)
00805     {
00806       ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
00807         resources.window_id);
00808       return;
00809     }
00810   /*
00811     Determine window visual id.
00812   */
00813   window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
00814   window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
00815   (void) CopyMagickString(visual_type,"default",MaxTextExtent);
00816   status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
00817     MagickTrue : MagickFalse;
00818   if (status != MagickFalse)
00819     (void) FormatMagickString(visual_type,MaxTextExtent,"0x%lx",
00820       XVisualIDFromVisual(window_attributes.visual));
00821   if (visual_info == (XVisualInfo *) NULL)
00822     {
00823       /*
00824         Allocate standard colormap.
00825       */
00826       map_info=XAllocStandardColormap();
00827       if (map_info == (XStandardColormap *) NULL)
00828         ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
00829           images->filename);
00830       map_info->colormap=(Colormap) NULL;
00831       pixel.pixels=(unsigned long *) NULL;
00832       /*
00833         Initialize visual info.
00834       */
00835       resources.map_type=(char *) NULL;
00836       resources.visual_type=visual_type;
00837       visual_info=XBestVisualInfo(display,map_info,&resources);
00838       if (visual_info == (XVisualInfo *) NULL)
00839         ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
00840           images->filename);
00841       /*
00842         Initialize window info.
00843       */
00844       window_info.ximage=(XImage *) NULL;
00845       window_info.matte_image=(XImage *) NULL;
00846       window_info.pixmap=(Pixmap) NULL;
00847       window_info.matte_pixmap=(Pixmap) NULL;
00848     }
00849   /*
00850     Free previous root colors.
00851   */
00852   if (window_info.id == root_window)
00853     XDestroyWindowColors(display,root_window);
00854   coalesce_image=CoalesceImages(images,&images->exception);
00855   if (coalesce_image == (Image *) NULL)
00856     ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
00857       images->filename);
00858   images=coalesce_image;
00859   if (resources.map_type == (char *) NULL)
00860     if ((visual_info->klass != TrueColor) &&
00861         (visual_info->klass != DirectColor))
00862       {
00863         Image
00864           *next;
00865 
00866         /*
00867           Determine if the sequence of images has the identical colormap.
00868         */
00869         for (next=images; next != (Image *) NULL; )
00870         {
00871           next->matte=MagickFalse;
00872           if ((next->storage_class == DirectClass) ||
00873               (next->colors != images->colors) ||
00874               (next->colors > (unsigned long) visual_info->colormap_size))
00875             break;
00876           for (i=0; i < (long) images->colors; i++)
00877             if (IsColorEqual(next->colormap+i,images->colormap+i) == MagickFalse)
00878               break;
00879           if (i < (long) images->colors)
00880             break;
00881           next=GetNextImageInList(next);
00882         }
00883         if (next != (Image *) NULL)
00884           (void) RemapImages(resources.quantize_info,images,(Image *) NULL);
00885       }
00886   /*
00887     Sort images by increasing scene number.
00888   */
00889   number_scenes=GetImageListLength(images);
00890   image_list=ImageListToArray(images,&images->exception);
00891   if (image_list == (Image **) NULL)
00892     ThrowXWindowFatalException(ResourceLimitFatalError,
00893       "MemoryAllocationFailed",images->filename);
00894   for (i=0; i < (long) number_scenes; i++)
00895     if (image_list[i]->scene == 0)
00896       break;
00897   if (i == (long) number_scenes)
00898     qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
00899   /*
00900     Initialize Standard Colormap.
00901   */
00902   resources.colormap=SharedColormap;
00903   display_image=image_list[0];
00904   for (scene=0; scene < (int) number_scenes; scene++)
00905   {
00906     if ((resource_info->map_type != (char *) NULL) ||
00907         (visual_info->klass == TrueColor) ||
00908         (visual_info->klass == DirectColor))
00909       (void) SetImageType(image_list[scene],image_list[scene]->matte ==
00910         MagickFalse ? TrueColorType : TrueColorMatteType);
00911     if ((display_image->columns < image_list[scene]->columns) &&
00912         (display_image->rows < image_list[scene]->rows))
00913       display_image=image_list[scene];
00914   }
00915   if ((resource_info->map_type != (char *) NULL) ||
00916       (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
00917     (void) SetImageType(display_image,display_image->matte == MagickFalse ?
00918       TrueColorType : TrueColorMatteType);
00919   XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
00920     &pixel);
00921   /*
00922     Graphic context superclass.
00923   */
00924   context_values.background=pixel.background_color.pixel;
00925   context_values.foreground=pixel.foreground_color.pixel;
00926   pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
00927     GCBackground | GCForeground,&context_values);
00928   if (pixel.annotate_context == (GC) NULL)
00929     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
00930       images->filename);
00931   /*
00932     Initialize Image window attributes.
00933   */
00934   XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
00935     &resources,&window_info);
00936   /*
00937     Create the X image.
00938   */
00939   window_info.width=(unsigned int) image_list[0]->columns;
00940   window_info.height=(unsigned int) image_list[0]->rows;
00941   if ((image_list[0]->columns != window_info.width) ||
00942       (image_list[0]->rows != window_info.height))
00943     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
00944       image_list[0]->filename);
00945   (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>",
00946     window_attributes.width,window_attributes.height);
00947   geometry_info.width=window_info.width;
00948   geometry_info.height=window_info.height;
00949   geometry_info.x=window_info.x;
00950   geometry_info.y=window_info.y;
00951   (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
00952     &geometry_info.width,&geometry_info.height);
00953   window_info.width=(unsigned int) geometry_info.width;
00954   window_info.height=(unsigned int) geometry_info.height;
00955   window_info.x=(int) geometry_info.x;
00956   window_info.y=(int) geometry_info.y;
00957   status=XMakeImage(display,&resources,&window_info,image_list[0],
00958     window_info.width,window_info.height);
00959   if (status == MagickFalse)
00960     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
00961       images->filename);
00962   window_info.x=0;
00963   window_info.y=0;
00964   if (display_image->debug != MagickFalse)
00965     {
00966       (void) LogMagickEvent(X11Event,GetMagickModule(),
00967         "Image: %s[%lu] %lux%lu ",image_list[0]->filename,
00968         image_list[0]->scene,image_list[0]->columns,image_list[0]->rows);
00969       if (image_list[0]->colors != 0)
00970         (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
00971           image_list[0]->colors);
00972       (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
00973         image_list[0]->magick);
00974     }
00975   /*
00976     Adjust image dimensions as specified by backdrop or geometry options.
00977   */
00978   width=window_info.width;
00979   height=window_info.height;
00980   if (resources.backdrop != MagickFalse)
00981     {
00982       /*
00983         Center image on window.
00984       */
00985       window_info.x=(int) (window_attributes.width/2)-
00986         (window_info.ximage->width/2);
00987       window_info.y=(int) (window_attributes.height/2)-
00988         (window_info.ximage->height/2);
00989       width=(unsigned int) window_attributes.width;
00990       height=(unsigned int) window_attributes.height;
00991     }
00992   if (resources.image_geometry != (char *) NULL)
00993     {
00994       char
00995         default_geometry[MaxTextExtent];
00996 
00997       int
00998         flags,
00999         gravity;
01000 
01001       XSizeHints
01002         *size_hints;
01003 
01004       /*
01005         User specified geometry.
01006       */
01007       size_hints=XAllocSizeHints();
01008       if (size_hints == (XSizeHints *) NULL)
01009         ThrowXWindowFatalException(ResourceLimitFatalError,
01010           "MemoryAllocationFailed",images->filename);
01011       size_hints->flags=0L;
01012       (void) FormatMagickString(default_geometry,MaxTextExtent,"%ux%u",width,
01013         height);
01014       flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
01015         default_geometry,window_info.border_width,size_hints,&window_info.x,
01016         &window_info.y,(int *) &width,(int *) &height,&gravity);
01017       if (((flags & (XValue | YValue))) != 0)
01018         {
01019           width=(unsigned int) window_attributes.width;
01020           height=(unsigned int) window_attributes.height;
01021         }
01022       (void) XFree((void *) size_hints);
01023     }
01024   /*
01025     Create the X pixmap.
01026   */
01027   window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
01028     (unsigned int) height,window_info.depth);
01029   if (window_info.pixmap == (Pixmap) NULL)
01030     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
01031       images->filename);
01032   /*
01033     Display pixmap on the window.
01034   */
01035   if (((unsigned int) width > window_info.width) ||
01036       ((unsigned int) height > window_info.height))
01037     (void) XFillRectangle(display,window_info.pixmap,
01038       window_info.annotate_context,0,0,(unsigned int) width,
01039       (unsigned int) height);
01040   (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
01041     window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
01042     window_info.height);
01043   (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
01044   (void) XClearWindow(display,window_info.id);
01045   /*
01046     Initialize image pixmaps structure.
01047   */
01048   window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
01049     sizeof(*window_info.pixmaps));
01050   window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
01051     sizeof(*window_info.matte_pixmaps));
01052   if ((window_info.pixmaps == (Pixmap *) NULL) ||
01053       (window_info.matte_pixmaps == (Pixmap *) NULL))
01054     ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
01055       images->filename);
01056   window_info.pixmaps[0]=window_info.pixmap;
01057   window_info.matte_pixmaps[0]=window_info.pixmap;
01058   for (scene=1; scene < (int) number_scenes; scene++)
01059   {
01060     unsigned int
01061       columns,
01062       rows;
01063 
01064     /*
01065       Create X image.
01066     */
01067     window_info.pixmap=(Pixmap) NULL;
01068     window_info.matte_pixmap=(Pixmap) NULL;
01069     if ((resources.map_type != (char *) NULL) ||
01070         (visual_info->klass == TrueColor) ||
01071         (visual_info->klass == DirectColor))
01072       if (image_list[scene]->storage_class == PseudoClass)
01073         XGetPixelPacket(display,visual_info,map_info,&resources,
01074           image_list[scene],window_info.pixel_info);
01075     columns=(unsigned int) image_list[scene]->columns;
01076     rows=(unsigned int) image_list[scene]->rows;
01077     if ((image_list[scene]->columns != columns) ||
01078         (image_list[scene]->rows != rows))
01079       ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
01080         image_list[scene]->filename);
01081     status=XMakeImage(display,&resources,&window_info,image_list[scene],
01082       columns,rows);
01083     if (status == MagickFalse)
01084       ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
01085         images->filename);
01086     if (display_image->debug != MagickFalse)
01087       {
01088         (void) LogMagickEvent(X11Event,GetMagickModule(),
01089           "Image: [%lu] %s %ux%u ",image_list[scene]->scene,
01090           image_list[scene]->filename,columns,rows);
01091         if (image_list[scene]->colors != 0)
01092           (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
01093             image_list[scene]->colors);
01094         (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
01095           image_list[scene]->magick);
01096       }
01097     /*
01098       Create the X pixmap.
01099     */
01100     window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
01101       window_info.depth);
01102     if (window_info.pixmap == (Pixmap) NULL)
01103       ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
01104         images->filename);
01105     /*
01106       Display pixmap on the window.
01107     */
01108     if ((width > window_info.width) || (height > window_info.height))
01109       (void) XFillRectangle(display,window_info.pixmap,
01110         window_info.annotate_context,0,0,width,height);
01111     (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
01112       window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
01113       window_info.height);
01114     (void) XSetWindowBackgroundPixmap(display,window_info.id,
01115       window_info.pixmap);
01116     (void) XClearWindow(display,window_info.id);
01117     window_info.pixmaps[scene]=window_info.pixmap;
01118     window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
01119     if (image_list[scene]->matte)
01120       (void) XClearWindow(display,window_info.id);
01121     delay=1000*image_list[scene]->delay/MagickMax(
01122       image_list[scene]->ticks_per_second,1L);
01123     XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
01124   }
01125   window_info.pixel_info=(&pixel);
01126   /*
01127     Display pixmap on the window.
01128   */
01129   (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
01130   event.type=Expose;
01131   do
01132   {
01133     for (scene=0; scene < (int) number_scenes; scene++)
01134     {
01135       if (XEventsQueued(display,QueuedAfterFlush) > 0)
01136         {
01137           (void) XNextEvent(display,&event);
01138           if (event.type == DestroyNotify)
01139             break;
01140         }
01141       window_info.pixmap=window_info.pixmaps[scene];
01142       window_info.matte_pixmap=window_info.matte_pixmaps[scene];
01143       (void) XSetWindowBackgroundPixmap(display,window_info.id,
01144         window_info.pixmap);
01145       (void) XClearWindow(display,window_info.id);
01146       (void) XSync(display,MagickFalse);
01147       delay=1000*image_list[scene]->delay/MagickMax(
01148         image_list[scene]->ticks_per_second,1L);
01149       XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
01150     }
01151   } while (event.type != DestroyNotify);
01152   (void) XSync(display,MagickFalse);
01153   image_list=(Image **) RelinquishMagickMemory(image_list);
01154   images=DestroyImageList(images);
01155 }
01156 
01157 /*
01158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01159 %                                                                             %
01160 %                                                                             %
01161 %                                                                             %
01162 +   X A n i m a t e I m a g e s                                               %
01163 %                                                                             %
01164 %                                                                             %
01165 %                                                                             %
01166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01167 %
01168 %  XAnimateImages() displays an image via X11.
01169 %
01170 %  The format of the XAnimateImages method is:
01171 %
01172 %      Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
01173 %        char **argv,const int argc,Image *images)
01174 %
01175 %  A description of each parameter follows:
01176 %
01177 %    o display: Specifies a connection to an X server;  returned from
01178 %      XOpenDisplay.
01179 %
01180 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01181 %
01182 %    o argv: Specifies the application's argument list.
01183 %
01184 %    o argc: Specifies the number of arguments.
01185 %
01186 %    o images: the image list.
01187 %
01188 */
01189 MagickExport Image *XAnimateImages(Display *display,
01190   XResourceInfo *resource_info,char **argv,const int argc,Image *images)
01191 {
01192 #define MagickMenus  4
01193 #define MaXWindows  8
01194 #define MagickTitle  "Commands"
01195 
01196   static const char
01197     *CommandMenu[]=
01198     {
01199       "Animate",
01200       "Speed",
01201       "Direction",
01202       "Help",
01203       "Image Info",
01204       "Quit",
01205       (char *) NULL
01206     },
01207     *AnimateMenu[]=
01208     {
01209       "Open...",
01210       "Play",
01211       "Step",
01212       "Repeat",
01213       "Auto Reverse",
01214       "Save...",
01215       (char *) NULL
01216     },
01217     *SpeedMenu[]=
01218     {
01219       "Faster",
01220       "Slower",
01221       (char *) NULL
01222     },
01223     *DirectionMenu[]=
01224     {
01225       "Forward",
01226       "Reverse",
01227       (char *) NULL
01228     },
01229     *HelpMenu[]=
01230     {
01231       "Overview",
01232       "Browse Documentation",
01233       "About Animate",
01234       (char *) NULL
01235     };
01236 
01237   static const char
01238     **Menus[MagickMenus]=
01239     {
01240       AnimateMenu,
01241       SpeedMenu,
01242       DirectionMenu,
01243       HelpMenu
01244     };
01245 
01246   static const CommandType
01247     CommandMenus[]=
01248     {
01249       NullCommand,
01250       NullCommand,
01251       NullCommand,
01252       NullCommand,
01253       InfoCommand,
01254       QuitCommand
01255     },
01256     CommandTypes[]=
01257     {
01258       OpenCommand,
01259       PlayCommand,
01260       StepCommand,
01261       RepeatCommand,
01262       AutoReverseCommand,
01263       SaveCommand
01264     },
01265     SpeedCommands[]=
01266     {
01267       FasterCommand,
01268       SlowerCommand
01269     },
01270     DirectionCommands[]=
01271     {
01272       ForwardCommand,
01273       ReverseCommand
01274     },
01275     HelpCommands[]=
01276     {
01277       HelpCommand,
01278       BrowseDocumentationCommand,
01279       VersionCommand
01280     };
01281 
01282   static const CommandType
01283     *Commands[MagickMenus]=
01284     {
01285       CommandTypes,
01286       SpeedCommands,
01287       DirectionCommands,
01288       HelpCommands
01289     };
01290 
01291   char
01292     command[MaxTextExtent],
01293     *cwd,
01294     geometry[MaxTextExtent],
01295     resource_name[MaxTextExtent];
01296 
01297   CommandType
01298     command_type;
01299 
01300   Image
01301     *coalesce_image,
01302     *display_image,
01303     *image,
01304     **image_list,
01305     *nexus;
01306 
01307   int
01308     status;
01309 
01310   long
01311     first_scene,
01312     iterations,
01313     scene;
01314 
01315   KeySym
01316     key_symbol;
01317 
01318   MagickStatusType
01319     context_mask,
01320     state;
01321 
01322   RectangleInfo
01323     geometry_info;
01324 
01325   register char
01326     *p;
01327 
01328   register long
01329     i;
01330 
01331   static char
01332     working_directory[MaxTextExtent];
01333 
01334   static unsigned long
01335     number_windows;
01336 
01337   static XWindowInfo
01338     *magick_windows[MaXWindows];
01339 
01340   time_t
01341     timestamp;
01342 
01343   unsigned long
01344     delay,
01345     number_scenes;
01346 
01347   WarningHandler
01348     warning_handler;
01349 
01350   Window
01351     root_window;
01352 
01353   XClassHint
01354     *class_hints;
01355 
01356   XEvent
01357     event;
01358 
01359   XFontStruct
01360     *font_info;
01361 
01362   XGCValues
01363     context_values;
01364 
01365   XPixelInfo
01366     *icon_pixel,
01367     *pixel;
01368 
01369   XResourceInfo
01370     *icon_resources;
01371 
01372   XStandardColormap
01373     *icon_map,
01374     *map_info;
01375 
01376   XTextProperty
01377     window_name;
01378 
01379   XVisualInfo
01380     *icon_visual,
01381     *visual_info;
01382 
01383   XWindowChanges
01384     window_changes;
01385 
01386   XWindows
01387     *windows;
01388 
01389   XWMHints
01390     *manager_hints;
01391 
01392   assert(images != (Image *) NULL);
01393   assert(images->signature == MagickSignature);
01394   if (images->debug != MagickFalse)
01395     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
01396   warning_handler=(WarningHandler) NULL;
01397   windows=XSetWindows((XWindows *) ~0);
01398   if (windows != (XWindows *) NULL)
01399     {
01400       int
01401         status;
01402 
01403       status=chdir(working_directory);
01404       if (status == -1)
01405         (void) ThrowMagickException(&images->exception,GetMagickModule(),
01406           FileOpenError,"UnableToOpenFile","%s",working_directory);
01407       warning_handler=resource_info->display_warnings ?
01408         SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
01409       warning_handler=resource_info->display_warnings ?
01410         SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
01411     }
01412   else
01413     {
01414       register Image
01415         *p;
01416 
01417       /*
01418         Initialize window structure.
01419       */
01420       for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
01421       {
01422         if (p->storage_class == DirectClass)
01423           {
01424             resource_info->colors=0;
01425             break;
01426           }
01427         if (p->colors > resource_info->colors)
01428           resource_info->colors=p->colors;
01429       }
01430       windows=XSetWindows(XInitializeWindows(display,resource_info));
01431       if (windows == (XWindows *) NULL)
01432         ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
01433           images->filename);
01434       /*
01435         Initialize window id's.
01436       */
01437       number_windows=0;
01438       magick_windows[number_windows++]=(&windows->icon);
01439       magick_windows[number_windows++]=(&windows->backdrop);
01440       magick_windows[number_windows++]=(&windows->image);
01441       magick_windows[number_windows++]=(&windows->info);
01442       magick_windows[number_windows++]=(&windows->command);
01443       magick_windows[number_windows++]=(&windows->widget);
01444       magick_windows[number_windows++]=(&windows->popup);
01445       for (i=0; i < (long) number_windows; i++)
01446         magick_windows[i]->id=(Window) NULL;
01447     }
01448   /*
01449     Initialize font info.
01450   */
01451   if (windows->font_info != (XFontStruct *) NULL)
01452     (void) XFreeFont(display,windows->font_info);
01453   windows->font_info=XBestFont(display,resource_info,MagickFalse);
01454   if (windows->font_info == (XFontStruct *) NULL)
01455     ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
01456       resource_info->font);
01457   /*
01458     Initialize Standard Colormap.
01459   */
01460   map_info=windows->map_info;
01461   icon_map=windows->icon_map;
01462   visual_info=windows->visual_info;
01463   icon_visual=windows->icon_visual;
01464   pixel=windows->pixel_info;
01465   icon_pixel=windows->icon_pixel;
01466   font_info=windows->font_info;
01467   icon_resources=windows->icon_resources;
01468   class_hints=windows->class_hints;
01469   manager_hints=windows->manager_hints;
01470   root_window=XRootWindow(display,visual_info->screen);
01471   coalesce_image=CoalesceImages(images,&images->exception);
01472   if (coalesce_image == (Image *) NULL)
01473     ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
01474       images->filename);
01475   images=coalesce_image;
01476   if (resource_info->map_type == (char *) NULL)
01477     if ((visual_info->klass != TrueColor) &&
01478         (visual_info->klass != DirectColor))
01479       {
01480         Image
01481           *next;
01482 
01483         /*
01484           Determine if the sequence of images has the identical colormap.
01485         */
01486         for (next=images; next != (Image *) NULL; )
01487         {
01488           next->matte=MagickFalse;
01489           if ((next->storage_class == DirectClass) ||
01490               (next->colors != images->colors) ||
01491               (next->colors > (unsigned long) visual_info->colormap_size))
01492             break;
01493           for (i=0; i < (long) images->colors; i++)
01494             if (IsColorEqual(next->colormap+i,images->colormap+i) == MagickFalse)
01495               break;
01496           if (i < (long) images->colors)
01497             break;
01498           next=GetNextImageInList(next);
01499         }
01500         if (next != (Image *) NULL)
01501           (void) RemapImages(resource_info->quantize_info,images,
01502             (Image *) NULL);
01503       }
01504   /*
01505     Sort images by increasing scene number.
01506   */
01507   number_scenes=GetImageListLength(images);
01508   image_list=ImageListToArray(images,&images->exception);
01509   if (image_list == (Image **) NULL)
01510     ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
01511       images->filename);
01512   for (scene=0; scene < (long) number_scenes; scene++)
01513     if (image_list[scene]->scene == 0)
01514       break;
01515   if (scene == (long) number_scenes)
01516     qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
01517   /*
01518     Initialize Standard Colormap.
01519   */
01520   nexus=NewImageList();
01521   display_image=image_list[0];
01522   for (scene=0; scene < (long) number_scenes; scene++)
01523   {
01524     if ((resource_info->map_type != (char *) NULL) ||
01525         (visual_info->klass == TrueColor) ||
01526         (visual_info->klass == DirectColor))
01527       (void) SetImageType(image_list[scene],image_list[scene]->matte ==
01528         MagickFalse ? TrueColorType : TrueColorMatteType);
01529     if ((display_image->columns < image_list[scene]->columns) &&
01530         (display_image->rows < image_list[scene]->rows))
01531       display_image=image_list[scene];
01532   }
01533   if (display_image->debug != MagickFalse)
01534     {
01535       (void) LogMagickEvent(X11Event,GetMagickModule(),
01536         "Image: %s[%lu] %lux%lu ",display_image->filename,
01537         display_image->scene,display_image->columns,display_image->rows);
01538       if (display_image->colors != 0)
01539         (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
01540           display_image->colors);
01541       (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
01542         display_image->magick);
01543     }
01544   XMakeStandardColormap(display,visual_info,resource_info,display_image,
01545     map_info,pixel);
01546   /*
01547     Initialize graphic context.
01548   */
01549   windows->context.id=(Window) NULL;
01550   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
01551     resource_info,&windows->context);
01552   (void) CloneString(&class_hints->res_name,resource_info->client_name);
01553   (void) CloneString(&class_hints->res_class,resource_info->client_name);
01554   class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
01555   manager_hints->flags=InputHint | StateHint;
01556   manager_hints->input=MagickFalse;
01557   manager_hints->initial_state=WithdrawnState;
01558   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
01559     &windows->context);
01560   if (display_image->debug != MagickFalse)
01561     (void) LogMagickEvent(X11Event,GetMagickModule(),
01562       "Window id: 0x%lx (context)",windows->context.id);
01563   context_values.background=pixel->background_color.pixel;
01564   context_values.font=font_info->fid;
01565   context_values.foreground=pixel->foreground_color.pixel;
01566   context_values.graphics_exposures=MagickFalse;
01567   context_mask=(MagickStatusType)
01568     (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
01569   if (pixel->annotate_context != (GC) NULL)
01570     (void) XFreeGC(display,pixel->annotate_context);
01571   pixel->annotate_context=
01572     XCreateGC(display,windows->context.id,context_mask,&context_values);
01573   if (pixel->annotate_context == (GC) NULL)
01574     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
01575       images->filename);
01576   context_values.background=pixel->depth_color.pixel;
01577   if (pixel->widget_context != (GC) NULL)
01578     (void) XFreeGC(display,pixel->widget_context);
01579   pixel->widget_context=
01580     XCreateGC(display,windows->context.id,context_mask,&context_values);
01581   if (pixel->widget_context == (GC) NULL)
01582     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
01583       images->filename);
01584   context_values.background=pixel->foreground_color.pixel;
01585   context_values.foreground=pixel->background_color.pixel;
01586   context_values.plane_mask=
01587     context_values.background ^ context_values.foreground;
01588   if (pixel->highlight_context != (GC) NULL)
01589     (void) XFreeGC(display,pixel->highlight_context);
01590   pixel->highlight_context=XCreateGC(display,windows->context.id,
01591     (unsigned long) (context_mask | GCPlaneMask),&context_values);
01592   if (pixel->highlight_context == (GC) NULL)
01593     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
01594       images->filename);
01595   (void) XDestroyWindow(display,windows->context.id);
01596   /*
01597     Initialize icon window.
01598   */
01599   XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
01600     icon_resources,&windows->icon);
01601   windows->icon.geometry=resource_info->icon_geometry;
01602   XBestIconSize(display,&windows->icon,display_image);
01603   windows->icon.attributes.colormap=
01604     XDefaultColormap(display,icon_visual->screen);
01605   windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
01606   manager_hints->flags=InputHint | StateHint;
01607   manager_hints->input=MagickFalse;
01608   manager_hints->initial_state=IconicState;
01609   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
01610     &windows->icon);
01611   if (display_image->debug != MagickFalse)
01612     (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
01613       windows->icon.id);
01614   /*
01615     Initialize graphic context for icon window.
01616   */
01617   if (icon_pixel->annotate_context != (GC) NULL)
01618     (void) XFreeGC(display,icon_pixel->annotate_context);
01619   context_values.background=icon_pixel->background_color.pixel;
01620   context_values.foreground=icon_pixel->foreground_color.pixel;
01621   icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
01622     (unsigned long) (GCBackground | GCForeground),&context_values);
01623   if (icon_pixel->annotate_context == (GC) NULL)
01624     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
01625       images->filename);
01626   windows->icon.annotate_context=icon_pixel->annotate_context;
01627   /*
01628     Initialize Image window.
01629   */
01630   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
01631     resource_info,&windows->image);
01632   windows->image.shape=MagickTrue;  /* non-rectangular shape hint */
01633   if (resource_info->use_shared_memory == MagickFalse)
01634     windows->image.shared_memory=MagickFalse;
01635   if (resource_info->title != (char *) NULL)
01636     {
01637       char
01638         *title;
01639 
01640       title=InterpretImageProperties(resource_info->image_info,display_image,
01641         resource_info->title);
01642       (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
01643       (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
01644       title=DestroyString(title);
01645     }
01646   else
01647     {
01648       char
01649         filename[MaxTextExtent];
01650 
01651       /*
01652         Window name is the base of the filename.
01653       */
01654       GetPathComponent(display_image->magick_filename,TailPath,filename);
01655       (void) FormatMagickString(windows->image.name,MaxTextExtent,
01656         "ImageMagick: %s[%lu of %lu]",filename,display_image->scene,
01657         number_scenes);
01658       (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
01659     }
01660   if (resource_info->immutable != MagickFalse)
01661     windows->image.immutable=MagickTrue;
01662   windows->image.shape=MagickTrue;
01663   windows->image.geometry=resource_info->image_geometry;
01664   (void) FormatMagickString(geometry,MaxTextExtent,"%ux%u+0+0>!",
01665     XDisplayWidth(display,visual_info->screen),
01666     XDisplayHeight(display,visual_info->screen));
01667   geometry_info.width=display_image->columns;
01668   geometry_info.height=display_image->rows;
01669   geometry_info.x=0;
01670   geometry_info.y=0;
01671   (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
01672     &geometry_info.width,&geometry_info.height);
01673   windows->image.width=(unsigned int) geometry_info.width;
01674   windows->image.height=(unsigned int) geometry_info.height;
01675   windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
01676     ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
01677     KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
01678     PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
01679   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
01680     resource_info,&windows->backdrop);
01681   if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
01682     {
01683       /*
01684         Initialize backdrop window.
01685       */
01686       windows->backdrop.x=0;
01687       windows->backdrop.y=0;
01688       (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
01689       windows->backdrop.flags=(unsigned long) (USSize | USPosition);
01690       windows->backdrop.width=(unsigned int)
01691         XDisplayWidth(display,visual_info->screen);
01692       windows->backdrop.height=(unsigned int)
01693         XDisplayHeight(display,visual_info->screen);
01694       windows->backdrop.border_width=0;
01695       windows->backdrop.immutable=MagickTrue;
01696       windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
01697         ButtonReleaseMask;
01698       windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
01699         StructureNotifyMask;
01700       manager_hints->flags=IconWindowHint | InputHint | StateHint;
01701       manager_hints->icon_window=windows->icon.id;
01702       manager_hints->input=MagickTrue;
01703       manager_hints->initial_state=
01704         resource_info->iconic ? IconicState : NormalState;
01705       XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
01706         &windows->backdrop);
01707       if (display_image->debug != MagickFalse)
01708         (void) LogMagickEvent(X11Event,GetMagickModule(),
01709           "Window id: 0x%lx (backdrop)",windows->backdrop.id);
01710       (void) XMapWindow(display,windows->backdrop.id);
01711       (void) XClearWindow(display,windows->backdrop.id);
01712       if (windows->image.id != (Window) NULL)
01713         {
01714           (void) XDestroyWindow(display,windows->image.id);
01715           windows->image.id=(Window) NULL;
01716         }
01717       /*
01718         Position image in the center the backdrop.
01719       */
01720       windows->image.flags|=USPosition;
01721       windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
01722         (windows->image.width/2);
01723       windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
01724         (windows->image.height/2);
01725     }
01726   manager_hints->flags=IconWindowHint | InputHint | StateHint;
01727   manager_hints->icon_window=windows->icon.id;
01728   manager_hints->input=MagickTrue;
01729   manager_hints->initial_state=
01730     resource_info->iconic ? IconicState : NormalState;
01731   if (windows->group_leader.id != (Window) NULL)
01732     {
01733       /*
01734         Follow the leader.
01735       */
01736       manager_hints->flags|=(MagickStatusType) WindowGroupHint;
01737       manager_hints->window_group=windows->group_leader.id;
01738       (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
01739       if (display_image->debug != MagickFalse)
01740         (void) LogMagickEvent(X11Event,GetMagickModule(),
01741           "Window id: 0x%lx (group leader)",windows->group_leader.id);
01742     }
01743   XMakeWindow(display,
01744     (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
01745     argv,argc,class_hints,manager_hints,&windows->image);
01746   (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
01747     XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
01748   if (windows->group_leader.id != (Window) NULL)
01749     (void) XSetTransientForHint(display,windows->image.id,
01750       windows->group_leader.id);
01751   if (display_image->debug != MagickFalse)
01752     (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
01753       windows->image.id);
01754   /*
01755     Initialize Info widget.
01756   */
01757   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
01758     resource_info,&windows->info);
01759   (void) CloneString(&windows->info.name,"Info");
01760   (void) CloneString(&windows->info.icon_name,"Info");
01761   windows->info.border_width=1;
01762   windows->info.x=2;
01763   windows->info.y=2;
01764   windows->info.flags|=PPosition;
01765   windows->info.attributes.win_gravity=UnmapGravity;
01766   windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
01767     StructureNotifyMask;
01768   manager_hints->flags=InputHint | StateHint | WindowGroupHint;
01769   manager_hints->input=MagickFalse;
01770   manager_hints->initial_state=NormalState;
01771   manager_hints->window_group=windows->image.id;
01772   XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
01773     &windows->info);
01774   windows->info.highlight_stipple=XCreateBitmapFromData(display,
01775     windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
01776   windows->info.shadow_stipple=XCreateBitmapFromData(display,
01777     windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
01778   (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
01779   if (windows->image.mapped)
01780     (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
01781   if (display_image->debug != MagickFalse)
01782     (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
01783       windows->info.id);
01784   /*
01785     Initialize Command widget.
01786   */
01787   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
01788     resource_info,&windows->command);
01789   windows->command.data=MagickMenus;
01790   (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
01791   (void) FormatMagickString(resource_name,MaxTextExtent,"%s.command",
01792     resource_info->client_name);
01793   windows->command.geometry=XGetResourceClass(resource_info->resource_database,
01794     resource_name,"geometry",(char *) NULL);
01795   (void) CloneString(&windows->command.name,MagickTitle);
01796   windows->command.border_width=0;
01797   windows->command.flags|=PPosition;
01798   windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
01799     ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
01800     OwnerGrabButtonMask | StructureNotifyMask;
01801   manager_hints->flags=InputHint | StateHint | WindowGroupHint;
01802   manager_hints->input=MagickTrue;
01803   manager_hints->initial_state=NormalState;
01804   manager_hints->window_group=windows->image.id;
01805   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
01806     &windows->command);
01807   windows->command.highlight_stipple=XCreateBitmapFromData(display,
01808     windows->command.id,(char *) HighlightBitmap,HighlightWidth,
01809     HighlightHeight);
01810   windows->command.shadow_stipple=XCreateBitmapFromData(display,
01811     windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
01812   (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
01813   if (display_image->debug != MagickFalse)
01814     (void) LogMagickEvent(X11Event,GetMagickModule(),
01815       "Window id: 0x%lx (command)",windows->command.id);
01816   /*
01817     Initialize Widget window.
01818   */
01819   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
01820     resource_info,&windows->widget);
01821   (void) FormatMagickString(resource_name,MaxTextExtent,"%s.widget",
01822     resource_info->client_name);
01823   windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
01824     resource_name,"geometry",(char *) NULL);
01825   windows->widget.border_width=0;
01826   windows->widget.flags|=PPosition;
01827   windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
01828     ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
01829     KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
01830     StructureNotifyMask;
01831   manager_hints->flags=InputHint | StateHint | WindowGroupHint;
01832   manager_hints->input=MagickTrue;
01833   manager_hints->initial_state=NormalState;
01834   manager_hints->window_group=windows->image.id;
01835   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
01836     &windows->widget);
01837   windows->widget.highlight_stipple=XCreateBitmapFromData(display,
01838     windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
01839   windows->widget.shadow_stipple=XCreateBitmapFromData(display,
01840     windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
01841   (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
01842   if (display_image->debug != MagickFalse)
01843     (void) LogMagickEvent(X11Event,GetMagickModule(),
01844       "Window id: 0x%lx (widget)",windows->widget.id);
01845   /*
01846     Initialize popup window.
01847   */
01848   XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
01849     resource_info,&windows->popup);
01850   windows->popup.border_width=0;
01851   windows->popup.flags|=PPosition;
01852   windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
01853     ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
01854     KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
01855   manager_hints->flags=InputHint | StateHint | WindowGroupHint;
01856   manager_hints->input=MagickTrue;
01857   manager_hints->initial_state=NormalState;
01858   manager_hints->window_group=windows->image.id;
01859   XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
01860     &windows->popup);
01861   windows->popup.highlight_stipple=XCreateBitmapFromData(display,
01862     windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
01863   windows->popup.shadow_stipple=XCreateBitmapFromData(display,
01864     windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
01865   (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
01866   if (display_image->debug != MagickFalse)
01867     (void) LogMagickEvent(X11Event,GetMagickModule(),
01868       "Window id: 0x%lx (pop up)",windows->popup.id);
01869   if ((windows->image.mapped == MagickFalse) ||
01870       (windows->backdrop.id != (Window) NULL))
01871     (void) XMapWindow(display,windows->image.id);
01872   /*
01873     Set out progress and warning handlers.
01874   */
01875   if (warning_handler == (WarningHandler) NULL)
01876     {
01877       warning_handler=resource_info->display_warnings ?
01878         SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
01879       warning_handler=resource_info->display_warnings ?
01880         SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
01881     }
01882   /*
01883     Initialize X image structure.
01884   */
01885   windows->image.x=0;
01886   windows->image.y=0;
01887   status=XMakeImage(display,resource_info,&windows->image,display_image,
01888     (unsigned int) display_image->columns,(unsigned int) display_image->rows);
01889   if (status == MagickFalse)
01890     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
01891       images->filename);
01892   if (windows->image.mapped)
01893     XRefreshWindow(display,&windows->image,(XEvent *) NULL);
01894   /*
01895     Initialize image pixmaps structure.
01896   */
01897   window_changes.width=(int) windows->image.width;
01898   window_changes.height=(int) windows->image.height;
01899   (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
01900     (unsigned int) (CWWidth | CWHeight),&window_changes);
01901   (void) XMapWindow(display,windows->image.id);
01902   windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
01903     sizeof(*windows->image.pixmaps));
01904   windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
01905     sizeof(*windows->image.pixmaps));
01906   if ((windows->image.pixmaps == (Pixmap *) NULL) ||
01907       (windows->image.matte_pixmaps == (Pixmap *) NULL))
01908     ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
01909       images->filename);
01910   windows->image.pixmaps[0]=windows->image.pixmap;
01911   windows->image.matte_pixmaps[0]=windows->image.matte_pixmap;
01912   for (scene=1; scene < (long) number_scenes; scene++)
01913   {
01914     unsigned int
01915       columns,
01916       rows;
01917 
01918     /*
01919       Create X image.
01920     */
01921     (void) TransformImageColorspace(image_list[scene],RGBColorspace);
01922     windows->image.pixmap=(Pixmap) NULL;
01923     windows->image.matte_pixmap=(Pixmap) NULL;
01924     if ((resource_info->map_type != (char *) NULL) ||
01925         (visual_info->klass == TrueColor) ||
01926         (visual_info->klass == DirectColor))
01927       if (image_list[scene]->storage_class == PseudoClass)
01928         XGetPixelPacket(display,visual_info,map_info,resource_info,
01929           image_list[scene],windows->image.pixel_info);
01930     columns=(unsigned int) image_list[scene]->columns;
01931     rows=(unsigned int) image_list[scene]->rows;
01932     if ((image_list[scene]->columns != columns) ||
01933         (image_list[scene]->rows != rows))
01934       ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
01935         image_list[scene]->filename);
01936     status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
01937       columns,rows);
01938     if (status == MagickFalse)
01939       ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
01940         images->filename);
01941     if (image_list[scene]->debug != MagickFalse)
01942       {
01943         (void) LogMagickEvent(X11Event,GetMagickModule(),
01944           "Image: [%lu] %s %ux%u ",image_list[scene]->scene,
01945           image_list[scene]->filename,columns,rows);
01946         if (image_list[scene]->colors != 0)
01947           (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
01948             image_list[scene]->colors);
01949         (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
01950           image_list[scene]->magick);
01951       }
01952     /*
01953       Window name is the base of the filename.
01954     */
01955     if (resource_info->title != (char *) NULL)
01956       {
01957         char
01958           *title;
01959 
01960         title=InterpretImageProperties(resource_info->image_info,
01961           image_list[scene],resource_info->title);
01962         (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
01963         title=DestroyString(title);
01964       }
01965     else
01966       {
01967         p=image_list[scene]->magick_filename+
01968           strlen(image_list[scene]->magick_filename)-1;
01969         while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
01970           p--;
01971         (void) FormatMagickString(windows->image.name,MaxTextExtent,
01972           "ImageMagick: %s[%lu of %lu]",p,scene+1,number_scenes);
01973       }
01974     status=XStringListToTextProperty(&windows->image.name,1,&window_name);
01975     if (status != Success)
01976       {
01977         XSetWMName(display,windows->image.id,&window_name);
01978         (void) XFree((void *) window_name.value);
01979       }
01980     windows->image.pixmaps[scene]=windows->image.pixmap;
01981     windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
01982     event.xexpose.x=0;
01983     event.xexpose.y=0;
01984     event.xexpose.width=(int) image_list[scene]->columns;
01985     event.xexpose.height=(int) image_list[scene]->rows;
01986     XRefreshWindow(display,&windows->image,&event);
01987     (void) XSync(display,MagickFalse);
01988     delay=1000*image_list[scene]->delay/MagickMax(images->ticks_per_second,1L);
01989     XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
01990     if (XCheckTypedWindowEvent(display,windows->image.id,KeyPress,&event) != 0)
01991       {
01992         int
01993           length;
01994 
01995         length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
01996           sizeof(command),&key_symbol,(XComposeStatus *) NULL);
01997         *(command+length)='\0';
01998         if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
01999           {
02000             XClientMessage(display,windows->image.id,windows->im_protocols,
02001               windows->im_exit,CurrentTime);
02002             break;
02003           }
02004       }
02005   }
02006   if (windows->command.mapped)
02007     (void) XMapRaised(display,windows->command.id);
02008   /*
02009     Respond to events.
02010   */
02011   nexus=NewImageList();
02012   scene=0;
02013   first_scene=0;
02014   iterations=0;
02015   image=image_list[0];
02016   state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
02017   (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
02018     &state);
02019   do
02020   {
02021     if (XEventsQueued(display,QueuedAfterFlush) == 0)
02022       if ((state & PlayAnimationState) || (state & StepAnimationState))
02023         {
02024           MagickBooleanType
02025             pause;
02026 
02027           pause=MagickFalse;
02028           delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
02029           XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
02030           if (state & ForwardAnimationState)
02031             {
02032               /*
02033                 Forward animation:  increment scene number.
02034               */
02035               if (scene < ((long) number_scenes-1))
02036                 scene++;
02037               else
02038                 {
02039                   iterations++;
02040                   if (iterations == (long) image_list[0]->iterations)
02041                     {
02042                       iterations=0;
02043                       state|=ExitState;
02044                     }
02045                   if (state & AutoReverseAnimationState)
02046                     {
02047                       state&=(~ForwardAnimationState);
02048                       scene--;
02049                     }
02050                   else
02051                     {
02052                       if ((state & RepeatAnimationState) == MagickFalse)
02053                         state&=(~PlayAnimationState);
02054                       scene=first_scene;
02055                       pause=MagickTrue;
02056                     }
02057                 }
02058             }
02059           else
02060             {
02061               /*
02062                 Reverse animation:  decrement scene number.
02063               */
02064               if (scene > first_scene)
02065                 scene--;
02066               else
02067                 {
02068                   iterations++;
02069                   if (iterations == (long) image_list[0]->iterations)
02070                     {
02071                       iterations=0;
02072                       state&=(~RepeatAnimationState);
02073                     }
02074                   if (state & AutoReverseAnimationState)
02075                     {
02076                       state|=ForwardAnimationState;
02077                       scene=first_scene;
02078                       pause=MagickTrue;
02079                     }
02080                   else
02081                     {
02082                       if ((state & RepeatAnimationState) == MagickFalse)
02083                         state&=(~PlayAnimationState);
02084                       scene=(long) number_scenes-1;
02085                     }
02086                 }
02087             }
02088           scene=MagickMax(scene,0);
02089           image=image_list[scene];
02090           if ((image != (Image *) NULL) && (image->start_loop != 0))
02091             first_scene=scene;
02092           if ((state & StepAnimationState) ||
02093               (resource_info->title != (char *) NULL))
02094             {
02095               /*
02096                 Update window title.
02097               */
02098               p=image_list[scene]->filename+
02099                 strlen(image_list[scene]->filename)-1;
02100               while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
02101                 p--;
02102               (void) FormatMagickString(windows->image.name,MaxTextExtent,
02103                 "ImageMagick: %s[%lu of %lu]",p,scene+1,number_scenes);
02104               if (resource_info->title != (char *) NULL)
02105                 {
02106                   char
02107                     *title;
02108 
02109                   title=InterpretImageProperties(resource_info->image_info,
02110                     image,resource_info->title);
02111                   (void) CopyMagickString(windows->image.name,title,
02112                     MaxTextExtent);
02113                   title=DestroyString(title);
02114                 }
02115               status=XStringListToTextProperty(&windows->image.name,1,
02116                 &window_name);
02117               if (status != Success)
02118                 {
02119                   XSetWMName(display,windows->image.id,&window_name);
02120                   (void) XFree((void *) window_name.value);
02121                 }
02122             }
02123           /*
02124             Copy X pixmap to Image window.
02125           */
02126           XGetPixelPacket(display,visual_info,map_info,resource_info,
02127             image_list[scene],windows->image.pixel_info);
02128           windows->image.ximage->width=(int) image->columns;
02129           windows->image.ximage->height=(int) image->rows;
02130           windows->image.pixmap=windows->image.pixmaps[scene];
02131           windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
02132           event.xexpose.x=0;
02133           event.xexpose.y=0;
02134           event.xexpose.width=(int) image->columns;
02135           event.xexpose.height=(int) image->rows;
02136           XRefreshWindow(display,&windows->image,&event);
02137           (void) XSync(display,MagickFalse);
02138           state&=(~StepAnimationState);
02139           if (pause != MagickFalse)
02140             for (i=0; i < (long) resource_info->pause; i++)
02141             {
02142               int
02143                 status;
02144 
02145               status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
02146                 &event);
02147               if (status != 0)
02148                 {
02149                   int
02150                     length;
02151 
02152                   length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
02153                     sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02154                   *(command+length)='\0';
02155                   if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
02156                     {
02157                       XClientMessage(display,windows->image.id,
02158                         windows->im_protocols,windows->im_exit,CurrentTime);
02159                       break;
02160                     }
02161                 }
02162               (void) sleep(1);
02163             }
02164           continue;
02165         }
02166     /*
02167       Handle a window event.
02168     */
02169     timestamp=time((time_t *) NULL);
02170     (void) XNextEvent(display,&event);
02171     if (windows->image.stasis == MagickFalse)
02172       windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
02173         MagickTrue : MagickFalse;
02174     if (event.xany.window == windows->command.id)
02175       {
02176         int
02177           id;
02178 
02179         /*
02180           Select a command from the Command widget.
02181         */
02182         id=XCommandWidget(display,windows,CommandMenu,&event);
02183         if (id < 0)
02184           continue;
02185         (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
02186         command_type=CommandMenus[id];
02187         if (id < MagickMenus)
02188           {
02189             int
02190               entry;
02191 
02192             /*
02193               Select a command from a pop-up menu.
02194             */
02195             entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
02196               command);
02197             if (entry < 0)
02198               continue;
02199             (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
02200             command_type=Commands[id][entry];
02201           }
02202         if (command_type != NullCommand)
02203           nexus=XMagickCommand(display,resource_info,windows,
02204             command_type,&image,&state);
02205         continue;
02206       }
02207     switch (event.type)
02208     {
02209       case ButtonPress:
02210       {
02211         if (display_image->debug != MagickFalse)
02212           (void) LogMagickEvent(X11Event,GetMagickModule(),
02213             "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
02214             event.xbutton.button,event.xbutton.x,event.xbutton.y);
02215         if ((event.xbutton.button == Button3) &&
02216             (event.xbutton.state & Mod1Mask))
02217           {
02218             /*
02219               Convert Alt-Button3 to Button2.
02220             */
02221             event.xbutton.button=Button2;
02222             event.xbutton.state&=(~Mod1Mask);
02223           }
02224         if (event.xbutton.window == windows->backdrop.id)
02225           {
02226             (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
02227               event.xbutton.time);
02228             break;
02229           }
02230         if (event.xbutton.window == windows->image.id)
02231           {
02232             if (resource_info->immutable != MagickFalse)
02233               {
02234                 state|=ExitState;
02235                 break;
02236               }
02237             /*
02238               Map/unmap Command widget.
02239             */
02240             if (windows->command.mapped)
02241               (void) XWithdrawWindow(display,windows->command.id,
02242                 windows->command.screen);
02243             else
02244               {
02245                 (void) XCommandWidget(display,windows,CommandMenu,
02246                   (XEvent *) NULL);
02247                 (void) XMapRaised(display,windows->command.id);
02248               }
02249           }
02250         break;
02251       }
02252       case ButtonRelease:
02253       {
02254         if (display_image->debug != MagickFalse)
02255           (void) LogMagickEvent(X11Event,GetMagickModule(),
02256             "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
02257             event.xbutton.button,event.xbutton.x,event.xbutton.y);
02258         break;
02259       }
02260       case ClientMessage:
02261       {
02262         if (display_image->debug != MagickFalse)
02263           (void) LogMagickEvent(X11Event,GetMagickModule(),
02264             "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
02265             event.xclient.message_type,event.xclient.format,(unsigned long)
02266             event.xclient.data.l[0]);
02267         if (event.xclient.message_type == windows->im_protocols)
02268           {
02269             if (*event.xclient.data.l == (long) windows->im_update_colormap)
02270               {
02271                 /*
02272                   Update graphic context and window colormap.
02273                 */
02274                 for (i=0; i < (long) number_windows; i++)
02275                 {
02276                   if (magick_windows[i]->id == windows->icon.id)
02277                     continue;
02278                   context_values.background=pixel->background_color.pixel;
02279                   context_values.foreground=pixel->foreground_color.pixel;
02280                   (void) XChangeGC(display,magick_windows[i]->annotate_context,
02281                     context_mask,&context_values);
02282                   (void) XChangeGC(display,magick_windows[i]->widget_context,
02283                     context_mask,&context_values);
02284                   context_values.background=pixel->foreground_color.pixel;
02285                   context_values.foreground=pixel->background_color.pixel;
02286                   context_values.plane_mask=
02287                     context_values.background ^ context_values.foreground;
02288                   (void) XChangeGC(display,magick_windows[i]->highlight_context,
02289                     (unsigned long) (context_mask | GCPlaneMask),
02290                     &context_values);
02291                   magick_windows[i]->attributes.background_pixel=
02292                     pixel->background_color.pixel;
02293                   magick_windows[i]->attributes.border_pixel=
02294                     pixel->border_color.pixel;
02295                   magick_windows[i]->attributes.colormap=map_info->colormap;
02296                   (void) XChangeWindowAttributes(display,magick_windows[i]->id,
02297                     magick_windows[i]->mask,&magick_windows[i]->attributes);
02298                 }
02299                 if (windows->backdrop.id != (Window) NULL)
02300                   (void) XInstallColormap(display,map_info->colormap);
02301                 break;
02302               }
02303             if (*event.xclient.data.l == (long) windows->im_exit)
02304               {
02305                 state|=ExitState;
02306                 break;
02307               }
02308             break;
02309           }
02310         if (event.xclient.message_type == windows->dnd_protocols)
02311           {
02312             Atom
02313               selection,
02314               type;
02315 
02316             int
02317               format,
02318               status;
02319 
02320             unsigned char
02321               *data;
02322 
02323             unsigned long
02324               after,
02325               length;
02326 
02327             /*
02328               Display image named by the Drag-and-Drop selection.
02329             */
02330             if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
02331               break;
02332             selection=XInternAtom(display,"DndSelection",MagickFalse);
02333             status=XGetWindowProperty(display,root_window,selection,0L,2047L,
02334               MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
02335               &data);
02336             if ((status != Success) || (length == 0))
02337               break;
02338             if (*event.xclient.data.l == 2)
02339               {
02340                 /*
02341                   Offix DND.
02342                 */
02343                 (void) CopyMagickString(resource_info->image_info->filename,
02344                   (char *) data,MaxTextExtent);
02345               }
02346             else
02347               {
02348                 /*
02349                   XDND.
02350                 */
02351                 if (LocaleNCompare((char *) data,"file:",5) != 0)
02352                   {
02353                     (void) XFree((void *) data);
02354                     break;
02355                   }
02356                 (void) CopyMagickString(resource_info->image_info->filename,
02357                   ((char *) data)+5,MaxTextExtent);
02358               }
02359             nexus=ReadImage(resource_info->image_info,&image->exception);
02360             CatchException(&image->exception);
02361             if (nexus != (Image *) NULL)
02362               state|=ExitState;
02363             (void) XFree((void *) data);
02364             break;
02365           }
02366         /*
02367           If client window delete message, exit.
02368         */
02369         if (event.xclient.message_type != windows->wm_protocols)
02370           break;
02371         if (*event.xclient.data.l == (long) windows->wm_take_focus)
02372           {
02373             (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
02374               (Time) event.xclient.data.l[1]);
02375             break;
02376           }
02377         if (*event.xclient.data.l != (long) windows->wm_delete_window)
02378           break;
02379         (void) XWithdrawWindow(display,event.xclient.window,
02380           visual_info->screen);
02381         if (event.xclient.window == windows->image.id)
02382           {
02383             state|=ExitState;
02384             break;
02385           }
02386         break;
02387       }
02388       case ConfigureNotify:
02389       {
02390         if (display_image->debug != MagickFalse)
02391           (void) LogMagickEvent(X11Event,GetMagickModule(),
02392             "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
02393             event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
02394             event.xconfigure.y,event.xconfigure.send_event);
02395         if (event.xconfigure.window == windows->image.id)
02396           {
02397             if (event.xconfigure.send_event != 0)
02398               {
02399                 XWindowChanges
02400                   window_changes;
02401 
02402                 /*
02403                   Position the transient windows relative of the Image window.
02404                 */
02405                 if (windows->command.geometry == (char *) NULL)
02406                   if (windows->command.mapped == MagickFalse)
02407                     {
02408                        windows->command.x=
02409                           event.xconfigure.x-windows->command.width-25;
02410                         windows->command.y=event.xconfigure.y;
02411                         XConstrainWindowPosition(display,&windows->command);
02412                         window_changes.x=windows->command.x;
02413                         window_changes.y=windows->command.y;
02414                         (void) XReconfigureWMWindow(display,windows->command.id,
02415                           windows->command.screen,(unsigned int) (CWX | CWY),
02416                           &window_changes);
02417                     }
02418                 if (windows->widget.geometry == (char *) NULL)
02419                   if (windows->widget.mapped == MagickFalse)
02420                     {
02421                       windows->widget.x=
02422                         event.xconfigure.x+event.xconfigure.width/10;
02423                       windows->widget.y=
02424                         event.xconfigure.y+event.xconfigure.height/10;
02425                       XConstrainWindowPosition(display,&windows->widget);
02426                       window_changes.x=windows->widget.x;
02427                       window_changes.y=windows->widget.y;
02428                       (void) XReconfigureWMWindow(display,windows->widget.id,
02429                         windows->widget.screen,(unsigned int) (CWX | CWY),
02430                         &window_changes);
02431                     }
02432               }
02433             /*
02434               Image window has a new configuration.
02435             */
02436             windows->image.width=(unsigned int) event.xconfigure.width;
02437             windows->image.height=(unsigned int) event.xconfigure.height;
02438             break;
02439           }
02440         if (event.xconfigure.window == windows->icon.id)
02441           {
02442             /*
02443               Icon window has a new configuration.
02444             */
02445             windows->icon.width=(unsigned int) event.xconfigure.width;
02446             windows->icon.height=(unsigned int) event.xconfigure.height;
02447             break;
02448           }
02449         break;
02450       }
02451       case DestroyNotify:
02452       {
02453         /*
02454           Group leader has exited.
02455         */
02456         if (display_image->debug != MagickFalse)
02457           (void) LogMagickEvent(X11Event,GetMagickModule(),
02458             "Destroy Notify: 0x%lx",event.xdestroywindow.window);
02459         if (event.xdestroywindow.window == windows->group_leader.id)
02460           {
02461             state|=ExitState;
02462             break;
02463           }
02464         break;
02465       }
02466       case EnterNotify:
02467       {
02468         /*
02469           Selectively install colormap.
02470         */
02471         if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
02472           if (event.xcrossing.mode != NotifyUngrab)
02473             XInstallColormap(display,map_info->colormap);
02474         break;
02475       }
02476       case Expose:
02477       {
02478         if (display_image->debug != MagickFalse)
02479           (void) LogMagickEvent(X11Event,GetMagickModule(),
02480             "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
02481             event.xexpose.width,event.xexpose.height,event.xexpose.x,
02482             event.xexpose.y);
02483         /*
02484           Repaint windows that are now exposed.
02485         */
02486         if (event.xexpose.window == windows->image.id)
02487           {
02488             windows->image.pixmap=windows->image.pixmaps[scene];
02489             windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
02490             XRefreshWindow(display,&windows->image,&event);
02491             break;
02492           }
02493         if (event.xexpose.window == windows->icon.id)
02494           if (event.xexpose.count == 0)
02495             {
02496               XRefreshWindow(display,&windows->icon,&event);
02497               break;
02498             }
02499         break;
02500       }
02501       case KeyPress:
02502       {
02503         static int
02504           length;
02505 
02506         /*
02507           Respond to a user key press.
02508         */
02509         length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
02510           sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02511         *(command+length)='\0';
02512         if (display_image->debug != MagickFalse)
02513           (void) LogMagickEvent(X11Event,GetMagickModule(),
02514             "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
02515         command_type=NullCommand;
02516         switch (key_symbol)
02517         {
02518           case XK_o:
02519           {
02520             if ((event.xkey.state & ControlMask) == MagickFalse)
02521               break;
02522             command_type=OpenCommand;
02523             break;
02524           }
02525           case XK_BackSpace:
02526           {
02527             command_type=StepBackwardCommand;
02528             break;
02529           }
02530           case XK_space:
02531           {
02532             command_type=StepForwardCommand;
02533             break;
02534           }
02535           case XK_less:
02536           {
02537             command_type=FasterCommand;
02538             break;
02539           }
02540           case XK_greater:
02541           {
02542             command_type=SlowerCommand;
02543             break;
02544           }
02545           case XK_F1:
02546           {
02547             command_type=HelpCommand;
02548             break;
02549           }
02550           case XK_Find:
02551           {
02552             command_type=BrowseDocumentationCommand;
02553             break;
02554           }
02555           case XK_question:
02556           {
02557             command_type=InfoCommand;
02558             break;
02559           }
02560           case XK_q:
02561           case XK_Escape:
02562           {
02563             command_type=QuitCommand;
02564             break;
02565           }
02566           default:
02567             break;
02568         }
02569         if (command_type != NullCommand)
02570           nexus=XMagickCommand(display,resource_info,windows,
02571             command_type,&image,&state);
02572         break;
02573       }
02574       case KeyRelease:
02575       {
02576         /*
02577           Respond to a user key release.
02578         */
02579         (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
02580           sizeof(command),&key_symbol,(XComposeStatus *) NULL);
02581         if (display_image->debug != MagickFalse)
02582           (void) LogMagickEvent(X11Event,GetMagickModule(),
02583             "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
02584         break;
02585       }
02586       case LeaveNotify:
02587       {
02588         /*
02589           Selectively uninstall colormap.
02590         */
02591         if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
02592           if (event.xcrossing.mode != NotifyUngrab)
02593             XUninstallColormap(display,map_info->colormap);
02594         break;
02595       }
02596       case MapNotify:
02597       {
02598         if (display_image->debug != MagickFalse)
02599           (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
02600             event.xmap.window);
02601         if (event.xmap.window == windows->backdrop.id)
02602           {
02603             (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
02604               CurrentTime);
02605             windows->backdrop.mapped=MagickTrue;
02606             break;
02607           }
02608         if (event.xmap.window == windows->image.id)
02609           {
02610             if (windows->backdrop.id != (Window) NULL)
02611               (void) XInstallColormap(display,map_info->colormap);
02612             if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
02613               {
02614                 if (LocaleCompare(display_image->filename,"LOGO") == 0)
02615                   nexus=XMagickCommand(display,resource_info,windows,
02616                     OpenCommand,&image,&state);
02617                 else
02618                   state|=ExitState;
02619               }
02620             windows->image.mapped=MagickTrue;
02621             break;
02622           }
02623         if (event.xmap.window == windows->info.id)
02624           {
02625             windows->info.mapped=MagickTrue;
02626             break;
02627           }
02628         if (event.xmap.window == windows->icon.id)
02629           {
02630             /*
02631               Create an icon image.
02632             */
02633             XMakeStandardColormap(display,icon_visual,icon_resources,
02634               display_image,icon_map,icon_pixel);
02635             (void) XMakeImage(display,icon_resources,&windows->icon,
02636               display_image,windows->icon.width,windows->icon.height);
02637             (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
02638               windows->icon.pixmap);
02639             (void) XClearWindow(display,windows->icon.id);
02640             (void) XWithdrawWindow(display,windows->info.id,
02641               windows->info.screen);
02642             windows->icon.mapped=MagickTrue;
02643             break;
02644           }
02645         if (event.xmap.window == windows->command.id)
02646           {
02647             windows->command.mapped=MagickTrue;
02648             break;
02649           }
02650         if (event.xmap.window == windows->popup.id)
02651           {
02652             windows->popup.mapped=MagickTrue;
02653             break;
02654           }
02655         if (event.xmap.window == windows->widget.id)
02656           {
02657             windows->widget.mapped=MagickTrue;
02658             break;
02659           }
02660         break;
02661       }
02662       case MappingNotify:
02663       {
02664         (void) XRefreshKeyboardMapping(&event.xmapping);
02665         break;
02666       }
02667       case NoExpose:
02668         break;
02669       case PropertyNotify:
02670       {
02671         Atom
02672           type;
02673 
02674         int
02675           format,
02676           status;
02677 
02678         unsigned char
02679           *data;
02680 
02681         unsigned long
02682           after,
02683           length;
02684 
02685         if (display_image->debug != MagickFalse)
02686           (void) LogMagickEvent(X11Event,GetMagickModule(),
02687             "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
02688             event.xproperty.atom,event.xproperty.state);
02689         if (event.xproperty.atom != windows->im_remote_command)
02690           break;
02691         /*
02692           Display image named by the remote command protocol.
02693         */
02694         status=XGetWindowProperty(display,event.xproperty.window,
02695           event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
02696           AnyPropertyType,&type,&format,&length,&after,&data);
02697         if ((status != Success) || (length == 0))
02698           break;
02699         (void) CopyMagickString(resource_info->image_info->filename,
02700           (char *) data,MaxTextExtent);
02701         nexus=ReadImage(resource_info->image_info,&image->exception);
02702         CatchException(&image->exception);
02703         if (nexus != (Image *) NULL)
02704           state|=ExitState;
02705         (void) XFree((void *) data);
02706         break;
02707       }
02708       case ReparentNotify:
02709       {
02710         if (display_image->debug != MagickFalse)
02711           (void) LogMagickEvent(X11Event,GetMagickModule(),
02712             "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
02713             event.xreparent.window);
02714         break;
02715       }
02716       case UnmapNotify:
02717       {
02718         if (display_image->debug != MagickFalse)
02719           (void) LogMagickEvent(X11Event,GetMagickModule(),
02720             "Unmap Notify: 0x%lx",event.xunmap.window);
02721         if (event.xunmap.window == windows->backdrop.id)
02722           {
02723             windows->backdrop.mapped=MagickFalse;
02724             break;
02725           }
02726         if (event.xunmap.window == windows->image.id)
02727           {
02728             windows->image.mapped=MagickFalse;
02729             break;
02730           }
02731         if (event.xunmap.window == windows->info.id)
02732           {
02733             windows->info.mapped=MagickFalse;
02734             break;
02735           }
02736         if (event.xunmap.window == windows->icon.id)
02737           {
02738             if (map_info->colormap == icon_map->colormap)
02739               XConfigureImageColormap(display,resource_info,windows,
02740                 display_image);
02741             (void) XFreeStandardColormap(display,icon_visual,icon_map,
02742               icon_pixel);
02743             windows->icon.mapped=MagickFalse;
02744             break;
02745           }
02746         if (event.xunmap.window == windows->command.id)
02747           {
02748             windows->command.mapped=MagickFalse;
02749             break;
02750           }
02751         if (event.xunmap.window == windows->popup.id)
02752           {
02753             if (windows->backdrop.id != (Window) NULL)
02754               (void) XSetInputFocus(display,windows->image.id,RevertToParent,
02755                 CurrentTime);
02756             windows->popup.mapped=MagickFalse;
02757             break;
02758           }
02759         if (event.xunmap.window == windows->widget.id)
02760           {
02761             if (windows->backdrop.id != (Window) NULL)
02762               (void) XSetInputFocus(display,windows->image.id,RevertToParent,
02763                 CurrentTime);
02764             windows->widget.mapped=MagickFalse;
02765             break;
02766           }
02767         break;
02768       }
02769       default:
02770       {
02771         if (display_image->debug != MagickFalse)
02772           (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
02773             event.type);
02774         break;
02775       }
02776     }
02777   }
02778   while (!(state & ExitState));
02779   image_list=(Image **) RelinquishMagickMemory(image_list);
02780   images=DestroyImageList(images);
02781   if ((windows->visual_info->klass == GrayScale) ||
02782       (windows->visual_info->klass == PseudoColor) ||
02783       (windows->visual_info->klass == DirectColor))
02784     {
02785       /*
02786         Withdraw windows.
02787       */
02788       if (windows->info.mapped)
02789         (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
02790       if (windows->command.mapped)
02791         (void) XWithdrawWindow(display,windows->command.id,
02792           windows->command.screen);
02793     }
02794   if (resource_info->backdrop == MagickFalse)
02795     if (windows->backdrop.mapped)
02796       {
02797         (void) XWithdrawWindow(display,windows->backdrop.id,\
02798           windows->backdrop.screen);
02799         (void) XDestroyWindow(display,windows->backdrop.id);
02800         windows->backdrop.id=(Window) NULL;
02801         (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
02802         (void) XDestroyWindow(display,windows->image.id);
02803         windows->image.id=(Window) NULL;
02804       }
02805   XSetCursorState(display,windows,MagickTrue);
02806   XCheckRefreshWindows(display,windows);
02807   for (scene=1; scene < (long) number_scenes; scene++)
02808   {
02809     if (windows->image.pixmaps[scene] != (Pixmap) NULL)
02810       (void) XFreePixmap(display,windows->image.pixmaps[scene]);
02811     windows->image.pixmaps[scene]=(Pixmap) NULL;
02812     if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
02813       (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
02814     windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
02815   }
02816   windows->image.pixmaps=(Pixmap *)
02817     RelinquishMagickMemory(windows->image.pixmaps);
02818   windows->image.matte_pixmaps=(Pixmap *)
02819     RelinquishMagickMemory(windows->image.matte_pixmaps);
02820   if (nexus == (Image *) NULL)
02821     {
02822       /*
02823         Free X resources.
02824       */
02825       if (windows->image.mapped != MagickFalse)
02826         (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);      XDelay(display,SuspendTime);
02827       (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
02828       if (resource_info->map_type == (char *) NULL)
02829         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
02830       DestroyXResources();
02831     }
02832   (void) XSync(display,MagickFalse);
02833   /*
02834     Restore our progress monitor and warning handlers.
02835   */
02836   (void) SetErrorHandler(warning_handler);
02837   (void) SetWarningHandler(warning_handler);
02838   /*
02839     Change to home directory.
02840   */
02841   cwd=getcwd(working_directory,MaxTextExtent);
02842   status=chdir(resource_info->home_directory);
02843   if (status == -1)
02844     (void) ThrowMagickException(&images->exception,GetMagickModule(),
02845       FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
02846   return(nexus);
02847 }
02848 
02849 /*
02850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02851 %                                                                             %
02852 %                                                                             %
02853 %                                                                             %
02854 +   X S a v e I m a g e                                                       %
02855 %                                                                             %
02856 %                                                                             %
02857 %                                                                             %
02858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02859 %
02860 %  XSaveImage() saves an image to a file.
02861 %
02862 %  The format of the XSaveImage method is:
02863 %
02864 %      MagickBooleanType XSaveImage(Display *display,
02865 %        XResourceInfo *resource_info,XWindows *windows,Image *image)
02866 %
02867 %  A description of each parameter follows:
02868 %
02869 %    o status: Method XSaveImage return True if the image is
02870 %      written.  False is returned is there is a memory shortage or if the
02871 %      image fails to write.
02872 %
02873 %    o display: Specifies a connection to an X server; returned from
02874 %      XOpenDisplay.
02875 %
02876 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02877 %
02878 %    o windows: Specifies a pointer to a XWindows structure.
02879 %
02880 %    o image: the image.
02881 %
02882 */
02883 static MagickBooleanType XSaveImage(Display *display,
02884   XResourceInfo *resource_info,XWindows *windows,Image *image)
02885 {
02886   char
02887     filename[MaxTextExtent];
02888 
02889   ImageInfo
02890     *image_info;
02891 
02892   MagickStatusType
02893     status;
02894 
02895   /*
02896     Request file name from user.
02897   */
02898   if (resource_info->write_filename != (char *) NULL)
02899     (void) CopyMagickString(filename,resource_info->write_filename,
02900       MaxTextExtent);
02901   else
02902     {
02903       char
02904         path[MaxTextExtent];
02905 
02906       int
02907         status;
02908 
02909       GetPathComponent(image->filename,HeadPath,path);
02910       GetPathComponent(image->filename,TailPath,filename);
02911       status=chdir(path);
02912       if (status == -1)
02913         (void) ThrowMagickException(&image->exception,GetMagickModule(),
02914           FileOpenError,"UnableToOpenFile","%s",path);
02915     }
02916   XFileBrowserWidget(display,windows,"Save",filename);
02917   if (*filename == '\0')
02918     return(MagickTrue);
02919   if (IsPathAccessible(filename) != MagickFalse)
02920     {
02921       int
02922         status;
02923 
02924       /*
02925         File exists-- seek user's permission before overwriting.
02926       */
02927       status=XConfirmWidget(display,windows,"Overwrite",filename);
02928       if (status == 0)
02929         return(MagickTrue);
02930     }
02931   image_info=CloneImageInfo(resource_info->image_info);
02932   (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
02933   (void) SetImageInfo(image_info,MagickFalse,&image->exception);
02934   if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
02935       (LocaleCompare(image_info->magick,"JPG") == 0))
02936     {
02937       char
02938         quality[MaxTextExtent];
02939 
02940       int
02941         status;
02942 
02943       /*
02944         Request JPEG quality from user.
02945       */
02946       (void) FormatMagickString(quality,MaxTextExtent,"%lu",
02947         image_info->quality);
02948       status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
02949         quality);
02950       if (*quality == '\0')
02951         return(MagickTrue);
02952       image->quality=(unsigned long) atol(quality);
02953       image_info->interlace=status != MagickFalse ?  NoInterlace :
02954         PlaneInterlace;
02955     }
02956   if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
02957       (LocaleCompare(image_info->magick,"PDF") == 0) ||
02958       (LocaleCompare(image_info->magick,"PS") == 0) ||
02959       (LocaleCompare(image_info->magick,"PS2") == 0))
02960     {
02961       char
02962         geometry[MaxTextExtent];
02963 
02964       /*
02965         Request page geometry from user.
02966       */
02967       (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
02968       if (LocaleCompare(image_info->magick,"PDF") == 0)
02969         (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
02970       if (image_info->page != (char *) NULL)
02971         (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
02972       XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
02973         "Select page geometry:",geometry);
02974       if (*geometry != '\0')
02975         image_info->page=GetPageGeometry(geometry);
02976     }
02977   /*
02978     Write image.
02979   */
02980   image=GetFirstImageInList(image);
02981   status=WriteImages(image_info,image,filename,&image->exception);
02982   if (status != MagickFalse)
02983     image->taint=MagickFalse;
02984   image_info=DestroyImageInfo(image_info);
02985   XSetCursorState(display,windows,MagickFalse);
02986   return(status != 0 ? MagickTrue : MagickFalse);
02987 }
02988 #else
02989 
02990 /*
02991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02992 %                                                                             %
02993 %                                                                             %
02994 %                                                                             %
02995 +   A n i m a t e I m a g e s                                                 %
02996 %                                                                             %
02997 %                                                                             %
02998 %                                                                             %
02999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03000 %
03001 %  AnimateImages() repeatedly displays an image sequence to any X window
03002 %  screen.  It returns a value other than 0 if successful.  Check the
03003 %  exception member of image to determine the reason for any failure.
03004 %
03005 %  The format of the AnimateImages method is:
03006 %
03007 %      MagickBooleanType AnimateImages(const ImageInfo *image_info,
03008 %        Image *images)
03009 %
03010 %  A description of each parameter follows:
03011 %
03012 %    o image_info: the image info.
03013 %
03014 %    o image: the image.
03015 %
03016 */
03017 MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info,
03018   Image *image)
03019 {
03020   assert(image_info != (const ImageInfo *) NULL);
03021   assert(image_info->signature == MagickSignature);
03022   assert(image != (Image *) NULL);
03023   assert(image->signature == MagickSignature);
03024   if (image->debug != MagickFalse)
03025     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03026   (void) ThrowMagickException(&image->exception,GetMagickModule(),
03027     MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (X11)",
03028     image->filename);
03029   return(MagickFalse);
03030 }
03031 #endif

Generated on 19 Nov 2009 for MagickCore by  doxygen 1.6.1