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