MagickCore  7.0.3
animate.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % AAA N N IIIII M M AAA TTTTT EEEEE %
7 % A A NN N I MM MM A A T E %
8 % AAAAA N N N I M M M AAAAA T EEE %
9 % A A N NN I M M A A T E %
10 % A A N N IIIII M M A A T EEEEE %
11 % %
12 % %
13 % Methods to Interactively Animate an Image Sequence %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/animate.h"
45 #include "MagickCore/attribute.h"
46 #include "MagickCore/client.h"
47 #include "MagickCore/color.h"
49 #include "MagickCore/colorspace.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/exception.h"
55 #include "MagickCore/geometry.h"
57 #include "MagickCore/layer.h"
58 #include "MagickCore/list.h"
59 #include "MagickCore/log.h"
60 #include "MagickCore/image.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/monitor.h"
64 #include "MagickCore/option.h"
66 #include "MagickCore/property.h"
67 #include "MagickCore/resource_.h"
68 #include "MagickCore/string_.h"
71 #include "MagickCore/transform.h"
72 #include "MagickCore/utility.h"
74 #include "MagickCore/version.h"
75 #include "MagickCore/widget.h"
77 #include "MagickCore/xwindow.h"
79 
80 #if defined(MAGICKCORE_X11_DELEGATE)
81 /*
82  Animate state declarations.
83 */
84 #define AutoReverseAnimationState 0x0004
85 #define ForwardAnimationState 0x0008
86 #define HighlightState 0x0010
87 #define PlayAnimationState 0x0020
88 #define RepeatAnimationState 0x0040
89 #define StepAnimationState 0x0080
90 
91 /*
92  Static declarations.
93 */
94 static const char
95  AnimateHelp[] =
96  {
97  "BUTTONS\n"
98  "\n"
99  " Press any button to map or unmap the Command widget.\n"
100  "\n"
101  "COMMAND WIDGET\n"
102  " The Command widget lists a number of sub-menus and commands.\n"
103  " They are\n"
104  "\n"
105  " Animate\n"
106  " Open...\n"
107  " Save...\n"
108  " Play\n"
109  " Step\n"
110  " Repeat\n"
111  " Auto Reverse\n"
112  " Speed\n"
113  " Slower\n"
114  " Faster\n"
115  " Direction\n"
116  " Forward\n"
117  " Reverse\n"
118  " Help\n"
119  " Overview\n"
120  " Browse Documentation\n"
121  " About Animate\n"
122  " Image Info\n"
123  " Quit\n"
124  "\n"
125  " Menu items with a indented triangle have a sub-menu. They\n"
126  " are represented above as the indented items. To access a\n"
127  " sub-menu item, move the pointer to the appropriate menu and\n"
128  " press a button and drag. When you find the desired sub-menu\n"
129  " item, release the button and the command is executed. Move\n"
130  " the pointer away from the sub-menu if you decide not to\n"
131  " execute a particular command.\n"
132  "\n"
133  "KEYBOARD ACCELERATORS\n"
134  " Accelerators are one or two key presses that effect a\n"
135  " particular command. The keyboard accelerators that\n"
136  " animate(1) understands is:\n"
137  "\n"
138  " Ctl+O Press to open an image from a file.\n"
139  "\n"
140  " space Press to display the next image in the sequence.\n"
141  "\n"
142  " < Press to speed-up the display of the images. Refer to\n"
143  " -delay for more information.\n"
144  "\n"
145  " > Press to slow the display of the images. Refer to\n"
146  " -delay for more information.\n"
147  "\n"
148  " F1 Press to display helpful information about animate(1).\n"
149  "\n"
150  " Find Press to browse documentation about ImageMagick.\n"
151  "\n"
152  " ? Press to display information about the image. Press\n"
153  " any key or button to erase the information.\n"
154  "\n"
155  " This information is printed: image name; image size;\n"
156  " and the total number of unique colors in the image.\n"
157  "\n"
158  " Ctl-q Press to discard all images and exit program.\n"
159  };
160 
161 /*
162  Constant declarations.
163 */
164 static const char
165  *PageSizes[] =
166  {
167  "Letter",
168  "Tabloid",
169  "Ledger",
170  "Legal",
171  "Statement",
172  "Executive",
173  "A3",
174  "A4",
175  "A5",
176  "B4",
177  "B5",
178  "Folio",
179  "Quarto",
180  "10x14",
181  (char *) NULL
182  };
183 
184 static const unsigned char
185  HighlightBitmap[8] =
186  {
187  (unsigned char) 0xaa,
188  (unsigned char) 0x55,
189  (unsigned char) 0xaa,
190  (unsigned char) 0x55,
191  (unsigned char) 0xaa,
192  (unsigned char) 0x55,
193  (unsigned char) 0xaa,
194  (unsigned char) 0x55
195  },
196  ShadowBitmap[8] =
197  {
198  (unsigned char) 0x00,
199  (unsigned char) 0x00,
200  (unsigned char) 0x00,
201  (unsigned char) 0x00,
202  (unsigned char) 0x00,
203  (unsigned char) 0x00,
204  (unsigned char) 0x00,
205  (unsigned char) 0x00
206  };
207 
208 /*
209  Enumeration declarations.
210 */
211 typedef enum
212 {
213  OpenCommand,
214  SaveCommand,
215  PlayCommand,
216  StepCommand,
217  RepeatCommand,
218  AutoReverseCommand,
219  SlowerCommand,
220  FasterCommand,
221  ForwardCommand,
222  ReverseCommand,
223  HelpCommand,
224  BrowseDocumentationCommand,
225  VersionCommand,
226  InfoCommand,
227  QuitCommand,
228  StepBackwardCommand,
229  StepForwardCommand,
230  NullCommand
231 } CommandType;
232 
233 /*
234  Stipples.
235 */
236 #define HighlightWidth 8
237 #define HighlightHeight 8
238 #define ShadowWidth 8
239 #define ShadowHeight 8
240 
241 /*
242  Forward declarations.
243 */
244 static Image
245  *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
247 
248 static MagickBooleanType
249  XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
250 
251 /*
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % %
254 % %
255 % %
256 % A n i m a t e I m a g e s %
257 % %
258 % %
259 % %
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 %
262 % AnimateImages() repeatedly displays an image sequence to any X window
263 % screen. It returns a value other than 0 if successful. Check the
264 % exception member of image to determine the reason for any failure.
265 %
266 % The format of the AnimateImages method is:
267 %
268 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
269 % Image *images,ExceptionInfo *exception)
270 %
271 % A description of each parameter follows:
272 %
273 % o image_info: the image info.
274 %
275 % o image: the image.
276 %
277 % o exception: return any errors or warnings in this structure.
278 %
279 */
281  Image *images,ExceptionInfo *exception)
282 {
283  char
284  *argv[1];
285 
286  Display
287  *display;
288 
290  status;
291 
292  XrmDatabase
293  resource_database;
294 
295  XResourceInfo
297 
298  assert(image_info != (const ImageInfo *) NULL);
299  assert(image_info->signature == MagickCoreSignature);
300  assert(images != (Image *) NULL);
301  assert(images->signature == MagickCoreSignature);
302  if (images->debug != MagickFalse)
303  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
304  display=XOpenDisplay(image_info->server_name);
305  if (display == (Display *) NULL)
306  {
308  "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
309  return(MagickFalse);
310  }
311  if (exception->severity != UndefinedException)
312  CatchException(exception);
313  (void) XSetErrorHandler(XError);
314  resource_database=XGetResourceDatabase(display,GetClientName());
315  (void) memset(&resource_info,0,sizeof(XResourceInfo));
316  XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
317  if (image_info->page != (char *) NULL)
318  resource_info.image_geometry=AcquireString(image_info->page);
319  resource_info.immutable=MagickTrue;
320  argv[0]=AcquireString(GetClientName());
321  (void) XAnimateImages(display,&resource_info,argv,1,images,exception);
322  (void) SetErrorHandler((ErrorHandler) NULL);
323  (void) SetWarningHandler((WarningHandler) NULL);
324  argv[0]=DestroyString(argv[0]);
325  (void) XCloseDisplay(display);
326  XDestroyResourceInfo(&resource_info);
327  status=exception->severity == UndefinedException ? MagickTrue : MagickFalse;
328  return(status != 0 ? MagickTrue : MagickFalse);
329 }
330 
331 /*
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 % %
334 % %
335 % %
336 + X M a g i c k C o m m a n d %
337 % %
338 % %
339 % %
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 %
342 % XMagickCommand() makes a transform to the image or Image window as specified
343 % by a user menu button or keyboard command.
344 %
345 % The format of the XMagickCommand method is:
346 %
347 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
348 % XWindows *windows,const CommandType command_type,Image **image,
349 % MagickStatusType *state,ExceptionInfo *exception)
350 %
351 % A description of each parameter follows:
352 %
353 % o display: Specifies a connection to an X server; returned from
354 % XOpenDisplay.
355 %
356 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
357 %
358 % o windows: Specifies a pointer to a XWindows structure.
359 %
360 % o image: the image; XMagickCommand
361 % may transform the image and return a new image pointer.
362 %
363 % o state: Specifies a MagickStatusType; XMagickCommand may return a
364 % modified state.
365 %
366 % o exception: return any errors or warnings in this structure.
367 %
368 %
369 */
370 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
371  XWindows *windows,const CommandType command_type,Image **image,
372  MagickStatusType *state,ExceptionInfo *exception)
373 {
374  Image
375  *nexus;
376 
378  proceed;
379 
381  status;
382 
383  XTextProperty
384  window_name;
385 
386  /*
387  Process user command.
388  */
389  nexus=NewImageList();
390  switch (command_type)
391  {
392  case OpenCommand:
393  {
394  char
395  **filelist;
396 
397  Image
398  *images,
399  *next;
400 
401  ImageInfo
402  *read_info;
403 
404  int
405  number_files;
406 
407  register int
408  i;
409 
410  static char
411  filenames[MagickPathExtent] = "*";
412 
413  if (resource_info->immutable != MagickFalse)
414  break;
415  /*
416  Request file name from user.
417  */
418  XFileBrowserWidget(display,windows,"Animate",filenames);
419  if (*filenames == '\0')
420  return((Image *) NULL);
421  /*
422  Expand the filenames.
423  */
424  filelist=(char **) AcquireMagickMemory(sizeof(char *));
425  if (filelist == (char **) NULL)
426  {
427  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
428  filenames);
429  return((Image *) NULL);
430  }
431  number_files=1;
432  filelist[0]=filenames;
433  status=ExpandFilenames(&number_files,&filelist);
434  if ((status == MagickFalse) || (number_files == 0))
435  {
436  for (i=0; i < number_files; i++)
437  filelist[i]=DestroyString(filelist[i]);
438  filelist=(char **) RelinquishMagickMemory(filelist);
439  if (number_files == 0)
440  {
441  ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
442  return((Image *) NULL);
443  }
444  ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
445  filenames);
446  return((Image *) NULL);
447  }
448  read_info=CloneImageInfo(resource_info->image_info);
449  images=NewImageList();
450  XSetCursorState(display,windows,MagickTrue);
451  XCheckRefreshWindows(display,windows);
452  for (i=0; i < number_files; i++)
453  {
454  (void) CopyMagickString(read_info->filename,filelist[i],MagickPathExtent);
455  filelist[i]=DestroyString(filelist[i]);
456  *read_info->magick='\0';
457  next=ReadImage(read_info,exception);
458  CatchException(exception);
459  if (next != (Image *) NULL)
460  AppendImageToList(&images,next);
461  if (number_files <= 5)
462  continue;
463  proceed=SetImageProgress(images,LoadImageTag,i,(MagickSizeType)
464  number_files);
465  if (proceed == MagickFalse)
466  break;
467  }
468  filelist=(char **) RelinquishMagickMemory(filelist);
469  read_info=DestroyImageInfo(read_info);
470  if (images == (Image *) NULL)
471  {
472  XSetCursorState(display,windows,MagickFalse);
473  ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
474  return((Image *) NULL);
475  }
476  nexus=GetFirstImageInList(images);
477  *state|=ExitState;
478  break;
479  }
480  case PlayCommand:
481  {
482  char
483  basename[MagickPathExtent];
484 
485  int
486  status;
487 
488  /*
489  Window name is the base of the filename.
490  */
491  *state|=PlayAnimationState;
492  *state&=(~AutoReverseAnimationState);
493  GetPathComponent((*image)->magick_filename,BasePath,basename);
494  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
495  "%s: %s",MagickPackageName,basename);
496  if (resource_info->title != (char *) NULL)
497  {
498  char
499  *title;
500 
501  title=InterpretImageProperties(resource_info->image_info,*image,
502  resource_info->title,exception);
503  (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
504  title=DestroyString(title);
505  }
506  status=XStringListToTextProperty(&windows->image.name,1,&window_name);
507  if (status == 0)
508  break;
509  XSetWMName(display,windows->image.id,&window_name);
510  (void) XFree((void *) window_name.value);
511  break;
512  }
513  case StepCommand:
514  case StepBackwardCommand:
515  case StepForwardCommand:
516  {
517  *state|=StepAnimationState;
518  *state&=(~PlayAnimationState);
519  if (command_type == StepBackwardCommand)
520  *state&=(~ForwardAnimationState);
521  if (command_type == StepForwardCommand)
522  *state|=ForwardAnimationState;
523  if (resource_info->title != (char *) NULL)
524  break;
525  break;
526  }
527  case RepeatCommand:
528  {
529  *state|=RepeatAnimationState;
530  *state&=(~AutoReverseAnimationState);
531  *state|=PlayAnimationState;
532  break;
533  }
534  case AutoReverseCommand:
535  {
536  *state|=AutoReverseAnimationState;
537  *state&=(~RepeatAnimationState);
538  *state|=PlayAnimationState;
539  break;
540  }
541  case SaveCommand:
542  {
543  /*
544  Save image.
545  */
546  status=XSaveImage(display,resource_info,windows,*image,exception);
547  if (status == MagickFalse)
548  {
549  char
550  message[MagickPathExtent];
551 
552  (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
553  exception->reason != (char *) NULL ? exception->reason : "",
554  exception->description != (char *) NULL ? exception->description :
555  "");
556  XNoticeWidget(display,windows,"Unable to save file:",message);
557  break;
558  }
559  break;
560  }
561  case SlowerCommand:
562  {
563  resource_info->delay++;
564  break;
565  }
566  case FasterCommand:
567  {
568  if (resource_info->delay == 0)
569  break;
570  resource_info->delay--;
571  break;
572  }
573  case ForwardCommand:
574  {
575  *state=ForwardAnimationState;
576  *state&=(~AutoReverseAnimationState);
577  break;
578  }
579  case ReverseCommand:
580  {
581  *state&=(~ForwardAnimationState);
582  *state&=(~AutoReverseAnimationState);
583  break;
584  }
585  case InfoCommand:
586  {
587  XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image,
588  exception);
589  break;
590  }
591  case HelpCommand:
592  {
593  /*
594  User requested help.
595  */
596  XTextViewHelp(display,resource_info,windows,MagickFalse,
597  "Help Viewer - Animate",AnimateHelp);
598  break;
599  }
600  case BrowseDocumentationCommand:
601  {
602  Atom
603  mozilla_atom;
604 
605  Window
606  mozilla_window,
607  root_window;
608 
609  /*
610  Browse the ImageMagick documentation.
611  */
612  root_window=XRootWindow(display,XDefaultScreen(display));
613  mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
614  mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
615  if (mozilla_window != (Window) NULL)
616  {
617  char
618  command[MagickPathExtent],
619  *url;
620 
621  /*
622  Display documentation using Netscape remote control.
623  */
624  url=GetMagickHomeURL();
625  (void) FormatLocaleString(command,MagickPathExtent,
626  "openurl(%s,new-tab)",url);
627  url=DestroyString(url);
628  mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
629  (void) XChangeProperty(display,mozilla_window,mozilla_atom,
630  XA_STRING,8,PropModeReplace,(unsigned char *) command,
631  (int) strlen(command));
632  XSetCursorState(display,windows,MagickFalse);
633  break;
634  }
635  XSetCursorState(display,windows,MagickTrue);
636  XCheckRefreshWindows(display,windows);
637  status=InvokeDelegate(resource_info->image_info,*image,"browse",
638  (char *) NULL,exception);
639  if (status == MagickFalse)
640  XNoticeWidget(display,windows,"Unable to browse documentation",
641  (char *) NULL);
642  XDelay(display,1500);
643  XSetCursorState(display,windows,MagickFalse);
644  break;
645  }
646  case VersionCommand:
647  {
648  XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
650  break;
651  }
652  case QuitCommand:
653  {
654  /*
655  exit program
656  */
657  if (resource_info->confirm_exit == MagickFalse)
658  XClientMessage(display,windows->image.id,windows->im_protocols,
659  windows->im_exit,CurrentTime);
660  else
661  {
662  int
663  status;
664 
665  /*
666  Confirm program exit.
667  */
668  status=XConfirmWidget(display,windows,"Do you really want to exit",
669  resource_info->client_name);
670  if (status != 0)
671  XClientMessage(display,windows->image.id,windows->im_protocols,
672  windows->im_exit,CurrentTime);
673  }
674  break;
675  }
676  default:
677  break;
678  }
679  return(nexus);
680 }
681 
682 /*
683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 % %
685 % %
686 % %
687 + X A n i m a t e B a c k g r o u n d I m a g e %
688 % %
689 % %
690 % %
691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692 %
693 % XAnimateBackgroundImage() animates an image sequence in the background of
694 % a window.
695 %
696 % The format of the XAnimateBackgroundImage method is:
697 %
698 % void XAnimateBackgroundImage(Display *display,
699 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
700 %
701 % A description of each parameter follows:
702 %
703 % o display: Specifies a connection to an X server; returned from
704 % XOpenDisplay.
705 %
706 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
707 %
708 % o images: the image list.
709 %
710 % o exception: return any errors or warnings in this structure.
711 %
712 */
713 
714 #if defined(__cplusplus) || defined(c_plusplus)
715 extern "C" {
716 #endif
717 
718 static int SceneCompare(const void *x,const void *y)
719 {
720  const Image
721  **image_1,
722  **image_2;
723 
724  image_1=(const Image **) x;
725  image_2=(const Image **) y;
726  return((int) ((*image_1)->scene-(*image_2)->scene));
727 }
728 
729 #if defined(__cplusplus) || defined(c_plusplus)
730 }
731 #endif
732 
733 MagickExport void XAnimateBackgroundImage(Display *display,
734  XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
735 {
736  char
737  geometry[MagickPathExtent],
738  visual_type[MagickPathExtent];
739 
740  Image
741  *coalesce_image,
742  *display_image,
743  **image_list;
744 
745  int
746  scene;
747 
749  status;
750 
752  geometry_info;
753 
754  register ssize_t
755  i;
756 
757  size_t
758  delay,
759  number_scenes;
760 
761  ssize_t
762  iterations;
763 
764  static XPixelInfo
765  pixel;
766 
767  static XStandardColormap
768  *map_info;
769 
770  static XVisualInfo
771  *visual_info = (XVisualInfo *) NULL;
772 
773  static XWindowInfo
774  window_info;
775 
776  unsigned int
777  height,
778  width;
779 
780  Window
781  root_window;
782 
783  XEvent
784  event;
785 
786  XGCValues
787  context_values;
788 
789  XResourceInfo
790  resources;
791 
792  XWindowAttributes
793  window_attributes;
794 
795  /*
796  Determine target window.
797  */
798  assert(images != (Image *) NULL);
799  assert(images->signature == MagickCoreSignature);
800  if (images->debug != MagickFalse)
801  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
802  resources=(*resource_info);
803  window_info.id=(Window) NULL;
804  root_window=XRootWindow(display,XDefaultScreen(display));
805  if (LocaleCompare(resources.window_id,"root") == 0)
806  window_info.id=root_window;
807  else
808  {
809  if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
810  window_info.id=XWindowByID(display,root_window,
811  (Window) strtol((char *) resources.window_id,(char **) NULL,0));
812  if (window_info.id == (Window) NULL)
813  window_info.id=
814  XWindowByName(display,root_window,resources.window_id);
815  }
816  if (window_info.id == (Window) NULL)
817  {
818  ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
819  resources.window_id);
820  return;
821  }
822  /*
823  Determine window visual id.
824  */
825  window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
826  window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
827  (void) CopyMagickString(visual_type,"default",MagickPathExtent);
828  status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
830  if (status != MagickFalse)
831  (void) FormatLocaleString(visual_type,MagickPathExtent,"0x%lx",
832  XVisualIDFromVisual(window_attributes.visual));
833  if (visual_info == (XVisualInfo *) NULL)
834  {
835  /*
836  Allocate standard colormap.
837  */
838  map_info=XAllocStandardColormap();
839  if (map_info == (XStandardColormap *) NULL)
840  ThrowXWindowFatalException(ResourceLimitFatalError,
841  "MemoryAllocationFailed",images->filename);
842  map_info->colormap=(Colormap) NULL;
843  pixel.pixels=(unsigned long *) NULL;
844  /*
845  Initialize visual info.
846  */
847  resources.map_type=(char *) NULL;
848  resources.visual_type=visual_type;
849  visual_info=XBestVisualInfo(display,map_info,&resources);
850  if (visual_info == (XVisualInfo *) NULL)
851  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
852  images->filename);
853  /*
854  Initialize window info.
855  */
856  window_info.ximage=(XImage *) NULL;
857  window_info.matte_image=(XImage *) NULL;
858  window_info.pixmap=(Pixmap) NULL;
859  window_info.matte_pixmap=(Pixmap) NULL;
860  }
861  /*
862  Free previous root colors.
863  */
864  if (window_info.id == root_window)
865  XDestroyWindowColors(display,root_window);
866  coalesce_image=CoalesceImages(images,exception);
867  if (coalesce_image == (Image *) NULL)
868  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
869  images->filename);
870  images=coalesce_image;
871  if (resources.map_type == (char *) NULL)
872  if ((visual_info->klass != TrueColor) &&
873  (visual_info->klass != DirectColor))
874  {
875  Image
876  *next;
877 
878  /*
879  Determine if the sequence of images has the identical colormap.
880  */
881  for (next=images; next != (Image *) NULL; )
882  {
884  if ((next->storage_class == DirectClass) ||
885  (next->colors != images->colors) ||
886  (next->colors > (size_t) visual_info->colormap_size))
887  break;
888  for (i=0; i < (ssize_t) images->colors; i++)
889  if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
890  break;
891  if (i < (ssize_t) images->colors)
892  break;
893  next=GetNextImageInList(next);
894  }
895  if (next != (Image *) NULL)
896  (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
897  exception);
898  }
899  /*
900  Sort images by increasing scene number.
901  */
902  number_scenes=GetImageListLength(images);
903  image_list=ImageListToArray(images,exception);
904  if (image_list == (Image **) NULL)
905  ThrowXWindowFatalException(ResourceLimitFatalError,
906  "MemoryAllocationFailed",images->filename);
907  for (i=0; i < (ssize_t) number_scenes; i++)
908  if (image_list[i]->scene == 0)
909  break;
910  if (i == (ssize_t) number_scenes)
911  qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
912  /*
913  Initialize Standard Colormap.
914  */
915  resources.colormap=SharedColormap;
916  display_image=image_list[0];
917  for (scene=0; scene < (int) number_scenes; scene++)
918  {
919  if ((resource_info->map_type != (char *) NULL) ||
920  (visual_info->klass == TrueColor) ||
921  (visual_info->klass == DirectColor))
922  (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
924  if ((display_image->columns < image_list[scene]->columns) &&
925  (display_image->rows < image_list[scene]->rows))
926  display_image=image_list[scene];
927  }
928  if ((resource_info->map_type != (char *) NULL) ||
929  (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
930  (void) SetImageType(display_image,display_image->alpha_trait !=
931  BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
932  XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
933  &pixel,exception);
934  /*
935  Graphic context superclass.
936  */
937  context_values.background=pixel.background_color.pixel;
938  context_values.foreground=pixel.foreground_color.pixel;
939  pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
940  (GCBackground | GCForeground),&context_values);
941  if (pixel.annotate_context == (GC) NULL)
942  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
943  images->filename);
944  /*
945  Initialize Image window attributes.
946  */
947  XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
948  &resources,&window_info);
949  /*
950  Create the X image.
951  */
952  window_info.width=(unsigned int) image_list[0]->columns;
953  window_info.height=(unsigned int) image_list[0]->rows;
954  if ((image_list[0]->columns != window_info.width) ||
955  (image_list[0]->rows != window_info.height))
956  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
957  image_list[0]->filename);
958  (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>",
959  window_attributes.width,window_attributes.height);
960  geometry_info.width=window_info.width;
961  geometry_info.height=window_info.height;
962  geometry_info.x=(ssize_t) window_info.x;
963  geometry_info.y=(ssize_t) window_info.y;
964  (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
965  &geometry_info.width,&geometry_info.height);
966  window_info.width=(unsigned int) geometry_info.width;
967  window_info.height=(unsigned int) geometry_info.height;
968  window_info.x=(int) geometry_info.x;
969  window_info.y=(int) geometry_info.y;
970  status=XMakeImage(display,&resources,&window_info,image_list[0],
971  window_info.width,window_info.height,exception);
972  if (status == MagickFalse)
973  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
974  images->filename);
975  window_info.x=0;
976  window_info.y=0;
977  if (display_image->debug != MagickFalse)
978  {
980  "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
981  image_list[0]->scene,(double) image_list[0]->columns,(double)
982  image_list[0]->rows);
983  if (image_list[0]->colors != 0)
984  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
985  image_list[0]->colors);
987  image_list[0]->magick);
988  }
989  /*
990  Adjust image dimensions as specified by backdrop or geometry options.
991  */
992  width=window_info.width;
993  height=window_info.height;
994  if (resources.backdrop != MagickFalse)
995  {
996  /*
997  Center image on window.
998  */
999  window_info.x=(int) (window_attributes.width/2)-
1000  (window_info.ximage->width/2);
1001  window_info.y=(int) (window_attributes.height/2)-
1002  (window_info.ximage->height/2);
1003  width=(unsigned int) window_attributes.width;
1004  height=(unsigned int) window_attributes.height;
1005  }
1006  if (resources.image_geometry != (char *) NULL)
1007  {
1008  char
1009  default_geometry[MagickPathExtent];
1010 
1011  int
1012  flags,
1013  gravity;
1014 
1015  XSizeHints
1016  *size_hints;
1017 
1018  /*
1019  User specified geometry.
1020  */
1021  size_hints=XAllocSizeHints();
1022  if (size_hints == (XSizeHints *) NULL)
1023  ThrowXWindowFatalException(ResourceLimitFatalError,
1024  "MemoryAllocationFailed",images->filename);
1025  size_hints->flags=0L;
1026  (void) FormatLocaleString(default_geometry,MagickPathExtent,"%ux%u",width,
1027  height);
1028  flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1029  default_geometry,window_info.border_width,size_hints,&window_info.x,
1030  &window_info.y,(int *) &width,(int *) &height,&gravity);
1031  if (((flags & (XValue | YValue))) != 0)
1032  {
1033  width=(unsigned int) window_attributes.width;
1034  height=(unsigned int) window_attributes.height;
1035  }
1036  (void) XFree((void *) size_hints);
1037  }
1038  /*
1039  Create the X pixmap.
1040  */
1041  window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1042  (unsigned int) height,window_info.depth);
1043  if (window_info.pixmap == (Pixmap) NULL)
1044  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1045  images->filename);
1046  /*
1047  Display pixmap on the window.
1048  */
1049  if (((unsigned int) width > window_info.width) ||
1050  ((unsigned int) height > window_info.height))
1051  (void) XFillRectangle(display,window_info.pixmap,
1052  window_info.annotate_context,0,0,(unsigned int) width,
1053  (unsigned int) height);
1054  (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1055  window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1056  window_info.height);
1057  (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1058  (void) XClearWindow(display,window_info.id);
1059  /*
1060  Initialize image pixmaps structure.
1061  */
1062  window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1063  sizeof(*window_info.pixmaps));
1064  window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1065  sizeof(*window_info.matte_pixmaps));
1066  if ((window_info.pixmaps == (Pixmap *) NULL) ||
1067  (window_info.matte_pixmaps == (Pixmap *) NULL))
1068  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1069  images->filename);
1070  window_info.pixmaps[0]=window_info.pixmap;
1071  window_info.matte_pixmaps[0]=window_info.pixmap;
1072  for (scene=1; scene < (int) number_scenes; scene++)
1073  {
1074  unsigned int
1075  columns,
1076  rows;
1077 
1078  /*
1079  Create X image.
1080  */
1081  window_info.pixmap=(Pixmap) NULL;
1082  window_info.matte_pixmap=(Pixmap) NULL;
1083  if ((resources.map_type != (char *) NULL) ||
1084  (visual_info->klass == TrueColor) ||
1085  (visual_info->klass == DirectColor))
1086  if (image_list[scene]->storage_class == PseudoClass)
1087  XGetPixelInfo(display,visual_info,map_info,&resources,
1088  image_list[scene],window_info.pixel_info);
1089  columns=(unsigned int) image_list[scene]->columns;
1090  rows=(unsigned int) image_list[scene]->rows;
1091  if ((image_list[scene]->columns != columns) ||
1092  (image_list[scene]->rows != rows))
1093  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1094  image_list[scene]->filename);
1095  status=XMakeImage(display,&resources,&window_info,image_list[scene],
1096  columns,rows,exception);
1097  if (status == MagickFalse)
1098  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1099  images->filename);
1100  if (display_image->debug != MagickFalse)
1101  {
1103  "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1104  image_list[scene]->filename,(double) columns,(double) rows);
1105  if (image_list[scene]->colors != 0)
1106  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1107  image_list[scene]->colors);
1108  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1109  image_list[scene]->magick);
1110  }
1111  /*
1112  Create the X pixmap.
1113  */
1114  window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1115  window_info.depth);
1116  if (window_info.pixmap == (Pixmap) NULL)
1117  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1118  images->filename);
1119  /*
1120  Display pixmap on the window.
1121  */
1122  if ((width > window_info.width) || (height > window_info.height))
1123  (void) XFillRectangle(display,window_info.pixmap,
1124  window_info.annotate_context,0,0,width,height);
1125  (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1126  window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1127  window_info.height);
1128  (void) XSetWindowBackgroundPixmap(display,window_info.id,
1129  window_info.pixmap);
1130  (void) XClearWindow(display,window_info.id);
1131  window_info.pixmaps[scene]=window_info.pixmap;
1132  window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1133  if (image_list[scene]->alpha_trait)
1134  (void) XClearWindow(display,window_info.id);
1135  delay=1000*image_list[scene]->delay/MagickMax(
1136  image_list[scene]->ticks_per_second,1L);
1137  XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1138  }
1139  window_info.pixel_info=(&pixel);
1140  /*
1141  Display pixmap on the window.
1142  */
1143  (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1144  event.type=Expose;
1145  iterations=0;
1146  do
1147  {
1148  for (scene=0; scene < (int) number_scenes; scene++)
1149  {
1150  if (XEventsQueued(display,QueuedAfterFlush) > 0)
1151  {
1152  (void) XNextEvent(display,&event);
1153  if (event.type == DestroyNotify)
1154  break;
1155  }
1156  window_info.pixmap=window_info.pixmaps[scene];
1157  window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1158  (void) XSetWindowBackgroundPixmap(display,window_info.id,
1159  window_info.pixmap);
1160  (void) XClearWindow(display,window_info.id);
1161  (void) XSync(display,MagickFalse);
1162  delay=1000*image_list[scene]->delay/MagickMax(
1163  image_list[scene]->ticks_per_second,1L);
1164  XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1165  }
1166  iterations++;
1167  if (iterations == (ssize_t) image_list[0]->iterations)
1168  break;
1169  } while (event.type != DestroyNotify);
1170  (void) XSync(display,MagickFalse);
1171  image_list=(Image **) RelinquishMagickMemory(image_list);
1172  images=DestroyImageList(images);
1173 }
1174 
1175 /*
1176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1177 % %
1178 % %
1179 % %
1180 + X A n i m a t e I m a g e s %
1181 % %
1182 % %
1183 % %
1184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 %
1186 % XAnimateImages() displays an image via X11.
1187 %
1188 % The format of the XAnimateImages method is:
1189 %
1190 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1191 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1192 %
1193 % A description of each parameter follows:
1194 %
1195 % o display: Specifies a connection to an X server; returned from
1196 % XOpenDisplay.
1197 %
1198 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1199 %
1200 % o argv: Specifies the application's argument list.
1201 %
1202 % o argc: Specifies the number of arguments.
1203 %
1204 % o images: the image list.
1205 %
1206 % o exception: return any errors or warnings in this structure.
1207 %
1208 */
1209 MagickExport Image *XAnimateImages(Display *display,
1210  XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1211  ExceptionInfo *exception)
1212 {
1213 #define MagickMenus 4
1214 #define MaXWindows 8
1215 #define MagickTitle "Commands"
1216 
1217  static const char
1218  *CommandMenu[]=
1219  {
1220  "Animate",
1221  "Speed",
1222  "Direction",
1223  "Help",
1224  "Image Info",
1225  "Quit",
1226  (char *) NULL
1227  },
1228  *AnimateMenu[]=
1229  {
1230  "Open...",
1231  "Play",
1232  "Step",
1233  "Repeat",
1234  "Auto Reverse",
1235  "Save...",
1236  (char *) NULL
1237  },
1238  *SpeedMenu[]=
1239  {
1240  "Faster",
1241  "Slower",
1242  (char *) NULL
1243  },
1244  *DirectionMenu[]=
1245  {
1246  "Forward",
1247  "Reverse",
1248  (char *) NULL
1249  },
1250  *HelpMenu[]=
1251  {
1252  "Overview",
1253  "Browse Documentation",
1254  "About Animate",
1255  (char *) NULL
1256  };
1257 
1258  static const char
1259  **Menus[MagickMenus]=
1260  {
1261  AnimateMenu,
1262  SpeedMenu,
1263  DirectionMenu,
1264  HelpMenu
1265  };
1266 
1267  static const CommandType
1268  CommandMenus[]=
1269  {
1270  NullCommand,
1271  NullCommand,
1272  NullCommand,
1273  NullCommand,
1274  InfoCommand,
1275  QuitCommand
1276  },
1277  CommandTypes[]=
1278  {
1279  OpenCommand,
1280  PlayCommand,
1281  StepCommand,
1282  RepeatCommand,
1283  AutoReverseCommand,
1284  SaveCommand
1285  },
1286  SpeedCommands[]=
1287  {
1288  FasterCommand,
1289  SlowerCommand
1290  },
1291  DirectionCommands[]=
1292  {
1293  ForwardCommand,
1294  ReverseCommand
1295  },
1296  HelpCommands[]=
1297  {
1298  HelpCommand,
1299  BrowseDocumentationCommand,
1300  VersionCommand
1301  };
1302 
1303  static const CommandType
1304  *Commands[MagickMenus]=
1305  {
1306  CommandTypes,
1307  SpeedCommands,
1308  DirectionCommands,
1309  HelpCommands
1310  };
1311 
1312  char
1313  command[MagickPathExtent],
1314  *directory,
1315  geometry[MagickPathExtent],
1316  resource_name[MagickPathExtent];
1317 
1318  CommandType
1319  command_type;
1320 
1321  Image
1322  *coalesce_image,
1323  *display_image,
1324  *image,
1325  **image_list,
1326  *nexus;
1327 
1328  int
1329  status;
1330 
1331  KeySym
1332  key_symbol;
1333 
1335  context_mask,
1336  state;
1337 
1339  geometry_info;
1340 
1341  register char
1342  *p;
1343 
1344  register ssize_t
1345  i;
1346 
1347  ssize_t
1348  first_scene,
1349  iterations,
1350  scene;
1351 
1352  static char
1353  working_directory[MagickPathExtent];
1354 
1355  static size_t
1356  number_windows;
1357 
1358  static XWindowInfo
1359  *magick_windows[MaXWindows];
1360 
1361  time_t
1362  timestamp;
1363 
1364  size_t
1365  delay,
1366  number_scenes;
1367 
1370 
1371  Window
1372  root_window;
1373 
1374  XClassHint
1375  *class_hints;
1376 
1377  XEvent
1378  event;
1379 
1380  XFontStruct
1381  *font_info;
1382 
1383  XGCValues
1384  context_values;
1385 
1386  XPixelInfo
1387  *icon_pixel,
1388  *pixel;
1389 
1390  XResourceInfo
1391  *icon_resources;
1392 
1393  XStandardColormap
1394  *icon_map,
1395  *map_info;
1396 
1397  XTextProperty
1398  window_name;
1399 
1400  XVisualInfo
1401  *icon_visual,
1402  *visual_info;
1403 
1404  XWindowChanges
1405  window_changes;
1406 
1407  XWindows
1408  *windows;
1409 
1410  XWMHints
1411  *manager_hints;
1412 
1413  assert(images != (Image *) NULL);
1414  assert(images->signature == MagickCoreSignature);
1415  if (images->debug != MagickFalse)
1416  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1417  warning_handler=(WarningHandler) NULL;
1418  windows=XSetWindows((XWindows *) ~0);
1419  if (windows != (XWindows *) NULL)
1420  {
1421  int
1422  status;
1423 
1424  if (*working_directory == '\0')
1425  (void) CopyMagickString(working_directory,".",MagickPathExtent);
1426  status=chdir(working_directory);
1427  if (status == -1)
1429  "UnableToOpenFile","%s",working_directory);
1430  warning_handler=resource_info->display_warnings ?
1431  SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1432  warning_handler=resource_info->display_warnings ?
1434  }
1435  else
1436  {
1437  register Image
1438  *p;
1439 
1440  /*
1441  Initialize window structure.
1442  */
1443  for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1444  {
1445  if (p->storage_class == DirectClass)
1446  {
1447  resource_info->colors=0;
1448  break;
1449  }
1450  if (p->colors > resource_info->colors)
1451  resource_info->colors=p->colors;
1452  }
1453  windows=XSetWindows(XInitializeWindows(display,resource_info));
1454  if (windows == (XWindows *) NULL)
1455  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1456  images->filename);
1457  /*
1458  Initialize window id's.
1459  */
1460  number_windows=0;
1461  magick_windows[number_windows++]=(&windows->icon);
1462  magick_windows[number_windows++]=(&windows->backdrop);
1463  magick_windows[number_windows++]=(&windows->image);
1464  magick_windows[number_windows++]=(&windows->info);
1465  magick_windows[number_windows++]=(&windows->command);
1466  magick_windows[number_windows++]=(&windows->widget);
1467  magick_windows[number_windows++]=(&windows->popup);
1468  for (i=0; i < (ssize_t) number_windows; i++)
1469  magick_windows[i]->id=(Window) NULL;
1470  }
1471  /*
1472  Initialize font info.
1473  */
1474  if (windows->font_info != (XFontStruct *) NULL)
1475  (void) XFreeFont(display,windows->font_info);
1476  windows->font_info=XBestFont(display,resource_info,MagickFalse);
1477  if (windows->font_info == (XFontStruct *) NULL)
1478  ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1479  resource_info->font);
1480  /*
1481  Initialize Standard Colormap.
1482  */
1483  map_info=windows->map_info;
1484  icon_map=windows->icon_map;
1485  visual_info=windows->visual_info;
1486  icon_visual=windows->icon_visual;
1487  pixel=windows->pixel_info;
1488  icon_pixel=windows->icon_pixel;
1489  font_info=windows->font_info;
1490  icon_resources=windows->icon_resources;
1491  class_hints=windows->class_hints;
1492  manager_hints=windows->manager_hints;
1493  root_window=XRootWindow(display,visual_info->screen);
1494  coalesce_image=CoalesceImages(images,exception);
1495  if (coalesce_image == (Image *) NULL)
1496  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1497  images->filename);
1498  images=coalesce_image;
1499  if (resource_info->map_type == (char *) NULL)
1500  if ((visual_info->klass != TrueColor) &&
1501  (visual_info->klass != DirectColor))
1502  {
1503  Image
1504  *next;
1505 
1506  /*
1507  Determine if the sequence of images has the identical colormap.
1508  */
1509  for (next=images; next != (Image *) NULL; )
1510  {
1512  if ((next->storage_class == DirectClass) ||
1513  (next->colors != images->colors) ||
1514  (next->colors > (size_t) visual_info->colormap_size))
1515  break;
1516  for (i=0; i < (ssize_t) images->colors; i++)
1517  if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1518  break;
1519  if (i < (ssize_t) images->colors)
1520  break;
1521  next=GetNextImageInList(next);
1522  }
1523  if (next != (Image *) NULL)
1524  (void) RemapImages(resource_info->quantize_info,images,
1525  (Image *) NULL,exception);
1526  }
1527  /*
1528  Sort images by increasing scene number.
1529  */
1530  number_scenes=GetImageListLength(images);
1531  image_list=ImageListToArray(images,exception);
1532  if (image_list == (Image **) NULL)
1533  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1534  images->filename);
1535  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1536  if (image_list[scene]->scene == 0)
1537  break;
1538  if (scene == (ssize_t) number_scenes)
1539  qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1540  /*
1541  Initialize Standard Colormap.
1542  */
1543  nexus=NewImageList();
1544  display_image=image_list[0];
1545  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1546  {
1547  if ((resource_info->map_type != (char *) NULL) ||
1548  (visual_info->klass == TrueColor) ||
1549  (visual_info->klass == DirectColor))
1550  (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
1551  BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
1552  if ((display_image->columns < image_list[scene]->columns) &&
1553  (display_image->rows < image_list[scene]->rows))
1554  display_image=image_list[scene];
1555  }
1556  if (display_image->debug != MagickFalse)
1557  {
1559  "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1560  display_image->scene,(double) display_image->columns,(double)
1561  display_image->rows);
1562  if (display_image->colors != 0)
1563  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1564  display_image->colors);
1565  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1566  display_image->magick);
1567  }
1568  XMakeStandardColormap(display,visual_info,resource_info,display_image,
1569  map_info,pixel,exception);
1570  /*
1571  Initialize graphic context.
1572  */
1573  windows->context.id=(Window) NULL;
1574  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1575  resource_info,&windows->context);
1576  (void) CloneString(&class_hints->res_name,resource_info->client_name);
1577  (void) CloneString(&class_hints->res_class,resource_info->client_name);
1578  class_hints->res_class[0]=(char) LocaleUppercase((int)
1579  class_hints->res_class[0]);
1580  manager_hints->flags=InputHint | StateHint;
1581  manager_hints->input=MagickFalse;
1582  manager_hints->initial_state=WithdrawnState;
1583  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1584  &windows->context);
1585  if (display_image->debug != MagickFalse)
1587  "Window id: 0x%lx (context)",windows->context.id);
1588  context_values.background=pixel->background_color.pixel;
1589  context_values.font=font_info->fid;
1590  context_values.foreground=pixel->foreground_color.pixel;
1591  context_values.graphics_exposures=MagickFalse;
1592  context_mask=(MagickStatusType)
1593  (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1594  if (pixel->annotate_context != (GC) NULL)
1595  (void) XFreeGC(display,pixel->annotate_context);
1596  pixel->annotate_context=
1597  XCreateGC(display,windows->context.id,context_mask,&context_values);
1598  if (pixel->annotate_context == (GC) NULL)
1599  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1600  images->filename);
1601  context_values.background=pixel->depth_color.pixel;
1602  if (pixel->widget_context != (GC) NULL)
1603  (void) XFreeGC(display,pixel->widget_context);
1604  pixel->widget_context=
1605  XCreateGC(display,windows->context.id,context_mask,&context_values);
1606  if (pixel->widget_context == (GC) NULL)
1607  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1608  images->filename);
1609  context_values.background=pixel->foreground_color.pixel;
1610  context_values.foreground=pixel->background_color.pixel;
1611  context_values.plane_mask=
1612  context_values.background ^ context_values.foreground;
1613  if (pixel->highlight_context != (GC) NULL)
1614  (void) XFreeGC(display,pixel->highlight_context);
1615  pixel->highlight_context=XCreateGC(display,windows->context.id,
1616  (size_t) (context_mask | GCPlaneMask),&context_values);
1617  if (pixel->highlight_context == (GC) NULL)
1618  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1619  images->filename);
1620  (void) XDestroyWindow(display,windows->context.id);
1621  /*
1622  Initialize icon window.
1623  */
1624  XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1625  icon_resources,&windows->icon);
1626  windows->icon.geometry=resource_info->icon_geometry;
1627  XBestIconSize(display,&windows->icon,display_image);
1628  windows->icon.attributes.colormap=
1629  XDefaultColormap(display,icon_visual->screen);
1630  windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1631  manager_hints->flags=InputHint | StateHint;
1632  manager_hints->input=MagickFalse;
1633  manager_hints->initial_state=IconicState;
1634  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1635  &windows->icon);
1636  if (display_image->debug != MagickFalse)
1637  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1638  windows->icon.id);
1639  /*
1640  Initialize graphic context for icon window.
1641  */
1642  if (icon_pixel->annotate_context != (GC) NULL)
1643  (void) XFreeGC(display,icon_pixel->annotate_context);
1644  context_values.background=icon_pixel->background_color.pixel;
1645  context_values.foreground=icon_pixel->foreground_color.pixel;
1646  icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1647  (size_t) (GCBackground | GCForeground),&context_values);
1648  if (icon_pixel->annotate_context == (GC) NULL)
1649  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1650  images->filename);
1651  windows->icon.annotate_context=icon_pixel->annotate_context;
1652  /*
1653  Initialize Image window.
1654  */
1655  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1656  resource_info,&windows->image);
1657  windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1658  if (resource_info->use_shared_memory == MagickFalse)
1659  windows->image.shared_memory=MagickFalse;
1660  if (resource_info->title != (char *) NULL)
1661  {
1662  char
1663  *title;
1664 
1665  title=InterpretImageProperties(resource_info->image_info,display_image,
1666  resource_info->title,exception);
1667  (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1668  (void) CopyMagickString(windows->image.icon_name,title,MagickPathExtent);
1669  title=DestroyString(title);
1670  }
1671  else
1672  {
1673  char
1674  filename[MagickPathExtent];
1675 
1676  /*
1677  Window name is the base of the filename.
1678  */
1679  GetPathComponent(display_image->magick_filename,TailPath,filename);
1680  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1681  "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1682  display_image->scene,(double) number_scenes);
1683  (void) CopyMagickString(windows->image.icon_name,filename,MagickPathExtent);
1684  }
1685  if (resource_info->immutable != MagickFalse)
1686  windows->image.immutable=MagickTrue;
1687  windows->image.shape=MagickTrue;
1688  windows->image.geometry=resource_info->image_geometry;
1689  (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
1690  XDisplayWidth(display,visual_info->screen),
1691  XDisplayHeight(display,visual_info->screen));
1692  geometry_info.width=display_image->columns;
1693  geometry_info.height=display_image->rows;
1694  geometry_info.x=0;
1695  geometry_info.y=0;
1696  (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1697  &geometry_info.width,&geometry_info.height);
1698  windows->image.width=(unsigned int) geometry_info.width;
1699  windows->image.height=(unsigned int) geometry_info.height;
1700  windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1701  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1702  KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1703  PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1704  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1705  resource_info,&windows->backdrop);
1706  if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1707  {
1708  /*
1709  Initialize backdrop window.
1710  */
1711  windows->backdrop.x=0;
1712  windows->backdrop.y=0;
1713  (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1714  windows->backdrop.flags=(size_t) (USSize | USPosition);
1715  windows->backdrop.width=(unsigned int)
1716  XDisplayWidth(display,visual_info->screen);
1717  windows->backdrop.height=(unsigned int)
1718  XDisplayHeight(display,visual_info->screen);
1719  windows->backdrop.border_width=0;
1720  windows->backdrop.immutable=MagickTrue;
1721  windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1722  ButtonReleaseMask;
1723  windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1724  StructureNotifyMask;
1725  manager_hints->flags=IconWindowHint | InputHint | StateHint;
1726  manager_hints->icon_window=windows->icon.id;
1727  manager_hints->input=MagickTrue;
1728  manager_hints->initial_state=
1729  resource_info->iconic ? IconicState : NormalState;
1730  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1731  &windows->backdrop);
1732  if (display_image->debug != MagickFalse)
1734  "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1735  (void) XMapWindow(display,windows->backdrop.id);
1736  (void) XClearWindow(display,windows->backdrop.id);
1737  if (windows->image.id != (Window) NULL)
1738  {
1739  (void) XDestroyWindow(display,windows->image.id);
1740  windows->image.id=(Window) NULL;
1741  }
1742  /*
1743  Position image in the center the backdrop.
1744  */
1745  windows->image.flags|=USPosition;
1746  windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1747  (windows->image.width/2);
1748  windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1749  (windows->image.height/2);
1750  }
1751  manager_hints->flags=IconWindowHint | InputHint | StateHint;
1752  manager_hints->icon_window=windows->icon.id;
1753  manager_hints->input=MagickTrue;
1754  manager_hints->initial_state=
1755  resource_info->iconic ? IconicState : NormalState;
1756  if (windows->group_leader.id != (Window) NULL)
1757  {
1758  /*
1759  Follow the leader.
1760  */
1761  manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1762  manager_hints->window_group=windows->group_leader.id;
1763  (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1764  if (display_image->debug != MagickFalse)
1766  "Window id: 0x%lx (group leader)",windows->group_leader.id);
1767  }
1768  XMakeWindow(display,
1769  (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1770  argv,argc,class_hints,manager_hints,&windows->image);
1771  (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1772  XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1773  if (windows->group_leader.id != (Window) NULL)
1774  (void) XSetTransientForHint(display,windows->image.id,
1775  windows->group_leader.id);
1776  if (display_image->debug != MagickFalse)
1777  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1778  windows->image.id);
1779  /*
1780  Initialize Info widget.
1781  */
1782  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1783  resource_info,&windows->info);
1784  (void) CloneString(&windows->info.name,"Info");
1785  (void) CloneString(&windows->info.icon_name,"Info");
1786  windows->info.border_width=1;
1787  windows->info.x=2;
1788  windows->info.y=2;
1789  windows->info.flags|=PPosition;
1790  windows->info.attributes.win_gravity=UnmapGravity;
1791  windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1792  StructureNotifyMask;
1793  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1794  manager_hints->input=MagickFalse;
1795  manager_hints->initial_state=NormalState;
1796  manager_hints->window_group=windows->image.id;
1797  XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1798  &windows->info);
1799  windows->info.highlight_stipple=XCreateBitmapFromData(display,
1800  windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1801  windows->info.shadow_stipple=XCreateBitmapFromData(display,
1802  windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1803  (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1804  if (windows->image.mapped)
1805  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1806  if (display_image->debug != MagickFalse)
1807  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1808  windows->info.id);
1809  /*
1810  Initialize Command widget.
1811  */
1812  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1813  resource_info,&windows->command);
1814  windows->command.data=MagickMenus;
1815  (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1816  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.command",
1817  resource_info->client_name);
1818  windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1819  resource_name,"geometry",(char *) NULL);
1820  (void) CloneString(&windows->command.name,MagickTitle);
1821  windows->command.border_width=0;
1822  windows->command.flags|=PPosition;
1823  windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1824  ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1825  OwnerGrabButtonMask | StructureNotifyMask;
1826  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1827  manager_hints->input=MagickTrue;
1828  manager_hints->initial_state=NormalState;
1829  manager_hints->window_group=windows->image.id;
1830  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1831  &windows->command);
1832  windows->command.highlight_stipple=XCreateBitmapFromData(display,
1833  windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1834  HighlightHeight);
1835  windows->command.shadow_stipple=XCreateBitmapFromData(display,
1836  windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1837  (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1838  if (display_image->debug != MagickFalse)
1840  "Window id: 0x%lx (command)",windows->command.id);
1841  /*
1842  Initialize Widget window.
1843  */
1844  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1845  resource_info,&windows->widget);
1846  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.widget",
1847  resource_info->client_name);
1848  windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1849  resource_name,"geometry",(char *) NULL);
1850  windows->widget.border_width=0;
1851  windows->widget.flags|=PPosition;
1852  windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1853  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1854  KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1855  StructureNotifyMask;
1856  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1857  manager_hints->input=MagickTrue;
1858  manager_hints->initial_state=NormalState;
1859  manager_hints->window_group=windows->image.id;
1860  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1861  &windows->widget);
1862  windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1863  windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1864  windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1865  windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1866  (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1867  if (display_image->debug != MagickFalse)
1869  "Window id: 0x%lx (widget)",windows->widget.id);
1870  /*
1871  Initialize popup window.
1872  */
1873  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1874  resource_info,&windows->popup);
1875  windows->popup.border_width=0;
1876  windows->popup.flags|=PPosition;
1877  windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1878  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1879  KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1880  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1881  manager_hints->input=MagickTrue;
1882  manager_hints->initial_state=NormalState;
1883  manager_hints->window_group=windows->image.id;
1884  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1885  &windows->popup);
1886  windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1887  windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1888  windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1889  windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1890  (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1891  if (display_image->debug != MagickFalse)
1893  "Window id: 0x%lx (pop up)",windows->popup.id);
1894  /*
1895  Set out progress and warning handlers.
1896  */
1897  if (warning_handler == (WarningHandler) NULL)
1898  {
1899  warning_handler=resource_info->display_warnings ?
1900  SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1901  warning_handler=resource_info->display_warnings ?
1903  }
1904  /*
1905  Initialize X image structure.
1906  */
1907  windows->image.x=0;
1908  windows->image.y=0;
1909  /*
1910  Initialize image pixmaps structure.
1911  */
1912  window_changes.width=(int) windows->image.width;
1913  window_changes.height=(int) windows->image.height;
1914  (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1915  (unsigned int) (CWWidth | CWHeight),&window_changes);
1916  windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1917  sizeof(*windows->image.pixmaps));
1918  windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1919  sizeof(*windows->image.pixmaps));
1920  if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1921  (windows->image.matte_pixmaps == (Pixmap *) NULL))
1922  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1923  images->filename);
1924  if ((windows->image.mapped == MagickFalse) ||
1925  (windows->backdrop.id != (Window) NULL))
1926  (void) XMapWindow(display,windows->image.id);
1927  XSetCursorState(display,windows,MagickTrue);
1928  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1929  {
1930  unsigned int
1931  columns,
1932  rows;
1933 
1934  /*
1935  Create X image.
1936  */
1937  windows->image.pixmap=(Pixmap) NULL;
1938  windows->image.matte_pixmap=(Pixmap) NULL;
1939  if ((resource_info->map_type != (char *) NULL) ||
1940  (visual_info->klass == TrueColor) ||
1941  (visual_info->klass == DirectColor))
1942  if (image_list[scene]->storage_class == PseudoClass)
1943  XGetPixelInfo(display,visual_info,map_info,resource_info,
1944  image_list[scene],windows->image.pixel_info);
1945  columns=(unsigned int) image_list[scene]->columns;
1946  rows=(unsigned int) image_list[scene]->rows;
1947  if ((image_list[scene]->columns != columns) ||
1948  (image_list[scene]->rows != rows))
1949  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1950  image_list[scene]->filename);
1951  status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1952  columns,rows,exception);
1953  if (status == MagickFalse)
1954  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1955  images->filename);
1956  if (image_list[scene]->debug != MagickFalse)
1957  {
1959  "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1960  image_list[scene]->filename,(double) columns,(double) rows);
1961  if (image_list[scene]->colors != 0)
1962  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1963  image_list[scene]->colors);
1964  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1965  image_list[scene]->magick);
1966  }
1967  /*
1968  Window name is the base of the filename.
1969  */
1970  if (resource_info->title != (char *) NULL)
1971  {
1972  char
1973  *title;
1974 
1975  title=InterpretImageProperties(resource_info->image_info,
1976  image_list[scene],resource_info->title,exception);
1977  (void) CopyMagickString(windows->image.name,title,MagickPathExtent);
1978  title=DestroyString(title);
1979  }
1980  else
1981  {
1982  p=image_list[scene]->magick_filename+
1983  strlen(image_list[scene]->magick_filename)-1;
1984  while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1985  p--;
1986  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
1987  "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1988  (double) number_scenes);
1989  }
1990  status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1991  if (status != Success)
1992  {
1993  XSetWMName(display,windows->image.id,&window_name);
1994  (void) XFree((void *) window_name.value);
1995  }
1996  windows->image.pixmaps[scene]=windows->image.pixmap;
1997  windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
1998  if (scene == 0)
1999  {
2000  event.xexpose.x=0;
2001  event.xexpose.y=0;
2002  event.xexpose.width=(int) image_list[scene]->columns;
2003  event.xexpose.height=(int) image_list[scene]->rows;
2004  XRefreshWindow(display,&windows->image,&event);
2005  (void) XSync(display,MagickFalse);
2006  }
2007  }
2008  XSetCursorState(display,windows,MagickFalse);
2009  if (windows->command.mapped)
2010  (void) XMapRaised(display,windows->command.id);
2011  /*
2012  Respond to events.
2013  */
2014  nexus=NewImageList();
2015  scene=0;
2016  first_scene=0;
2017  iterations=0;
2018  image=image_list[0];
2019  state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2020  (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2021  &state,exception);
2022  do
2023  {
2024  if (XEventsQueued(display,QueuedAfterFlush) == 0)
2025  if ((state & PlayAnimationState) || (state & StepAnimationState))
2026  {
2028  pause;
2029 
2030  pause=MagickFalse;
2031  delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2032  XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2033  if (state & ForwardAnimationState)
2034  {
2035  /*
2036  Forward animation: increment scene number.
2037  */
2038  if (scene < ((ssize_t) number_scenes-1))
2039  scene++;
2040  else
2041  {
2042  iterations++;
2043  if (iterations == (ssize_t) image_list[0]->iterations)
2044  {
2045  iterations=0;
2046  state|=ExitState;
2047  }
2048  if ((state & AutoReverseAnimationState) != 0)
2049  {
2050  state&=(~ForwardAnimationState);
2051  scene--;
2052  }
2053  else
2054  {
2055  if ((state & RepeatAnimationState) == 0)
2056  state&=(~PlayAnimationState);
2057  scene=first_scene;
2058  pause=MagickTrue;
2059  }
2060  }
2061  }
2062  else
2063  {
2064  /*
2065  Reverse animation: decrement scene number.
2066  */
2067  if (scene > first_scene)
2068  scene--;
2069  else
2070  {
2071  iterations++;
2072  if (iterations == (ssize_t) image_list[0]->iterations)
2073  {
2074  iterations=0;
2075  state&=(~RepeatAnimationState);
2076  }
2077  if (state & AutoReverseAnimationState)
2078  {
2079  state|=ForwardAnimationState;
2080  scene=first_scene;
2081  pause=MagickTrue;
2082  }
2083  else
2084  {
2085  if ((state & RepeatAnimationState) == MagickFalse)
2086  state&=(~PlayAnimationState);
2087  scene=(ssize_t) number_scenes-1;
2088  }
2089  }
2090  }
2091  scene=MagickMax(scene,0);
2092  image=image_list[scene];
2093  if ((image != (Image *) NULL) && (image->start_loop != 0))
2094  first_scene=scene;
2095  if ((state & StepAnimationState) ||
2096  (resource_info->title != (char *) NULL))
2097  {
2098  /*
2099  Update window title.
2100  */
2101  p=image_list[scene]->filename+
2102  strlen(image_list[scene]->filename)-1;
2103  while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2104  p--;
2105  (void) FormatLocaleString(windows->image.name,MagickPathExtent,
2106  "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2107  scene+1,(double) number_scenes);
2108  if (resource_info->title != (char *) NULL)
2109  {
2110  char
2111  *title;
2112 
2113  title=InterpretImageProperties(resource_info->image_info,
2114  image,resource_info->title,exception);
2115  (void) CopyMagickString(windows->image.name,title,
2117  title=DestroyString(title);
2118  }
2119  status=XStringListToTextProperty(&windows->image.name,1,
2120  &window_name);
2121  if (status != Success)
2122  {
2123  XSetWMName(display,windows->image.id,&window_name);
2124  (void) XFree((void *) window_name.value);
2125  }
2126  }
2127  /*
2128  Copy X pixmap to Image window.
2129  */
2130  XGetPixelInfo(display,visual_info,map_info,resource_info,
2131  image_list[scene],windows->image.pixel_info);
2132  windows->image.ximage->width=(int) image->columns;
2133  windows->image.ximage->height=(int) image->rows;
2134  windows->image.pixmap=windows->image.pixmaps[scene];
2135  windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2136  event.xexpose.x=0;
2137  event.xexpose.y=0;
2138  event.xexpose.width=(int) image->columns;
2139  event.xexpose.height=(int) image->rows;
2140  if ((state & ExitState) == 0)
2141  {
2142  XRefreshWindow(display,&windows->image,&event);
2143  (void) XSync(display,MagickFalse);
2144  }
2145  state&=(~StepAnimationState);
2146  if (pause != MagickFalse)
2147  for (i=0; i < (ssize_t) resource_info->pause; i++)
2148  {
2149  int
2150  status;
2151 
2152  status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2153  &event);
2154  if (status != 0)
2155  {
2156  int
2157  length;
2158 
2159  length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2160  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2161  *(command+length)='\0';
2162  if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2163  {
2164  XClientMessage(display,windows->image.id,
2165  windows->im_protocols,windows->im_exit,CurrentTime);
2166  break;
2167  }
2168  }
2169  MagickDelay(1000);
2170  }
2171  continue;
2172  }
2173  /*
2174  Handle a window event.
2175  */
2176  timestamp=GetMagickTime();
2177  (void) XNextEvent(display,&event);
2178  if (windows->image.stasis == MagickFalse)
2179  windows->image.stasis=(GetMagickTime()-timestamp) > 0 ?
2181  if (event.xany.window == windows->command.id)
2182  {
2183  int
2184  id;
2185 
2186  /*
2187  Select a command from the Command widget.
2188  */
2189  id=XCommandWidget(display,windows,CommandMenu,&event);
2190  if (id < 0)
2191  continue;
2192  (void) CopyMagickString(command,CommandMenu[id],MagickPathExtent);
2193  command_type=CommandMenus[id];
2194  if (id < MagickMenus)
2195  {
2196  int
2197  entry;
2198 
2199  /*
2200  Select a command from a pop-up menu.
2201  */
2202  entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2203  command);
2204  if (entry < 0)
2205  continue;
2206  (void) CopyMagickString(command,Menus[id][entry],MagickPathExtent);
2207  command_type=Commands[id][entry];
2208  }
2209  if (command_type != NullCommand)
2210  nexus=XMagickCommand(display,resource_info,windows,
2211  command_type,&image,&state,exception);
2212  continue;
2213  }
2214  switch (event.type)
2215  {
2216  case ButtonPress:
2217  {
2218  if (display_image->debug != MagickFalse)
2220  "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2221  event.xbutton.button,event.xbutton.x,event.xbutton.y);
2222  if ((event.xbutton.button == Button3) &&
2223  (event.xbutton.state & Mod1Mask))
2224  {
2225  /*
2226  Convert Alt-Button3 to Button2.
2227  */
2228  event.xbutton.button=Button2;
2229  event.xbutton.state&=(~Mod1Mask);
2230  }
2231  if (event.xbutton.window == windows->backdrop.id)
2232  {
2233  (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2234  event.xbutton.time);
2235  break;
2236  }
2237  if (event.xbutton.window == windows->image.id)
2238  {
2239  if (resource_info->immutable != MagickFalse)
2240  {
2241  state|=ExitState;
2242  break;
2243  }
2244  /*
2245  Map/unmap Command widget.
2246  */
2247  if (windows->command.mapped)
2248  (void) XWithdrawWindow(display,windows->command.id,
2249  windows->command.screen);
2250  else
2251  {
2252  (void) XCommandWidget(display,windows,CommandMenu,
2253  (XEvent *) NULL);
2254  (void) XMapRaised(display,windows->command.id);
2255  }
2256  }
2257  break;
2258  }
2259  case ButtonRelease:
2260  {
2261  if (display_image->debug != MagickFalse)
2263  "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2264  event.xbutton.button,event.xbutton.x,event.xbutton.y);
2265  break;
2266  }
2267  case ClientMessage:
2268  {
2269  if (display_image->debug != MagickFalse)
2271  "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2272  event.xclient.window,(unsigned long) event.xclient.message_type,
2273  event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2274  if (event.xclient.message_type == windows->im_protocols)
2275  {
2276  if (*event.xclient.data.l == (long) windows->im_update_colormap)
2277  {
2278  /*
2279  Update graphic context and window colormap.
2280  */
2281  for (i=0; i < (ssize_t) number_windows; i++)
2282  {
2283  if (magick_windows[i]->id == windows->icon.id)
2284  continue;
2285  context_values.background=pixel->background_color.pixel;
2286  context_values.foreground=pixel->foreground_color.pixel;
2287  (void) XChangeGC(display,magick_windows[i]->annotate_context,
2288  context_mask,&context_values);
2289  (void) XChangeGC(display,magick_windows[i]->widget_context,
2290  context_mask,&context_values);
2291  context_values.background=pixel->foreground_color.pixel;
2292  context_values.foreground=pixel->background_color.pixel;
2293  context_values.plane_mask=
2294  context_values.background ^ context_values.foreground;
2295  (void) XChangeGC(display,magick_windows[i]->highlight_context,
2296  (size_t) (context_mask | GCPlaneMask),
2297  &context_values);
2298  magick_windows[i]->attributes.background_pixel=
2299  pixel->background_color.pixel;
2300  magick_windows[i]->attributes.border_pixel=
2301  pixel->border_color.pixel;
2302  magick_windows[i]->attributes.colormap=map_info->colormap;
2303  (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2304  (unsigned long) magick_windows[i]->mask,
2305  &magick_windows[i]->attributes);
2306  }
2307  if (windows->backdrop.id != (Window) NULL)
2308  (void) XInstallColormap(display,map_info->colormap);
2309  break;
2310  }
2311  if (*event.xclient.data.l == (long) windows->im_exit)
2312  {
2313  state|=ExitState;
2314  break;
2315  }
2316  break;
2317  }
2318  if (event.xclient.message_type == windows->dnd_protocols)
2319  {
2320  Atom
2321  selection,
2322  type;
2323 
2324  int
2325  format,
2326  status;
2327 
2328  unsigned char
2329  *data;
2330 
2331  unsigned long
2332  after,
2333  length;
2334 
2335  /*
2336  Display image named by the Drag-and-Drop selection.
2337  */
2338  if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2339  break;
2340  selection=XInternAtom(display,"DndSelection",MagickFalse);
2341  status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2342  MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2343  &data);
2344  if ((status != Success) || (length == 0))
2345  break;
2346  if (*event.xclient.data.l == 2)
2347  {
2348  /*
2349  Offix DND.
2350  */
2351  (void) CopyMagickString(resource_info->image_info->filename,
2352  (char *) data,MagickPathExtent);
2353  }
2354  else
2355  {
2356  /*
2357  XDND.
2358  */
2359  if (LocaleNCompare((char *) data,"file:",5) != 0)
2360  {
2361  (void) XFree((void *) data);
2362  break;
2363  }
2364  (void) CopyMagickString(resource_info->image_info->filename,
2365  ((char *) data)+5,MagickPathExtent);
2366  }
2367  nexus=ReadImage(resource_info->image_info,exception);
2368  CatchException(exception);
2369  if (nexus != (Image *) NULL)
2370  state|=ExitState;
2371  (void) XFree((void *) data);
2372  break;
2373  }
2374  /*
2375  If client window delete message, exit.
2376  */
2377  if (event.xclient.message_type != windows->wm_protocols)
2378  break;
2379  if (*event.xclient.data.l == (long) windows->wm_take_focus)
2380  {
2381  (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2382  (Time) event.xclient.data.l[1]);
2383  break;
2384  }
2385  if (*event.xclient.data.l != (long) windows->wm_delete_window)
2386  break;
2387  (void) XWithdrawWindow(display,event.xclient.window,
2388  visual_info->screen);
2389  if (event.xclient.window == windows->image.id)
2390  {
2391  state|=ExitState;
2392  break;
2393  }
2394  break;
2395  }
2396  case ConfigureNotify:
2397  {
2398  if (display_image->debug != MagickFalse)
2400  "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2401  event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2402  event.xconfigure.y,event.xconfigure.send_event);
2403  if (event.xconfigure.window == windows->image.id)
2404  {
2405  if (event.xconfigure.send_event != 0)
2406  {
2407  XWindowChanges
2408  window_changes;
2409 
2410  /*
2411  Position the transient windows relative of the Image window.
2412  */
2413  if (windows->command.geometry == (char *) NULL)
2414  if (windows->command.mapped == MagickFalse)
2415  {
2416  windows->command.x=
2417  event.xconfigure.x-windows->command.width-25;
2418  windows->command.y=event.xconfigure.y;
2419  XConstrainWindowPosition(display,&windows->command);
2420  window_changes.x=windows->command.x;
2421  window_changes.y=windows->command.y;
2422  (void) XReconfigureWMWindow(display,windows->command.id,
2423  windows->command.screen,(unsigned int) (CWX | CWY),
2424  &window_changes);
2425  }
2426  if (windows->widget.geometry == (char *) NULL)
2427  if (windows->widget.mapped == MagickFalse)
2428  {
2429  windows->widget.x=
2430  event.xconfigure.x+event.xconfigure.width/10;
2431  windows->widget.y=
2432  event.xconfigure.y+event.xconfigure.height/10;
2433  XConstrainWindowPosition(display,&windows->widget);
2434  window_changes.x=windows->widget.x;
2435  window_changes.y=windows->widget.y;
2436  (void) XReconfigureWMWindow(display,windows->widget.id,
2437  windows->widget.screen,(unsigned int) (CWX | CWY),
2438  &window_changes);
2439  }
2440  }
2441  /*
2442  Image window has a new configuration.
2443  */
2444  windows->image.width=(unsigned int) event.xconfigure.width;
2445  windows->image.height=(unsigned int) event.xconfigure.height;
2446  break;
2447  }
2448  if (event.xconfigure.window == windows->icon.id)
2449  {
2450  /*
2451  Icon window has a new configuration.
2452  */
2453  windows->icon.width=(unsigned int) event.xconfigure.width;
2454  windows->icon.height=(unsigned int) event.xconfigure.height;
2455  break;
2456  }
2457  break;
2458  }
2459  case DestroyNotify:
2460  {
2461  /*
2462  Group leader has exited.
2463  */
2464  if (display_image->debug != MagickFalse)
2466  "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2467  if (event.xdestroywindow.window == windows->group_leader.id)
2468  {
2469  state|=ExitState;
2470  break;
2471  }
2472  break;
2473  }
2474  case EnterNotify:
2475  {
2476  /*
2477  Selectively install colormap.
2478  */
2479  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2480  if (event.xcrossing.mode != NotifyUngrab)
2481  XInstallColormap(display,map_info->colormap);
2482  break;
2483  }
2484  case Expose:
2485  {
2486  if (display_image->debug != MagickFalse)
2488  "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2489  event.xexpose.width,event.xexpose.height,event.xexpose.x,
2490  event.xexpose.y);
2491  /*
2492  Repaint windows that are now exposed.
2493  */
2494  if (event.xexpose.window == windows->image.id)
2495  {
2496  windows->image.pixmap=windows->image.pixmaps[scene];
2497  windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2498  XRefreshWindow(display,&windows->image,&event);
2499  break;
2500  }
2501  if (event.xexpose.window == windows->icon.id)
2502  if (event.xexpose.count == 0)
2503  {
2504  XRefreshWindow(display,&windows->icon,&event);
2505  break;
2506  }
2507  break;
2508  }
2509  case KeyPress:
2510  {
2511  static int
2512  length;
2513 
2514  /*
2515  Respond to a user key press.
2516  */
2517  length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2518  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2519  *(command+length)='\0';
2520  if (display_image->debug != MagickFalse)
2522  "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2523  command_type=NullCommand;
2524  switch (key_symbol)
2525  {
2526  case XK_o:
2527  {
2528  if ((event.xkey.state & ControlMask) == MagickFalse)
2529  break;
2530  command_type=OpenCommand;
2531  break;
2532  }
2533  case XK_BackSpace:
2534  {
2535  command_type=StepBackwardCommand;
2536  break;
2537  }
2538  case XK_space:
2539  {
2540  command_type=StepForwardCommand;
2541  break;
2542  }
2543  case XK_less:
2544  {
2545  command_type=FasterCommand;
2546  break;
2547  }
2548  case XK_greater:
2549  {
2550  command_type=SlowerCommand;
2551  break;
2552  }
2553  case XK_F1:
2554  {
2555  command_type=HelpCommand;
2556  break;
2557  }
2558  case XK_Find:
2559  {
2560  command_type=BrowseDocumentationCommand;
2561  break;
2562  }
2563  case XK_question:
2564  {
2565  command_type=InfoCommand;
2566  break;
2567  }
2568  case XK_q:
2569  case XK_Escape:
2570  {
2571  command_type=QuitCommand;
2572  break;
2573  }
2574  default:
2575  break;
2576  }
2577  if (command_type != NullCommand)
2578  nexus=XMagickCommand(display,resource_info,windows,
2579  command_type,&image,&state,exception);
2580  break;
2581  }
2582  case KeyRelease:
2583  {
2584  /*
2585  Respond to a user key release.
2586  */
2587  (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2588  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2589  if (display_image->debug != MagickFalse)
2591  "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2592  break;
2593  }
2594  case LeaveNotify:
2595  {
2596  /*
2597  Selectively uninstall colormap.
2598  */
2599  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2600  if (event.xcrossing.mode != NotifyUngrab)
2601  XUninstallColormap(display,map_info->colormap);
2602  break;
2603  }
2604  case MapNotify:
2605  {
2606  if (display_image->debug != MagickFalse)
2607  (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2608  event.xmap.window);
2609  if (event.xmap.window == windows->backdrop.id)
2610  {
2611  (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2612  CurrentTime);
2613  windows->backdrop.mapped=MagickTrue;
2614  break;
2615  }
2616  if (event.xmap.window == windows->image.id)
2617  {
2618  if (windows->backdrop.id != (Window) NULL)
2619  (void) XInstallColormap(display,map_info->colormap);
2620  if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2621  {
2622  if (LocaleCompare(display_image->filename,"LOGO") == 0)
2623  nexus=XMagickCommand(display,resource_info,windows,
2624  OpenCommand,&image,&state,exception);
2625  else
2626  state|=ExitState;
2627  }
2628  windows->image.mapped=MagickTrue;
2629  break;
2630  }
2631  if (event.xmap.window == windows->info.id)
2632  {
2633  windows->info.mapped=MagickTrue;
2634  break;
2635  }
2636  if (event.xmap.window == windows->icon.id)
2637  {
2638  /*
2639  Create an icon image.
2640  */
2641  XMakeStandardColormap(display,icon_visual,icon_resources,
2642  display_image,icon_map,icon_pixel,exception);
2643  (void) XMakeImage(display,icon_resources,&windows->icon,
2644  display_image,windows->icon.width,windows->icon.height,
2645  exception);
2646  (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2647  windows->icon.pixmap);
2648  (void) XClearWindow(display,windows->icon.id);
2649  (void) XWithdrawWindow(display,windows->info.id,
2650  windows->info.screen);
2651  windows->icon.mapped=MagickTrue;
2652  break;
2653  }
2654  if (event.xmap.window == windows->command.id)
2655  {
2656  windows->command.mapped=MagickTrue;
2657  break;
2658  }
2659  if (event.xmap.window == windows->popup.id)
2660  {
2661  windows->popup.mapped=MagickTrue;
2662  break;
2663  }
2664  if (event.xmap.window == windows->widget.id)
2665  {
2666  windows->widget.mapped=MagickTrue;
2667  break;
2668  }
2669  break;
2670  }
2671  case MappingNotify:
2672  {
2673  (void) XRefreshKeyboardMapping(&event.xmapping);
2674  break;
2675  }
2676  case NoExpose:
2677  break;
2678  case PropertyNotify:
2679  {
2680  Atom
2681  type;
2682 
2683  int
2684  format,
2685  status;
2686 
2687  unsigned char
2688  *data;
2689 
2690  unsigned long
2691  after,
2692  length;
2693 
2694  if (display_image->debug != MagickFalse)
2696  "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2697  event.xproperty.window,(unsigned long) event.xproperty.atom,
2698  event.xproperty.state);
2699  if (event.xproperty.atom != windows->im_remote_command)
2700  break;
2701  /*
2702  Display image named by the remote command protocol.
2703  */
2704  status=XGetWindowProperty(display,event.xproperty.window,
2705  event.xproperty.atom,0L,(long) MagickPathExtent,MagickFalse,(Atom)
2706  AnyPropertyType,&type,&format,&length,&after,&data);
2707  if ((status != Success) || (length == 0))
2708  break;
2709  (void) CopyMagickString(resource_info->image_info->filename,
2710  (char *) data,MagickPathExtent);
2711  nexus=ReadImage(resource_info->image_info,exception);
2712  CatchException(exception);
2713  if (nexus != (Image *) NULL)
2714  state|=ExitState;
2715  (void) XFree((void *) data);
2716  break;
2717  }
2718  case ReparentNotify:
2719  {
2720  if (display_image->debug != MagickFalse)
2722  "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2723  event.xreparent.window);
2724  break;
2725  }
2726  case UnmapNotify:
2727  {
2728  if (display_image->debug != MagickFalse)
2730  "Unmap Notify: 0x%lx",event.xunmap.window);
2731  if (event.xunmap.window == windows->backdrop.id)
2732  {
2733  windows->backdrop.mapped=MagickFalse;
2734  break;
2735  }
2736  if (event.xunmap.window == windows->image.id)
2737  {
2738  windows->image.mapped=MagickFalse;
2739  break;
2740  }
2741  if (event.xunmap.window == windows->info.id)
2742  {
2743  windows->info.mapped=MagickFalse;
2744  break;
2745  }
2746  if (event.xunmap.window == windows->icon.id)
2747  {
2748  if (map_info->colormap == icon_map->colormap)
2749  XConfigureImageColormap(display,resource_info,windows,
2750  display_image,exception);
2751  (void) XFreeStandardColormap(display,icon_visual,icon_map,
2752  icon_pixel);
2753  windows->icon.mapped=MagickFalse;
2754  break;
2755  }
2756  if (event.xunmap.window == windows->command.id)
2757  {
2758  windows->command.mapped=MagickFalse;
2759  break;
2760  }
2761  if (event.xunmap.window == windows->popup.id)
2762  {
2763  if (windows->backdrop.id != (Window) NULL)
2764  (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2765  CurrentTime);
2766  windows->popup.mapped=MagickFalse;
2767  break;
2768  }
2769  if (event.xunmap.window == windows->widget.id)
2770  {
2771  if (windows->backdrop.id != (Window) NULL)
2772  (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2773  CurrentTime);
2774  windows->widget.mapped=MagickFalse;
2775  break;
2776  }
2777  break;
2778  }
2779  default:
2780  {
2781  if (display_image->debug != MagickFalse)
2782  (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2783  event.type);
2784  break;
2785  }
2786  }
2787  }
2788  while (!(state & ExitState));
2789  image_list=(Image **) RelinquishMagickMemory(image_list);
2790  images=DestroyImageList(images);
2791  if ((windows->visual_info->klass == GrayScale) ||
2792  (windows->visual_info->klass == PseudoColor) ||
2793  (windows->visual_info->klass == DirectColor))
2794  {
2795  /*
2796  Withdraw windows.
2797  */
2798  if (windows->info.mapped)
2799  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2800  if (windows->command.mapped)
2801  (void) XWithdrawWindow(display,windows->command.id,
2802  windows->command.screen);
2803  }
2804  if (resource_info->backdrop == MagickFalse)
2805  if (windows->backdrop.mapped)
2806  {
2807  (void) XWithdrawWindow(display,windows->backdrop.id,\
2808  windows->backdrop.screen);
2809  (void) XDestroyWindow(display,windows->backdrop.id);
2810  windows->backdrop.id=(Window) NULL;
2811  (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2812  (void) XDestroyWindow(display,windows->image.id);
2813  windows->image.id=(Window) NULL;
2814  }
2815  XSetCursorState(display,windows,MagickTrue);
2816  XCheckRefreshWindows(display,windows);
2817  for (scene=1; scene < (ssize_t) number_scenes; scene++)
2818  {
2819  if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2820  (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2821  windows->image.pixmaps[scene]=(Pixmap) NULL;
2822  if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2823  (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2824  windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2825  }
2826  XSetCursorState(display,windows,MagickFalse);
2827  windows->image.pixmaps=(Pixmap *)
2828  RelinquishMagickMemory(windows->image.pixmaps);
2829  windows->image.matte_pixmaps=(Pixmap *)
2830  RelinquishMagickMemory(windows->image.matte_pixmaps);
2831  if (nexus == (Image *) NULL)
2832  {
2833  /*
2834  Free X resources.
2835  */
2836  if (windows->image.mapped != MagickFalse)
2837  (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2838  XDelay(display,SuspendTime);
2839  (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2840  if (resource_info->map_type == (char *) NULL)
2841  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2842  DestroyXResources();
2843  }
2844  (void) XSync(display,MagickFalse);
2845  /*
2846  Restore our progress monitor and warning handlers.
2847  */
2848  (void) SetErrorHandler(warning_handler);
2849  (void) SetWarningHandler(warning_handler);
2850  /*
2851  Change to home directory.
2852  */
2853  directory=getcwd(working_directory,MagickPathExtent);
2854  (void) directory;
2855  if (*resource_info->home_directory == '\0')
2856  (void) CopyMagickString(resource_info->home_directory,".",MagickPathExtent);
2857  status=chdir(resource_info->home_directory);
2858  if (status == -1)
2860  "UnableToOpenFile","%s",resource_info->home_directory);
2861  return(nexus);
2862 }
2863 
2864 /*
2865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2866 % %
2867 % %
2868 % %
2869 + X S a v e I m a g e %
2870 % %
2871 % %
2872 % %
2873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2874 %
2875 % XSaveImage() saves an image to a file.
2876 %
2877 % The format of the XSaveImage method is:
2878 %
2879 % MagickBooleanType XSaveImage(Display *display,
2880 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2881 % ExceptionInfo *exception)
2882 %
2883 % A description of each parameter follows:
2884 %
2885 % o status: Method XSaveImage return True if the image is
2886 % written. False is returned is there is a memory shortage or if the
2887 % image fails to write.
2888 %
2889 % o display: Specifies a connection to an X server; returned from
2890 % XOpenDisplay.
2891 %
2892 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2893 %
2894 % o windows: Specifies a pointer to a XWindows structure.
2895 %
2896 % o image: the image.
2897 %
2898 */
2899 static MagickBooleanType XSaveImage(Display *display,
2900  XResourceInfo *resource_info,XWindows *windows,Image *image,
2901  ExceptionInfo *exception)
2902 {
2903  char
2904  filename[MagickPathExtent];
2905 
2906  ImageInfo
2907  *image_info;
2908 
2910  status;
2911 
2912  /*
2913  Request file name from user.
2914  */
2915  if (resource_info->write_filename != (char *) NULL)
2916  (void) CopyMagickString(filename,resource_info->write_filename,
2918  else
2919  {
2920  char
2921  path[MagickPathExtent];
2922 
2923  int
2924  status;
2925 
2926  GetPathComponent(image->filename,HeadPath,path);
2927  GetPathComponent(image->filename,TailPath,filename);
2928  if (*path == '\0')
2929  (void) CopyMagickString(path,".",MagickPathExtent);
2930  status=chdir(path);
2931  if (status == -1)
2933  "UnableToOpenFile","%s",path);
2934  }
2935  XFileBrowserWidget(display,windows,"Save",filename);
2936  if (*filename == '\0')
2937  return(MagickTrue);
2938  if (IsPathAccessible(filename) != MagickFalse)
2939  {
2940  int
2941  status;
2942 
2943  /*
2944  File exists-- seek user's permission before overwriting.
2945  */
2946  status=XConfirmWidget(display,windows,"Overwrite",filename);
2947  if (status == 0)
2948  return(MagickTrue);
2949  }
2950  image_info=CloneImageInfo(resource_info->image_info);
2951  (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
2952  (void) SetImageInfo(image_info,1,exception);
2953  if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2954  (LocaleCompare(image_info->magick,"JPG") == 0))
2955  {
2956  char
2957  quality[MagickPathExtent];
2958 
2959  int
2960  status;
2961 
2962  /*
2963  Request JPEG quality from user.
2964  */
2965  (void) FormatLocaleString(quality,MagickPathExtent,"%.20g",(double)
2966  image_info->quality);
2967  status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2968  quality);
2969  if (*quality == '\0')
2970  return(MagickTrue);
2971  image->quality=StringToUnsignedLong(quality);
2972  image_info->interlace=status != MagickFalse ? NoInterlace :
2974  }
2975  if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2976  (LocaleCompare(image_info->magick,"PDF") == 0) ||
2977  (LocaleCompare(image_info->magick,"PS") == 0) ||
2978  (LocaleCompare(image_info->magick,"PS2") == 0))
2979  {
2980  char
2981  geometry[MagickPathExtent];
2982 
2983  /*
2984  Request page geometry from user.
2985  */
2987  if (LocaleCompare(image_info->magick,"PDF") == 0)
2989  if (image_info->page != (char *) NULL)
2990  (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
2991  XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
2992  "Select page geometry:",geometry);
2993  if (*geometry != '\0')
2994  image_info->page=GetPageGeometry(geometry);
2995  }
2996  /*
2997  Write image.
2998  */
2999  image=GetFirstImageInList(image);
3000  status=WriteImages(image_info,image,filename,exception);
3001  if (status != MagickFalse)
3002  image->taint=MagickFalse;
3003  image_info=DestroyImageInfo(image_info);
3004  XSetCursorState(display,windows,MagickFalse);
3005  return(status != 0 ? MagickTrue : MagickFalse);
3006 }
3007 #else
3008 
3009 /*
3010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3011 % %
3012 % %
3013 % %
3014 + A n i m a t e I m a g e s %
3015 % %
3016 % %
3017 % %
3018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3019 %
3020 % AnimateImages() repeatedly displays an image sequence to any X window
3021 % screen. It returns a value other than 0 if successful. Check the
3022 % exception member of image to determine the reason for any failure.
3023 %
3024 % The format of the AnimateImages method is:
3025 %
3026 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3027 % Image *images)
3028 %
3029 % A description of each parameter follows:
3030 %
3031 % o image_info: the image info.
3032 %
3033 % o image: the image.
3034 %
3035 % o exception: return any errors or warnings in this structure.
3036 %
3037 */
3039  Image *image,ExceptionInfo *exception)
3040 {
3041  assert(image_info != (const ImageInfo *) NULL);
3042  assert(image_info->signature == MagickCoreSignature);
3043  (void) image_info;
3044  assert(image != (Image *) NULL);
3045  assert(image->signature == MagickCoreSignature);
3046  if (image->debug != MagickFalse)
3047  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3049  "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
3050  return(MagickFalse);
3051 }
3052 #endif
size_t rows
Definition: image.h:172
MagickExport Image * CoalesceImages(const Image *image, ExceptionInfo *exception)
Definition: layer.c:229
size_t signature
Definition: image.h:488
PixelInfo * colormap
Definition: image.h:179
char magick[MagickPathExtent]
Definition: image.h:480
size_t iterations
Definition: image.h:248
ssize_t ticks_per_second
Definition: image.h:245
static const ColormapInfo Colormap[]
Definition: color.c:104
#define XWMGeometry
Definition: vms.h:334
static unsigned long StringToUnsignedLong(const char *magick_restrict value)
#define XInternAtom
Definition: vms.h:189
Definition: log.h:56
MagickBooleanType taint
Definition: image.h:169
static ResourceInfo resource_info
Definition: resource.c:116
#define MagickPackageName
Definition: version.h:28
MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
Definition: exception.c:947
#define XDisplayName
Definition: vms.h:106
#define XChangeWindowAttributes
Definition: vms.h:60
MagickExport MagickStatusType ParseMetaGeometry(const char *geometry, ssize_t *x, ssize_t *y, size_t *width, size_t *height)
Definition: geometry.c:1368
#define XCheckTypedWindowEvent
Definition: vms.h:63
MagickExport char * GetMagickHomeURL(void)
Definition: version.c:299
#define XPutImage
Definition: vms.h:228
#define XSetTransientForHint
Definition: vms.h:292
MagickExport const char LoadImageTag[]
Definition: image.c:117
MagickExport MagickBooleanType AnimateImages(const ImageInfo *image_info, Image *image, ExceptionInfo *exception)
Definition: animate.c:3038
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:499
size_t delay
Definition: image.h:240
char magick[MagickPathExtent]
Definition: image.h:319
MagickExport char * GetPageGeometry(const char *page_geometry)
Definition: geometry.c:362
#define XFreePixmap
Definition: vms.h:150
#define XVisualIDFromVisual
Definition: vms.h:333
InterlaceType interlace
Definition: image.h:401
ClassType storage_class
Definition: image.h:154
#define XDefaultScreen
Definition: vms.h:94
size_t width
Definition: geometry.h:130
Definition: log.h:52
static MagickBooleanType IsPixelInfoEquivalent(const PixelInfo *magick_restrict p, const PixelInfo *magick_restrict q)
Definition: image.h:151
#define XSync
Definition: vms.h:315
#define XCreatePixmap
Definition: vms.h:83
#define XAllocStandardColormap
Definition: vms.h:46
#define MagickCoreSignature
MagickExport int LocaleUppercase(const int c)
Definition: locale.c:1662
MagickExport MagickBooleanType SetImageType(Image *image, const ImageType type, ExceptionInfo *exception)
Definition: attribute.c:1461
MagickExport Image * GetFirstImageInList(const Image *images)
Definition: list.c:561
#define XDisplayHeight
Definition: vms.h:105
MagickExport MagickBooleanType RemapImages(const QuantizeInfo *quantize_info, Image *images, const Image *remap_image, ExceptionInfo *exception)
Definition: quantize.c:3200
#define XSetInputFocus
Definition: vms.h:278
MagickExport void GetPathComponent(const char *path, PathType type, char *component)
Definition: utility.c:1213
static WarningHandler warning_handler
Definition: exception.c:89
MagickBooleanType
Definition: magick-type.h:158
MagickExport Image * NewImageList(void)
Definition: list.c:938
size_t scene
Definition: image.h:240
unsigned int MagickStatusType
Definition: magick-type.h:121
MagickExport char * AcquireString(const char *source)
Definition: string.c:129
#define XReconfigureWMWindow
Definition: vms.h:240
MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
Definition: exception.c:873
char * reason
Definition: exception.h:110
#define XFillRectangle
Definition: vms.h:132
#define XChangeProperty
Definition: vms.h:59
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:543
char filename[MagickPathExtent]
Definition: image.h:480
MagickExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition: locale.c:1570
#define XStringListToTextProperty
Definition: vms.h:311
MagickExport time_t GetMagickTime(void)
Definition: timer.c:326
#define XFree
Definition: vms.h:138
void(* ErrorHandler)(const ExceptionType, const char *, const char *)
Definition: exception.h:127
size_t MagickSizeType
Definition: magick-type.h:130
#define MagickPathExtent
MagickExport void MagickDelay(const MagickSizeType milliseconds)
Definition: utility.c:1702
PixelTrait alpha_trait
Definition: image.h:280
#define XSelectInput
Definition: vms.h:256
MagickExport Image * ReadImage(const ImageInfo *image_info, ExceptionInfo *exception)
Definition: constitute.c:415
MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info, const unsigned int frames, ExceptionInfo *exception)
Definition: image.c:2705
#define XClearWindow
Definition: vms.h:66
char magick_filename[MagickPathExtent]
Definition: image.h:319
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1145
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1397
MagickExport MagickBooleanType IsPathAccessible(const char *path)
Definition: utility.c:1465
MagickExport const char * GetMagickVersion(size_t *version)
Definition: version.c:589
size_t signature
Definition: image.h:354
size_t columns
Definition: image.h:172
#define XCreateBitmapFromData
Definition: vms.h:76
ssize_t x
Definition: geometry.h:134
MagickExport const char * GetMagickCopyright(void)
Definition: version.c:75
size_t height
Definition: geometry.h:130
#define XRootWindow
Definition: vms.h:249
MagickExport void CatchException(ExceptionInfo *exception)
Definition: exception.c:203
MagickExport size_t CopyMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:755
MagickExport Image * DestroyImageList(Image *images)
Definition: list.c:462
MagickExport const char * GetClientName(void)
Definition: client.c:64
static int SceneCompare(const void *x, const void *y)
Definition: montage.c:291
#define MagickMax(x, y)
Definition: image-private.h:26
#define XGetWindowAttributes
Definition: vms.h:179
size_t quality
Definition: image.h:163
size_t colors
Definition: image.h:172
#define XAllocSizeHints
Definition: vms.h:45
#define XEventsQueued
Definition: vms.h:126
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1435
char filename[MagickPathExtent]
Definition: image.h:319
#define GetMagickModule()
Definition: log.h:28
MagickExport MagickBooleanType ExpandFilenames(int *number_arguments, char ***arguments)
Definition: utility.c:735
size_t quality
Definition: image.h:410
#define XFreeFont
Definition: vms.h:144
#define XSetWindowBackgroundPixmap
Definition: vms.h:301
#define XDisplayWidth
Definition: vms.h:108
MagickExport Image ** ImageListToArray(const Image *images, ExceptionInfo *exception)
Definition: list.c:844
MagickExport char * InterpretImageProperties(ImageInfo *image_info, Image *image, const char *embed_text, ExceptionInfo *exception)
Definition: property.c:3389
MagickExport ImageInfo * DestroyImageInfo(ImageInfo *image_info)
Definition: image.c:1252
ssize_t start_loop
Definition: image.h:252
void(* WarningHandler)(const ExceptionType, const char *, const char *)
Definition: exception.h:133
#define XGetWindowProperty
Definition: vms.h:180
#define XDefaultColormap
Definition: vms.h:89
char * server_name
Definition: image.h:413
#define XSetErrorHandler
Definition: vms.h:267
MagickExport Image * GetNextImageInList(const Image *images)
Definition: list.c:771
#define XMapWindow
Definition: vms.h:210
MagickExport char * DestroyString(char *string)
Definition: string.c:823
#define XUninstallColormap
Definition: vms.h:327
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:472
#define XCloseDisplay
Definition: vms.h:68
#define XWithdrawWindow
Definition: vms.h:339
MagickExport ImageInfo * CloneImageInfo(const ImageInfo *image_info)
Definition: image.c:940
MagickExport void AppendImageToList(Image **images, const Image *append)
Definition: list.c:78
#define XDestroyWindow
Definition: vms.h:102
#define XSetWMName
Definition: vms.h:296
#define XOpenDisplay
Definition: vms.h:218
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1069
#define XFreeGC
Definition: vms.h:148
#define XChangeGC
Definition: vms.h:57
MagickExport char * CloneString(char **destination, const char *source)
Definition: string.c:286
MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, Image *image, const char *decode, const char *encode, ExceptionInfo *exception)
Definition: delegate.c:1646
#define XLookupString
Definition: vms.h:206
#define XInstallColormap
Definition: vms.h:188
#define MagickExport
ssize_t y
Definition: geometry.h:134
#define XMapRaised
Definition: vms.h:208
char * page
Definition: image.h:390
MagickExport size_t GetImageListLength(const Image *images)
Definition: list.c:696
#define XNextEvent
Definition: vms.h:215
#define XCreateGC
Definition: vms.h:80
char * description
Definition: exception.h:110
#define XRefreshKeyboardMapping
Definition: vms.h:242
MagickExport const char PSPageGeometry[]
Definition: image.c:121
MagickExport MagickBooleanType SetImageProgress(const Image *image, const char *tag, const MagickOffsetType offset, const MagickSizeType extent)
Definition: monitor.c:136
MagickBooleanType debug
Definition: image.h:334
MagickExport MagickBooleanType WriteImages(const ImageInfo *image_info, Image *images, const char *filename, ExceptionInfo *exception)
Definition: constitute.c:1291
ExceptionType severity
Definition: exception.h:104