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