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  name[MagickPathExtent];
485 
486  int
487  status;
488 
489  /*
490  Window name is the base of the filename.
491  */
492  *state|=PlayAnimationState;
493  *state&=(~AutoReverseAnimationState);
494  GetPathComponent((*image)->magick_filename,BasePath,basename);
495  (void) FormatLocaleString(name,MagickPathExtent,"%s: %s",
496  MagickPackageName,basename);
497  (void) CloneString(&windows->image.name,name);
498  if (resource_info->title != (char *) NULL)
499  {
500  char
501  *title;
502 
503  title=InterpretImageProperties(resource_info->image_info,*image,
504  resource_info->title,exception);
505  (void) CloneString(&windows->image.name,title);
506  title=DestroyString(title);
507  }
508  status=XStringListToTextProperty(&windows->image.name,1,&window_name);
509  if (status == 0)
510  break;
511  XSetWMName(display,windows->image.id,&window_name);
512  (void) XFree((void *) window_name.value);
513  break;
514  }
515  case StepCommand:
516  case StepBackwardCommand:
517  case StepForwardCommand:
518  {
519  *state|=StepAnimationState;
520  *state&=(~PlayAnimationState);
521  if (command_type == StepBackwardCommand)
522  *state&=(~ForwardAnimationState);
523  if (command_type == StepForwardCommand)
524  *state|=ForwardAnimationState;
525  if (resource_info->title != (char *) NULL)
526  break;
527  break;
528  }
529  case RepeatCommand:
530  {
531  *state|=RepeatAnimationState;
532  *state&=(~AutoReverseAnimationState);
533  *state|=PlayAnimationState;
534  break;
535  }
536  case AutoReverseCommand:
537  {
538  *state|=AutoReverseAnimationState;
539  *state&=(~RepeatAnimationState);
540  *state|=PlayAnimationState;
541  break;
542  }
543  case SaveCommand:
544  {
545  /*
546  Save image.
547  */
548  status=XSaveImage(display,resource_info,windows,*image,exception);
549  if (status == MagickFalse)
550  {
551  char
552  message[MagickPathExtent];
553 
554  (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",
555  exception->reason != (char *) NULL ? exception->reason : "",
556  exception->description != (char *) NULL ? exception->description :
557  "");
558  XNoticeWidget(display,windows,"Unable to save file:",message);
559  break;
560  }
561  break;
562  }
563  case SlowerCommand:
564  {
565  resource_info->delay++;
566  break;
567  }
568  case FasterCommand:
569  {
570  if (resource_info->delay == 0)
571  break;
572  resource_info->delay--;
573  break;
574  }
575  case ForwardCommand:
576  {
577  *state=ForwardAnimationState;
578  *state&=(~AutoReverseAnimationState);
579  break;
580  }
581  case ReverseCommand:
582  {
583  *state&=(~ForwardAnimationState);
584  *state&=(~AutoReverseAnimationState);
585  break;
586  }
587  case InfoCommand:
588  {
589  XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image,
590  exception);
591  break;
592  }
593  case HelpCommand:
594  {
595  /*
596  User requested help.
597  */
598  XTextViewHelp(display,resource_info,windows,MagickFalse,
599  "Help Viewer - Animate",AnimateHelp);
600  break;
601  }
602  case BrowseDocumentationCommand:
603  {
604  Atom
605  mozilla_atom;
606 
607  Window
608  mozilla_window,
609  root_window;
610 
611  /*
612  Browse the ImageMagick documentation.
613  */
614  root_window=XRootWindow(display,XDefaultScreen(display));
615  mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
616  mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
617  if (mozilla_window != (Window) NULL)
618  {
619  char
620  command[MagickPathExtent],
621  *url;
622 
623  /*
624  Display documentation using Netscape remote control.
625  */
626  url=GetMagickHomeURL();
627  (void) FormatLocaleString(command,MagickPathExtent,
628  "openurl(%s,new-tab)",url);
629  url=DestroyString(url);
630  mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
631  (void) XChangeProperty(display,mozilla_window,mozilla_atom,
632  XA_STRING,8,PropModeReplace,(unsigned char *) command,
633  (int) strlen(command));
634  XSetCursorState(display,windows,MagickFalse);
635  break;
636  }
637  XSetCursorState(display,windows,MagickTrue);
638  XCheckRefreshWindows(display,windows);
639  status=InvokeDelegate(resource_info->image_info,*image,"browse",
640  (char *) NULL,exception);
641  if (status == MagickFalse)
642  XNoticeWidget(display,windows,"Unable to browse documentation",
643  (char *) NULL);
644  XDelay(display,1500);
645  XSetCursorState(display,windows,MagickFalse);
646  break;
647  }
648  case VersionCommand:
649  {
650  XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
652  break;
653  }
654  case QuitCommand:
655  {
656  /*
657  exit program
658  */
659  if (resource_info->confirm_exit == MagickFalse)
660  XClientMessage(display,windows->image.id,windows->im_protocols,
661  windows->im_exit,CurrentTime);
662  else
663  {
664  int
665  status;
666 
667  /*
668  Confirm program exit.
669  */
670  status=XConfirmWidget(display,windows,"Do you really want to exit",
671  resource_info->client_name);
672  if (status != 0)
673  XClientMessage(display,windows->image.id,windows->im_protocols,
674  windows->im_exit,CurrentTime);
675  }
676  break;
677  }
678  default:
679  break;
680  }
681  return(nexus);
682 }
683 
684 /*
685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686 % %
687 % %
688 % %
689 + X A n i m a t e B a c k g r o u n d I m a g e %
690 % %
691 % %
692 % %
693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694 %
695 % XAnimateBackgroundImage() animates an image sequence in the background of
696 % a window.
697 %
698 % The format of the XAnimateBackgroundImage method is:
699 %
700 % void XAnimateBackgroundImage(Display *display,
701 % XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
702 %
703 % A description of each parameter follows:
704 %
705 % o display: Specifies a connection to an X server; returned from
706 % XOpenDisplay.
707 %
708 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
709 %
710 % o images: the image list.
711 %
712 % o exception: return any errors or warnings in this structure.
713 %
714 */
715 
716 #if defined(__cplusplus) || defined(c_plusplus)
717 extern "C" {
718 #endif
719 
720 static int SceneCompare(const void *x,const void *y)
721 {
722  const Image
723  **image_1,
724  **image_2;
725 
726  image_1=(const Image **) x;
727  image_2=(const Image **) y;
728  return((int) ((*image_1)->scene-(*image_2)->scene));
729 }
730 
731 #if defined(__cplusplus) || defined(c_plusplus)
732 }
733 #endif
734 
735 MagickExport void XAnimateBackgroundImage(Display *display,
736  XResourceInfo *resource_info,Image *images,ExceptionInfo *exception)
737 {
738  char
739  geometry[MagickPathExtent],
740  visual_type[MagickPathExtent];
741 
742  Image
743  *coalesce_image,
744  *display_image,
745  **image_list;
746 
747  int
748  scene;
749 
751  status;
752 
754  geometry_info;
755 
756  register ssize_t
757  i;
758 
759  size_t
760  delay,
761  number_scenes;
762 
763  ssize_t
764  iterations;
765 
766  static XPixelInfo
767  pixel;
768 
769  static XStandardColormap
770  *map_info;
771 
772  static XVisualInfo
773  *visual_info = (XVisualInfo *) NULL;
774 
775  static XWindowInfo
776  window_info;
777 
778  unsigned int
779  height,
780  width;
781 
782  Window
783  root_window;
784 
785  XEvent
786  event;
787 
788  XGCValues
789  context_values;
790 
791  XResourceInfo
792  resources;
793 
794  XWindowAttributes
795  window_attributes;
796 
797  /*
798  Determine target window.
799  */
800  assert(images != (Image *) NULL);
801  assert(images->signature == MagickCoreSignature);
802  if (images->debug != MagickFalse)
803  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
804  resources=(*resource_info);
805  window_info.id=(Window) NULL;
806  root_window=XRootWindow(display,XDefaultScreen(display));
807  if (LocaleCompare(resources.window_id,"root") == 0)
808  window_info.id=root_window;
809  else
810  {
811  if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
812  window_info.id=XWindowByID(display,root_window,
813  (Window) strtol((char *) resources.window_id,(char **) NULL,0));
814  if (window_info.id == (Window) NULL)
815  window_info.id=
816  XWindowByName(display,root_window,resources.window_id);
817  }
818  if (window_info.id == (Window) NULL)
819  {
820  ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
821  resources.window_id);
822  return;
823  }
824  /*
825  Determine window visual id.
826  */
827  window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
828  window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
829  (void) CopyMagickString(visual_type,"default",MagickPathExtent);
830  status=XGetWindowAttributes(display,window_info.id,&window_attributes) != 0 ?
832  if (status != MagickFalse)
833  (void) FormatLocaleString(visual_type,MagickPathExtent,"0x%lx",
834  XVisualIDFromVisual(window_attributes.visual));
835  if (visual_info == (XVisualInfo *) NULL)
836  {
837  /*
838  Allocate standard colormap.
839  */
840  map_info=XAllocStandardColormap();
841  if (map_info == (XStandardColormap *) NULL)
842  ThrowXWindowFatalException(ResourceLimitFatalError,
843  "MemoryAllocationFailed",images->filename);
844  map_info->colormap=(Colormap) NULL;
845  pixel.pixels=(unsigned long *) NULL;
846  /*
847  Initialize visual info.
848  */
849  resources.map_type=(char *) NULL;
850  resources.visual_type=visual_type;
851  visual_info=XBestVisualInfo(display,map_info,&resources);
852  if (visual_info == (XVisualInfo *) NULL)
853  ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
854  images->filename);
855  /*
856  Initialize window info.
857  */
858  window_info.ximage=(XImage *) NULL;
859  window_info.matte_image=(XImage *) NULL;
860  window_info.pixmap=(Pixmap) NULL;
861  window_info.matte_pixmap=(Pixmap) NULL;
862  }
863  /*
864  Free previous root colors.
865  */
866  if (window_info.id == root_window)
867  XDestroyWindowColors(display,root_window);
868  coalesce_image=CoalesceImages(images,exception);
869  if (coalesce_image == (Image *) NULL)
870  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
871  images->filename);
872  images=coalesce_image;
873  if (resources.map_type == (char *) NULL)
874  if ((visual_info->klass != TrueColor) &&
875  (visual_info->klass != DirectColor))
876  {
877  Image
878  *next;
879 
880  /*
881  Determine if the sequence of images has the identical colormap.
882  */
883  for (next=images; next != (Image *) NULL; )
884  {
886  if ((next->storage_class == DirectClass) ||
887  (next->colors != images->colors) ||
888  (next->colors > (size_t) visual_info->colormap_size))
889  break;
890  for (i=0; i < (ssize_t) images->colors; i++)
891  if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
892  break;
893  if (i < (ssize_t) images->colors)
894  break;
895  next=GetNextImageInList(next);
896  }
897  if (next != (Image *) NULL)
898  (void) RemapImages(resources.quantize_info,images,(Image *) NULL,
899  exception);
900  }
901  /*
902  Sort images by increasing scene number.
903  */
904  number_scenes=GetImageListLength(images);
905  image_list=ImageListToArray(images,exception);
906  if (image_list == (Image **) NULL)
907  ThrowXWindowFatalException(ResourceLimitFatalError,
908  "MemoryAllocationFailed",images->filename);
909  for (i=0; i < (ssize_t) number_scenes; i++)
910  if (image_list[i]->scene == 0)
911  break;
912  if (i == (ssize_t) number_scenes)
913  qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
914  /*
915  Initialize Standard Colormap.
916  */
917  resources.colormap=SharedColormap;
918  display_image=image_list[0];
919  for (scene=0; scene < (int) number_scenes; scene++)
920  {
921  if ((resource_info->map_type != (char *) NULL) ||
922  (visual_info->klass == TrueColor) ||
923  (visual_info->klass == DirectColor))
924  (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
926  if ((display_image->columns < image_list[scene]->columns) &&
927  (display_image->rows < image_list[scene]->rows))
928  display_image=image_list[scene];
929  }
930  if ((resource_info->map_type != (char *) NULL) ||
931  (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor))
932  (void) SetImageType(display_image,display_image->alpha_trait !=
933  BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
934  XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
935  &pixel,exception);
936  /*
937  Graphic context superclass.
938  */
939  context_values.background=pixel.background_color.pixel;
940  context_values.foreground=pixel.foreground_color.pixel;
941  pixel.annotate_context=XCreateGC(display,window_info.id,(unsigned long)
942  (GCBackground | GCForeground),&context_values);
943  if (pixel.annotate_context == (GC) NULL)
944  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
945  images->filename);
946  /*
947  Initialize Image window attributes.
948  */
949  XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
950  &resources,&window_info);
951  /*
952  Create the X image.
953  */
954  window_info.width=(unsigned int) image_list[0]->columns;
955  window_info.height=(unsigned int) image_list[0]->rows;
956  if ((image_list[0]->columns != window_info.width) ||
957  (image_list[0]->rows != window_info.height))
958  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
959  image_list[0]->filename);
960  (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>",
961  window_attributes.width,window_attributes.height);
962  geometry_info.width=window_info.width;
963  geometry_info.height=window_info.height;
964  geometry_info.x=(ssize_t) window_info.x;
965  geometry_info.y=(ssize_t) window_info.y;
966  (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
967  &geometry_info.width,&geometry_info.height);
968  window_info.width=(unsigned int) geometry_info.width;
969  window_info.height=(unsigned int) geometry_info.height;
970  window_info.x=(int) geometry_info.x;
971  window_info.y=(int) geometry_info.y;
972  status=XMakeImage(display,&resources,&window_info,image_list[0],
973  window_info.width,window_info.height,exception);
974  if (status == MagickFalse)
975  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
976  images->filename);
977  window_info.x=0;
978  window_info.y=0;
979  if (display_image->debug != MagickFalse)
980  {
982  "Image: %s[%.20g] %.20gx%.20g ",image_list[0]->filename,(double)
983  image_list[0]->scene,(double) image_list[0]->columns,(double)
984  image_list[0]->rows);
985  if (image_list[0]->colors != 0)
986  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
987  image_list[0]->colors);
989  image_list[0]->magick);
990  }
991  /*
992  Adjust image dimensions as specified by backdrop or geometry options.
993  */
994  width=window_info.width;
995  height=window_info.height;
996  if (resources.backdrop != MagickFalse)
997  {
998  /*
999  Center image on window.
1000  */
1001  window_info.x=(int) (window_attributes.width/2)-
1002  (window_info.ximage->width/2);
1003  window_info.y=(int) (window_attributes.height/2)-
1004  (window_info.ximage->height/2);
1005  width=(unsigned int) window_attributes.width;
1006  height=(unsigned int) window_attributes.height;
1007  }
1008  if (resources.image_geometry != (char *) NULL)
1009  {
1010  char
1011  default_geometry[MagickPathExtent];
1012 
1013  int
1014  flags,
1015  gravity;
1016 
1017  XSizeHints
1018  *size_hints;
1019 
1020  /*
1021  User specified geometry.
1022  */
1023  size_hints=XAllocSizeHints();
1024  if (size_hints == (XSizeHints *) NULL)
1025  ThrowXWindowFatalException(ResourceLimitFatalError,
1026  "MemoryAllocationFailed",images->filename);
1027  size_hints->flags=0L;
1028  (void) FormatLocaleString(default_geometry,MagickPathExtent,"%ux%u",width,
1029  height);
1030  flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
1031  default_geometry,window_info.border_width,size_hints,&window_info.x,
1032  &window_info.y,(int *) &width,(int *) &height,&gravity);
1033  if (((flags & (XValue | YValue))) != 0)
1034  {
1035  width=(unsigned int) window_attributes.width;
1036  height=(unsigned int) window_attributes.height;
1037  }
1038  (void) XFree((void *) size_hints);
1039  }
1040  /*
1041  Create the X pixmap.
1042  */
1043  window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
1044  (unsigned int) height,window_info.depth);
1045  if (window_info.pixmap == (Pixmap) NULL)
1046  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1047  images->filename);
1048  /*
1049  Display pixmap on the window.
1050  */
1051  if (((unsigned int) width > window_info.width) ||
1052  ((unsigned int) height > window_info.height))
1053  (void) XFillRectangle(display,window_info.pixmap,
1054  window_info.annotate_context,0,0,(unsigned int) width,
1055  (unsigned int) height);
1056  (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1057  window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1058  window_info.height);
1059  (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
1060  (void) XClearWindow(display,window_info.id);
1061  /*
1062  Initialize image pixmaps structure.
1063  */
1064  window_info.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1065  sizeof(*window_info.pixmaps));
1066  window_info.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1067  sizeof(*window_info.matte_pixmaps));
1068  if ((window_info.pixmaps == (Pixmap *) NULL) ||
1069  (window_info.matte_pixmaps == (Pixmap *) NULL))
1070  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1071  images->filename);
1072  window_info.pixmaps[0]=window_info.pixmap;
1073  window_info.matte_pixmaps[0]=window_info.pixmap;
1074  for (scene=1; scene < (int) number_scenes; scene++)
1075  {
1076  unsigned int
1077  columns,
1078  rows;
1079 
1080  /*
1081  Create X image.
1082  */
1083  window_info.pixmap=(Pixmap) NULL;
1084  window_info.matte_pixmap=(Pixmap) NULL;
1085  if ((resources.map_type != (char *) NULL) ||
1086  (visual_info->klass == TrueColor) ||
1087  (visual_info->klass == DirectColor))
1088  if (image_list[scene]->storage_class == PseudoClass)
1089  XGetPixelInfo(display,visual_info,map_info,&resources,
1090  image_list[scene],window_info.pixel_info);
1091  columns=(unsigned int) image_list[scene]->columns;
1092  rows=(unsigned int) image_list[scene]->rows;
1093  if ((image_list[scene]->columns != columns) ||
1094  (image_list[scene]->rows != rows))
1095  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1096  image_list[scene]->filename);
1097  status=XMakeImage(display,&resources,&window_info,image_list[scene],
1098  columns,rows,exception);
1099  if (status == MagickFalse)
1100  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1101  images->filename);
1102  if (display_image->debug != MagickFalse)
1103  {
1105  "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1106  image_list[scene]->filename,(double) columns,(double) rows);
1107  if (image_list[scene]->colors != 0)
1108  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1109  image_list[scene]->colors);
1110  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1111  image_list[scene]->magick);
1112  }
1113  /*
1114  Create the X pixmap.
1115  */
1116  window_info.pixmap=XCreatePixmap(display,window_info.id,width,height,
1117  window_info.depth);
1118  if (window_info.pixmap == (Pixmap) NULL)
1119  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
1120  images->filename);
1121  /*
1122  Display pixmap on the window.
1123  */
1124  if ((width > window_info.width) || (height > window_info.height))
1125  (void) XFillRectangle(display,window_info.pixmap,
1126  window_info.annotate_context,0,0,width,height);
1127  (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
1128  window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
1129  window_info.height);
1130  (void) XSetWindowBackgroundPixmap(display,window_info.id,
1131  window_info.pixmap);
1132  (void) XClearWindow(display,window_info.id);
1133  window_info.pixmaps[scene]=window_info.pixmap;
1134  window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
1135  if (image_list[scene]->alpha_trait)
1136  (void) XClearWindow(display,window_info.id);
1137  delay=1000*image_list[scene]->delay/MagickMax(
1138  image_list[scene]->ticks_per_second,1L);
1139  XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1140  }
1141  window_info.pixel_info=(&pixel);
1142  /*
1143  Display pixmap on the window.
1144  */
1145  (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
1146  event.type=Expose;
1147  iterations=0;
1148  do
1149  {
1150  for (scene=0; scene < (int) number_scenes; scene++)
1151  {
1152  if (XEventsQueued(display,QueuedAfterFlush) > 0)
1153  {
1154  (void) XNextEvent(display,&event);
1155  if (event.type == DestroyNotify)
1156  break;
1157  }
1158  window_info.pixmap=window_info.pixmaps[scene];
1159  window_info.matte_pixmap=window_info.matte_pixmaps[scene];
1160  (void) XSetWindowBackgroundPixmap(display,window_info.id,
1161  window_info.pixmap);
1162  (void) XClearWindow(display,window_info.id);
1163  (void) XSync(display,MagickFalse);
1164  delay=1000*image_list[scene]->delay/MagickMax(
1165  image_list[scene]->ticks_per_second,1L);
1166  XDelay(display,resources.delay*(delay == 0 ? 10 : delay));
1167  }
1168  iterations++;
1169  if (iterations == (ssize_t) image_list[0]->iterations)
1170  break;
1171  } while (event.type != DestroyNotify);
1172  (void) XSync(display,MagickFalse);
1173  image_list=(Image **) RelinquishMagickMemory(image_list);
1174  images=DestroyImageList(images);
1175 }
1176 
1177 /*
1178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1179 % %
1180 % %
1181 % %
1182 + X A n i m a t e I m a g e s %
1183 % %
1184 % %
1185 % %
1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187 %
1188 % XAnimateImages() displays an image via X11.
1189 %
1190 % The format of the XAnimateImages method is:
1191 %
1192 % Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
1193 % char **argv,const int argc,Image *images,ExceptionInfo *exception)
1194 %
1195 % A description of each parameter follows:
1196 %
1197 % o display: Specifies a connection to an X server; returned from
1198 % XOpenDisplay.
1199 %
1200 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1201 %
1202 % o argv: Specifies the application's argument list.
1203 %
1204 % o argc: Specifies the number of arguments.
1205 %
1206 % o images: the image list.
1207 %
1208 % o exception: return any errors or warnings in this structure.
1209 %
1210 */
1211 MagickExport Image *XAnimateImages(Display *display,
1212  XResourceInfo *resource_info,char **argv,const int argc,Image *images,
1213  ExceptionInfo *exception)
1214 {
1215 #define MagickMenus 4
1216 #define MaXWindows 8
1217 #define MagickTitle "Commands"
1218 
1219  const char
1220  *const CommandMenu[]=
1221  {
1222  "Animate",
1223  "Speed",
1224  "Direction",
1225  "Help",
1226  "Image Info",
1227  "Quit",
1228  (char *) NULL
1229  },
1230  *const AnimateMenu[]=
1231  {
1232  "Open...",
1233  "Play",
1234  "Step",
1235  "Repeat",
1236  "Auto Reverse",
1237  "Save...",
1238  (char *) NULL
1239  },
1240  *const SpeedMenu[]=
1241  {
1242  "Faster",
1243  "Slower",
1244  (char *) NULL
1245  },
1246  *const DirectionMenu[]=
1247  {
1248  "Forward",
1249  "Reverse",
1250  (char *) NULL
1251  },
1252  *const HelpMenu[]=
1253  {
1254  "Overview",
1255  "Browse Documentation",
1256  "About Animate",
1257  (char *) NULL
1258  };
1259 
1260  const char
1261  *const *Menus[MagickMenus]=
1262  {
1263  AnimateMenu,
1264  SpeedMenu,
1265  DirectionMenu,
1266  HelpMenu
1267  };
1268 
1269  static const CommandType
1270  CommandMenus[]=
1271  {
1272  NullCommand,
1273  NullCommand,
1274  NullCommand,
1275  NullCommand,
1276  InfoCommand,
1277  QuitCommand
1278  },
1279  CommandTypes[]=
1280  {
1281  OpenCommand,
1282  PlayCommand,
1283  StepCommand,
1284  RepeatCommand,
1285  AutoReverseCommand,
1286  SaveCommand
1287  },
1288  SpeedCommands[]=
1289  {
1290  FasterCommand,
1291  SlowerCommand
1292  },
1293  DirectionCommands[]=
1294  {
1295  ForwardCommand,
1296  ReverseCommand
1297  },
1298  HelpCommands[]=
1299  {
1300  HelpCommand,
1301  BrowseDocumentationCommand,
1302  VersionCommand
1303  };
1304 
1305  static const CommandType
1306  *Commands[MagickMenus]=
1307  {
1308  CommandTypes,
1309  SpeedCommands,
1310  DirectionCommands,
1311  HelpCommands
1312  };
1313 
1314  char
1315  command[MagickPathExtent],
1316  *directory,
1317  geometry[MagickPathExtent],
1318  resource_name[MagickPathExtent];
1319 
1320  CommandType
1321  command_type;
1322 
1323  Image
1324  *coalesce_image,
1325  *display_image,
1326  *image,
1327  **image_list,
1328  *nexus;
1329 
1330  int
1331  status;
1332 
1333  KeySym
1334  key_symbol;
1335 
1337  context_mask,
1338  state;
1339 
1341  geometry_info;
1342 
1343  register char
1344  *p;
1345 
1346  register ssize_t
1347  i;
1348 
1349  ssize_t
1350  first_scene,
1351  iterations,
1352  scene;
1353 
1354  static char
1355  working_directory[MagickPathExtent];
1356 
1357  static size_t
1358  number_windows;
1359 
1360  static XWindowInfo
1361  *magick_windows[MaXWindows];
1362 
1363  time_t
1364  timestamp;
1365 
1366  size_t
1367  delay,
1368  number_scenes;
1369 
1372 
1373  Window
1374  root_window;
1375 
1376  XClassHint
1377  *class_hints;
1378 
1379  XEvent
1380  event;
1381 
1382  XFontStruct
1383  *font_info;
1384 
1385  XGCValues
1386  context_values;
1387 
1388  XPixelInfo
1389  *icon_pixel,
1390  *pixel;
1391 
1392  XResourceInfo
1393  *icon_resources;
1394 
1395  XStandardColormap
1396  *icon_map,
1397  *map_info;
1398 
1399  XTextProperty
1400  window_name;
1401 
1402  XVisualInfo
1403  *icon_visual,
1404  *visual_info;
1405 
1406  XWindowChanges
1407  window_changes;
1408 
1409  XWindows
1410  *windows;
1411 
1412  XWMHints
1413  *manager_hints;
1414 
1415  assert(images != (Image *) NULL);
1416  assert(images->signature == MagickCoreSignature);
1417  if (images->debug != MagickFalse)
1418  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1419  warning_handler=(WarningHandler) NULL;
1420  windows=XSetWindows((XWindows *) ~0);
1421  if (windows != (XWindows *) NULL)
1422  {
1423  int
1424  status;
1425 
1426  if (*working_directory == '\0')
1427  (void) CopyMagickString(working_directory,".",MagickPathExtent);
1428  status=chdir(working_directory);
1429  if (status == -1)
1431  "UnableToOpenFile","%s",working_directory);
1432  warning_handler=resource_info->display_warnings ?
1433  SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1434  warning_handler=resource_info->display_warnings ?
1436  }
1437  else
1438  {
1439  register Image
1440  *p;
1441 
1442  /*
1443  Initialize window structure.
1444  */
1445  for (p=images; p != (Image *) NULL; p=GetNextImageInList(p))
1446  {
1447  if (p->storage_class == DirectClass)
1448  {
1449  resource_info->colors=0;
1450  break;
1451  }
1452  if (p->colors > resource_info->colors)
1453  resource_info->colors=p->colors;
1454  }
1455  windows=XSetWindows(XInitializeWindows(display,resource_info));
1456  if (windows == (XWindows *) NULL)
1457  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1458  images->filename);
1459  /*
1460  Initialize window id's.
1461  */
1462  number_windows=0;
1463  magick_windows[number_windows++]=(&windows->icon);
1464  magick_windows[number_windows++]=(&windows->backdrop);
1465  magick_windows[number_windows++]=(&windows->image);
1466  magick_windows[number_windows++]=(&windows->info);
1467  magick_windows[number_windows++]=(&windows->command);
1468  magick_windows[number_windows++]=(&windows->widget);
1469  magick_windows[number_windows++]=(&windows->popup);
1470  for (i=0; i < (ssize_t) number_windows; i++)
1471  magick_windows[i]->id=(Window) NULL;
1472  }
1473  /*
1474  Initialize font info.
1475  */
1476  if (windows->font_info != (XFontStruct *) NULL)
1477  (void) XFreeFont(display,windows->font_info);
1478  windows->font_info=XBestFont(display,resource_info,MagickFalse);
1479  if (windows->font_info == (XFontStruct *) NULL)
1480  ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
1481  resource_info->font);
1482  /*
1483  Initialize Standard Colormap.
1484  */
1485  map_info=windows->map_info;
1486  icon_map=windows->icon_map;
1487  visual_info=windows->visual_info;
1488  icon_visual=windows->icon_visual;
1489  pixel=windows->pixel_info;
1490  icon_pixel=windows->icon_pixel;
1491  font_info=windows->font_info;
1492  icon_resources=windows->icon_resources;
1493  class_hints=windows->class_hints;
1494  manager_hints=windows->manager_hints;
1495  root_window=XRootWindow(display,visual_info->screen);
1496  coalesce_image=CoalesceImages(images,exception);
1497  if (coalesce_image == (Image *) NULL)
1498  ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
1499  images->filename);
1500  images=coalesce_image;
1501  if (resource_info->map_type == (char *) NULL)
1502  if ((visual_info->klass != TrueColor) &&
1503  (visual_info->klass != DirectColor))
1504  {
1505  Image
1506  *next;
1507 
1508  /*
1509  Determine if the sequence of images has the identical colormap.
1510  */
1511  for (next=images; next != (Image *) NULL; )
1512  {
1514  if ((next->storage_class == DirectClass) ||
1515  (next->colors != images->colors) ||
1516  (next->colors > (size_t) visual_info->colormap_size))
1517  break;
1518  for (i=0; i < (ssize_t) images->colors; i++)
1519  if (IsPixelInfoEquivalent(next->colormap+i,images->colormap+i) == MagickFalse)
1520  break;
1521  if (i < (ssize_t) images->colors)
1522  break;
1523  next=GetNextImageInList(next);
1524  }
1525  if (next != (Image *) NULL)
1526  (void) RemapImages(resource_info->quantize_info,images,
1527  (Image *) NULL,exception);
1528  }
1529  /*
1530  Sort images by increasing scene number.
1531  */
1532  number_scenes=GetImageListLength(images);
1533  image_list=ImageListToArray(images,exception);
1534  if (image_list == (Image **) NULL)
1535  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1536  images->filename);
1537  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1538  if (image_list[scene]->scene == 0)
1539  break;
1540  if (scene == (ssize_t) number_scenes)
1541  qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
1542  /*
1543  Initialize Standard Colormap.
1544  */
1545  nexus=NewImageList();
1546  display_image=image_list[0];
1547  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1548  {
1549  if ((resource_info->map_type != (char *) NULL) ||
1550  (visual_info->klass == TrueColor) ||
1551  (visual_info->klass == DirectColor))
1552  (void) SetImageType(image_list[scene],image_list[scene]->alpha_trait ==
1553  BlendPixelTrait ? TrueColorType : TrueColorAlphaType,exception);
1554  if ((display_image->columns < image_list[scene]->columns) &&
1555  (display_image->rows < image_list[scene]->rows))
1556  display_image=image_list[scene];
1557  }
1558  if (display_image->debug != MagickFalse)
1559  {
1561  "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,(double)
1562  display_image->scene,(double) display_image->columns,(double)
1563  display_image->rows);
1564  if (display_image->colors != 0)
1565  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1566  display_image->colors);
1567  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1568  display_image->magick);
1569  }
1570  XMakeStandardColormap(display,visual_info,resource_info,display_image,
1571  map_info,pixel,exception);
1572  /*
1573  Initialize graphic context.
1574  */
1575  windows->context.id=(Window) NULL;
1576  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1577  resource_info,&windows->context);
1578  (void) CloneString(&class_hints->res_name,resource_info->client_name);
1579  (void) CloneString(&class_hints->res_class,resource_info->client_name);
1580  class_hints->res_class[0]=(char) LocaleUppercase((int)
1581  class_hints->res_class[0]);
1582  manager_hints->flags=InputHint | StateHint;
1583  manager_hints->input=MagickFalse;
1584  manager_hints->initial_state=WithdrawnState;
1585  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1586  &windows->context);
1587  if (display_image->debug != MagickFalse)
1589  "Window id: 0x%lx (context)",windows->context.id);
1590  context_values.background=pixel->background_color.pixel;
1591  context_values.font=font_info->fid;
1592  context_values.foreground=pixel->foreground_color.pixel;
1593  context_values.graphics_exposures=MagickFalse;
1594  context_mask=(MagickStatusType)
1595  (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
1596  if (pixel->annotate_context != (GC) NULL)
1597  (void) XFreeGC(display,pixel->annotate_context);
1598  pixel->annotate_context=
1599  XCreateGC(display,windows->context.id,context_mask,&context_values);
1600  if (pixel->annotate_context == (GC) NULL)
1601  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1602  images->filename);
1603  context_values.background=pixel->depth_color.pixel;
1604  if (pixel->widget_context != (GC) NULL)
1605  (void) XFreeGC(display,pixel->widget_context);
1606  pixel->widget_context=
1607  XCreateGC(display,windows->context.id,context_mask,&context_values);
1608  if (pixel->widget_context == (GC) NULL)
1609  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1610  images->filename);
1611  context_values.background=pixel->foreground_color.pixel;
1612  context_values.foreground=pixel->background_color.pixel;
1613  context_values.plane_mask=
1614  context_values.background ^ context_values.foreground;
1615  if (pixel->highlight_context != (GC) NULL)
1616  (void) XFreeGC(display,pixel->highlight_context);
1617  pixel->highlight_context=XCreateGC(display,windows->context.id,
1618  (size_t) (context_mask | GCPlaneMask),&context_values);
1619  if (pixel->highlight_context == (GC) NULL)
1620  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1621  images->filename);
1622  (void) XDestroyWindow(display,windows->context.id);
1623  /*
1624  Initialize icon window.
1625  */
1626  XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
1627  icon_resources,&windows->icon);
1628  windows->icon.geometry=resource_info->icon_geometry;
1629  XBestIconSize(display,&windows->icon,display_image);
1630  windows->icon.attributes.colormap=
1631  XDefaultColormap(display,icon_visual->screen);
1632  windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
1633  manager_hints->flags=InputHint | StateHint;
1634  manager_hints->input=MagickFalse;
1635  manager_hints->initial_state=IconicState;
1636  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1637  &windows->icon);
1638  if (display_image->debug != MagickFalse)
1639  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
1640  windows->icon.id);
1641  /*
1642  Initialize graphic context for icon window.
1643  */
1644  if (icon_pixel->annotate_context != (GC) NULL)
1645  (void) XFreeGC(display,icon_pixel->annotate_context);
1646  context_values.background=icon_pixel->background_color.pixel;
1647  context_values.foreground=icon_pixel->foreground_color.pixel;
1648  icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
1649  (size_t) (GCBackground | GCForeground),&context_values);
1650  if (icon_pixel->annotate_context == (GC) NULL)
1651  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
1652  images->filename);
1653  windows->icon.annotate_context=icon_pixel->annotate_context;
1654  /*
1655  Initialize Image window.
1656  */
1657  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1658  resource_info,&windows->image);
1659  windows->image.shape=MagickTrue; /* non-rectangular shape hint */
1660  if (resource_info->use_shared_memory == MagickFalse)
1661  windows->image.shared_memory=MagickFalse;
1662  if (resource_info->title != (char *) NULL)
1663  {
1664  char
1665  *title;
1666 
1667  title=InterpretImageProperties(resource_info->image_info,display_image,
1668  resource_info->title,exception);
1669  (void) CloneString(&windows->image.name,title);
1670  (void) CloneString(&windows->image.icon_name,title);
1671  title=DestroyString(title);
1672  }
1673  else
1674  {
1675  char
1676  filename[MagickPathExtent],
1677  window_name[MagickPathExtent];
1678 
1679  /*
1680  Window name is the base of the filename.
1681  */
1682  GetPathComponent(display_image->magick_filename,TailPath,filename);
1683  (void) FormatLocaleString(window_name,MagickPathExtent,
1684  "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,(double)
1685  display_image->scene,(double) number_scenes);
1686  (void) CloneString(&windows->image.name,window_name);
1687  (void) CloneString(&windows->image.icon_name,filename);
1688  }
1689  if (resource_info->immutable != MagickFalse)
1690  windows->image.immutable=MagickTrue;
1691  windows->image.shape=MagickTrue;
1692  windows->image.geometry=resource_info->image_geometry;
1693  (void) FormatLocaleString(geometry,MagickPathExtent,"%ux%u+0+0>!",
1694  XDisplayWidth(display,visual_info->screen),
1695  XDisplayHeight(display,visual_info->screen));
1696  geometry_info.width=display_image->columns;
1697  geometry_info.height=display_image->rows;
1698  geometry_info.x=0;
1699  geometry_info.y=0;
1700  (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
1701  &geometry_info.width,&geometry_info.height);
1702  windows->image.width=(unsigned int) geometry_info.width;
1703  windows->image.height=(unsigned int) geometry_info.height;
1704  windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1705  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1706  KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1707  PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
1708  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1709  resource_info,&windows->backdrop);
1710  if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
1711  {
1712  /*
1713  Initialize backdrop window.
1714  */
1715  windows->backdrop.x=0;
1716  windows->backdrop.y=0;
1717  (void) CloneString(&windows->backdrop.name,"ImageMagick Backdrop");
1718  windows->backdrop.flags=(size_t) (USSize | USPosition);
1719  windows->backdrop.width=(unsigned int)
1720  XDisplayWidth(display,visual_info->screen);
1721  windows->backdrop.height=(unsigned int)
1722  XDisplayHeight(display,visual_info->screen);
1723  windows->backdrop.border_width=0;
1724  windows->backdrop.immutable=MagickTrue;
1725  windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
1726  ButtonReleaseMask;
1727  windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
1728  StructureNotifyMask;
1729  manager_hints->flags=IconWindowHint | InputHint | StateHint;
1730  manager_hints->icon_window=windows->icon.id;
1731  manager_hints->input=MagickTrue;
1732  manager_hints->initial_state=
1733  resource_info->iconic ? IconicState : NormalState;
1734  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1735  &windows->backdrop);
1736  if (display_image->debug != MagickFalse)
1738  "Window id: 0x%lx (backdrop)",windows->backdrop.id);
1739  (void) XMapWindow(display,windows->backdrop.id);
1740  (void) XClearWindow(display,windows->backdrop.id);
1741  if (windows->image.id != (Window) NULL)
1742  {
1743  (void) XDestroyWindow(display,windows->image.id);
1744  windows->image.id=(Window) NULL;
1745  }
1746  /*
1747  Position image in the center the backdrop.
1748  */
1749  windows->image.flags|=USPosition;
1750  windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
1751  (windows->image.width/2);
1752  windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
1753  (windows->image.height/2);
1754  }
1755  manager_hints->flags=IconWindowHint | InputHint | StateHint;
1756  manager_hints->icon_window=windows->icon.id;
1757  manager_hints->input=MagickTrue;
1758  manager_hints->initial_state=
1759  resource_info->iconic ? IconicState : NormalState;
1760  if (windows->group_leader.id != (Window) NULL)
1761  {
1762  /*
1763  Follow the leader.
1764  */
1765  manager_hints->flags|=(MagickStatusType) WindowGroupHint;
1766  manager_hints->window_group=windows->group_leader.id;
1767  (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
1768  if (display_image->debug != MagickFalse)
1770  "Window id: 0x%lx (group leader)",windows->group_leader.id);
1771  }
1772  XMakeWindow(display,
1773  (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
1774  argv,argc,class_hints,manager_hints,&windows->image);
1775  (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
1776  XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
1777  if (windows->group_leader.id != (Window) NULL)
1778  (void) XSetTransientForHint(display,windows->image.id,
1779  windows->group_leader.id);
1780  if (display_image->debug != MagickFalse)
1781  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
1782  windows->image.id);
1783  /*
1784  Initialize Info widget.
1785  */
1786  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1787  resource_info,&windows->info);
1788  (void) CloneString(&windows->info.name,"Info");
1789  (void) CloneString(&windows->info.icon_name,"Info");
1790  windows->info.border_width=1;
1791  windows->info.x=2;
1792  windows->info.y=2;
1793  windows->info.flags|=PPosition;
1794  windows->info.attributes.win_gravity=UnmapGravity;
1795  windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
1796  StructureNotifyMask;
1797  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1798  manager_hints->input=MagickFalse;
1799  manager_hints->initial_state=NormalState;
1800  manager_hints->window_group=windows->image.id;
1801  XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
1802  &windows->info);
1803  windows->info.highlight_stipple=XCreateBitmapFromData(display,
1804  windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1805  windows->info.shadow_stipple=XCreateBitmapFromData(display,
1806  windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1807  (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
1808  if (windows->image.mapped)
1809  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
1810  if (display_image->debug != MagickFalse)
1811  (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
1812  windows->info.id);
1813  /*
1814  Initialize Command widget.
1815  */
1816  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1817  resource_info,&windows->command);
1818  windows->command.data=MagickMenus;
1819  (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
1820  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.command",
1821  resource_info->client_name);
1822  windows->command.geometry=XGetResourceClass(resource_info->resource_database,
1823  resource_name,"geometry",(char *) NULL);
1824  (void) CloneString(&windows->command.name,MagickTitle);
1825  windows->command.border_width=0;
1826  windows->command.flags|=PPosition;
1827  windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1828  ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
1829  OwnerGrabButtonMask | StructureNotifyMask;
1830  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1831  manager_hints->input=MagickTrue;
1832  manager_hints->initial_state=NormalState;
1833  manager_hints->window_group=windows->image.id;
1834  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1835  &windows->command);
1836  windows->command.highlight_stipple=XCreateBitmapFromData(display,
1837  windows->command.id,(char *) HighlightBitmap,HighlightWidth,
1838  HighlightHeight);
1839  windows->command.shadow_stipple=XCreateBitmapFromData(display,
1840  windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1841  (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
1842  if (display_image->debug != MagickFalse)
1844  "Window id: 0x%lx (command)",windows->command.id);
1845  /*
1846  Initialize Widget window.
1847  */
1848  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1849  resource_info,&windows->widget);
1850  (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.widget",
1851  resource_info->client_name);
1852  windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
1853  resource_name,"geometry",(char *) NULL);
1854  windows->widget.border_width=0;
1855  windows->widget.flags|=PPosition;
1856  windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1857  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1858  KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
1859  StructureNotifyMask;
1860  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1861  manager_hints->input=MagickTrue;
1862  manager_hints->initial_state=NormalState;
1863  manager_hints->window_group=windows->image.id;
1864  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1865  &windows->widget);
1866  windows->widget.highlight_stipple=XCreateBitmapFromData(display,
1867  windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1868  windows->widget.shadow_stipple=XCreateBitmapFromData(display,
1869  windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1870  (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
1871  if (display_image->debug != MagickFalse)
1873  "Window id: 0x%lx (widget)",windows->widget.id);
1874  /*
1875  Initialize popup window.
1876  */
1877  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
1878  resource_info,&windows->popup);
1879  windows->popup.border_width=0;
1880  windows->popup.flags|=PPosition;
1881  windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
1882  ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
1883  KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
1884  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
1885  manager_hints->input=MagickTrue;
1886  manager_hints->initial_state=NormalState;
1887  manager_hints->window_group=windows->image.id;
1888  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
1889  &windows->popup);
1890  windows->popup.highlight_stipple=XCreateBitmapFromData(display,
1891  windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
1892  windows->popup.shadow_stipple=XCreateBitmapFromData(display,
1893  windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
1894  (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
1895  if (display_image->debug != MagickFalse)
1897  "Window id: 0x%lx (pop up)",windows->popup.id);
1898  /*
1899  Set out progress and warning handlers.
1900  */
1901  if (warning_handler == (WarningHandler) NULL)
1902  {
1903  warning_handler=resource_info->display_warnings ?
1904  SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
1905  warning_handler=resource_info->display_warnings ?
1907  }
1908  /*
1909  Initialize X image structure.
1910  */
1911  windows->image.x=0;
1912  windows->image.y=0;
1913  /*
1914  Initialize image pixmaps structure.
1915  */
1916  window_changes.width=(int) windows->image.width;
1917  window_changes.height=(int) windows->image.height;
1918  (void) XReconfigureWMWindow(display,windows->image.id,windows->command.screen,
1919  (unsigned int) (CWWidth | CWHeight),&window_changes);
1920  windows->image.pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1921  sizeof(*windows->image.pixmaps));
1922  windows->image.matte_pixmaps=(Pixmap *) AcquireQuantumMemory(number_scenes,
1923  sizeof(*windows->image.pixmaps));
1924  if ((windows->image.pixmaps == (Pixmap *) NULL) ||
1925  (windows->image.matte_pixmaps == (Pixmap *) NULL))
1926  ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
1927  images->filename);
1928  if ((windows->image.mapped == MagickFalse) ||
1929  (windows->backdrop.id != (Window) NULL))
1930  (void) XMapWindow(display,windows->image.id);
1931  XSetCursorState(display,windows,MagickTrue);
1932  for (scene=0; scene < (ssize_t) number_scenes; scene++)
1933  {
1934  unsigned int
1935  columns,
1936  rows;
1937 
1938  /*
1939  Create X image.
1940  */
1941  windows->image.pixmap=(Pixmap) NULL;
1942  windows->image.matte_pixmap=(Pixmap) NULL;
1943  if ((resource_info->map_type != (char *) NULL) ||
1944  (visual_info->klass == TrueColor) ||
1945  (visual_info->klass == DirectColor))
1946  if (image_list[scene]->storage_class == PseudoClass)
1947  XGetPixelInfo(display,visual_info,map_info,resource_info,
1948  image_list[scene],windows->image.pixel_info);
1949  columns=(unsigned int) image_list[scene]->columns;
1950  rows=(unsigned int) image_list[scene]->rows;
1951  if ((image_list[scene]->columns != columns) ||
1952  (image_list[scene]->rows != rows))
1953  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1954  image_list[scene]->filename);
1955  status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
1956  columns,rows,exception);
1957  if (status == MagickFalse)
1958  ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
1959  images->filename);
1960  if (image_list[scene]->debug != MagickFalse)
1961  {
1963  "Image: [%.20g] %s %.20gx%.20g ",(double) image_list[scene]->scene,
1964  image_list[scene]->filename,(double) columns,(double) rows);
1965  if (image_list[scene]->colors != 0)
1966  (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
1967  image_list[scene]->colors);
1968  (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
1969  image_list[scene]->magick);
1970  }
1971  /*
1972  Window name is the base of the filename.
1973  */
1974  if (resource_info->title != (char *) NULL)
1975  {
1976  char
1977  *title;
1978 
1979  title=InterpretImageProperties(resource_info->image_info,
1980  image_list[scene],resource_info->title,exception);
1981  (void) CloneString(&windows->image.name,title);
1982  title=DestroyString(title);
1983  }
1984  else
1985  {
1986  char
1987  window_name[MaxTextExtent];
1988 
1989  p=image_list[scene]->magick_filename+
1990  strlen(image_list[scene]->magick_filename)-1;
1991  while ((p > image_list[scene]->magick_filename) && (*(p-1) != '/'))
1992  p--;
1993  (void) FormatLocaleString(window_name,MagickPathExtent,
1994  "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double) scene+1,
1995  (double) number_scenes);
1996  (void) CloneString(&windows->image.name,window_name);
1997  }
1998  status=XStringListToTextProperty(&windows->image.name,1,&window_name);
1999  if (status != Success)
2000  {
2001  XSetWMName(display,windows->image.id,&window_name);
2002  (void) XFree((void *) window_name.value);
2003  }
2004  windows->image.pixmaps[scene]=windows->image.pixmap;
2005  windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
2006  if (scene == 0)
2007  {
2008  event.xexpose.x=0;
2009  event.xexpose.y=0;
2010  event.xexpose.width=(int) image_list[scene]->columns;
2011  event.xexpose.height=(int) image_list[scene]->rows;
2012  XRefreshWindow(display,&windows->image,&event);
2013  (void) XSync(display,MagickFalse);
2014  }
2015  }
2016  XSetCursorState(display,windows,MagickFalse);
2017  if (windows->command.mapped)
2018  (void) XMapRaised(display,windows->command.id);
2019  /*
2020  Respond to events.
2021  */
2022  nexus=NewImageList();
2023  scene=0;
2024  first_scene=0;
2025  iterations=0;
2026  image=image_list[0];
2027  state=(MagickStatusType) (ForwardAnimationState | RepeatAnimationState);
2028  (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
2029  &state,exception);
2030  do
2031  {
2032  if (XEventsQueued(display,QueuedAfterFlush) == 0)
2033  if ((state & PlayAnimationState) || (state & StepAnimationState))
2034  {
2036  pause;
2037 
2038  pause=MagickFalse;
2039  delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
2040  XDelay(display,resource_info->delay*(delay == 0 ? 10 : delay));
2041  if (state & ForwardAnimationState)
2042  {
2043  /*
2044  Forward animation: increment scene number.
2045  */
2046  if (scene < ((ssize_t) number_scenes-1))
2047  scene++;
2048  else
2049  {
2050  iterations++;
2051  if (iterations == (ssize_t) image_list[0]->iterations)
2052  {
2053  iterations=0;
2054  state|=ExitState;
2055  }
2056  if ((state & AutoReverseAnimationState) != 0)
2057  {
2058  state&=(~ForwardAnimationState);
2059  scene--;
2060  }
2061  else
2062  {
2063  if ((state & RepeatAnimationState) == 0)
2064  state&=(~PlayAnimationState);
2065  scene=first_scene;
2066  pause=MagickTrue;
2067  }
2068  }
2069  }
2070  else
2071  {
2072  /*
2073  Reverse animation: decrement scene number.
2074  */
2075  if (scene > first_scene)
2076  scene--;
2077  else
2078  {
2079  iterations++;
2080  if (iterations == (ssize_t) image_list[0]->iterations)
2081  {
2082  iterations=0;
2083  state&=(~RepeatAnimationState);
2084  }
2085  if (state & AutoReverseAnimationState)
2086  {
2087  state|=ForwardAnimationState;
2088  scene=first_scene;
2089  pause=MagickTrue;
2090  }
2091  else
2092  {
2093  if ((state & RepeatAnimationState) == MagickFalse)
2094  state&=(~PlayAnimationState);
2095  scene=(ssize_t) number_scenes-1;
2096  }
2097  }
2098  }
2099  scene=MagickMax(scene,0);
2100  image=image_list[scene];
2101  if ((image != (Image *) NULL) && (image->start_loop != 0))
2102  first_scene=scene;
2103  if ((state & StepAnimationState) ||
2104  (resource_info->title != (char *) NULL))
2105  {
2106  char
2107  name[MaxTextExtent];
2108 
2109  /*
2110  Update window title.
2111  */
2112  p=image_list[scene]->filename+
2113  strlen(image_list[scene]->filename)-1;
2114  while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
2115  p--;
2117  "%s: %s[%.20g of %.20g]",MagickPackageName,p,(double)
2118  scene+1,(double) number_scenes);
2119  (void) CloneString(&windows->image.name,name);
2120  if (resource_info->title != (char *) NULL)
2121  {
2122  char
2123  *title;
2124 
2125  title=InterpretImageProperties(resource_info->image_info,
2126  image,resource_info->title,exception);
2127  (void) CloneString(&windows->image.name,title);
2128  title=DestroyString(title);
2129  }
2130  status=XStringListToTextProperty(&windows->image.name,1,
2131  &window_name);
2132  if (status != Success)
2133  {
2134  XSetWMName(display,windows->image.id,&window_name);
2135  (void) XFree((void *) window_name.value);
2136  }
2137  }
2138  /*
2139  Copy X pixmap to Image window.
2140  */
2141  XGetPixelInfo(display,visual_info,map_info,resource_info,
2142  image_list[scene],windows->image.pixel_info);
2143  windows->image.ximage->width=(int) image->columns;
2144  windows->image.ximage->height=(int) image->rows;
2145  windows->image.pixmap=windows->image.pixmaps[scene];
2146  windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2147  event.xexpose.x=0;
2148  event.xexpose.y=0;
2149  event.xexpose.width=(int) image->columns;
2150  event.xexpose.height=(int) image->rows;
2151  if ((state & ExitState) == 0)
2152  {
2153  XRefreshWindow(display,&windows->image,&event);
2154  (void) XSync(display,MagickFalse);
2155  }
2156  state&=(~StepAnimationState);
2157  if (pause != MagickFalse)
2158  for (i=0; i < (ssize_t) resource_info->pause; i++)
2159  {
2160  int
2161  status;
2162 
2163  status=XCheckTypedWindowEvent(display,windows->image.id,KeyPress,
2164  &event);
2165  if (status != 0)
2166  {
2167  int
2168  length;
2169 
2170  length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2171  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2172  *(command+length)='\0';
2173  if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
2174  {
2175  XClientMessage(display,windows->image.id,
2176  windows->im_protocols,windows->im_exit,CurrentTime);
2177  break;
2178  }
2179  }
2180  MagickDelay(1000);
2181  }
2182  continue;
2183  }
2184  /*
2185  Handle a window event.
2186  */
2187  timestamp=GetMagickTime();
2188  (void) XNextEvent(display,&event);
2189  if (windows->image.stasis == MagickFalse)
2190  windows->image.stasis=(GetMagickTime()-timestamp) > 0 ?
2192  if (event.xany.window == windows->command.id)
2193  {
2194  int
2195  id;
2196 
2197  /*
2198  Select a command from the Command widget.
2199  */
2200  id=XCommandWidget(display,windows,CommandMenu,&event);
2201  if (id < 0)
2202  continue;
2203  (void) CopyMagickString(command,CommandMenu[id],MagickPathExtent);
2204  command_type=CommandMenus[id];
2205  if (id < MagickMenus)
2206  {
2207  int
2208  entry;
2209 
2210  /*
2211  Select a command from a pop-up menu.
2212  */
2213  entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
2214  command);
2215  if (entry < 0)
2216  continue;
2217  (void) CopyMagickString(command,Menus[id][entry],MagickPathExtent);
2218  command_type=Commands[id][entry];
2219  }
2220  if (command_type != NullCommand)
2221  nexus=XMagickCommand(display,resource_info,windows,
2222  command_type,&image,&state,exception);
2223  continue;
2224  }
2225  switch (event.type)
2226  {
2227  case ButtonPress:
2228  {
2229  if (display_image->debug != MagickFalse)
2231  "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
2232  event.xbutton.button,event.xbutton.x,event.xbutton.y);
2233  if ((event.xbutton.button == Button3) &&
2234  (event.xbutton.state & Mod1Mask))
2235  {
2236  /*
2237  Convert Alt-Button3 to Button2.
2238  */
2239  event.xbutton.button=Button2;
2240  event.xbutton.state&=(~Mod1Mask);
2241  }
2242  if (event.xbutton.window == windows->backdrop.id)
2243  {
2244  (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
2245  event.xbutton.time);
2246  break;
2247  }
2248  if (event.xbutton.window == windows->image.id)
2249  {
2250  if (resource_info->immutable != MagickFalse)
2251  {
2252  state|=ExitState;
2253  break;
2254  }
2255  /*
2256  Map/unmap Command widget.
2257  */
2258  if (windows->command.mapped)
2259  (void) XWithdrawWindow(display,windows->command.id,
2260  windows->command.screen);
2261  else
2262  {
2263  (void) XCommandWidget(display,windows,CommandMenu,
2264  (XEvent *) NULL);
2265  (void) XMapRaised(display,windows->command.id);
2266  }
2267  }
2268  break;
2269  }
2270  case ButtonRelease:
2271  {
2272  if (display_image->debug != MagickFalse)
2274  "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
2275  event.xbutton.button,event.xbutton.x,event.xbutton.y);
2276  break;
2277  }
2278  case ClientMessage:
2279  {
2280  if (display_image->debug != MagickFalse)
2282  "Client Message: 0x%lx 0x%lx %d 0x%lx",(unsigned long)
2283  event.xclient.window,(unsigned long) event.xclient.message_type,
2284  event.xclient.format,(unsigned long) event.xclient.data.l[0]);
2285  if (event.xclient.message_type == windows->im_protocols)
2286  {
2287  if (*event.xclient.data.l == (long) windows->im_update_colormap)
2288  {
2289  /*
2290  Update graphic context and window colormap.
2291  */
2292  for (i=0; i < (ssize_t) number_windows; i++)
2293  {
2294  if (magick_windows[i]->id == windows->icon.id)
2295  continue;
2296  context_values.background=pixel->background_color.pixel;
2297  context_values.foreground=pixel->foreground_color.pixel;
2298  (void) XChangeGC(display,magick_windows[i]->annotate_context,
2299  context_mask,&context_values);
2300  (void) XChangeGC(display,magick_windows[i]->widget_context,
2301  context_mask,&context_values);
2302  context_values.background=pixel->foreground_color.pixel;
2303  context_values.foreground=pixel->background_color.pixel;
2304  context_values.plane_mask=
2305  context_values.background ^ context_values.foreground;
2306  (void) XChangeGC(display,magick_windows[i]->highlight_context,
2307  (size_t) (context_mask | GCPlaneMask),
2308  &context_values);
2309  magick_windows[i]->attributes.background_pixel=
2310  pixel->background_color.pixel;
2311  magick_windows[i]->attributes.border_pixel=
2312  pixel->border_color.pixel;
2313  magick_windows[i]->attributes.colormap=map_info->colormap;
2314  (void) XChangeWindowAttributes(display,magick_windows[i]->id,
2315  (unsigned long) magick_windows[i]->mask,
2316  &magick_windows[i]->attributes);
2317  }
2318  if (windows->backdrop.id != (Window) NULL)
2319  (void) XInstallColormap(display,map_info->colormap);
2320  break;
2321  }
2322  if (*event.xclient.data.l == (long) windows->im_exit)
2323  {
2324  state|=ExitState;
2325  break;
2326  }
2327  break;
2328  }
2329  if (event.xclient.message_type == windows->dnd_protocols)
2330  {
2331  Atom
2332  selection,
2333  type;
2334 
2335  int
2336  format,
2337  status;
2338 
2339  unsigned char
2340  *data;
2341 
2342  unsigned long
2343  after,
2344  length;
2345 
2346  /*
2347  Display image named by the Drag-and-Drop selection.
2348  */
2349  if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
2350  break;
2351  selection=XInternAtom(display,"DndSelection",MagickFalse);
2352  status=XGetWindowProperty(display,root_window,selection,0L,2047L,
2353  MagickFalse,(Atom) AnyPropertyType,&type,&format,&length,&after,
2354  &data);
2355  if ((status != Success) || (length == 0))
2356  break;
2357  if (*event.xclient.data.l == 2)
2358  {
2359  /*
2360  Offix DND.
2361  */
2362  (void) CopyMagickString(resource_info->image_info->filename,
2363  (char *) data,MagickPathExtent);
2364  }
2365  else
2366  {
2367  /*
2368  XDND.
2369  */
2370  if (LocaleNCompare((char *) data,"file:",5) != 0)
2371  {
2372  (void) XFree((void *) data);
2373  break;
2374  }
2375  (void) CopyMagickString(resource_info->image_info->filename,
2376  ((char *) data)+5,MagickPathExtent);
2377  }
2378  nexus=ReadImage(resource_info->image_info,exception);
2379  CatchException(exception);
2380  if (nexus != (Image *) NULL)
2381  state|=ExitState;
2382  (void) XFree((void *) data);
2383  break;
2384  }
2385  /*
2386  If client window delete message, exit.
2387  */
2388  if (event.xclient.message_type != windows->wm_protocols)
2389  break;
2390  if (*event.xclient.data.l == (long) windows->wm_take_focus)
2391  {
2392  (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
2393  (Time) event.xclient.data.l[1]);
2394  break;
2395  }
2396  if (*event.xclient.data.l != (long) windows->wm_delete_window)
2397  break;
2398  (void) XWithdrawWindow(display,event.xclient.window,
2399  visual_info->screen);
2400  if (event.xclient.window == windows->image.id)
2401  {
2402  state|=ExitState;
2403  break;
2404  }
2405  break;
2406  }
2407  case ConfigureNotify:
2408  {
2409  if (display_image->debug != MagickFalse)
2411  "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
2412  event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
2413  event.xconfigure.y,event.xconfigure.send_event);
2414  if (event.xconfigure.window == windows->image.id)
2415  {
2416  if (event.xconfigure.send_event != 0)
2417  {
2418  XWindowChanges
2419  window_changes;
2420 
2421  /*
2422  Position the transient windows relative of the Image window.
2423  */
2424  if (windows->command.geometry == (char *) NULL)
2425  if (windows->command.mapped == MagickFalse)
2426  {
2427  windows->command.x=
2428  event.xconfigure.x-windows->command.width-25;
2429  windows->command.y=event.xconfigure.y;
2430  XConstrainWindowPosition(display,&windows->command);
2431  window_changes.x=windows->command.x;
2432  window_changes.y=windows->command.y;
2433  (void) XReconfigureWMWindow(display,windows->command.id,
2434  windows->command.screen,(unsigned int) (CWX | CWY),
2435  &window_changes);
2436  }
2437  if (windows->widget.geometry == (char *) NULL)
2438  if (windows->widget.mapped == MagickFalse)
2439  {
2440  windows->widget.x=
2441  event.xconfigure.x+event.xconfigure.width/10;
2442  windows->widget.y=
2443  event.xconfigure.y+event.xconfigure.height/10;
2444  XConstrainWindowPosition(display,&windows->widget);
2445  window_changes.x=windows->widget.x;
2446  window_changes.y=windows->widget.y;
2447  (void) XReconfigureWMWindow(display,windows->widget.id,
2448  windows->widget.screen,(unsigned int) (CWX | CWY),
2449  &window_changes);
2450  }
2451  }
2452  /*
2453  Image window has a new configuration.
2454  */
2455  windows->image.width=(unsigned int) event.xconfigure.width;
2456  windows->image.height=(unsigned int) event.xconfigure.height;
2457  break;
2458  }
2459  if (event.xconfigure.window == windows->icon.id)
2460  {
2461  /*
2462  Icon window has a new configuration.
2463  */
2464  windows->icon.width=(unsigned int) event.xconfigure.width;
2465  windows->icon.height=(unsigned int) event.xconfigure.height;
2466  break;
2467  }
2468  break;
2469  }
2470  case DestroyNotify:
2471  {
2472  /*
2473  Group leader has exited.
2474  */
2475  if (display_image->debug != MagickFalse)
2477  "Destroy Notify: 0x%lx",event.xdestroywindow.window);
2478  if (event.xdestroywindow.window == windows->group_leader.id)
2479  {
2480  state|=ExitState;
2481  break;
2482  }
2483  break;
2484  }
2485  case EnterNotify:
2486  {
2487  /*
2488  Selectively install colormap.
2489  */
2490  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2491  if (event.xcrossing.mode != NotifyUngrab)
2492  XInstallColormap(display,map_info->colormap);
2493  break;
2494  }
2495  case Expose:
2496  {
2497  if (display_image->debug != MagickFalse)
2499  "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
2500  event.xexpose.width,event.xexpose.height,event.xexpose.x,
2501  event.xexpose.y);
2502  /*
2503  Repaint windows that are now exposed.
2504  */
2505  if (event.xexpose.window == windows->image.id)
2506  {
2507  windows->image.pixmap=windows->image.pixmaps[scene];
2508  windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
2509  XRefreshWindow(display,&windows->image,&event);
2510  break;
2511  }
2512  if (event.xexpose.window == windows->icon.id)
2513  if (event.xexpose.count == 0)
2514  {
2515  XRefreshWindow(display,&windows->icon,&event);
2516  break;
2517  }
2518  break;
2519  }
2520  case KeyPress:
2521  {
2522  static int
2523  length;
2524 
2525  /*
2526  Respond to a user key press.
2527  */
2528  length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2529  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2530  *(command+length)='\0';
2531  if (display_image->debug != MagickFalse)
2533  "Key press: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2534  command_type=NullCommand;
2535  switch (key_symbol)
2536  {
2537  case XK_o:
2538  {
2539  if ((event.xkey.state & ControlMask) == MagickFalse)
2540  break;
2541  command_type=OpenCommand;
2542  break;
2543  }
2544  case XK_BackSpace:
2545  {
2546  command_type=StepBackwardCommand;
2547  break;
2548  }
2549  case XK_space:
2550  {
2551  command_type=StepForwardCommand;
2552  break;
2553  }
2554  case XK_less:
2555  {
2556  command_type=FasterCommand;
2557  break;
2558  }
2559  case XK_greater:
2560  {
2561  command_type=SlowerCommand;
2562  break;
2563  }
2564  case XK_F1:
2565  {
2566  command_type=HelpCommand;
2567  break;
2568  }
2569  case XK_Find:
2570  {
2571  command_type=BrowseDocumentationCommand;
2572  break;
2573  }
2574  case XK_question:
2575  {
2576  command_type=InfoCommand;
2577  break;
2578  }
2579  case XK_q:
2580  case XK_Escape:
2581  {
2582  command_type=QuitCommand;
2583  break;
2584  }
2585  default:
2586  break;
2587  }
2588  if (command_type != NullCommand)
2589  nexus=XMagickCommand(display,resource_info,windows,
2590  command_type,&image,&state,exception);
2591  break;
2592  }
2593  case KeyRelease:
2594  {
2595  /*
2596  Respond to a user key release.
2597  */
2598  (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2599  sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2600  if (display_image->debug != MagickFalse)
2602  "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
2603  break;
2604  }
2605  case LeaveNotify:
2606  {
2607  /*
2608  Selectively uninstall colormap.
2609  */
2610  if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2611  if (event.xcrossing.mode != NotifyUngrab)
2612  XUninstallColormap(display,map_info->colormap);
2613  break;
2614  }
2615  case MapNotify:
2616  {
2617  if (display_image->debug != MagickFalse)
2618  (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
2619  event.xmap.window);
2620  if (event.xmap.window == windows->backdrop.id)
2621  {
2622  (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
2623  CurrentTime);
2624  windows->backdrop.mapped=MagickTrue;
2625  break;
2626  }
2627  if (event.xmap.window == windows->image.id)
2628  {
2629  if (windows->backdrop.id != (Window) NULL)
2630  (void) XInstallColormap(display,map_info->colormap);
2631  if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
2632  {
2633  if (LocaleCompare(display_image->filename,"LOGO") == 0)
2634  nexus=XMagickCommand(display,resource_info,windows,
2635  OpenCommand,&image,&state,exception);
2636  else
2637  state|=ExitState;
2638  }
2639  windows->image.mapped=MagickTrue;
2640  break;
2641  }
2642  if (event.xmap.window == windows->info.id)
2643  {
2644  windows->info.mapped=MagickTrue;
2645  break;
2646  }
2647  if (event.xmap.window == windows->icon.id)
2648  {
2649  /*
2650  Create an icon image.
2651  */
2652  XMakeStandardColormap(display,icon_visual,icon_resources,
2653  display_image,icon_map,icon_pixel,exception);
2654  (void) XMakeImage(display,icon_resources,&windows->icon,
2655  display_image,windows->icon.width,windows->icon.height,
2656  exception);
2657  (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
2658  windows->icon.pixmap);
2659  (void) XClearWindow(display,windows->icon.id);
2660  (void) XWithdrawWindow(display,windows->info.id,
2661  windows->info.screen);
2662  windows->icon.mapped=MagickTrue;
2663  break;
2664  }
2665  if (event.xmap.window == windows->command.id)
2666  {
2667  windows->command.mapped=MagickTrue;
2668  break;
2669  }
2670  if (event.xmap.window == windows->popup.id)
2671  {
2672  windows->popup.mapped=MagickTrue;
2673  break;
2674  }
2675  if (event.xmap.window == windows->widget.id)
2676  {
2677  windows->widget.mapped=MagickTrue;
2678  break;
2679  }
2680  break;
2681  }
2682  case MappingNotify:
2683  {
2684  (void) XRefreshKeyboardMapping(&event.xmapping);
2685  break;
2686  }
2687  case NoExpose:
2688  break;
2689  case PropertyNotify:
2690  {
2691  Atom
2692  type;
2693 
2694  int
2695  format,
2696  status;
2697 
2698  unsigned char
2699  *data;
2700 
2701  unsigned long
2702  after,
2703  length;
2704 
2705  if (display_image->debug != MagickFalse)
2707  "Property Notify: 0x%lx 0x%lx %d",(unsigned long)
2708  event.xproperty.window,(unsigned long) event.xproperty.atom,
2709  event.xproperty.state);
2710  if (event.xproperty.atom != windows->im_remote_command)
2711  break;
2712  /*
2713  Display image named by the remote command protocol.
2714  */
2715  status=XGetWindowProperty(display,event.xproperty.window,
2716  event.xproperty.atom,0L,(long) MagickPathExtent,MagickFalse,(Atom)
2717  AnyPropertyType,&type,&format,&length,&after,&data);
2718  if ((status != Success) || (length == 0))
2719  break;
2720  (void) CopyMagickString(resource_info->image_info->filename,
2721  (char *) data,MagickPathExtent);
2722  nexus=ReadImage(resource_info->image_info,exception);
2723  CatchException(exception);
2724  if (nexus != (Image *) NULL)
2725  state|=ExitState;
2726  (void) XFree((void *) data);
2727  break;
2728  }
2729  case ReparentNotify:
2730  {
2731  if (display_image->debug != MagickFalse)
2733  "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
2734  event.xreparent.window);
2735  break;
2736  }
2737  case UnmapNotify:
2738  {
2739  if (display_image->debug != MagickFalse)
2741  "Unmap Notify: 0x%lx",event.xunmap.window);
2742  if (event.xunmap.window == windows->backdrop.id)
2743  {
2744  windows->backdrop.mapped=MagickFalse;
2745  break;
2746  }
2747  if (event.xunmap.window == windows->image.id)
2748  {
2749  windows->image.mapped=MagickFalse;
2750  break;
2751  }
2752  if (event.xunmap.window == windows->info.id)
2753  {
2754  windows->info.mapped=MagickFalse;
2755  break;
2756  }
2757  if (event.xunmap.window == windows->icon.id)
2758  {
2759  if (map_info->colormap == icon_map->colormap)
2760  XConfigureImageColormap(display,resource_info,windows,
2761  display_image,exception);
2762  (void) XFreeStandardColormap(display,icon_visual,icon_map,
2763  icon_pixel);
2764  windows->icon.mapped=MagickFalse;
2765  break;
2766  }
2767  if (event.xunmap.window == windows->command.id)
2768  {
2769  windows->command.mapped=MagickFalse;
2770  break;
2771  }
2772  if (event.xunmap.window == windows->popup.id)
2773  {
2774  if (windows->backdrop.id != (Window) NULL)
2775  (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2776  CurrentTime);
2777  windows->popup.mapped=MagickFalse;
2778  break;
2779  }
2780  if (event.xunmap.window == windows->widget.id)
2781  {
2782  if (windows->backdrop.id != (Window) NULL)
2783  (void) XSetInputFocus(display,windows->image.id,RevertToParent,
2784  CurrentTime);
2785  windows->widget.mapped=MagickFalse;
2786  break;
2787  }
2788  break;
2789  }
2790  default:
2791  {
2792  if (display_image->debug != MagickFalse)
2793  (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
2794  event.type);
2795  break;
2796  }
2797  }
2798  }
2799  while (!(state & ExitState));
2800  image_list=(Image **) RelinquishMagickMemory(image_list);
2801  images=DestroyImageList(images);
2802  if ((windows->visual_info->klass == GrayScale) ||
2803  (windows->visual_info->klass == PseudoColor) ||
2804  (windows->visual_info->klass == DirectColor))
2805  {
2806  /*
2807  Withdraw windows.
2808  */
2809  if (windows->info.mapped)
2810  (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2811  if (windows->command.mapped)
2812  (void) XWithdrawWindow(display,windows->command.id,
2813  windows->command.screen);
2814  }
2815  if (resource_info->backdrop == MagickFalse)
2816  if (windows->backdrop.mapped)
2817  {
2818  (void) XWithdrawWindow(display,windows->backdrop.id,\
2819  windows->backdrop.screen);
2820  (void) XDestroyWindow(display,windows->backdrop.id);
2821  windows->backdrop.id=(Window) NULL;
2822  (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2823  (void) XDestroyWindow(display,windows->image.id);
2824  windows->image.id=(Window) NULL;
2825  }
2826  XSetCursorState(display,windows,MagickTrue);
2827  XCheckRefreshWindows(display,windows);
2828  for (scene=1; scene < (ssize_t) number_scenes; scene++)
2829  {
2830  if (windows->image.pixmaps[scene] != (Pixmap) NULL)
2831  (void) XFreePixmap(display,windows->image.pixmaps[scene]);
2832  windows->image.pixmaps[scene]=(Pixmap) NULL;
2833  if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
2834  (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
2835  windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
2836  }
2837  XSetCursorState(display,windows,MagickFalse);
2838  windows->image.pixmaps=(Pixmap *)
2839  RelinquishMagickMemory(windows->image.pixmaps);
2840  windows->image.matte_pixmaps=(Pixmap *)
2841  RelinquishMagickMemory(windows->image.matte_pixmaps);
2842  if (nexus == (Image *) NULL)
2843  {
2844  /*
2845  Free X resources.
2846  */
2847  if (windows->image.mapped != MagickFalse)
2848  (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
2849  XDelay(display,SuspendTime);
2850  (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
2851  if (resource_info->map_type == (char *) NULL)
2852  (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2853  DestroyXResources();
2854  }
2855  (void) XSync(display,MagickFalse);
2856  /*
2857  Restore our progress monitor and warning handlers.
2858  */
2859  (void) SetErrorHandler(warning_handler);
2860  (void) SetWarningHandler(warning_handler);
2861  /*
2862  Change to home directory.
2863  */
2864  directory=getcwd(working_directory,MagickPathExtent);
2865  (void) directory;
2866  if (*resource_info->home_directory == '\0')
2867  (void) CopyMagickString(resource_info->home_directory,".",MagickPathExtent);
2868  status=chdir(resource_info->home_directory);
2869  if (status == -1)
2871  "UnableToOpenFile","%s",resource_info->home_directory);
2872  return(nexus);
2873 }
2874 
2875 /*
2876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877 % %
2878 % %
2879 % %
2880 + X S a v e I m a g e %
2881 % %
2882 % %
2883 % %
2884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2885 %
2886 % XSaveImage() saves an image to a file.
2887 %
2888 % The format of the XSaveImage method is:
2889 %
2890 % MagickBooleanType XSaveImage(Display *display,
2891 % XResourceInfo *resource_info,XWindows *windows,Image *image,
2892 % ExceptionInfo *exception)
2893 %
2894 % A description of each parameter follows:
2895 %
2896 % o status: Method XSaveImage return True if the image is
2897 % written. False is returned is there is a memory shortage or if the
2898 % image fails to write.
2899 %
2900 % o display: Specifies a connection to an X server; returned from
2901 % XOpenDisplay.
2902 %
2903 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2904 %
2905 % o windows: Specifies a pointer to a XWindows structure.
2906 %
2907 % o image: the image.
2908 %
2909 */
2910 static MagickBooleanType XSaveImage(Display *display,
2911  XResourceInfo *resource_info,XWindows *windows,Image *image,
2912  ExceptionInfo *exception)
2913 {
2914  char
2915  filename[MagickPathExtent];
2916 
2917  ImageInfo
2918  *image_info;
2919 
2921  status;
2922 
2923  /*
2924  Request file name from user.
2925  */
2926  if (resource_info->write_filename != (char *) NULL)
2927  (void) CopyMagickString(filename,resource_info->write_filename,
2929  else
2930  {
2931  char
2932  path[MagickPathExtent];
2933 
2934  int
2935  status;
2936 
2937  GetPathComponent(image->filename,HeadPath,path);
2938  GetPathComponent(image->filename,TailPath,filename);
2939  if (*path == '\0')
2940  (void) CopyMagickString(path,".",MagickPathExtent);
2941  status=chdir(path);
2942  if (status == -1)
2944  "UnableToOpenFile","%s",path);
2945  }
2946  XFileBrowserWidget(display,windows,"Save",filename);
2947  if (*filename == '\0')
2948  return(MagickTrue);
2949  if (IsPathAccessible(filename) != MagickFalse)
2950  {
2951  int
2952  status;
2953 
2954  /*
2955  File exists-- seek user's permission before overwriting.
2956  */
2957  status=XConfirmWidget(display,windows,"Overwrite",filename);
2958  if (status == 0)
2959  return(MagickTrue);
2960  }
2961  image_info=CloneImageInfo(resource_info->image_info);
2962  (void) CopyMagickString(image_info->filename,filename,MagickPathExtent);
2963  (void) SetImageInfo(image_info,1,exception);
2964  if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
2965  (LocaleCompare(image_info->magick,"JPG") == 0))
2966  {
2967  char
2968  quality[MagickPathExtent];
2969 
2970  int
2971  status;
2972 
2973  /*
2974  Request JPEG quality from user.
2975  */
2976  (void) FormatLocaleString(quality,MagickPathExtent,"%.20g",(double)
2977  image_info->quality);
2978  status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
2979  quality);
2980  if (*quality == '\0')
2981  return(MagickTrue);
2982  image->quality=StringToUnsignedLong(quality);
2983  image_info->interlace=status != MagickFalse ? NoInterlace :
2985  }
2986  if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
2987  (LocaleCompare(image_info->magick,"PDF") == 0) ||
2988  (LocaleCompare(image_info->magick,"PS") == 0) ||
2989  (LocaleCompare(image_info->magick,"PS2") == 0))
2990  {
2991  char
2992  geometry[MagickPathExtent];
2993 
2994  /*
2995  Request page geometry from user.
2996  */
2998  if (LocaleCompare(image_info->magick,"PDF") == 0)
3000  if (image_info->page != (char *) NULL)
3001  (void) CopyMagickString(geometry,image_info->page,MagickPathExtent);
3002  XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
3003  "Select page geometry:",geometry);
3004  if (*geometry != '\0')
3005  image_info->page=GetPageGeometry(geometry);
3006  }
3007  /*
3008  Write image.
3009  */
3010  image=GetFirstImageInList(image);
3011  status=WriteImages(image_info,image,filename,exception);
3012  if (status != MagickFalse)
3013  image->taint=MagickFalse;
3014  image_info=DestroyImageInfo(image_info);
3015  XSetCursorState(display,windows,MagickFalse);
3016  return(status != 0 ? MagickTrue : MagickFalse);
3017 }
3018 #else
3019 
3020 /*
3021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3022 % %
3023 % %
3024 % %
3025 + A n i m a t e I m a g e s %
3026 % %
3027 % %
3028 % %
3029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3030 %
3031 % AnimateImages() repeatedly displays an image sequence to any X window
3032 % screen. It returns a value other than 0 if successful. Check the
3033 % exception member of image to determine the reason for any failure.
3034 %
3035 % The format of the AnimateImages method is:
3036 %
3037 % MagickBooleanType AnimateImages(const ImageInfo *image_info,
3038 % Image *images)
3039 %
3040 % A description of each parameter follows:
3041 %
3042 % o image_info: the image info.
3043 %
3044 % o image: the image.
3045 %
3046 % o exception: return any errors or warnings in this structure.
3047 %
3048 */
3050  Image *image,ExceptionInfo *exception)
3051 {
3052  assert(image_info != (const ImageInfo *) NULL);
3053  assert(image_info->signature == MagickCoreSignature);
3054  (void) image_info;
3055  assert(image != (Image *) NULL);
3056  assert(image->signature == MagickCoreSignature);
3057  if (image->debug != MagickFalse)
3058  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3060  "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
3061  return(MagickFalse);
3062 }
3063 #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:3049
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:3199
#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
#define MaxTextExtent
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:1704
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:2703
#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:1413
MagickExport MagickBooleanType IsPathAccessible(const char *path)
Definition: utility.c:1467
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:65
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:3388
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