~ubuntu-branches/ubuntu/intrepid/graphicsmagick/intrepid

« back to all changes in this revision

Viewing changes to magick/animate.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2006-05-06 16:28:08 UTC
  • Revision ID: james.westby@ubuntu.com-20060506162808-vt2ni3r5nytcszms
Tags: upstream-1.1.7
ImportĀ upstreamĀ versionĀ 1.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
% Copyright (C) 2003, 2004 GraphicsMagick Group
 
3
% Copyright (C) 2002 ImageMagick Studio
 
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
 
5
%
 
6
% This program is covered by multiple licenses, which are described in
 
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
 
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
 
9
%
 
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
11
%                                                                             %
 
12
%                                                                             %
 
13
%                                                                             %
 
14
%              AAA   N   N  IIIII  M   M   AAA   TTTTT  EEEEE                 %
 
15
%             A   A  NN  N    I    MM MM  A   A    T    E                     %
 
16
%             AAAAA  N N N    I    M M M  AAAAA    T    EEE                   %
 
17
%             A   A  N  NN    I    M   M  A   A    T    E                     %
 
18
%             A   A  N   N  IIIII  M   M  A   A    T    EEEEE                 %
 
19
%                                                                             %
 
20
%                                                                             %
 
21
%            Methods to Interactively Animate an Image Sequence               %
 
22
%                                                                             %
 
23
%                                                                             %
 
24
%                           Software Design                                   %
 
25
%                             John Cristy                                     %
 
26
%                              July 1992                                      %
 
27
%                                                                             %
 
28
%                                                                             %
 
29
%                                                                             %
 
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
31
%
 
32
%
 
33
*/
 
34
 
 
35
/*
 
36
  Include declarations.
 
37
*/
 
38
#include "magick/studio.h"
 
39
#include "magick/constitute.h"
 
40
#include "magick/delegate.h"
 
41
#include "magick/log.h"
 
42
#include "magick/monitor.h"
 
43
#include "magick/transform.h"
 
44
#include "magick/utility.h"
 
45
#include "magick/version.h"
 
46
#include "magick/xwindow.h"
 
47
#if defined(HasX11)
 
48
#include "magick/animate.h"
 
49
 
 
50
/*
 
51
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
52
%                                                                             %
 
53
%                                                                             %
 
54
%                                                                             %
 
55
+   X M a g i c k C o m m a n d                                               %
 
56
%                                                                             %
 
57
%                                                                             %
 
58
%                                                                             %
 
59
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
60
%
 
61
%  Method XMagickCommand makes a transform to the image or Image window as
 
62
%  specified by a user menu button or keyboard command.
 
63
%
 
64
%  The format of the XMagickCommand method is:
 
65
%
 
66
%      Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
 
67
%        XWindows *windows,const CommandType command_type,Image **image,
 
68
%        unsigned int *state)
 
69
%
 
70
%  A description of each parameter follows:
 
71
%
 
72
%    o display: Specifies a connection to an X server; returned from
 
73
%      XOpenDisplay.
 
74
%
 
75
%    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
 
76
%
 
77
%    o windows: Specifies a pointer to a XWindows structure.
 
78
%
 
79
%    o image: Specifies a pointer to an Image structure;  XMagickCommand
 
80
%      may transform the image and return a new image pointer.
 
81
%
 
82
%    o state: Specifies an unsigned int;  XMagickCommand may return a
 
83
%      modified state.
 
84
%
 
85
%
 
86
*/
 
87
static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
 
88
  XWindows *windows,const CommandType command_type,Image **image,
 
89
  unsigned int *state)
 
90
{
 
91
  Image
 
92
    *nexus;
 
93
 
 
94
  int
 
95
    status;
 
96
 
 
97
  XTextProperty
 
98
    window_name;
 
99
 
 
100
  /*
 
101
    Process user command.
 
102
  */
 
103
  nexus=(Image *) NULL;
 
104
  switch (command_type)
 
105
  {
 
106
    case OpenCommand:
 
107
    {
 
108
      char
 
109
        **filelist;
 
110
 
 
111
      ExceptionInfo
 
112
        exception;
 
113
 
 
114
      Image
 
115
        *image,
 
116
        *next;
 
117
 
 
118
      ImageInfo
 
119
        *clone_info;
 
120
 
 
121
      int
 
122
        number_files;
 
123
 
 
124
      MonitorHandler
 
125
        handler;
 
126
 
 
127
      register int
 
128
        i;
 
129
 
 
130
      static char
 
131
        filenames[MaxTextExtent] = "*";
 
132
 
 
133
      unsigned int
 
134
        status;
 
135
 
 
136
      if (resource_info->immutable)
 
137
        break;
 
138
      /*
 
139
        Request file name from user.
 
140
      */
 
141
      XFileBrowserWidget(display,windows,"Animate",filenames);
 
142
      if (*filenames == '\0')
 
143
        return((Image *) NULL);
 
144
      /*
 
145
        Expand the filenames.
 
146
      */
 
147
      filelist=MagickAllocateMemory(char **,sizeof(char *));
 
148
      if (filelist == (char **) NULL)
 
149
        {
 
150
          MagickError(ResourceLimitError,MemoryAllocationFailed,filenames);
 
151
          return((Image *) NULL);
 
152
        }
 
153
      number_files=1;
 
154
      filelist[0]=filenames;
 
155
      status=ExpandFilenames(&number_files,&filelist);
 
156
      if ((status == False) || (number_files == 0))
 
157
        {
 
158
          if (number_files == 0)
 
159
            MagickError(ImageError,NoImagesWereLoaded,filenames);
 
160
          else
 
161
            MagickError(ResourceLimitError,MemoryAllocationFailed,filenames);
 
162
          return((Image *) NULL);
 
163
        }
 
164
      clone_info=CloneImageInfo(resource_info->image_info);
 
165
      if (clone_info == (ImageInfo *) NULL)
 
166
        break;
 
167
      GetExceptionInfo(&exception);
 
168
      image=(Image *) NULL;
 
169
      handler=(MonitorHandler) NULL;
 
170
      XSetCursorState(display,windows,True);
 
171
      XCheckRefreshWindows(display,windows);
 
172
      for (i=0; i < number_files; i++)
 
173
      {
 
174
        if (number_files > 5)
 
175
          handler=SetMonitorHandler((MonitorHandler) NULL);
 
176
        (void) strncpy(clone_info->filename,filelist[i],MaxTextExtent-1);
 
177
        *clone_info->magick='\0';
 
178
        next=ReadImage(clone_info,&exception);
 
179
        if (exception.severity != UndefinedException)
 
180
          CatchException(&exception);
 
181
        if (next != (Image *) NULL)
 
182
          {
 
183
            if (image == (Image *) NULL)
 
184
              image=next;
 
185
            else
 
186
              {
 
187
                image->next=next;
 
188
                image->next->previous=image;
 
189
                image=image->next;
 
190
              }
 
191
          }
 
192
        if (number_files <= 5)
 
193
          continue;
 
194
        (void) SetMonitorHandler(handler);
 
195
        if (!MagickMonitor(LoadImageText,i,number_files,&image->exception))
 
196
          break;
 
197
      }
 
198
      DestroyExceptionInfo(&exception);
 
199
      DestroyImageInfo(clone_info);
 
200
      if (image == (Image *) NULL)
 
201
        {
 
202
          XSetCursorState(display,windows,False);
 
203
          MagickError(ImageError,NoImagesWereLoaded,filenames);
 
204
          return((Image *) NULL);
 
205
        }
 
206
      while (image->previous != (Image *) NULL)
 
207
        image=image->previous;
 
208
      nexus=image;
 
209
      *state|=ExitState;
 
210
      break;
 
211
    }
 
212
    case PlayCommand:
 
213
    {
 
214
      char
 
215
        basename[MaxTextExtent];
 
216
 
 
217
      /*
 
218
        Window name is the base of the filename.
 
219
      */
 
220
      *state|=PlayAnimationState;
 
221
      *state&=(~AutoReverseAnimationState);
 
222
      GetPathComponent((*image)->filename,BasePath,basename);
 
223
      FormatString(windows->image.name,"GraphicsMagick: %.1024s",basename);
 
224
      if (resource_info->title != (char *) NULL)
 
225
        windows->image.name=TranslateText(resource_info->image_info,*image,
 
226
          resource_info->title);
 
227
      status=XStringListToTextProperty(&windows->image.name,1,&window_name);
 
228
      if (status == 0)
 
229
        break;
 
230
      XSetWMName(display,windows->image.id,&window_name);
 
231
      (void) XFree((void *) window_name.value);
 
232
      break;
 
233
    }
 
234
    case StepCommand:
 
235
    case StepBackwardCommand:
 
236
    case StepForwardCommand:
 
237
    {
 
238
      *state|=StepAnimationState;
 
239
      *state&=(~PlayAnimationState);
 
240
      if (command_type == StepBackwardCommand)
 
241
        *state&=(~ForwardAnimationState);
 
242
      if (command_type == StepForwardCommand)
 
243
        *state|=ForwardAnimationState;
 
244
      if (resource_info->title != (char *) NULL)
 
245
        break;
 
246
      break;
 
247
    }
 
248
    case RepeatCommand:
 
249
    {
 
250
      *state|=RepeatAnimationState;
 
251
      *state&=(~AutoReverseAnimationState);
 
252
      *state|=PlayAnimationState;
 
253
      break;
 
254
    }
 
255
    case AutoReverseCommand:
 
256
    {
 
257
      *state|=AutoReverseAnimationState;
 
258
      *state&=(~RepeatAnimationState);
 
259
      *state|=PlayAnimationState;
 
260
      break;
 
261
    }
 
262
    case SlowerCommand:
 
263
    {
 
264
      resource_info->delay++;
 
265
      break;
 
266
    }
 
267
    case FasterCommand:
 
268
    {
 
269
      if (resource_info->delay == 0)
 
270
        break;
 
271
      resource_info->delay--;
 
272
      break;
 
273
    }
 
274
    case ForwardCommand:
 
275
    {
 
276
      *state=ForwardAnimationState;
 
277
      *state&=(~AutoReverseAnimationState);
 
278
      break;
 
279
    }
 
280
    case ReverseCommand:
 
281
    {
 
282
      *state&=(~ForwardAnimationState);
 
283
      *state&=(~AutoReverseAnimationState);
 
284
      break;
 
285
    }
 
286
    case InfoCommand:
 
287
    {
 
288
      XDisplayImageInfo(display,resource_info,windows,(Image *) NULL,*image);
 
289
      break;
 
290
    }
 
291
    case HelpCommand:
 
292
    {
 
293
      /*
 
294
        User requested help.
 
295
      */
 
296
      XTextViewWidget(display,resource_info,windows,False,
 
297
        "Help Viewer - Animate",AnimateHelp);
 
298
      break;
 
299
    }
 
300
    case BrowseDocumentationCommand:
 
301
    {
 
302
      Atom
 
303
        mozilla_atom;
 
304
 
 
305
      Window
 
306
        mozilla_window,
 
307
        root_window;
 
308
 
 
309
      /*
 
310
        Browse the GraphicsMagick documentation.
 
311
      */
 
312
      root_window=XRootWindow(display,XDefaultScreen(display));
 
313
      mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",False);
 
314
      mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
 
315
      if (mozilla_window != (Window) NULL)
 
316
        {
 
317
          char
 
318
            command[MaxTextExtent];
 
319
 
 
320
          /*
 
321
            Display documentation using Netscape remote control.
 
322
          */
 
323
          FormatString(command,"openURL(%.1024s,new-window,noraise)",
 
324
            "http://www.graphicsmagick.org/");
 
325
          mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",False);
 
326
          (void) XChangeProperty(display,mozilla_window,mozilla_atom,
 
327
            XA_STRING,8,PropModeReplace,(unsigned char *) command,
 
328
            (int) strlen(command));
 
329
          XSetCursorState(display,windows,False);
 
330
          break;
 
331
        }
 
332
      XSetCursorState(display,windows,True);
 
333
      XCheckRefreshWindows(display,windows);
 
334
      status=InvokeDelegate(resource_info->image_info,*image,"browse",
 
335
        (char *) NULL,&(*image)->exception);
 
336
      if (status == False)
 
337
        XNoticeWidget(display,windows,"Unable to browse documentation",
 
338
          (char *) NULL);
 
339
      XDelay(display,1500);
 
340
      XSetCursorState(display,windows,False);
 
341
      break;
 
342
    }
 
343
    case VersionCommand:
 
344
    {
 
345
      XNoticeWidget(display,windows,GetMagickVersion((unsigned long *) NULL),
 
346
        GetMagickCopyright());
 
347
      break;
 
348
    }
 
349
    case QuitCommand:
 
350
    {
 
351
      /*
 
352
        Exit program
 
353
      */
 
354
      if (!resource_info->confirm_exit)
 
355
        XClientMessage(display,windows->image.id,windows->im_protocols,
 
356
          windows->im_exit,CurrentTime);
 
357
      else
 
358
        {
 
359
          /*
 
360
            Confirm program exit.
 
361
          */
 
362
          status=XConfirmWidget(display,windows,"Do you really want to exit",
 
363
            resource_info->client_name);
 
364
          if (status > 0)
 
365
            XClientMessage(display,windows->image.id,windows->im_protocols,
 
366
              windows->im_exit,CurrentTime);
 
367
        }
 
368
      break;
 
369
    }
 
370
    default:
 
371
      break;
 
372
  }
 
373
  return(nexus);
 
374
}
 
375
 
 
376
/*
 
377
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
378
%                                                                             %
 
379
%                                                                             %
 
380
%                                                                             %
 
381
%   X A n i m a t e B a c k g r o u n d I m a g e                             %
 
382
%                                                                             %
 
383
%                                                                             %
 
384
%                                                                             %
 
385
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
386
%
 
387
%  XAnimateBackgroundImage() animates an image sequence in the background of
 
388
%  a window.
 
389
%
 
390
%  The format of the XAnimateBackgroundImage method is:
 
391
%
 
392
%      void XAnimateBackgroundImage(Display *display,
 
393
%        XResourceInfo *resource_info,Image *images)
 
394
%
 
395
%  A description of each parameter follows:
 
396
%
 
397
%    o display: Specifies a connection to an X server;  returned from
 
398
%      XOpenDisplay.
 
399
%
 
400
%    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
 
401
%
 
402
%    o images: The image list.
 
403
%
 
404
%
 
405
*/
 
406
 
 
407
#if defined(__cplusplus) || defined(c_plusplus)
 
408
extern "C" {
 
409
#endif
 
410
 
 
411
static int SceneCompare(const void *x,const void *y)
 
412
{
 
413
  Image
 
414
    **image_1,
 
415
    **image_2;
 
416
 
 
417
  image_1=(Image **) x;
 
418
  image_2=(Image **) y;
 
419
  return((int) ((*image_1)->scene-(*image_2)->scene));
 
420
}
 
421
 
 
422
#if defined(__cplusplus) || defined(c_plusplus)
 
423
}
 
424
#endif
 
425
 
 
426
MagickExport void XAnimateBackgroundImage(Display *display,
 
427
  XResourceInfo *resource_info,Image *images)
 
428
{
 
429
  char
 
430
    geometry[MaxTextExtent],
 
431
    visual_type[MaxTextExtent];
 
432
 
 
433
  long
 
434
    x,
 
435
    y;
 
436
 
 
437
  static XPixelInfo
 
438
    pixel;
 
439
 
 
440
  static XStandardColormap
 
441
    *map_info;
 
442
 
 
443
  static XVisualInfo
 
444
    *visual_info = (XVisualInfo *) NULL;
 
445
 
 
446
  static XWindowInfo
 
447
    window_info;
 
448
 
 
449
  Image
 
450
    *display_image,
 
451
    **image_list;
 
452
 
 
453
  int
 
454
    scene;
 
455
 
 
456
  register long
 
457
    i;
 
458
 
 
459
  size_t
 
460
    number_scenes;
 
461
 
 
462
  unsigned int
 
463
    coalesce,
 
464
    status;
 
465
 
 
466
  unsigned int
 
467
    height,
 
468
    width;
 
469
 
 
470
  Window
 
471
    root_window;
 
472
 
 
473
  XEvent
 
474
    event;
 
475
 
 
476
  XGCValues
 
477
    context_values;
 
478
 
 
479
  XPixelInfo
 
480
    scene_info;
 
481
 
 
482
  XResourceInfo
 
483
    resources;
 
484
 
 
485
  XWindowAttributes
 
486
    window_attributes;
 
487
 
 
488
  /*
 
489
    Determine target window.
 
490
  */
 
491
  assert(images != (Image *) NULL);
 
492
  assert(images->signature == MagickSignature);
 
493
  resources=(*resource_info);
 
494
  window_info.id=(Window) NULL;
 
495
  root_window=XRootWindow(display,XDefaultScreen(display));
 
496
  if (LocaleCompare(resources.window_id,"root") == 0)
 
497
    window_info.id=root_window;
 
498
  else
 
499
    {
 
500
      if (isdigit((int) (*resources.window_id)))
 
501
        window_info.id=XWindowByID(display,root_window,
 
502
          (Window) strtol((char *) resources.window_id,(char **) NULL,0));
 
503
      if (window_info.id == (Window) NULL)
 
504
        window_info.id=
 
505
          XWindowByName(display,root_window,resources.window_id);
 
506
    }
 
507
  if (window_info.id == (Window) NULL)
 
508
    {
 
509
      MagickError(XServerError,NoWindowWithSpecifiedIDExists,
 
510
        resources.window_id);
 
511
      return;
 
512
    }
 
513
  /*
 
514
    Determine window visual id.
 
515
  */
 
516
  window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
 
517
  window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
 
518
  (void) strcpy(visual_type,"default");
 
519
  status=XGetWindowAttributes(display,window_info.id,&window_attributes);
 
520
  if (status != False)
 
521
    FormatString(visual_type,"0x%lx",
 
522
      XVisualIDFromVisual(window_attributes.visual));
 
523
  if (visual_info == (XVisualInfo *) NULL)
 
524
    {
 
525
      /*
 
526
        Allocate standard colormap.
 
527
      */
 
528
      map_info=XAllocStandardColormap();
 
529
      if (map_info == (XStandardColormap *) NULL)
 
530
        MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
 
531
          MagickMsg(XServerFatalError,UnableToCreateStandardColormap));
 
532
      map_info->colormap=(Colormap) NULL;
 
533
      pixel.pixels=(unsigned long *) NULL;
 
534
      /*
 
535
        Initialize visual info.
 
536
      */
 
537
      resources.map_type=(char *) NULL;
 
538
      resources.visual_type=visual_type;
 
539
      visual_info=XBestVisualInfo(display,map_info,&resources);
 
540
      if (visual_info == (XVisualInfo *) NULL)
 
541
        MagickFatalError(XServerFatalError,UnableToGetVisual,
 
542
          resources.visual_type);
 
543
      /*
 
544
        Initialize window info.
 
545
      */
 
546
      window_info.ximage=(XImage *) NULL;
 
547
      window_info.matte_image=(XImage *) NULL;
 
548
      window_info.pixmap=(Pixmap) NULL;
 
549
      window_info.matte_pixmap=(Pixmap) NULL;
 
550
    }
 
551
  /*
 
552
    Free previous root colors.
 
553
  */
 
554
  if (window_info.id == root_window)
 
555
    XDestroyWindowColors(display,root_window);
 
556
  coalesce=False;
 
557
  if (images->next != (Image *) NULL)
 
558
    {
 
559
      Image
 
560
        *next;
 
561
 
 
562
      /*
 
563
        Determine if the sequence of images have identical page info.
 
564
      */
 
565
      for (next=images; next != (Image *) NULL; )
 
566
      {
 
567
        if ((images->page.width != 0) && (images->page.height != 0))
 
568
          if ((images->columns != next->columns) ||
 
569
              (images->rows != next->rows))
 
570
            break;
 
571
        if ((images->page.x != next->page.x) ||
 
572
            (images->page.y != next->page.y))
 
573
          break;
 
574
        next=next->next;
 
575
      }
 
576
      coalesce=next != (Image *) NULL;
 
577
      if (coalesce)
 
578
        {
 
579
          Image
 
580
            *coalesce_image;
 
581
 
 
582
          coalesce_image=CoalesceImages(images,&images->exception);
 
583
          if (coalesce_image == (Image *) NULL)
 
584
            MagickFatalError2(images->exception.severity,
 
585
              images->exception.reason,images->exception.description);
 
586
          images=coalesce_image;
 
587
        }
 
588
    }
 
589
  if (resources.map_type == (char *) NULL)
 
590
    if ((visual_info->storage_class != TrueColor) &&
 
591
        (visual_info->storage_class != DirectColor))
 
592
      {
 
593
        Image
 
594
          *next;
 
595
 
 
596
        /*
 
597
          Determine if the sequence of images has the identical colormap.
 
598
        */
 
599
        for (next=images; next != (Image *) NULL; )
 
600
        {
 
601
          next->matte=False;
 
602
          if ((next->storage_class == DirectClass) ||
 
603
              (next->colors != images->colors) ||
 
604
              (next->colors > (unsigned long) visual_info->colormap_size))
 
605
            break;
 
606
          for (i=0; i < (long) images->colors; i++)
 
607
            if (!ColorMatch(next->colormap+i,images->colormap+i))
 
608
              break;
 
609
          if (i < (long) images->colors)
 
610
            break;
 
611
          next=next->next;
 
612
        }
 
613
        if (next != (Image *) NULL)
 
614
          (void) MapImages(images,(Image *) NULL,
 
615
            resources.quantize_info->dither);
 
616
      }
 
617
  /*
 
618
    Sort images by increasing scene number.
 
619
  */
 
620
  number_scenes=GetImageListLength(images);
 
621
  image_list=ImageListToArray(images,&images->exception);
 
622
  if (image_list == (Image **) NULL)
 
623
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
 
624
      UnableToAnimateImageSequence);
 
625
  for (i=0; i < (long) number_scenes; i++)
 
626
    if (image_list[i]->scene == 0)
 
627
      break;
 
628
  if (i == (long) number_scenes)
 
629
    qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
 
630
  /*
 
631
    Initialize Standard Colormap.
 
632
  */
 
633
  resources.colormap=SharedColormap;
 
634
  display_image=image_list[0];
 
635
  for (scene=0; scene < (int) number_scenes; scene++)
 
636
  {
 
637
    if ((resource_info->map_type != (char *) NULL) ||
 
638
        (visual_info->storage_class == TrueColor) ||
 
639
        (visual_info->storage_class == DirectColor))
 
640
      SetImageType(image_list[scene],TrueColorType);
 
641
    if ((display_image->columns < image_list[scene]->columns) &&
 
642
        (display_image->rows < image_list[scene]->rows))
 
643
      display_image=image_list[scene];
 
644
  }
 
645
  if ((resource_info->map_type != (char *) NULL) ||
 
646
      (visual_info->storage_class == TrueColor) ||
 
647
      (visual_info->storage_class == DirectColor))
 
648
    SetImageType(display_image,TrueColorType);
 
649
  XMakeStandardColormap(display,visual_info,&resources,display_image,map_info,
 
650
    &pixel);
 
651
  /*
 
652
    Graphic context superclass.
 
653
  */
 
654
  context_values.background=pixel.background_color.pixel;
 
655
  context_values.foreground=pixel.foreground_color.pixel;
 
656
  pixel.annotate_context=XCreateGC(display,window_info.id,GCBackground |
 
657
    GCForeground,&context_values);
 
658
  if (pixel.annotate_context == (GC) NULL)
 
659
    MagickFatalError(XServerFatalError,UnableToCreateGraphicContext,
 
660
      (char *) NULL);
 
661
  /*
 
662
    Initialize Image window attributes.
 
663
  */
 
664
  XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
 
665
    &resources,&window_info);
 
666
  /*
 
667
    Create the X image.
 
668
  */
 
669
  window_info.width=(unsigned int) image_list[0]->columns;
 
670
  window_info.height=(unsigned int) image_list[0]->rows;
 
671
  FormatString(geometry,"%ux%u+0+0>",window_attributes.width,
 
672
    window_attributes.height);
 
673
  width=window_info.width;
 
674
  height=window_info.height;
 
675
  x=window_info.x;
 
676
  y=window_info.y;
 
677
  {
 
678
    unsigned long
 
679
      geometry_width=width,
 
680
      geometry_height=height;
 
681
 
 
682
    (void) GetMagickGeometry(geometry,&x,&y,&geometry_width,&geometry_height);
 
683
    width=(unsigned int) geometry_width;
 
684
    height=(unsigned int) geometry_height;
 
685
  }
 
686
  window_info.width=(unsigned int) height;
 
687
  window_info.height=(unsigned int) height;
 
688
  window_info.x=(int) x;
 
689
  window_info.y=(int) y;
 
690
  status=XMakeImage(display,&resources,&window_info,image_list[0],
 
691
    window_info.width,window_info.height);
 
692
  if (status == False)
 
693
    MagickFatalError(XServerFatalError,UnableToCreateXImage,(char *) NULL);
 
694
  window_info.x=0;
 
695
  window_info.y=0;
 
696
  if (IsEventLogging())
 
697
    {
 
698
      (void) LogMagickEvent(X11Event,GetMagickModule(),
 
699
        "Image: %.1024s[%lu] %lux%lu ",image_list[0]->filename,
 
700
        image_list[0]->scene,image_list[0]->columns,image_list[0]->rows);
 
701
      if (image_list[0]->colors != 0)
 
702
        (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
 
703
          image_list[0]->colors);
 
704
      (void) LogMagickEvent(X11Event,GetMagickModule(),"%.1024s",
 
705
        image_list[0]->magick);
 
706
    }
 
707
  /*
 
708
    Adjust image dimensions as specified by backdrop or geometry options.
 
709
  */
 
710
  width=window_info.width;
 
711
  height=window_info.height;
 
712
  if (resources.backdrop)
 
713
    {
 
714
      /*
 
715
        Center image on window.
 
716
      */
 
717
      window_info.x=(window_attributes.width/2)-(window_info.ximage->width/2);
 
718
      window_info.y=(window_attributes.height/2)-(window_info.ximage->height/2);
 
719
      width=window_attributes.width;
 
720
      height=window_attributes.height;
 
721
    }
 
722
  if (resources.image_geometry != (char *) NULL)
 
723
    {
 
724
      char
 
725
        default_geometry[MaxTextExtent];
 
726
 
 
727
      int
 
728
        gravity;
 
729
 
 
730
      XSizeHints
 
731
        *size_hints;
 
732
 
 
733
      unsigned int
 
734
        flags;
 
735
 
 
736
      /*
 
737
        User specified geometry.
 
738
      */
 
739
      size_hints=XAllocSizeHints();
 
740
      if (size_hints == (XSizeHints *) NULL)
 
741
        MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
 
742
          UnableToDisplayImage);
 
743
      size_hints->flags=(long) NULL;
 
744
      FormatString(default_geometry,"%ux%u",width,height);
 
745
      flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
 
746
        default_geometry,window_info.border_width,size_hints,&window_info.x,
 
747
        &window_info.y,(int *) &width,(int *) &height,&gravity);
 
748
      if (flags & (XValue | YValue))
 
749
        {
 
750
          width=window_attributes.width;
 
751
          height=window_attributes.height;
 
752
        }
 
753
      (void) XFree((void *) size_hints);
 
754
    }
 
755
  /*
 
756
    Create the X pixmap.
 
757
  */
 
758
  window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
 
759
    (unsigned int) height,window_info.depth);
 
760
  if (window_info.pixmap == (Pixmap) NULL)
 
761
    MagickFatalError(XServerFatalError,UnableToCreateXPixmap,(char *) NULL);
 
762
  /*
 
763
    Display pixmap on the window.
 
764
  */
 
765
  if (((unsigned int) width > window_info.width) ||
 
766
      ((unsigned int) height > window_info.height))
 
767
    (void) XFillRectangle(display,window_info.pixmap,
 
768
      window_info.annotate_context,0,0,(unsigned int) width,
 
769
      (unsigned int) height);
 
770
  (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
 
771
    window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
 
772
    window_info.height);
 
773
  (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
 
774
  (void) XClearWindow(display,window_info.id);
 
775
  /*
 
776
    Initialize image pixmaps structure.
 
777
  */
 
778
  window_info.pixmaps=MagickAllocateMemory(Pixmap *,number_scenes*sizeof(Pixmap));
 
779
  window_info.matte_pixmaps=MagickAllocateMemory(Pixmap *,
 
780
    number_scenes*sizeof(Pixmap));
 
781
  if ((window_info.pixmaps == (Pixmap *) NULL) ||
 
782
      (window_info.matte_pixmaps == (Pixmap *) NULL))
 
783
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
 
784
      UnableToAnimateImageSequence);
 
785
  window_info.pixmaps[0]=window_info.pixmap;
 
786
  window_info.matte_pixmaps[0]=window_info.pixmap;
 
787
  scene_info.pixels=(unsigned long *) NULL;
 
788
  for (scene=1; scene < (int) number_scenes; scene++)
 
789
  {
 
790
    /*
 
791
      Create X image.
 
792
    */
 
793
    window_info.pixmap=(Pixmap) NULL;
 
794
    window_info.matte_pixmap=(Pixmap) NULL;
 
795
    if ((resources.map_type != (char *) NULL) ||
 
796
        (visual_info->storage_class == TrueColor) ||
 
797
        (visual_info->storage_class == DirectColor))
 
798
      if (image_list[scene]->storage_class == PseudoClass)
 
799
        {
 
800
          /*
 
801
            Get pixel info for this scene.
 
802
          */
 
803
          XGetPixelPacket(display,visual_info,map_info,&resources,
 
804
            image_list[scene],&scene_info);
 
805
          window_info.pixel_info=(&scene_info);
 
806
        }
 
807
    status=XMakeImage(display,&resources,&window_info,image_list[scene],
 
808
      (unsigned int) image_list[scene]->columns,
 
809
      (unsigned int) image_list[scene]->rows);
 
810
    if (status == False)
 
811
      MagickFatalError(XServerFatalError,UnableToCreateXImage,(char *) NULL);
 
812
    if (IsEventLogging())
 
813
      {
 
814
        (void) LogMagickEvent(X11Event,GetMagickModule(),
 
815
          "Image: [%lu] %.1024s %lux%lu ",image_list[scene]->scene,
 
816
          image_list[scene]->filename,image_list[scene]->columns,
 
817
          image_list[scene]->rows);
 
818
        if (image_list[scene]->colors != 0)
 
819
          (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
 
820
            image_list[scene]->colors);
 
821
        (void) LogMagickEvent(X11Event,GetMagickModule(),"%.1024s",
 
822
          image_list[scene]->magick);
 
823
      }
 
824
    /*
 
825
      Create the X pixmap.
 
826
    */
 
827
    window_info.pixmap=XCreatePixmap(display,window_info.id,
 
828
      (unsigned int) width,(unsigned int) height,window_info.depth);
 
829
    if (window_info.pixmap == (Pixmap) NULL)
 
830
      MagickFatalError(XServerFatalError,UnableToCreateXPixmap,(char *) NULL);
 
831
    /*
 
832
      Display pixmap on the window.
 
833
    */
 
834
    if (((unsigned int) width > window_info.width) ||
 
835
        ((unsigned int) height > window_info.height))
 
836
      (void) XFillRectangle(display,window_info.pixmap,
 
837
        window_info.annotate_context,0,0,(unsigned int) width,
 
838
        (unsigned int) height);
 
839
    (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
 
840
      window_info.ximage,0,0,window_info.x,window_info.y,window_info.width,
 
841
      window_info.height);
 
842
    (void) XSetWindowBackgroundPixmap(display,window_info.id,
 
843
      window_info.pixmap);
 
844
    (void) XClearWindow(display,window_info.id);
 
845
    window_info.pixmaps[scene]=window_info.pixmap;
 
846
    window_info.matte_pixmaps[scene]=window_info.matte_pixmap;
 
847
    if (image_list[scene]->matte)
 
848
      (void) XClearWindow(display,window_info.id);
 
849
    XDelay(display,(unsigned long) resources.delay*10*Max(images->delay,1));
 
850
  }
 
851
  window_info.pixel_info=(&pixel);
 
852
  /*
 
853
    Display pixmap on the window.
 
854
  */
 
855
  (void) XSelectInput(display,window_info.id,SubstructureNotifyMask);
 
856
  event.type=Expose;
 
857
  do
 
858
  {
 
859
    for (scene=0; scene < (int) number_scenes; scene++)
 
860
    {
 
861
      if (XEventsQueued(display,QueuedAfterFlush) > 0)
 
862
        {
 
863
          (void) XNextEvent(display,&event);
 
864
          if (event.type == DestroyNotify)
 
865
            break;
 
866
        }
 
867
      window_info.pixmap=window_info.pixmaps[scene];
 
868
      window_info.matte_pixmap=window_info.matte_pixmaps[scene];
 
869
      (void) XSetWindowBackgroundPixmap(display,window_info.id,
 
870
        window_info.pixmap);
 
871
      (void) XClearWindow(display,window_info.id);
 
872
      (void) XSync(display,False);
 
873
      XDelay(display,(unsigned long) resources.delay*10*
 
874
        Max(image_list[scene]->delay,1));
 
875
    }
 
876
  } while (event.type != DestroyNotify);
 
877
  (void) XSync(display,False);
 
878
  MagickFreeMemory(image_list);
 
879
  if (coalesce)
 
880
    DestroyImageList(images);
 
881
}
 
882
 
 
883
/*
 
884
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
885
%                                                                             %
 
886
%                                                                             %
 
887
%                                                                             %
 
888
%   X A n i m a t e I m a g e                                                 %
 
889
%                                                                             %
 
890
%                                                                             %
 
891
%                                                                             %
 
892
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
893
%
 
894
%  XAnimateImages() displays an image via X11.
 
895
%
 
896
%  The format of the XAnimateImages method is:
 
897
%
 
898
%      Image *XAnimateImages(Display *display,XResourceInfo *resource_info,
 
899
%        char **argv,const int argc,Image *images)
 
900
%
 
901
%  A description of each parameter follows:
 
902
%
 
903
%    o display: Specifies a connection to an X server;  returned from
 
904
%      XOpenDisplay.
 
905
%
 
906
%    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
 
907
%
 
908
%    o argv: Specifies the application's argument list.
 
909
%
 
910
%    o argc: Specifies the number of arguments.
 
911
%
 
912
%    o images: The image list.
 
913
%
 
914
%
 
915
*/
 
916
MagickExport Image *XAnimateImages(Display *display,
 
917
  XResourceInfo *resource_info,char **argv,const int argc,Image *images)
 
918
{
 
919
#define MagickMenus  4
 
920
#define MaxWindows  8
 
921
#define MagickTitle  "Commands"
 
922
 
 
923
  static const char
 
924
    *CommandMenu[]=
 
925
    {
 
926
      "Animate",
 
927
      "Speed",
 
928
      "Direction",
 
929
      "Help",
 
930
      "Image Info",
 
931
      "Quit",
 
932
      (char *) NULL
 
933
    },
 
934
    *AnimateMenu[]=
 
935
    {
 
936
      "Open",
 
937
      "Play",
 
938
      "Step",
 
939
      "Repeat",
 
940
      "Auto Reverse",
 
941
      (char *) NULL
 
942
    },
 
943
    *SpeedMenu[]=
 
944
    {
 
945
      "Faster",
 
946
      "Slower",
 
947
      (char *) NULL
 
948
    },
 
949
    *DirectionMenu[]=
 
950
    {
 
951
      "Forward",
 
952
      "Reverse",
 
953
      (char *) NULL
 
954
    },
 
955
    *HelpMenu[]=
 
956
    {
 
957
      "Overview",
 
958
      "Browse Documentation",
 
959
      "About Animate",
 
960
      (char *) NULL
 
961
    };
 
962
 
 
963
 
 
964
  static const char
 
965
    **Menus[MagickMenus]=
 
966
    {
 
967
      AnimateMenu,
 
968
      SpeedMenu,
 
969
      DirectionMenu,
 
970
      HelpMenu
 
971
    };
 
972
 
 
973
  static const CommandType
 
974
    CommandMenus[]=
 
975
    {
 
976
      NullCommand,
 
977
      NullCommand,
 
978
      NullCommand,
 
979
      NullCommand,
 
980
      InfoCommand,
 
981
      QuitCommand
 
982
    },
 
983
    CommandTypes[]=
 
984
    {
 
985
      OpenCommand,
 
986
      PlayCommand,
 
987
      StepCommand,
 
988
      RepeatCommand,
 
989
      AutoReverseCommand
 
990
    },
 
991
    SpeedCommands[]=
 
992
    {
 
993
      FasterCommand,
 
994
      SlowerCommand
 
995
    },
 
996
    DirectionCommands[]=
 
997
    {
 
998
      ForwardCommand,
 
999
      ReverseCommand
 
1000
    },
 
1001
    HelpCommands[]=
 
1002
    {
 
1003
      HelpCommand,
 
1004
      BrowseDocumentationCommand,
 
1005
      VersionCommand
 
1006
    };
 
1007
 
 
1008
  static const CommandType
 
1009
    *Commands[MagickMenus]=
 
1010
    {
 
1011
      CommandTypes,
 
1012
      SpeedCommands,
 
1013
      DirectionCommands,
 
1014
      HelpCommands
 
1015
    };
 
1016
 
 
1017
  char
 
1018
    command[MaxTextExtent],
 
1019
    geometry[MaxTextExtent],
 
1020
    resource_name[MaxTextExtent];
 
1021
 
 
1022
  CommandType
 
1023
    command_type;
 
1024
 
 
1025
  Image
 
1026
    *display_image,
 
1027
    *image,
 
1028
    **image_list,
 
1029
    *nexus;
 
1030
 
 
1031
  int
 
1032
    status;
 
1033
 
 
1034
  long
 
1035
    first_scene,
 
1036
    iterations,
 
1037
    scene,
 
1038
    x,
 
1039
    y;
 
1040
 
 
1041
  KeySym
 
1042
    key_symbol;
 
1043
 
 
1044
  MonitorHandler
 
1045
    monitor_handler;
 
1046
 
 
1047
  register char
 
1048
    *p;
 
1049
 
 
1050
  register long
 
1051
    i;
 
1052
 
 
1053
  static char
 
1054
    working_directory[MaxTextExtent];
 
1055
 
 
1056
  static unsigned long
 
1057
    number_windows;
 
1058
 
 
1059
  static XWindowInfo
 
1060
    *magick_windows[MaxWindows];
 
1061
 
 
1062
  time_t
 
1063
    timestamp;
 
1064
 
 
1065
  unsigned int
 
1066
    context_mask,
 
1067
    coalesce,
 
1068
    state;
 
1069
 
 
1070
  unsigned long
 
1071
    height,
 
1072
    number_scenes,
 
1073
    width;
 
1074
 
 
1075
  WarningHandler
 
1076
    warning_handler;
 
1077
 
 
1078
  Window
 
1079
    root_window;
 
1080
 
 
1081
  XClassHint
 
1082
    *class_hints;
 
1083
 
 
1084
  XEvent
 
1085
    event;
 
1086
 
 
1087
  XFontStruct
 
1088
    *font_info;
 
1089
 
 
1090
  XGCValues
 
1091
    context_values;
 
1092
 
 
1093
  XPixelInfo
 
1094
    *icon_pixel,
 
1095
    *pixel,
 
1096
    scene_info;
 
1097
 
 
1098
  XResourceInfo
 
1099
    *icon_resources;
 
1100
 
 
1101
  XStandardColormap
 
1102
    *icon_map,
 
1103
    *map_info;
 
1104
 
 
1105
  XTextProperty
 
1106
    window_name;
 
1107
 
 
1108
  XVisualInfo
 
1109
    *icon_visual,
 
1110
    *visual_info;
 
1111
 
 
1112
  XWindows
 
1113
    *windows;
 
1114
 
 
1115
  XWMHints
 
1116
    *manager_hints;
 
1117
 
 
1118
  assert(images != (Image *) NULL);
 
1119
  assert(images->signature == MagickSignature);
 
1120
  monitor_handler=(MonitorHandler) NULL;
 
1121
  warning_handler=(WarningHandler) NULL;
 
1122
  windows=XSetWindows((XWindows *) ~0);
 
1123
  if (windows != (XWindows *) NULL)
 
1124
    {
 
1125
      (void) chdir(working_directory);
 
1126
      monitor_handler=SetMonitorHandler(XMagickMonitor);
 
1127
      warning_handler=resource_info->display_warnings ?
 
1128
        SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
 
1129
      warning_handler=resource_info->display_warnings ?
 
1130
        SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
 
1131
      (void) signal(SIGINT,XSignalHandler);
 
1132
      (void) signal(SIGSEGV,XSignalHandler);
 
1133
      (void) signal(SIGTERM,XSignalHandler);
 
1134
    }
 
1135
  else
 
1136
    {
 
1137
      register Image
 
1138
        *p;
 
1139
 
 
1140
      /*
 
1141
        Initialize window structure.
 
1142
      */
 
1143
      for (p=images; p != (Image *) NULL; p=p->next)
 
1144
      {
 
1145
        if (p->storage_class == DirectClass)
 
1146
          {
 
1147
            resource_info->colors=0;
 
1148
            break;
 
1149
          }
 
1150
        if (p->colors > resource_info->colors)
 
1151
          resource_info->colors=p->colors;
 
1152
      }
 
1153
      windows=XSetWindows(XInitializeWindows(display,resource_info));
 
1154
      if (windows == (XWindows *) NULL)
 
1155
        MagickFatalError(ResourceLimitFatalError,MemoryAllocationFailed,
 
1156
          MagickMsg(XServerFatalError,UnableToCreateXWindow));
 
1157
      /*
 
1158
        Initialize window id's.
 
1159
      */
 
1160
      number_windows=0;
 
1161
      magick_windows[number_windows++]=(&windows->icon);
 
1162
      magick_windows[number_windows++]=(&windows->backdrop);
 
1163
      magick_windows[number_windows++]=(&windows->image);
 
1164
      magick_windows[number_windows++]=(&windows->info);
 
1165
      magick_windows[number_windows++]=(&windows->command);
 
1166
      magick_windows[number_windows++]=(&windows->widget);
 
1167
      magick_windows[number_windows++]=(&windows->popup);
 
1168
      for (i=0; i < (long) number_windows; i++)
 
1169
        magick_windows[i]->id=(Window) NULL;
 
1170
    }
 
1171
  /*
 
1172
    Initialize font info.
 
1173
  */
 
1174
  if (windows->font_info != (XFontStruct *) NULL)
 
1175
    (void) XFreeFont(display,windows->font_info);
 
1176
  windows->font_info=XBestFont(display,resource_info,False);
 
1177
  if (windows->font_info == (XFontStruct *) NULL)
 
1178
    MagickFatalError(XServerFatalError,UnableToLoadFont,resource_info->font);
 
1179
  /*
 
1180
    Initialize Standard Colormap.
 
1181
  */
 
1182
  map_info=windows->map_info;
 
1183
  icon_map=windows->icon_map;
 
1184
  visual_info=windows->visual_info;
 
1185
  icon_visual=windows->icon_visual;
 
1186
  pixel=windows->pixel_info;
 
1187
  icon_pixel=windows->icon_pixel;
 
1188
  font_info=windows->font_info;
 
1189
  icon_resources=windows->icon_resources;
 
1190
  class_hints=windows->class_hints;
 
1191
  manager_hints=windows->manager_hints;
 
1192
  root_window=XRootWindow(display,visual_info->screen);
 
1193
  coalesce=False;
 
1194
  if (images->next != (Image *) NULL)
 
1195
    {
 
1196
      Image
 
1197
        *next;
 
1198
 
 
1199
      /*
 
1200
        Determine if the sequence of images have identical page info.
 
1201
      */
 
1202
      for (next=images; next != (Image *) NULL; )
 
1203
      {
 
1204
        if ((images->columns != next->columns) ||
 
1205
            (images->rows != next->rows))
 
1206
          break;
 
1207
        if ((images->page.x != next->page.x) ||
 
1208
            (images->page.y != next->page.y))
 
1209
          break;
 
1210
        next=next->next;
 
1211
      }
 
1212
      coalesce=next != (Image *) NULL;
 
1213
      if (coalesce)
 
1214
        {
 
1215
          Image
 
1216
            *coalesce_image;
 
1217
 
 
1218
          coalesce_image=CoalesceImages(images,&images->exception);
 
1219
          if (coalesce_image == (Image *) NULL)
 
1220
            MagickFatalError2(images->exception.severity,
 
1221
              images->exception.reason,images->exception.description);
 
1222
          images=coalesce_image;
 
1223
        }
 
1224
    }
 
1225
  if (resource_info->map_type == (char *) NULL)
 
1226
    if ((visual_info->storage_class != TrueColor) &&
 
1227
        (visual_info->storage_class != DirectColor))
 
1228
      {
 
1229
        Image
 
1230
          *next;
 
1231
 
 
1232
        /*
 
1233
          Determine if the sequence of images has the identical colormap.
 
1234
        */
 
1235
        for (next=images; next != (Image *) NULL; )
 
1236
        {
 
1237
          next->matte=False;
 
1238
          if ((next->storage_class == DirectClass) ||
 
1239
              (next->colors != images->colors) ||
 
1240
              (next->colors > (unsigned long) visual_info->colormap_size))
 
1241
            break;
 
1242
          for (i=0; i < (long) images->colors; i++)
 
1243
            if (!ColorMatch(next->colormap+i,images->colormap+i))
 
1244
              break;
 
1245
          if (i < (long) images->colors)
 
1246
            break;
 
1247
          next=next->next;
 
1248
        }
 
1249
        if (next != (Image *) NULL)
 
1250
          (void) MapImages(images,(Image *) NULL,
 
1251
            resource_info->quantize_info->dither);
 
1252
      }
 
1253
  /*
 
1254
    Sort images by increasing scene number.
 
1255
  */
 
1256
  number_scenes=GetImageListLength(images);
 
1257
  image_list=ImageListToArray(images,&images->exception);
 
1258
  if (image_list == (Image **) NULL)
 
1259
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
 
1260
      UnableToAnimateImageSequence);
 
1261
  for (scene=0; scene < (long) number_scenes; scene++)
 
1262
    if (image_list[scene]->scene == 0)
 
1263
      break;
 
1264
  if (scene == (long) number_scenes)
 
1265
    qsort((void *) image_list,number_scenes,sizeof(Image *),SceneCompare);
 
1266
  /*
 
1267
    Initialize Standard Colormap.
 
1268
  */
 
1269
  nexus=(Image *) NULL;
 
1270
  display_image=image_list[0];
 
1271
  TransformColorspace(display_image,RGBColorspace);
 
1272
  for (scene=0; scene < (long) number_scenes; scene++)
 
1273
  {
 
1274
    if ((resource_info->map_type != (char *) NULL) ||
 
1275
        (visual_info->storage_class == TrueColor) ||
 
1276
        (visual_info->storage_class == DirectColor))
 
1277
      SetImageType(image_list[scene],TrueColorType);
 
1278
    if ((display_image->columns < image_list[scene]->columns) &&
 
1279
        (display_image->rows < image_list[scene]->rows))
 
1280
      display_image=image_list[scene];
 
1281
  }
 
1282
  if (IsEventLogging())
 
1283
    {
 
1284
      (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1285
        "Image: %.1024s[%lu] %lux%lu ",display_image->filename,
 
1286
        display_image->scene,display_image->columns,display_image->rows);
 
1287
      if (display_image->colors != 0)
 
1288
        (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
 
1289
          display_image->colors);
 
1290
      (void) LogMagickEvent(X11Event,GetMagickModule(),"%.1024s",
 
1291
        display_image->magick);
 
1292
    }
 
1293
  XMakeStandardColormap(display,visual_info,resource_info,display_image,
 
1294
    map_info,pixel);
 
1295
  /*
 
1296
    Initialize graphic context.
 
1297
  */
 
1298
  windows->context.id=(Window) NULL;
 
1299
  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
 
1300
    resource_info,&windows->context);
 
1301
  class_hints->res_name=(char *) "superclass";
 
1302
  class_hints->res_class=(char *) "Display";
 
1303
  manager_hints->flags=InputHint | StateHint;
 
1304
  manager_hints->input=False;
 
1305
  manager_hints->initial_state=WithdrawnState;
 
1306
  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
 
1307
    &windows->context);
 
1308
  if (IsEventLogging())
 
1309
    (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1310
      "Window id: 0x%lx (context)",windows->context.id);
 
1311
  context_values.background=pixel->background_color.pixel;
 
1312
  context_values.font=font_info->fid;
 
1313
  context_values.foreground=pixel->foreground_color.pixel;
 
1314
  context_values.graphics_exposures=False;
 
1315
  context_mask=GCBackground | GCFont | GCForeground | GCGraphicsExposures;
 
1316
  if (pixel->annotate_context != (GC) NULL)
 
1317
    (void) XFreeGC(display,pixel->annotate_context);
 
1318
  pixel->annotate_context=
 
1319
    XCreateGC(display,windows->context.id,context_mask,&context_values);
 
1320
  if (pixel->annotate_context == (GC) NULL)
 
1321
    MagickFatalError(XServerFatalError,UnableToCreateGraphicContext,
 
1322
      (char *) NULL);
 
1323
  context_values.background=pixel->depth_color.pixel;
 
1324
  if (pixel->widget_context != (GC) NULL)
 
1325
    (void) XFreeGC(display,pixel->widget_context);
 
1326
  pixel->widget_context=
 
1327
    XCreateGC(display,windows->context.id,context_mask,&context_values);
 
1328
  if (pixel->widget_context == (GC) NULL)
 
1329
    MagickFatalError(XServerFatalError,UnableToCreateGraphicContext,
 
1330
      (char *) NULL);
 
1331
  context_values.background=pixel->foreground_color.pixel;
 
1332
  context_values.foreground=pixel->background_color.pixel;
 
1333
  context_values.plane_mask=
 
1334
    context_values.background ^ context_values.foreground;
 
1335
  if (pixel->highlight_context != (GC) NULL)
 
1336
    (void) XFreeGC(display,pixel->highlight_context);
 
1337
  pixel->highlight_context=XCreateGC(display,windows->context.id,
 
1338
    context_mask | GCPlaneMask,&context_values);
 
1339
  if (pixel->highlight_context == (GC) NULL)
 
1340
    MagickFatalError(XServerFatalError,UnableToCreateGraphicContext,
 
1341
      (char *) NULL);
 
1342
  (void) XDestroyWindow(display,windows->context.id);
 
1343
  /*
 
1344
    Initialize icon window.
 
1345
  */
 
1346
  XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
 
1347
    icon_resources,&windows->icon);
 
1348
  windows->icon.geometry=resource_info->icon_geometry;
 
1349
  XBestIconSize(display,&windows->icon,display_image);
 
1350
  windows->icon.attributes.colormap=
 
1351
    XDefaultColormap(display,icon_visual->screen);
 
1352
  windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
 
1353
  class_hints->res_name=(char *) "icon";
 
1354
  manager_hints->flags=InputHint | StateHint;
 
1355
  manager_hints->input=False;
 
1356
  manager_hints->initial_state=IconicState;
 
1357
  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
 
1358
    &windows->icon);
 
1359
  if (IsEventLogging())
 
1360
    (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
 
1361
      windows->icon.id);
 
1362
  /*
 
1363
    Initialize graphic context for icon window.
 
1364
  */
 
1365
  if (icon_pixel->annotate_context != (GC) NULL)
 
1366
    (void) XFreeGC(display,icon_pixel->annotate_context);
 
1367
  context_values.background=icon_pixel->background_color.pixel;
 
1368
  context_values.foreground=icon_pixel->foreground_color.pixel;
 
1369
  icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
 
1370
    GCBackground | GCForeground,&context_values);
 
1371
  if (icon_pixel->annotate_context == (GC) NULL)
 
1372
    MagickFatalError(XServerFatalError,UnableToCreateGraphicContext,
 
1373
      (char *) NULL);
 
1374
  windows->icon.annotate_context=icon_pixel->annotate_context;
 
1375
  /*
 
1376
    Initialize Image window.
 
1377
  */
 
1378
  if (windows->image.id != (Window) NULL)
 
1379
    {
 
1380
      MagickFreeMemory(windows->image.name);
 
1381
      MagickFreeMemory(windows->image.icon_name);
 
1382
    }
 
1383
  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
 
1384
    resource_info,&windows->image);
 
1385
  windows->image.shape=True;  /* non-rectangular shape hint */
 
1386
  windows->image.shared_memory&=resource_info->use_shared_memory;
 
1387
  if (resource_info->title != (char *) NULL)
 
1388
    {
 
1389
      windows->image.name=TranslateText(resource_info->image_info,
 
1390
        display_image,resource_info->title);
 
1391
      windows->image.icon_name=TranslateText(resource_info->image_info,
 
1392
        display_image,resource_info->title);
 
1393
    }
 
1394
  else
 
1395
    {
 
1396
      char
 
1397
        filename[MaxTextExtent];
 
1398
 
 
1399
      /*
 
1400
        Window name is the base of the filename.
 
1401
      */
 
1402
      windows->image.name=AllocateString((char *) NULL);
 
1403
      windows->image.icon_name=AllocateString((char *) NULL);
 
1404
      GetPathComponent(display_image->filename,TailPath,filename);
 
1405
      FormatString(windows->image.name,"GraphicsMagick: %.1024s[%lu of %lu]",
 
1406
        filename,display_image->scene,number_scenes);
 
1407
      (void) strncpy(windows->image.icon_name,filename,MaxTextExtent-1);
 
1408
    }
 
1409
  if (resource_info->immutable)
 
1410
    windows->image.immutable=True;
 
1411
  windows->image.shape=True;
 
1412
  windows->image.geometry=resource_info->image_geometry;
 
1413
  FormatString(geometry,"%ux%u+0+0>!",
 
1414
    90*XDisplayWidth(display,visual_info->screen)/100,
 
1415
    90*XDisplayHeight(display,visual_info->screen)/100);
 
1416
  width=display_image->columns;
 
1417
  height=display_image->rows;
 
1418
  x=0;
 
1419
  y=0;
 
1420
  (void) GetMagickGeometry(geometry,&x,&y,&width,&height);
 
1421
  windows->image.width=(unsigned int) width;
 
1422
  windows->image.height=(unsigned int) height;
 
1423
  windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
 
1424
    ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
 
1425
    KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
 
1426
    PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
 
1427
  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
 
1428
    resource_info,&windows->backdrop);
 
1429
  if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
 
1430
    {
 
1431
      /*
 
1432
        Initialize backdrop window.
 
1433
      */
 
1434
      windows->backdrop.x=0;
 
1435
      windows->backdrop.y=0;
 
1436
      (void) CloneString(&windows->backdrop.name,"GraphicsMagick Backdrop");
 
1437
      windows->backdrop.flags=USSize | USPosition;
 
1438
      windows->backdrop.width=XDisplayWidth(display,visual_info->screen);
 
1439
      windows->backdrop.height=XDisplayHeight(display,visual_info->screen);
 
1440
      windows->backdrop.border_width=0;
 
1441
      windows->backdrop.immutable=True;
 
1442
      windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
 
1443
        ButtonReleaseMask;
 
1444
      windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
 
1445
        StructureNotifyMask;
 
1446
      windows->backdrop.attributes.override_redirect=True;
 
1447
      class_hints->res_name=(char *) "backdrop";
 
1448
      manager_hints->flags=IconWindowHint | InputHint | StateHint;
 
1449
      manager_hints->icon_window=windows->icon.id;
 
1450
      manager_hints->input=True;
 
1451
      manager_hints->initial_state=
 
1452
        resource_info->iconic ? IconicState : NormalState;
 
1453
      XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
 
1454
        &windows->backdrop);
 
1455
      if (IsEventLogging())
 
1456
        (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1457
          "Window id: 0x%lx (backdrop)",windows->backdrop.id);
 
1458
      (void) XMapWindow(display,windows->backdrop.id);
 
1459
      (void) XClearWindow(display,windows->backdrop.id);
 
1460
      if (windows->image.id != (Window) NULL)
 
1461
        {
 
1462
          (void) XDestroyWindow(display,windows->image.id);
 
1463
          windows->image.id=(Window) NULL;
 
1464
        }
 
1465
      /*
 
1466
        Position image in the center the backdrop.
 
1467
      */
 
1468
      windows->image.flags|=USPosition;
 
1469
      windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
 
1470
        (windows->image.width/2);
 
1471
      windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
 
1472
        (windows->image.height/2);
 
1473
    }
 
1474
  if (resource_info->name == (char *) NULL)
 
1475
    class_hints->res_name=resource_info->client_name;
 
1476
  else
 
1477
    class_hints->res_name=resource_info->name;
 
1478
  manager_hints->flags=IconWindowHint | InputHint | StateHint;
 
1479
  manager_hints->icon_window=windows->icon.id;
 
1480
  manager_hints->input=True;
 
1481
  manager_hints->initial_state=
 
1482
    resource_info->iconic ? IconicState : NormalState;
 
1483
  if (windows->group_leader.id != (Window) NULL)
 
1484
    {
 
1485
      /*
 
1486
        Follow the leader.
 
1487
      */
 
1488
      manager_hints->flags|=(unsigned int) WindowGroupHint;
 
1489
      manager_hints->window_group=windows->group_leader.id;
 
1490
      (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
 
1491
      if (IsEventLogging())
 
1492
        (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1493
          "Window id: 0x%lx (group leader)",windows->group_leader.id);
 
1494
    }
 
1495
  XMakeWindow(display,
 
1496
    (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
 
1497
    argv,argc,class_hints,manager_hints,&windows->image);
 
1498
  (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
 
1499
    XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
 
1500
  if (windows->group_leader.id != (Window) NULL)
 
1501
    (void) XSetTransientForHint(display,windows->image.id,
 
1502
      windows->group_leader.id);
 
1503
  if (IsEventLogging())
 
1504
    (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
 
1505
      windows->image.id);
 
1506
  /*
 
1507
    Initialize Info widget.
 
1508
  */
 
1509
  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
 
1510
    resource_info,&windows->info);
 
1511
  (void) CloneString(&windows->info.name,"Info");
 
1512
  (void) CloneString(&windows->info.icon_name,"Info");
 
1513
  windows->info.border_width=1;
 
1514
  windows->info.x=2;
 
1515
  windows->info.y=2;
 
1516
  windows->info.flags|=PPosition;
 
1517
  windows->info.attributes.win_gravity=UnmapGravity;
 
1518
  windows->info.attributes.event_mask=
 
1519
    ButtonPressMask | ExposureMask | StructureNotifyMask;
 
1520
  class_hints->res_name=(char *) "info";
 
1521
  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
 
1522
  manager_hints->input=False;
 
1523
  manager_hints->initial_state=NormalState;
 
1524
  manager_hints->window_group=windows->image.id;
 
1525
  XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
 
1526
    &windows->info);
 
1527
  windows->info.highlight_stipple=XCreateBitmapFromData(display,
 
1528
    windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
 
1529
  windows->info.shadow_stipple=XCreateBitmapFromData(display,
 
1530
    windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
 
1531
  (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
 
1532
  if (windows->image.mapped)
 
1533
    (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
 
1534
  if (IsEventLogging())
 
1535
    (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
 
1536
      windows->info.id);
 
1537
  /*
 
1538
    Initialize Command widget.
 
1539
  */
 
1540
  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
 
1541
    resource_info,&windows->command);
 
1542
  windows->command.data=MagickMenus;
 
1543
  (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
 
1544
  FormatString(resource_name,"%.1024s.command",resource_info->client_name);
 
1545
  windows->command.geometry=XGetResourceClass(resource_info->resource_database,
 
1546
    resource_name,"geometry",(char *) NULL);
 
1547
  (void) CloneString(&windows->command.name,MagickTitle);
 
1548
  windows->command.border_width=0;
 
1549
  windows->command.flags|=PPosition;
 
1550
  windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
 
1551
    ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
 
1552
    OwnerGrabButtonMask | StructureNotifyMask;
 
1553
  class_hints->res_name=(char *) "command";
 
1554
  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
 
1555
  manager_hints->input=False;
 
1556
  manager_hints->initial_state=NormalState;
 
1557
  manager_hints->window_group=windows->image.id;
 
1558
  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
 
1559
    &windows->command);
 
1560
  windows->command.highlight_stipple=windows->info.highlight_stipple;
 
1561
  windows->command.shadow_stipple=windows->info.shadow_stipple;
 
1562
  (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
 
1563
  if (IsEventLogging())
 
1564
    (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (command)",
 
1565
      windows->command.id);
 
1566
  /*
 
1567
    Initialize Widget window.
 
1568
  */
 
1569
  if (windows->widget.id != (Window) NULL)
 
1570
    MagickFreeMemory(windows->widget.name);
 
1571
  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
 
1572
    resource_info,&windows->widget);
 
1573
  FormatString(resource_name,"%.1024s.widget",resource_info->client_name);
 
1574
  windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
 
1575
    resource_name,"geometry",(char *) NULL);
 
1576
  windows->widget.name=AllocateString((char *) NULL);
 
1577
  *windows->widget.name='\0';
 
1578
  windows->widget.border_width=0;
 
1579
  windows->widget.flags|=PPosition;
 
1580
  windows->widget.attributes.backing_store=WhenMapped;
 
1581
  windows->widget.attributes.save_under=True;
 
1582
  windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
 
1583
    ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
 
1584
    KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
 
1585
    StructureNotifyMask;
 
1586
  class_hints->res_name=(char *) "widget";
 
1587
  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
 
1588
  manager_hints->input=True;
 
1589
  manager_hints->initial_state=NormalState;
 
1590
  manager_hints->window_group=windows->image.id;
 
1591
  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
 
1592
    &windows->widget);
 
1593
  windows->widget.highlight_stipple=windows->info.highlight_stipple;
 
1594
  windows->widget.shadow_stipple=windows->info.shadow_stipple;
 
1595
  (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
 
1596
  if (IsEventLogging())
 
1597
    (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (widget)",
 
1598
      windows->widget.id);
 
1599
  /*
 
1600
    Initialize popup window.
 
1601
  */
 
1602
  if (windows->popup.id != (Window) NULL)
 
1603
    MagickFreeMemory(windows->popup.name);
 
1604
  XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
 
1605
    resource_info,&windows->popup);
 
1606
  windows->popup.name=AllocateString((char *) NULL);
 
1607
  *windows->popup.name='\0';
 
1608
  windows->popup.border_width=0;
 
1609
  windows->popup.flags|=PPosition;
 
1610
  windows->popup.attributes.backing_store=WhenMapped;
 
1611
  windows->popup.attributes.save_under=True;
 
1612
  windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
 
1613
    ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
 
1614
    KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
 
1615
  class_hints->res_name=(char *) "popup";
 
1616
  manager_hints->flags=InputHint | StateHint | WindowGroupHint;
 
1617
  manager_hints->input=True;
 
1618
  manager_hints->initial_state=NormalState;
 
1619
  manager_hints->window_group=windows->image.id;
 
1620
  XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
 
1621
    &windows->popup);
 
1622
  windows->popup.highlight_stipple=windows->info.highlight_stipple;
 
1623
  windows->popup.shadow_stipple=windows->info.shadow_stipple;
 
1624
  (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
 
1625
  if (IsEventLogging())
 
1626
    (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pop up)",
 
1627
      windows->popup.id);
 
1628
  if (!windows->image.mapped || (windows->backdrop.id != (Window) NULL))
 
1629
    (void) XMapWindow(display,windows->image.id);
 
1630
  /*
 
1631
    Set out progress and warning handlers.
 
1632
  */
 
1633
  if (monitor_handler == (MonitorHandler) NULL)
 
1634
    monitor_handler=SetMonitorHandler(XMagickMonitor);
 
1635
  if (warning_handler == (WarningHandler) NULL)
 
1636
    {
 
1637
      warning_handler=resource_info->display_warnings ?
 
1638
        SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
 
1639
      warning_handler=resource_info->display_warnings ?
 
1640
        SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
 
1641
    }
 
1642
  (void) signal(SIGINT,XSignalHandler);
 
1643
  (void) signal(SIGSEGV,XSignalHandler);
 
1644
  (void) signal(SIGTERM,XSignalHandler);
 
1645
  /*
 
1646
    Initialize X image structure.
 
1647
  */
 
1648
  windows->image.x=0;
 
1649
  windows->image.y=0;
 
1650
  status=XMakeImage(display,resource_info,&windows->image,display_image,
 
1651
    (unsigned int) display_image->columns,(unsigned int) display_image->rows);
 
1652
  if (status == False)
 
1653
    MagickFatalError(XServerFatalError,UnableToCreateXImage,(char *) NULL);
 
1654
  if (windows->image.mapped)
 
1655
    XRefreshWindow(display,&windows->image,(XEvent *) NULL);
 
1656
  /*
 
1657
    Initialize image pixmaps structure.
 
1658
  */
 
1659
  (void) XMapWindow(display,windows->image.id);
 
1660
  windows->image.pixmaps=MagickAllocateMemory(Pixmap *,number_scenes*sizeof(Pixmap));
 
1661
  windows->image.matte_pixmaps=MagickAllocateMemory(Pixmap *,
 
1662
    number_scenes*sizeof(Pixmap));
 
1663
  if ((windows->image.pixmaps == (Pixmap *) NULL) ||
 
1664
      (windows->image.matte_pixmaps == (Pixmap *) NULL))
 
1665
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
 
1666
      UnableToAnimateImageSequence);
 
1667
  windows->image.pixmaps[0]=windows->image.pixmap;
 
1668
  windows->image.matte_pixmaps[0]=windows->image.matte_pixmap;
 
1669
  scene_info.pixels=(unsigned long *) NULL;
 
1670
  for (scene=1; scene < (long) number_scenes; scene++)
 
1671
  {
 
1672
    /*
 
1673
      Create X image.
 
1674
    */
 
1675
    TransformColorspace(image_list[scene],RGBColorspace);
 
1676
    windows->image.pixmap=(Pixmap) NULL;
 
1677
    windows->image.matte_pixmap=(Pixmap) NULL;
 
1678
    if ((resource_info->map_type != (char *) NULL) ||
 
1679
        (visual_info->storage_class == TrueColor) ||
 
1680
        (visual_info->storage_class == DirectColor))
 
1681
      if (image_list[scene]->storage_class == PseudoClass)
 
1682
        {
 
1683
          /*
 
1684
            Get pixel info for this scene.
 
1685
          */
 
1686
          XGetPixelPacket(display,visual_info,map_info,resource_info,
 
1687
                          image_list[scene],&scene_info);
 
1688
          windows->image.pixel_info=(&scene_info);
 
1689
        }
 
1690
    status=XMakeImage(display,resource_info,&windows->image,image_list[scene],
 
1691
      (unsigned int) image_list[scene]->columns,
 
1692
      (unsigned int) image_list[scene]->rows);
 
1693
    if (status == False)
 
1694
      MagickFatalError(XServerFatalError,UnableToCreateXImage,(char *) NULL);
 
1695
    if (IsEventLogging())
 
1696
      {
 
1697
        (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1698
          "Image: [%lu] %.1024s %lux%lu ",image_list[scene]->scene,
 
1699
          image_list[scene]->filename,image_list[scene]->columns,
 
1700
          image_list[scene]->rows);
 
1701
        if (image_list[scene]->colors != 0)
 
1702
          (void) LogMagickEvent(X11Event,GetMagickModule(),"%luc ",
 
1703
            image_list[scene]->colors);
 
1704
        (void) LogMagickEvent(X11Event,GetMagickModule(),"%.1024s",
 
1705
          image_list[scene]->magick);
 
1706
      }
 
1707
    /*
 
1708
      Window name is the base of the filename.
 
1709
    */
 
1710
    if (resource_info->title != (char *) NULL)
 
1711
      windows->image.name=TranslateText(resource_info->image_info,
 
1712
        image_list[scene],resource_info->title);
 
1713
    else
 
1714
      {
 
1715
        p=image_list[scene]->filename+strlen(image_list[scene]->filename)-1;
 
1716
        while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
 
1717
          p--;
 
1718
        FormatString(windows->image.name,"GraphicsMagick: %.1024s[%lu of %lu]",p,
 
1719
          scene,number_scenes);
 
1720
      }
 
1721
    status=XStringListToTextProperty(&windows->image.name,1,&window_name);
 
1722
    if (status != 0)
 
1723
      {
 
1724
        XSetWMName(display,windows->image.id,&window_name);
 
1725
        (void) XFree((void *) window_name.value);
 
1726
      }
 
1727
    windows->image.pixmaps[scene]=windows->image.pixmap;
 
1728
    windows->image.matte_pixmaps[scene]=windows->image.matte_pixmap;
 
1729
    event.xexpose.x=0;
 
1730
    event.xexpose.y=0;
 
1731
    event.xexpose.width=(unsigned int) image_list[scene]->columns;
 
1732
    event.xexpose.height=(unsigned int) image_list[scene]->rows;
 
1733
    XRefreshWindow(display,&windows->image,&event);
 
1734
    XDelay(display,(unsigned long) resource_info->delay*10*Max(images->delay,1));
 
1735
  }
 
1736
  if (windows->command.mapped)
 
1737
    (void) XMapRaised(display,windows->command.id);
 
1738
  /*
 
1739
    Respond to events.
 
1740
  */
 
1741
  nexus=(Image *) NULL;
 
1742
  scene=0;
 
1743
  first_scene=0;
 
1744
  iterations=0;
 
1745
  image=image_list[0];
 
1746
  state=ForwardAnimationState | RepeatAnimationState;
 
1747
  (void) XMagickCommand(display,resource_info,windows,PlayCommand,&images,
 
1748
    &state);
 
1749
  do
 
1750
  {
 
1751
    if (XEventsQueued(display,QueuedAfterFlush) == 0)
 
1752
      if ((state & PlayAnimationState) || (state & StepAnimationState))
 
1753
        {
 
1754
          if (state & ForwardAnimationState)
 
1755
            {
 
1756
              /*
 
1757
                Forward animation:  increment scene number.
 
1758
              */
 
1759
              if (scene < ((long) number_scenes-1))
 
1760
                scene++;
 
1761
              else
 
1762
                {
 
1763
                  iterations++;
 
1764
                  if (iterations == image_list[0]->iterations)
 
1765
                    {
 
1766
                      iterations=0;
 
1767
                      state&=(~RepeatAnimationState);
 
1768
                    }
 
1769
                  if (state & AutoReverseAnimationState)
 
1770
                    {
 
1771
                      state&=(~ForwardAnimationState);
 
1772
                      scene--;
 
1773
                    }
 
1774
                  else
 
1775
                    {
 
1776
                      if (!(state & RepeatAnimationState))
 
1777
                        state&=(~PlayAnimationState);
 
1778
                      scene=first_scene;
 
1779
                      (void) sleep(resource_info->pause);
 
1780
                    }
 
1781
                }
 
1782
            }
 
1783
          else
 
1784
            {
 
1785
              /*
 
1786
                Reverse animation:  decrement scene number.
 
1787
              */
 
1788
              if (scene > first_scene)
 
1789
                scene--;
 
1790
              else
 
1791
                {
 
1792
                  iterations++;
 
1793
                  if (iterations == image_list[0]->iterations)
 
1794
                    {
 
1795
                      iterations=0;
 
1796
                      state&=(~RepeatAnimationState);
 
1797
                    }
 
1798
                  if (state & AutoReverseAnimationState)
 
1799
                    {
 
1800
                      state|=ForwardAnimationState;
 
1801
                      scene=first_scene;
 
1802
                      (void) sleep(resource_info->pause);
 
1803
                    }
 
1804
                  else
 
1805
                    {
 
1806
                      if (!(state & RepeatAnimationState))
 
1807
                        state&=(~PlayAnimationState);
 
1808
                      scene=(long) number_scenes-1;
 
1809
                    }
 
1810
                }
 
1811
            }
 
1812
          image=image_list[scene];
 
1813
          if ((image != (Image *) NULL) && image->start_loop)
 
1814
            first_scene=scene;
 
1815
          if ((state & StepAnimationState) ||
 
1816
              (resource_info->title != (char *) NULL))
 
1817
            {
 
1818
              /*
 
1819
                Update window title.
 
1820
              */
 
1821
              p=image_list[scene]->filename+
 
1822
                strlen(image_list[scene]->filename)-1;
 
1823
              while ((p > image_list[scene]->filename) && (*(p-1) != '/'))
 
1824
                p--;
 
1825
              FormatString(windows->image.name,
 
1826
                "GraphicsMagick: %.1024s[%lu of %lu]",p,scene,number_scenes);
 
1827
              if (resource_info->title != (char *) NULL)
 
1828
                windows->image.name=TranslateText(resource_info->image_info,
 
1829
                  image,resource_info->title);
 
1830
              status=
 
1831
                XStringListToTextProperty(&windows->image.name,1,&window_name);
 
1832
              if (status != 0)
 
1833
                {
 
1834
                  XSetWMName(display,windows->image.id,&window_name);
 
1835
                  (void) XFree((void *) window_name.value);
 
1836
                }
 
1837
            }
 
1838
          /*
 
1839
            Copy X pixmap to Image window.
 
1840
          */
 
1841
          XGetPixelPacket(display,visual_info,map_info,resource_info,
 
1842
            image_list[scene],&scene_info); /* FIXME leak here */
 
1843
          windows->image.pixel_info=(&scene_info);
 
1844
          windows->image.ximage->width=(unsigned int) image->columns;
 
1845
          windows->image.ximage->height=(unsigned int) image->rows;
 
1846
          windows->image.pixmap=windows->image.pixmaps[scene];
 
1847
          windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
 
1848
          event.xexpose.x=0;
 
1849
          event.xexpose.y=0;
 
1850
          event.xexpose.width=(unsigned int) image->columns;
 
1851
          event.xexpose.height=(unsigned int) image->rows;
 
1852
          XRefreshWindow(display,&windows->image,&event);
 
1853
          (void) XSync(display,False);
 
1854
          state&=(~StepAnimationState);
 
1855
          XDelay(display,(unsigned long) resource_info->delay*10*
 
1856
            Max(image->delay,1));
 
1857
          continue;
 
1858
        }
 
1859
    /*
 
1860
      Handle a window event.
 
1861
    */
 
1862
    timestamp=time((time_t *) NULL);
 
1863
    (void) XNextEvent(display,&event);
 
1864
    if (!windows->image.stasis)
 
1865
      windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0;
 
1866
    if (event.xany.window == windows->command.id)
 
1867
      {
 
1868
        int
 
1869
          id;
 
1870
 
 
1871
        /*
 
1872
          Select a command from the Command widget.
 
1873
        */
 
1874
        id=XCommandWidget(display,windows,CommandMenu,&event);
 
1875
        if (id < 0)
 
1876
          continue;
 
1877
        (void) strncpy(command,CommandMenu[id],MaxTextExtent-1);
 
1878
        command_type=CommandMenus[id];
 
1879
        if (id < MagickMenus)
 
1880
          {
 
1881
            int
 
1882
              entry;
 
1883
 
 
1884
            /*
 
1885
              Select a command from a pop-up menu.
 
1886
            */
 
1887
            entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
 
1888
              command);
 
1889
            if (entry < 0)
 
1890
              continue;
 
1891
            (void) strncpy(command,Menus[id][entry],MaxTextExtent-1);
 
1892
            command_type=Commands[id][entry];
 
1893
          }
 
1894
        if (command_type != NullCommand)
 
1895
          nexus=XMagickCommand(display,resource_info,windows,
 
1896
            command_type,&image,&state);
 
1897
        continue;
 
1898
      }
 
1899
    switch (event.type)
 
1900
    {
 
1901
      case ButtonPress:
 
1902
      {
 
1903
        if (IsEventLogging())
 
1904
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1905
            "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
 
1906
            event.xbutton.button,event.xbutton.x,event.xbutton.y);
 
1907
        if ((event.xbutton.button == Button3) &&
 
1908
            (event.xbutton.state & Mod1Mask))
 
1909
          {
 
1910
            /*
 
1911
              Convert Alt-Button3 to Button2.
 
1912
            */
 
1913
            event.xbutton.button=Button2;
 
1914
            event.xbutton.state&=(~Mod1Mask);
 
1915
          }
 
1916
        if (event.xbutton.window == windows->backdrop.id)
 
1917
          {
 
1918
            (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
 
1919
              event.xbutton.time);
 
1920
            break;
 
1921
          }
 
1922
        if (event.xbutton.window == windows->image.id)
 
1923
          {
 
1924
            if (resource_info->immutable)
 
1925
              {
 
1926
                state|=ExitState;
 
1927
                break;
 
1928
              }
 
1929
            /*
 
1930
              Map/unmap Command widget.
 
1931
            */
 
1932
            if (windows->command.mapped)
 
1933
              (void) XWithdrawWindow(display,windows->command.id,
 
1934
                windows->command.screen);
 
1935
            else
 
1936
              {
 
1937
                (void) XCommandWidget(display,windows,CommandMenu,
 
1938
                  (XEvent *) NULL);
 
1939
                (void) XMapRaised(display,windows->command.id);
 
1940
              }
 
1941
          }
 
1942
        break;
 
1943
      }
 
1944
      case ButtonRelease:
 
1945
      {
 
1946
        if (IsEventLogging())
 
1947
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1948
            "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
 
1949
            event.xbutton.button,event.xbutton.x,event.xbutton.y);
 
1950
        break;
 
1951
      }
 
1952
      case ClientMessage:
 
1953
      {
 
1954
        if (IsEventLogging())
 
1955
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
1956
            "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
 
1957
            event.xclient.message_type,event.xclient.format,(unsigned long)
 
1958
            event.xclient.data.l[0]);
 
1959
        if (event.xclient.message_type == windows->im_protocols)
 
1960
          {
 
1961
            if (*event.xclient.data.l == (long) windows->im_update_colormap)
 
1962
              {
 
1963
                /*
 
1964
                  Update graphic context and window colormap.
 
1965
                */
 
1966
                for (i=0; i < (long) number_windows; i++)
 
1967
                {
 
1968
                  if (magick_windows[i]->id == windows->icon.id)
 
1969
                    continue;
 
1970
                  context_values.background=pixel->background_color.pixel;
 
1971
                  context_values.foreground=pixel->foreground_color.pixel;
 
1972
                  (void) XChangeGC(display,magick_windows[i]->annotate_context,
 
1973
                    context_mask,&context_values);
 
1974
                  (void) XChangeGC(display,magick_windows[i]->widget_context,
 
1975
                    context_mask,&context_values);
 
1976
                  context_values.background=pixel->foreground_color.pixel;
 
1977
                  context_values.foreground=pixel->background_color.pixel;
 
1978
                  context_values.plane_mask=
 
1979
                    context_values.background ^ context_values.foreground;
 
1980
                  (void) XChangeGC(display,magick_windows[i]->highlight_context,
 
1981
                    context_mask | GCPlaneMask,&context_values);
 
1982
                  magick_windows[i]->attributes.background_pixel=
 
1983
                    pixel->background_color.pixel;
 
1984
                  magick_windows[i]->attributes.border_pixel=
 
1985
                    pixel->border_color.pixel;
 
1986
                  magick_windows[i]->attributes.colormap=map_info->colormap;
 
1987
                  (void) XChangeWindowAttributes(display,magick_windows[i]->id,
 
1988
                    magick_windows[i]->mask,&magick_windows[i]->attributes);
 
1989
                }
 
1990
                if (windows->backdrop.id != (Window) NULL)
 
1991
                  (void) XInstallColormap(display,map_info->colormap);
 
1992
                break;
 
1993
              }
 
1994
            if (*event.xclient.data.l == (long) windows->im_exit)
 
1995
              {
 
1996
                state|=ExitState;
 
1997
                break;
 
1998
              }
 
1999
            break;
 
2000
          }
 
2001
        if (event.xclient.message_type == windows->dnd_protocols)
 
2002
          {
 
2003
            Atom
 
2004
              selection,
 
2005
              type;
 
2006
 
 
2007
            int
 
2008
              format;
 
2009
 
 
2010
            unsigned char
 
2011
              *data;
 
2012
 
 
2013
            unsigned long
 
2014
              after,
 
2015
              length;
 
2016
 
 
2017
            /*
 
2018
              Display image named by the Drag-and-Drop selection.
 
2019
            */
 
2020
            if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
 
2021
              break;
 
2022
            selection=XInternAtom(display,"DndSelection",False);
 
2023
            status=XGetWindowProperty(display,root_window,selection,0L,2047L,
 
2024
              False,(Atom) AnyPropertyType,&type,&format,&length,&after,&data);
 
2025
            if ((status != Success) || (length == 0))
 
2026
              break;
 
2027
            if (*event.xclient.data.l == 2)
 
2028
              {
 
2029
                /*
 
2030
                  Offix DND.
 
2031
                */
 
2032
                (void) strncpy(resource_info->image_info->filename,
 
2033
                  (char *) data,MaxTextExtent-1);
 
2034
              }
 
2035
            else
 
2036
              {
 
2037
                /*
 
2038
                  XDND.
 
2039
                */
 
2040
                if (LocaleNCompare((char *) data,"file:",5) != 0)
 
2041
                  {
 
2042
                    (void) XFree((void *) data);
 
2043
                    break;
 
2044
                  }
 
2045
                (void) strncpy(resource_info->image_info->filename,
 
2046
                  ((char *) data)+5,MaxTextExtent-1);
 
2047
              }
 
2048
            nexus=ReadImage(resource_info->image_info,&image->exception);
 
2049
            if (image->exception.severity != UndefinedException)
 
2050
              MagickError2(image->exception.severity,image->exception.reason,
 
2051
                image->exception.description);
 
2052
            if (nexus != (Image *) NULL)
 
2053
              state|=ExitState;
 
2054
            (void) XFree((void *) data);
 
2055
            break;
 
2056
          }
 
2057
        /*
 
2058
          If client window delete message, exit.
 
2059
        */
 
2060
        if (event.xclient.message_type != windows->wm_protocols)
 
2061
          break;
 
2062
        if (*event.xclient.data.l == (long) windows->wm_take_focus)
 
2063
          {
 
2064
            (void) XSetInputFocus(display,event.xclient.window,RevertToParent,
 
2065
              event.xclient.data.l[1]);
 
2066
            break;
 
2067
          }
 
2068
        if (*event.xclient.data.l != (long) windows->wm_delete_window)
 
2069
          break;
 
2070
        (void) XWithdrawWindow(display,event.xclient.window,
 
2071
          visual_info->screen);
 
2072
        if (event.xclient.window == windows->image.id)
 
2073
          {
 
2074
            state|=ExitState;
 
2075
            break;
 
2076
          }
 
2077
        break;
 
2078
      }
 
2079
      case ConfigureNotify:
 
2080
      {
 
2081
        if (IsEventLogging())
 
2082
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
2083
            "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
 
2084
            event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
 
2085
            event.xconfigure.y,event.xconfigure.send_event);
 
2086
        if (event.xconfigure.window == windows->image.id)
 
2087
          {
 
2088
            if (event.xconfigure.send_event != 0)
 
2089
              {
 
2090
                XWindowChanges
 
2091
                  window_changes;
 
2092
 
 
2093
                /*
 
2094
                  Position the transient windows relative of the Image window.
 
2095
                */
 
2096
                if (windows->command.geometry == (char *) NULL)
 
2097
                  if (!windows->command.mapped)
 
2098
                    {
 
2099
                       windows->command.x=
 
2100
                          event.xconfigure.x-windows->command.width-25;
 
2101
                        windows->command.y=event.xconfigure.y;
 
2102
                        XConstrainWindowPosition(display,&windows->command);
 
2103
                        window_changes.x=windows->command.x;
 
2104
                        window_changes.y=windows->command.y;
 
2105
                        (void) XReconfigureWMWindow(display,windows->command.id,
 
2106
                          windows->command.screen,CWX | CWY,&window_changes);
 
2107
                    }
 
2108
                if (windows->widget.geometry == (char *) NULL)
 
2109
                  if (!windows->widget.mapped)
 
2110
                    {
 
2111
                      windows->widget.x=
 
2112
                        event.xconfigure.x+event.xconfigure.width/10;
 
2113
                      windows->widget.y=
 
2114
                        event.xconfigure.y+event.xconfigure.height/10;
 
2115
                      XConstrainWindowPosition(display,&windows->widget);
 
2116
                      window_changes.x=windows->widget.x;
 
2117
                      window_changes.y=windows->widget.y;
 
2118
                      (void) XReconfigureWMWindow(display,windows->widget.id,
 
2119
                        windows->widget.screen,CWX | CWY,&window_changes);
 
2120
                    }
 
2121
              }
 
2122
            /*
 
2123
              Image window has a new configuration.
 
2124
            */
 
2125
            windows->image.width=event.xconfigure.width;
 
2126
            windows->image.height=event.xconfigure.height;
 
2127
            break;
 
2128
          }
 
2129
        if (event.xconfigure.window == windows->icon.id)
 
2130
          {
 
2131
            /*
 
2132
              Icon window has a new configuration.
 
2133
            */
 
2134
            windows->icon.width=event.xconfigure.width;
 
2135
            windows->icon.height=event.xconfigure.height;
 
2136
            break;
 
2137
          }
 
2138
        break;
 
2139
      }
 
2140
      case DestroyNotify:
 
2141
      {
 
2142
        /*
 
2143
          Group leader has exited.
 
2144
        */
 
2145
        if (IsEventLogging())
 
2146
          (void) LogMagickEvent(X11Event,GetMagickModule(),"Destroy Notify: 0x%lx",
 
2147
            event.xdestroywindow.window);
 
2148
        if (event.xdestroywindow.window == windows->group_leader.id)
 
2149
          {
 
2150
            state|=ExitState;
 
2151
            break;
 
2152
          }
 
2153
        break;
 
2154
      }
 
2155
      case EnterNotify:
 
2156
      {
 
2157
        /*
 
2158
          Selectively install colormap.
 
2159
        */
 
2160
        if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
 
2161
          if (event.xcrossing.mode != NotifyUngrab)
 
2162
            XInductColormap(display,map_info->colormap);
 
2163
        break;
 
2164
      }
 
2165
      case Expose:
 
2166
      {
 
2167
        if (IsEventLogging())
 
2168
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
2169
            "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
 
2170
            event.xexpose.width,event.xexpose.height,event.xexpose.x,
 
2171
            event.xexpose.y);
 
2172
        /*
 
2173
          Repaint windows that are now exposed.
 
2174
        */
 
2175
        if (event.xexpose.window == windows->image.id)
 
2176
          {
 
2177
            windows->image.pixmap=windows->image.pixmaps[scene];
 
2178
            windows->image.matte_pixmap=windows->image.matte_pixmaps[scene];
 
2179
            XRefreshWindow(display,&windows->image,&event);
 
2180
            break;
 
2181
          }
 
2182
        if (event.xexpose.window == windows->icon.id)
 
2183
          if (event.xexpose.count == 0)
 
2184
            {
 
2185
              XRefreshWindow(display,&windows->icon,&event);
 
2186
              break;
 
2187
            }
 
2188
        break;
 
2189
      }
 
2190
      case KeyPress:
 
2191
      {
 
2192
        static int
 
2193
          length;
 
2194
 
 
2195
        /*
 
2196
          Respond to a user key press.
 
2197
        */
 
2198
        length=XLookupString((XKeyEvent *) &event.xkey,command,sizeof(command),
 
2199
          &key_symbol,(XComposeStatus *) NULL);
 
2200
        *(command+length)='\0';
 
2201
        if (IsEventLogging())
 
2202
          (void) LogMagickEvent(X11Event,GetMagickModule(),"Key press: 0x%lx (%c)",
 
2203
            key_symbol,*command);
 
2204
        command_type=NullCommand;
 
2205
        switch (key_symbol)
 
2206
        {
 
2207
          case XK_o:
 
2208
          {
 
2209
            if (!(event.xkey.state & ControlMask))
 
2210
              break;
 
2211
            command_type=OpenCommand;
 
2212
            break;
 
2213
          }
 
2214
          case XK_BackSpace:
 
2215
          {
 
2216
            command_type=StepBackwardCommand;
 
2217
            break;
 
2218
          }
 
2219
          case XK_space:
 
2220
          {
 
2221
            command_type=StepForwardCommand;
 
2222
            break;
 
2223
          }
 
2224
          case XK_less:
 
2225
          {
 
2226
            command_type=FasterCommand;
 
2227
            break;
 
2228
          }
 
2229
          case XK_greater:
 
2230
          {
 
2231
            command_type=SlowerCommand;
 
2232
            break;
 
2233
          }
 
2234
          case XK_F1:
 
2235
          {
 
2236
            command_type=HelpCommand;
 
2237
            break;
 
2238
          }
 
2239
          case XK_Find:
 
2240
          {
 
2241
            command_type=BrowseDocumentationCommand;
 
2242
            break;
 
2243
          }
 
2244
          case XK_question:
 
2245
          {
 
2246
            command_type=InfoCommand;
 
2247
            break;
 
2248
          }
 
2249
          case XK_q:
 
2250
          case XK_Cancel:
 
2251
          {
 
2252
            if (!(event.xkey.state & ControlMask))
 
2253
              break;
 
2254
            command_type=QuitCommand;
 
2255
            break;
 
2256
          }
 
2257
          default:
 
2258
            break;
 
2259
        }
 
2260
        if (command_type != NullCommand)
 
2261
          nexus=XMagickCommand(display,resource_info,windows,
 
2262
            command_type,&image,&state);
 
2263
        break;
 
2264
      }
 
2265
      case KeyRelease:
 
2266
      {
 
2267
        /*
 
2268
          Respond to a user key release.
 
2269
        */
 
2270
        (void) XLookupString((XKeyEvent *) &event.xkey,command,sizeof(command),
 
2271
          &key_symbol,(XComposeStatus *) NULL);
 
2272
        if (IsEventLogging())
 
2273
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
2274
            "Key release: 0x%lx (%c)",key_symbol,*command);
 
2275
        break;
 
2276
      }
 
2277
      case LeaveNotify:
 
2278
      {
 
2279
        /*
 
2280
          Selectively uninstall colormap.
 
2281
        */
 
2282
        if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
 
2283
          if (event.xcrossing.mode != NotifyUngrab)
 
2284
            XUninductColormap(display,map_info->colormap);
 
2285
        break;
 
2286
      }
 
2287
      case MapNotify:
 
2288
      {
 
2289
        if (IsEventLogging())
 
2290
          (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
 
2291
            event.xmap.window);
 
2292
        if (event.xmap.window == windows->backdrop.id)
 
2293
          {
 
2294
            (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
 
2295
              CurrentTime);
 
2296
            windows->backdrop.mapped=True;
 
2297
            break;
 
2298
          }
 
2299
        if (event.xmap.window == windows->image.id)
 
2300
          {
 
2301
            if (windows->backdrop.id != (Window) NULL)
 
2302
              (void) XInstallColormap(display,map_info->colormap);
 
2303
            if (LocaleCompare(image_list[0]->magick,"LOGO") == 0)
 
2304
              {
 
2305
                if (LocaleCompare(display_image->filename,"Untitled") == 0)
 
2306
                  nexus=XMagickCommand(display,resource_info,windows,
 
2307
                    OpenCommand,&image,&state);
 
2308
                else
 
2309
                  state|=ExitState;
 
2310
              }
 
2311
            windows->image.mapped=True;
 
2312
            break;
 
2313
          }
 
2314
        if (event.xmap.window == windows->info.id)
 
2315
          {
 
2316
            windows->info.mapped=True;
 
2317
            break;
 
2318
          }
 
2319
        if (event.xmap.window == windows->icon.id)
 
2320
          {
 
2321
            /*
 
2322
              Create an icon image.
 
2323
            */
 
2324
            XMakeStandardColormap(display,icon_visual,icon_resources,
 
2325
              display_image,icon_map,icon_pixel);
 
2326
            (void) XMakeImage(display,icon_resources,&windows->icon,
 
2327
              display_image,windows->icon.width,windows->icon.height);
 
2328
            (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
 
2329
              windows->icon.pixmap);
 
2330
            (void) XClearWindow(display,windows->icon.id);
 
2331
            (void) XWithdrawWindow(display,windows->info.id,
 
2332
              windows->info.screen);
 
2333
            windows->icon.mapped=True;
 
2334
            break;
 
2335
          }
 
2336
        if (event.xmap.window == windows->command.id)
 
2337
          {
 
2338
            windows->command.mapped=True;
 
2339
            break;
 
2340
          }
 
2341
        if (event.xmap.window == windows->popup.id)
 
2342
          {
 
2343
            windows->popup.mapped=True;
 
2344
            break;
 
2345
          }
 
2346
        if (event.xmap.window == windows->widget.id)
 
2347
          {
 
2348
            windows->widget.mapped=True;
 
2349
            break;
 
2350
          }
 
2351
        break;
 
2352
      }
 
2353
      case MappingNotify:
 
2354
      {
 
2355
        (void) XRefreshKeyboardMapping(&event.xmapping);
 
2356
        break;
 
2357
      }
 
2358
      case NoExpose:
 
2359
        break;
 
2360
      case PropertyNotify:
 
2361
      {
 
2362
        Atom
 
2363
          type;
 
2364
 
 
2365
        int
 
2366
          format;
 
2367
 
 
2368
        unsigned char
 
2369
          *data;
 
2370
 
 
2371
        unsigned long
 
2372
          after,
 
2373
          length;
 
2374
 
 
2375
        if (IsEventLogging())
 
2376
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
2377
            "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
 
2378
            event.xproperty.atom,event.xproperty.state);
 
2379
        if (event.xproperty.atom != windows->im_remote_command)
 
2380
          break;
 
2381
        /*
 
2382
          Display image named by the remote command protocol.
 
2383
        */
 
2384
        status=XGetWindowProperty(display,event.xproperty.window,
 
2385
          event.xproperty.atom,0L,MaxTextExtent-1,False,(Atom) AnyPropertyType,
 
2386
          &type,&format,&length,&after,&data);
 
2387
        if ((status != Success) || (length == 0))
 
2388
          break;
 
2389
        (void) strncpy(resource_info->image_info->filename,(char *) data,
 
2390
          MaxTextExtent-1);
 
2391
        nexus=ReadImage(resource_info->image_info,&image->exception);
 
2392
        if (image->exception.severity != UndefinedException)
 
2393
          MagickError2(image->exception.severity,image->exception.reason,
 
2394
            image->exception.description);
 
2395
        if (nexus != (Image *) NULL)
 
2396
          state|=ExitState;
 
2397
        (void) XFree((void *) data);
 
2398
        break;
 
2399
      }
 
2400
      case ReparentNotify:
 
2401
      {
 
2402
        if (IsEventLogging())
 
2403
          (void) LogMagickEvent(X11Event,GetMagickModule(),
 
2404
            "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
 
2405
            event.xreparent.window);
 
2406
        break;
 
2407
      }
 
2408
      case UnmapNotify:
 
2409
      {
 
2410
        if (IsEventLogging())
 
2411
          (void) LogMagickEvent(X11Event,GetMagickModule(),"Unmap Notify: 0x%lx",
 
2412
            event.xunmap.window);
 
2413
        if (event.xunmap.window == windows->backdrop.id)
 
2414
          {
 
2415
            windows->backdrop.mapped=False;
 
2416
            break;
 
2417
          }
 
2418
        if (event.xunmap.window == windows->image.id)
 
2419
          {
 
2420
            windows->image.mapped=False;
 
2421
            break;
 
2422
          }
 
2423
        if (event.xunmap.window == windows->info.id)
 
2424
          {
 
2425
            windows->info.mapped=False;
 
2426
            break;
 
2427
          }
 
2428
        if (event.xunmap.window == windows->icon.id)
 
2429
          {
 
2430
            if (map_info->colormap == icon_map->colormap)
 
2431
              XConfigureImageColormap(display,resource_info,windows,
 
2432
                display_image);
 
2433
            (void) XFreeStandardColormap(display,icon_visual,icon_map,
 
2434
              icon_pixel);
 
2435
            windows->icon.mapped=False;
 
2436
            break;
 
2437
          }
 
2438
        if (event.xunmap.window == windows->command.id)
 
2439
          {
 
2440
            windows->command.mapped=False;
 
2441
            break;
 
2442
          }
 
2443
        if (event.xunmap.window == windows->popup.id)
 
2444
          {
 
2445
            if (windows->backdrop.id != (Window) NULL)
 
2446
              (void) XSetInputFocus(display,windows->image.id,RevertToParent,
 
2447
                CurrentTime);
 
2448
            windows->popup.mapped=False;
 
2449
            break;
 
2450
          }
 
2451
        if (event.xunmap.window == windows->widget.id)
 
2452
          {
 
2453
            if (windows->backdrop.id != (Window) NULL)
 
2454
              (void) XSetInputFocus(display,windows->image.id,RevertToParent,
 
2455
                CurrentTime);
 
2456
            windows->widget.mapped=False;
 
2457
            break;
 
2458
          }
 
2459
        break;
 
2460
      }
 
2461
      default:
 
2462
      {
 
2463
        if (IsEventLogging())
 
2464
          (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
 
2465
            event.type);
 
2466
        break;
 
2467
      }
 
2468
    }
 
2469
  }
 
2470
  while (!(state & ExitState));
 
2471
  MagickFreeMemory(image_list);
 
2472
  if (coalesce)
 
2473
    {
 
2474
      DestroyImageList(images);
 
2475
      images=(Image *) NULL;
 
2476
    }
 
2477
  if ((windows->visual_info->storage_class == GrayScale) ||
 
2478
      (windows->visual_info->storage_class == PseudoColor) ||
 
2479
      (windows->visual_info->storage_class == DirectColor))
 
2480
    {
 
2481
      /*
 
2482
        Withdraw windows.
 
2483
      */
 
2484
      if (windows->info.mapped)
 
2485
        (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
 
2486
      if (windows->command.mapped)
 
2487
        (void) XWithdrawWindow(display,windows->command.id,
 
2488
          windows->command.screen);
 
2489
    }
 
2490
  if (!resource_info->backdrop)
 
2491
    if (windows->backdrop.mapped)
 
2492
      {
 
2493
        (void) XWithdrawWindow(display,windows->backdrop.id,
 
2494
          windows->backdrop.screen);
 
2495
        (void) XDestroyWindow(display,windows->backdrop.id);
 
2496
        windows->backdrop.id=(Window) NULL;
 
2497
        (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
 
2498
        (void) XDestroyWindow(display,windows->image.id);
 
2499
        windows->image.id=(Window) NULL;
 
2500
      }
 
2501
  XSetCursorState(display,windows,True);
 
2502
  XCheckRefreshWindows(display,windows);
 
2503
  for (scene=1; scene < (long) number_scenes; scene++)
 
2504
  {
 
2505
    if (windows->image.pixmaps[scene] != (Pixmap) NULL)
 
2506
      (void) XFreePixmap(display,windows->image.pixmaps[scene]);
 
2507
    windows->image.pixmaps[scene]=(Pixmap) NULL;
 
2508
 
 
2509
    if (windows->image.matte_pixmaps[scene] != (Pixmap) NULL)
 
2510
      (void) XFreePixmap(display,windows->image.matte_pixmaps[scene]);
 
2511
    windows->image.matte_pixmaps[scene]=(Pixmap) NULL;
 
2512
  }
 
2513
  MagickFreeMemory(windows->image.pixmaps);
 
2514
  MagickFreeMemory(windows->image.matte_pixmaps);
 
2515
  if (nexus == (Image *) NULL)
 
2516
    {
 
2517
      /*
 
2518
        Destroy X windows.
 
2519
      */
 
2520
      if (windows->image.mapped)
 
2521
        (void) XWithdrawWindow(display,windows->image.id,windows->image.screen);
 
2522
      XDelay(display,SuspendTime);
 
2523
 
 
2524
      /*
 
2525
        Free Standard Colormap.
 
2526
      */
 
2527
      (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
 
2528
      if (resource_info->map_type == (char *) NULL)
 
2529
        (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
 
2530
      /*
 
2531
        Free X resources.
 
2532
      */
 
2533
      XDestroyXWindows(windows);
 
2534
    }
 
2535
  (void) XSync(display,False);
 
2536
  /*
 
2537
    Restore our progress monitor and warning handlers.
 
2538
  */
 
2539
  (void) SetMonitorHandler(monitor_handler);
 
2540
  (void) SetErrorHandler(warning_handler);
 
2541
  (void) SetWarningHandler(warning_handler);
 
2542
  /*
 
2543
    Change to home directory.
 
2544
  */
 
2545
  (void) getcwd(working_directory,MaxTextExtent-1);
 
2546
  (void) chdir(resource_info->home_directory);
 
2547
  return(nexus);
 
2548
}
 
2549
#endif