home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / x / animutil / xanim229.lha / xanim / xanim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-08  |  37.6 KB  |  1,418 lines

  1.  
  2. /*
  3.  * xanim.c
  4.  *
  5.  * Copyright (C) 1990,1991,1992 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed
  9.  * without fee provided that this copyright notice is preserved 
  10.  * intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18.  
  19. #define DA_REV 2.29
  20.  
  21. /*
  22.  *
  23.  */
  24.  
  25. #include <X11/Xlib.h>
  26. #include <X11/Intrinsic.h>
  27. #include <X11/StringDefs.h>
  28. #include <X11/Shell.h>
  29. #include <stdio.h>
  30. #include <sys/types.h>
  31. #include <sys/signal.h>
  32. #include <sys/param.h>
  33. #include <sys/times.h>
  34. #include <memory.h>
  35. #include <ctype.h>
  36. #include "mytypes.h"
  37. #include "xanim.h"
  38. #include "xanim_x11.h"
  39.  
  40. void TheEnd();
  41. void TheEnd1();
  42. void Usage();
  43. ULONG GetWord();
  44. ULONG GetHalfWord();
  45. void ShowAnimation();
  46. void ShowAction();
  47. int Determine_Anim_Type();
  48. void Cycle_It();
  49.  
  50. /*
  51.  * Global X11 display configuation variables
  52.  *
  53.  * These are set by X11_Pre_Setup();
  54.  *
  55.  */
  56.  
  57. int x11_depth;
  58. int x11_class;
  59. int x11_bytes_pixel;
  60. int x11_cmap_flag;
  61. int x11_cmap_size;
  62. int x11_display_type;
  63.  
  64. /*
  65.  * Each animation is broken up into a series of individual actions.
  66.  * For example, a gif image would become two actions, 1 to setup the
  67.  * colormap and 1 to display the image.
  68.  *
  69.  * ACTION is defined in xanim.h. 
  70.  *
  71.  * action_cnt is a global variable that points to the next unused action.
  72.  * Currently, individual routines access this. This will change.
  73.  *
  74.  * action_start is a variable passed to the Read_Animation routines, It
  75.  * keeps track of the 1st action available to routine.
  76.  *
  77.  */
  78. ACTION action[2000];
  79. int action_cnt;
  80. int action_start;
  81.  
  82. /*
  83.  * This structure is set up for each animation file. It keeps track of
  84.  * special flags and which animation type.
  85.  *
  86.  * anim_cnt indexes the next available anim structure.
  87.  *
  88.  * anim_type is one of IFF_,FLI_,GIF_,TXT_,FADE_ANIM. 
  89.  *
  90.  * merged_anim_flags is the or of all anims read in. FLI's anims need
  91.  * only 1 buffer. IFF anims need two. This allows software to allocate
  92.  * for the worst case.
  93.  *
  94.  */
  95. ANIM_HDR anim[50];
  96. int anim_cnt;
  97. int anim_type;
  98. int merged_anim_flags;
  99.  
  100.  
  101. /*
  102.  * cmap keeps track of the current colors to the screen.
  103.  *
  104.  * hmap is IFF HAM specific and is needed to decode HAM images into 332
  105.  * and into 24bits when supported.
  106.  *
  107.  */
  108. ColorReg *cmap = 0;
  109. ColorReg ham_map[HMAP_SIZE];
  110.  
  111. /*
  112.  * Global variable to keep track of Anim type
  113.  */
  114. int filetype;
  115.  
  116. /*
  117.  * Global variables to keep track of current width, height, num of colors and
  118.  * number of bit planes respectively. 
  119.  *
  120.  * the max_ variable are used for worst case allocation. Are useful for Anims
  121.  * that have multiple image sizes.
  122.  *
  123.  * image_size and max_image_size are imagex * imagey, etc.
  124.  */
  125. int imagex, imagey, max_imagex, max_imagey;
  126. int disp_y, max_disp_y;
  127. int imagec, imaged;
  128. int image_size;
  129. int max_image_size;
  130.  
  131. /* 
  132.  * These variable keep track of where we are in the animation.
  133.  * cur_file  keeps track of which file we're displaying. (ie anim[ cur_file] )
  134.  * cur_floop keeps track of how many times we've looped a file.
  135.  * cur_frame keeps track of which frame(action) we're on.
  136.  *
  137.  * cycle_wait and cycle_cnt are used for color cycling.
  138.  *
  139.  * start_file indicates whether this is the 1st time we've looped a file
  140.  * or not. Is used to initialize variables and resize window if necessary.
  141.  * 
  142.  */
  143. int cur_file,cur_floop,cur_frame;
  144. int cycle_wait,cycle_cnt;
  145. int start_file;
  146. int anim_forward_flag;
  147. /*
  148.  * Image buffers.
  149.  * im_buff1 is used for double buffered anims(IFF).
  150.  * hbuff is need as temporary space for storing the 332 images with HAM(IFF).
  151.  *
  152.  * pic is a pointer to im_buff0 or im_buff1 during double buffering.
  153.  *
  154.  */
  155. char *im_buff0,*im_buff1,*pic,*hbuff;
  156.  
  157. /* 
  158.  * Global flags that are set on command line.
  159.  */
  160. int buff_flag;
  161. int loopeach_flag;
  162. int anim_flags;
  163. int cycle_on_flag;
  164. int debug_flag;
  165. int verbose;
  166. int jiffy_flag;
  167. int fade_flag,fade_time;
  168. int noresize_flag;
  169. int anim_running;
  170. int update_flag;
  171. int optimize_flag;
  172.  
  173. /*
  174.  * old_dlta is used for optimizing screen updates for IFF and FLI animations.
  175.  *
  176.  * act is a global pointer to the current action.
  177.  *
  178.  */
  179. ACT_IFF_DLTA_HDR old_dlta[2];
  180. ACTION *act;
  181.  
  182. /*
  183.  * This function (hopefully) provides a clean exit from our code.
  184.  */
  185. void TheEnd()
  186. {
  187.  if (action_cnt > 0 )
  188.  {
  189.   int i;
  190.   for(i=0;i<action_cnt;i++)
  191.    if (action[i].data != 0) free(action[i].data);
  192.  }
  193.  if (im_buff0) free(im_buff0);
  194.  if (im_buff1) free(im_buff1);
  195.  if (hbuff) free(hbuff);
  196.  if (cmap) free(cmap);
  197.  /*if (theDisp) XtCloseDisplay(theDisp); */
  198.  exit(0);
  199. }
  200.  
  201. /*
  202.  * just prints a message before calling TheEnd()
  203.  */
  204. void TheEnd1(err_mess)
  205. char *err_mess;
  206. {
  207.  fprintf(stderr,"%s\n",err_mess);
  208.  TheEnd();
  209. }
  210.  
  211. /*
  212.  * This function attempts to expain XAnim's usage if the command line
  213.  * wasn't correct.
  214.  */
  215. void Usage()
  216. {
  217.  fprintf(stderr,"Usage:\n\n");
  218.  fprintf(stderr,"xanim [ [+|-]opts ...] animfile [ [ [-opts] animfile] ... ]\n");
  219.  fprintf(stderr,"\n");
  220.  fprintf(stderr,"A + turns the following options on and a - turns them off.\n");
  221.  fprintf(stderr,"Option f,j and l ignore leading + and -'s.\n");
  222.  fprintf(stderr,"\n");
  223.  fprintf(stderr,"Options:\n");
  224.  fprintf(stderr,"\n");
  225.  fprintf(stderr,"       b    buffers images ahead of time. default is off.\n"); 
  226.  fprintf(stderr,"       c    disable looping for nonlooping iff anims.\n"); 
  227.  fprintf(stderr,"               default is off.\n"); 
  228.  fprintf(stderr,"       f#   fade to black in 16 frames. frame delay=#ms\n");
  229.  fprintf(stderr,"               default is off.\n"); 
  230.  fprintf(stderr,"       i    Interlace flag. Reduce image height by two\n"); 
  231.  fprintf(stderr,"               default is off.\n"); 
  232.  fprintf(stderr,"       j#   # is number of milliseconds between frames\n");
  233.  fprintf(stderr,"               (default is 17 unless specified inside the\n");
  234.  fprintf(stderr,"                the animation itself).\n");
  235.  fprintf(stderr,"       l#   # is number of loops(default = 1) through each\n"); fprintf(stderr,"               file before moving next file.\n");
  236.  fprintf(stderr,"       r    turn color cycling off. default is on\n"); 
  237.  fprintf(stderr,"       o    turns on certain optimizations. Turning this\n"); 
  238.  fprintf(stderr,"               off would only be useful if you are\n"); 
  239.  fprintf(stderr,"               buffering the anim and wish to run it\n");
  240.  fprintf(stderr,"               backwards. default is on.\n"); 
  241.  fprintf(stderr,"       s    prevents window from resizing to match image\n"); 
  242.  fprintf(stderr,"               size. Window is the size of largest image.\n"); 
  243.  fprintf(stderr,"               default is on.\n"); 
  244.  fprintf(stderr,"       u    when single stepping, anim is played until\n");
  245.  fprintf(stderr,"               image is updated/changed.(a new cmap is\n");
  246.  fprintf(stderr,"               not considered an update) default is on.\n");
  247.  fprintf(stderr,"       v    verbose mode. default is off.\n"); 
  248.  fprintf(stderr,"\n");
  249.  fprintf(stderr,"Window commands when anim is NOT running\n");
  250.  fprintf(stderr,"\n");
  251.  fprintf(stderr,"        q    quit\n");
  252.  fprintf(stderr,"        g    For cycling images, move to next file\n");
  253.  fprintf(stderr,"        s    Stop cycling\n");
  254.  fprintf(stderr,"        r    Restore Colors after stopping cycling\n");
  255.  fprintf(stderr,"      space  toggle. starts/stops animation\n");
  256.  fprintf(stderr,"        ,    go back one frame within file\n");
  257.  fprintf(stderr,"        .    go forward one frame within file\n");
  258.  fprintf(stderr,"        <    go back to start of previous file\n");
  259.  fprintf(stderr,"        >    go forward to start of next file\n");
  260.  fprintf(stderr,"\n");
  261.  
  262.  exit(0);
  263. }
  264.  
  265. main(argc, argv)
  266. int argc;
  267. char *argv[];
  268. {
  269.  char *filename,*in;
  270.  int i,j;
  271.  
  272. /* 
  273.  * Initialize global variables.
  274.  */
  275.  theDisp = NULL;
  276.  
  277.  im_buff0 = 0;
  278.  im_buff1 = 0;
  279.  hbuff = 0;
  280.  max_imagex = 0;
  281.  max_imagey = 0;
  282.  max_disp_y = 0;
  283.  
  284.  anim_cnt = 0;    
  285.  action_cnt = 0;
  286.  
  287.  anim_forward_flag = TRUE;
  288.  anim_running  = TRUE;
  289.  buff_flag     = FALSE;
  290.  cycle_on_flag = TRUE;
  291.  noresize_flag = FALSE;
  292.  verbose       = FALSE;
  293.  debug_flag    = FALSE;
  294.  update_flag   = TRUE;
  295.  optimize_flag = TRUE;
  296.  
  297.  anim_flags        = ANIM_CYCON;
  298.  merged_anim_flags = 0;
  299.  loopeach_flag     = 1;
  300.  jiffy_flag        = 0;
  301.  
  302.  
  303. /* What rev are we running
  304.  */
  305.  fprintf(stderr,"XAnim Rev %2.2f Beta by Mark Podlipec (c) 1990,1991,1992\n",DA_REV);
  306.  
  307. /* quick command line check.
  308.  */
  309.  if (argc<2) Usage();
  310.  
  311. /* setup for dying time.
  312.  */
  313.  signal(SIGINT,TheEnd);
  314.  
  315.  /* PreSet of X11 Display to find out what we're dealing with
  316.   */
  317.  X11_Pre_Setup();
  318.  
  319.  cmap = (ColorReg *) malloc( x11_cmap_size * sizeof(ColorReg) );
  320.  
  321. /* Parse command line.
  322.  */
  323.  for(i=1;i<argc;i++)
  324.  {
  325.    in = argv[i];
  326.    if ( (in[0]=='-') || (in[0]=='+') )
  327.    {
  328.      int len,opt_on;
  329.  
  330.      if (in[0]=='-') opt_on = FALSE;
  331.      else opt_on = TRUE;
  332.  
  333.      len = strlen(argv[i]);
  334.      j = 1;
  335.      while( (j<len) && (in[j]!=0) )
  336.      {
  337.        switch(in[j])
  338.        {
  339.         case 'b':
  340.         buff_flag = opt_on;
  341.         j++;
  342.           break;
  343.         case 'c':
  344.                 if (opt_on==TRUE)   anim_flags |= ANIM_NOLOP;
  345.                 else            anim_flags &= (~ANIM_NOLOP);
  346.         j++;
  347.           break;
  348.         case 'd':
  349.         debug_flag = opt_on;
  350.         if (opt_on==TRUE)   anim_flags |= ANIM_DEBUG;
  351.                 else            anim_flags &= (~ANIM_DEBUG);
  352.                 j++;
  353.           break;
  354.         case 'f':
  355.         fade_time = atoi(&in[2]);
  356.         if (fade_time <= 0) fade_flag = 0;
  357.         else fade_flag = 1;
  358.         j+=len;
  359.         break;
  360.         case 'l':
  361.         loopeach_flag = atoi(&in[2]);
  362.         if (loopeach_flag<=0) loopeach_flag = 1;
  363.         j+=len;
  364.           break;
  365.         case 'i':
  366.         if (opt_on==TRUE) anim_flags |= ANIM_LACE;
  367.                 else anim_flags &= (~ANIM_LACE);
  368.                 j++;
  369.           break;
  370.         case 'j':
  371.         jiffy_flag = atoi(&in[2]);
  372.         if (jiffy_flag<=0) jiffy_flag = 1;
  373.         j+=len;
  374.           break;
  375.         case 'o':
  376.         optimize_flag = opt_on;
  377.                 j++;
  378.           break;
  379.         case 'r':
  380.         cycle_on_flag = opt_on;
  381.                 if (opt_on==TRUE)   anim_flags |= ANIM_CYCON;
  382.                 else            anim_flags &= (~ANIM_CYCON);
  383.         j++;
  384.           break;
  385.         case 's':
  386.         noresize_flag = opt_on;
  387.                 j++;
  388.           break;
  389.         case 'u':
  390.         update_flag = opt_on;
  391.                 j++;
  392.           break;
  393.         case 'v':
  394.         verbose = opt_on;
  395.         j++;
  396.           break;
  397.         case '-':
  398.         opt_on = FALSE;
  399.         j++;
  400.           break;
  401.         case '+':
  402.         opt_on = TRUE;
  403.         j++;
  404.           break;
  405.         default:
  406.         Usage();
  407.        } /* end of option switch */
  408.      } /* end of loop through options */
  409.    } /* end of if - */
  410.    else 
  411.    /* If no hyphen in front of argument, assume it's a file.
  412.     */
  413.    {
  414.      action_start = action_cnt;
  415.      filename = argv[i];
  416.  
  417.     /* default is FLI  */
  418.      anim_type = Determine_Anim_Type(filename);
  419.      anim[anim_cnt].anim_type = anim_type;
  420.      switch(anim_type)
  421.      {
  422.         int action_number,ii;
  423.         case IFF_ANIM:
  424.         if (verbose) fprintf(stderr,"Reading IFF File %s\n",filename);
  425.         merged_anim_flags |= ANIM_IFF;
  426.          IFF_Read_File(filename);
  427.          if (buff_flag) IFF_Buffer_Action(action_start);
  428.         break;
  429.         case GIF_ANIM:
  430.         if (verbose) fprintf(stderr,"Reading GIF File %s\n",filename);
  431.         GIF_Read_File(filename,1);
  432.  
  433.         action_number = action_cnt - action_start;
  434.         anim[anim_cnt].frame_lst = 
  435.                       (int *)malloc(sizeof(int) * (action_number+1));
  436.         if (anim[anim_cnt].frame_lst == NULL)
  437.                       TheEnd1("GIF_ANIM: couldn't malloc for frame_lst\0");
  438.         for(ii=0; ii < action_number; ii++)
  439.                             anim[anim_cnt].frame_lst[ii]=action_start+ii;
  440.                 anim[anim_cnt].frame_lst[action_number] = -1;
  441.                 anim[anim_cnt].loop_frame = 0;
  442.                 anim[anim_cnt].last_frame = action_number-1;
  443.         break;
  444.         case TXT_ANIM:
  445.         if (verbose) fprintf(stderr,"Reading TXT File %s\n",filename);
  446.         TXT_Read_File(filename);
  447.         break;
  448.         case FLI_ANIM:
  449.         if (verbose) fprintf(stderr,"Reading FLI File %s\n",filename);
  450.         Read_Fli_File(filename);
  451.         if (buff_flag) Fli_Buffer_Action(action_start);
  452.  
  453.         action_number = action_cnt - action_start;
  454.         anim[anim_cnt].frame_lst = 
  455.                       (int *)malloc(sizeof(int) * (action_number+1));
  456.         if (anim[anim_cnt].frame_lst == NULL)
  457.                       TheEnd1("GIF_ANIM: couldn't malloc for frame_lst\0");
  458.         for(ii=0; ii < action_number; ii++)
  459.                             anim[anim_cnt].frame_lst[ii]=action_start+ii;
  460.                 anim[anim_cnt].frame_lst[action_number] = -1;
  461.                 anim[anim_cnt].loop_frame = 0;
  462.                 anim[anim_cnt].last_frame = action_number-1;
  463.         break;
  464.         default:
  465.         fprintf(stderr,"Unknown or unsupported animation type\n");
  466.         break;
  467.       } 
  468.       /*
  469.        * Setup up anim header.
  470.        */
  471.       anim[anim_cnt].imagex = imagex;
  472.       anim[anim_cnt].imagey = imagey;
  473.       anim[anim_cnt].imagec = imagec;
  474.       anim[anim_cnt].imaged = imaged;
  475.       anim[anim_cnt].anim_flags = anim_flags;
  476.       anim[anim_cnt].loop_num = loopeach_flag;
  477.       merged_anim_flags |= anim_flags;
  478.  
  479.       anim_cnt++;
  480.  
  481.       if (imagex > max_imagex) max_imagex = imagex;
  482.       if (imagey > max_imagey) max_imagey = imagey;
  483.       if (anim_flags & ANIM_LACE) 
  484.       {
  485.         if ((imagey/2) > max_disp_y) max_disp_y = imagey/2;
  486.       }
  487.       else
  488.       {
  489.         if ( imagey     > max_disp_y) max_disp_y = imagey;
  490.       }
  491.  
  492.       /*
  493.        * If fade flag is on, basically insert a fade anim.
  494.        */
  495.       if (fade_flag && (x11_cmap_flag == TRUE) )
  496.       {
  497.         int ii;
  498.         anim[anim_cnt].anim_type = FADE_ANIM;
  499.    
  500.         /* Fade to Black action */
  501.         action_start = action_cnt;
  502.         action[action_cnt].type = ACT_FADE;
  503.         action[action_cnt].time = fade_time;
  504.         action[action_cnt].data = 0;
  505.         action_cnt++;
  506.         /* Blank screen so next CMAP doesn't show */
  507.         action[action_cnt].type = ACT_FLI_BLACK;
  508.         action[action_cnt].time = fade_time;
  509.         action[action_cnt].data = 0;
  510.         action_cnt++;
  511.  
  512.  
  513.         /* 
  514.          * Setup frame list to call ACT_FADE sixteen times and FLI_BLACK once.
  515.          */
  516.         anim[anim_cnt].frame_lst = (int *)malloc(sizeof(int) * (18));
  517.         if (anim[anim_cnt].frame_lst == NULL)
  518.                   TheEnd1("FADE_ANIM: couldn't malloc for frame_lst\0");
  519.         for(ii=0;ii<16;ii++) anim[anim_cnt].frame_lst[ii] = action_start;
  520.         anim[anim_cnt].frame_lst[16] = action_start+1;
  521.         /* Last frame is always -1
  522.          */
  523.         anim[anim_cnt].frame_lst[17] = -1;
  524.  
  525.         anim[anim_cnt].imagex = imagex;
  526.         anim[anim_cnt].imagey = imagey;
  527.         anim[anim_cnt].imagec = imagec;
  528.         anim[anim_cnt].imaged = imaged;
  529.         anim[anim_cnt].anim_flags = anim_flags;
  530.         anim[anim_cnt].loop_num = 1;
  531.         anim[anim_cnt].loop_frame = 0;
  532.         anim[anim_cnt].last_frame = 16;
  533.         anim_cnt++;
  534.       } /* end of fade anim insertion */
  535.  
  536.     } /* end of read in file */
  537.  } /* end of loopin through arguments */
  538.  
  539.  /* No anims listed
  540.   */
  541.  if (anim_cnt == 0) Usage();
  542.  
  543.  /* Set up X11 Display
  544.   */
  545.  
  546.  if (noresize_flag==TRUE)
  547.   X11_Setup(max_imagex,max_disp_y,max_imagex,max_disp_y);
  548.  else
  549.   X11_Setup(max_imagex,max_disp_y,anim[0].imagex,
  550.      (anim[0].anim_flags & ANIM_LACE)?(anim[0].imagey/2):(anim[0].imagey) );
  551.  
  552.  /* Start off Animation.
  553.   */
  554.  ShowAnimation();
  555.  /* Wait for user input.
  556.   */
  557.  xanim_events();
  558.  
  559.  /* Self-Explanatory
  560.   */
  561.  TheEnd();
  562. }
  563.  
  564. /* Routine to read a long word.
  565.  * yeah, I know macro's are faster.
  566.  */
  567. ULONG GetWord(fp)
  568. FILE *fp;
  569. {
  570.  ULONG ret;
  571.  
  572.  ret =  fgetc(fp);
  573.  ret |= fgetc(fp) << 8;
  574.  ret |= fgetc(fp) << 16;
  575.  ret |= fgetc(fp) << 24;
  576.  return ret;
  577. }
  578.  
  579. /* Routine to read a half word.
  580.  * yeah, I know macro's are faster.
  581.  */
  582. ULONG GetHalfWord(fp)
  583. FILE *fp;
  584. {
  585.  ULONG ret;
  586.  
  587.  ret =  fgetc(fp);
  588.  ret |= fgetc(fp) << 8;
  589.  return ret;
  590. }
  591.  
  592.  
  593. /*
  594.  * ShowAnimation allocates and sets up required image buffers and
  595.  * initializes animation variables.
  596.  * It then kicks off the animation.
  597.  */
  598. void ShowAnimation()
  599. {
  600.  
  601.  max_image_size = max_imagex * max_imagey;
  602.  im_buff0 = (char *) malloc( max_image_size * x11_bytes_pixel);
  603.  if (im_buff0 == 0) TheEnd1("ShowAnimation: im_buff0 malloc failed");
  604.  if (merged_anim_flags & ANIM_IFF)
  605.  {
  606.   im_buff1 = (char *) malloc( max_image_size * x11_bytes_pixel);
  607.   if (im_buff1 == 0) TheEnd1("ShowAnimation: im_buff1 malloc failed");
  608.  
  609.   if ( (merged_anim_flags & ANIM_HAM) || (merged_anim_flags & ANIM_LACE) )
  610.   {
  611.    hbuff = (char *) malloc( max_image_size * x11_bytes_pixel);
  612.    if (hbuff == 0) TheEnd1("ShowAnimation: hbuff malloc failed");
  613.   }
  614.   old_dlta[0].minx = max_imagex; old_dlta[0].miny = max_imagey;
  615.   old_dlta[0].maxx = 0;          old_dlta[0].maxy = 0;
  616.   old_dlta[1].minx = max_imagex; old_dlta[1].miny = max_imagey;
  617.   old_dlta[1].maxx = 0;          old_dlta[1].maxy = 0;
  618.  }
  619.  pic = im_buff0;
  620.  
  621.  cur_file = 0;
  622.  cur_floop = 0;
  623.  cur_frame = 0;
  624.  start_file = 0;
  625.  cycle_wait = 0;
  626.  cycle_cnt = 0;
  627.  
  628.  XtAppAddTimeOut(theContext, 1, ShowAction, NULL);
  629. }
  630.  
  631. /*
  632.  * This is the heart of this program. It does each action and then calls
  633.  * itself with a timeout via the XtAppAddTimeOut call.
  634.  */
  635. void ShowAction(nothing,id)
  636. char *nothing;
  637. XtIntervalId *id;
  638. {
  639.  int screen_updated;
  640.  int t_frame_start,t_frame_end,t_frame_int;
  641.  struct tms tms3;
  642.  
  643.  screen_updated = FALSE;
  644. /* If color cycling, wait for user go ahead.
  645.  */
  646.  if (cycle_wait && cycle_cnt)
  647.  {
  648.   XtAppAddTimeOut(theContext, 10, ShowAction, NULL);
  649.   return;
  650.  }
  651.  
  652.  /* sanity check.
  653.   */
  654.  if (cur_file >= anim_cnt) return;
  655.  
  656.  /* 1st throught this particular file.
  657.   * Resize if necessary and init required variables.
  658.   */
  659.  if (start_file == 0)
  660.  {
  661.   start_file=1;
  662.   cycle_wait=0;
  663.   anim_flags = anim[cur_file].anim_flags;
  664.  
  665.   if (anim_flags & ANIM_DEBUG) debug_flag = 1;
  666.   else debug_flag = 0;
  667.   if (anim_flags & ANIM_CYCON) cycle_on_flag = 1;
  668.   else cycle_on_flag = 0;
  669.  
  670.   /* if interlaced flag then compare half-height images to current settings.
  671.    */
  672.   if (noresize_flag == FALSE)
  673.   {
  674.    if (  anim[cur_file].anim_flags & ANIM_LACE )
  675.    {
  676.     if (   (imagex != anim[cur_file].imagex)
  677.         || (disp_y != (anim[cur_file].imagey/2)) ) 
  678.      XResizeWindow(theDisp,mainW,anim[cur_file].imagex,
  679.                          anim[cur_file].imagey/2);
  680.    }
  681.    else
  682.    {
  683.     if (   (imagex != anim[cur_file].imagex)
  684.        || (disp_y != anim[cur_file].imagey) ) 
  685.      XResizeWindow(theDisp,mainW,anim[cur_file].imagex,
  686.                                  anim[cur_file].imagey);
  687.    }
  688.   }
  689.   else
  690.   {
  691.    if (imagex > anim[cur_file].imagex)
  692.      XClearArea(theDisp,mainW,anim[cur_file].imagex,0, 0,0,FALSE);
  693.    if (  anim[cur_file].anim_flags & ANIM_LACE )
  694.    {
  695.     if (disp_y > (anim[cur_file].imagey/2) )
  696.       XClearArea(theDisp,mainW,0,(anim[cur_file].imagey/2), 0,0,FALSE);
  697.    }
  698.    else
  699.    {
  700.     if (disp_y > anim[cur_file].imagey )
  701.       XClearArea(theDisp,mainW,0,anim[cur_file].imagey, 0,0,FALSE);
  702.    }
  703.   }
  704.   /* Initialize variables
  705.    */
  706.   imagex = anim[cur_file].imagex;
  707.   imagey = anim[cur_file].imagey;
  708.   imaged = anim[cur_file].imaged;
  709.   imagec = anim[cur_file].imagec;
  710.   image_size = imagex * imagey;
  711.  
  712.   /*
  713.    * What's this!? Direct access to X11 structures. tsch tsch.
  714.    *
  715.    * With half-height images, I fool X11 by telling it the image is
  716.    * twice as wide and half as high, then only display left half of image.
  717.    *
  718.    * NOTE: when adding TrueColor bytes_per_line needs modification.
  719.    */
  720.   if (anim_flags & ANIM_LACE) 
  721.   {
  722.    theImage->width = 2*imagex;
  723.    theImage->height = imagey/2;
  724.    theImage->bytes_per_line = 2*imagex * x11_bytes_pixel;
  725.    disp_y = imagey/2;
  726.   }
  727.   else
  728.   {
  729.    theImage->width = imagex;
  730.    theImage->height = imagey;
  731.    theImage->bytes_per_line = imagex * x11_bytes_pixel;
  732.    disp_y = imagey;
  733.   }
  734.  }
  735.  
  736.  /* OK. A quick sanity check and then we act.
  737.   */
  738.  if (   (anim[cur_file].frame_lst[cur_frame] >= 0)
  739.      && (anim[cur_file].frame_lst[cur_frame] <  action_cnt)  )
  740.  {
  741.     /* initialize act and get the current time.
  742.      */
  743.     act = &action[ anim[cur_file].frame_lst[cur_frame] ];
  744.     t_frame_start = times(&tms3);
  745.     t_frame_int = act->time;
  746.  
  747.  
  748.     /* lesdoit */
  749.     switch(act->type)
  750.     {
  751.        /* 
  752.     * NOP and DELAY don't change anything but can have timing info
  753.     * that might prove useful. ie dramatic pauses :^)
  754.     */
  755.      case ACT_NOP:    
  756.             break;
  757.      case ACT_DELAY:    
  758.             break;
  759.        /* 
  760.     * Change Color Map.
  761.     */
  762.      case ACT_CMAP:    
  763.             if (x11_cmap_flag == TRUE)
  764.             {
  765.              int off,j;
  766.              ColorReg *cptr;
  767.              CMAP_HDR *cmap_hdr;
  768.  
  769.              cmap_hdr = (CMAP_HDR *)act->data;
  770.              imagec = cmap_hdr->cmap_size;
  771.              cptr = (ColorReg *)cmap_hdr->data;
  772.  
  773.              off = x11_cmap_size - imagec;
  774.               for(j=0;j<imagec;j++)
  775.              {
  776.               defs[j].pixel = off+j;
  777.               defs[j].red   = cptr[j].red   << 8;
  778.               defs[j].green = cptr[j].green << 8;
  779.               defs[j].blue  = cptr[j].blue  << 8;
  780.               defs[j].flags = DoRed | DoGreen | DoBlue;
  781.               cmap[off+j].red   = cptr[j].red;
  782.               cmap[off+j].green = cptr[j].green;
  783.               cmap[off+j].blue  = cptr[j].blue;
  784.              }
  785.              XStoreColors(theDisp,theCmap,defs,imagec);
  786.               XFlush(theDisp);
  787.             }
  788.             break;
  789.        /* 
  790.     * Display an Image. Assumed to by imagex by imagey in size. 
  791.     */
  792.      case ACT_IMAGE:    
  793.  
  794.             theImage->data = act->data;
  795.  
  796.             XPutImage(theDisp,mainW,theGC,theImage,0,0,0,0,
  797.                                    imagex,disp_y);
  798.             XFlush(theDisp);
  799.             cycle_wait = 1;
  800.             screen_updated = TRUE;
  801.             break;
  802.        /* 
  803.     * Resize Window
  804.     */
  805.      case ACT_SIZE:
  806.                         {
  807.                          SIZE_HDR *size_hdr;
  808.  
  809.                          size_hdr = (SIZE_HDR *)act->data;
  810.                          imagex = size_hdr->imagex;
  811.                          imagey = size_hdr->imagey;
  812.              if (anim_flags & ANIM_LACE)
  813.                             disp_y = size_hdr->imagey/2;
  814.              else
  815.                             disp_y = size_hdr->imagey;
  816.              theImage->height = disp_y;
  817.              theImage->width = imagex;
  818.              theImage->bytes_per_line = imagex * x11_bytes_pixel;
  819.                         }
  820.                         break;
  821.        /* 
  822.     * Lower Color Intensity by 1/16.
  823.     */
  824.      case ACT_FADE:    
  825.             {
  826.              int off,j;
  827.  
  828.              off = x11_cmap_size - imagec;
  829.               for(j=0;j<imagec;j++)
  830.              {
  831.               if (cmap[off+j].red   <= 16) cmap[off+j].red   = 0;
  832.               else cmap[off+j].red   -= 16;
  833.               if (cmap[off+j].green <= 16) cmap[off+j].green = 0;
  834.               else cmap[off+j].green -= 16;
  835.               if (cmap[off+j].blue  <= 16) cmap[off+j].blue  = 0;
  836.               else cmap[off+j].blue  -= 16;
  837.  
  838.               defs[j].pixel = off+j;
  839.               defs[j].red   = cmap[off+j].red   << 8;
  840.               defs[j].green = cmap[off+j].green << 8;
  841.               defs[j].blue  = cmap[off+j].blue  << 8;
  842.               defs[j].flags = DoRed | DoGreen | DoBlue;
  843.              }
  844.              XStoreColors(theDisp,theCmap,defs,imagec);
  845.               XFlush(theDisp);
  846.             }
  847.             screen_updated = TRUE;
  848.             break;
  849.        /* 
  850.     * A REGION display only part of an IMAGE.
  851.     */
  852.      case ACT_REGION:    
  853.             {
  854.              ACT_REGION_HDR *act_reg_hdr;
  855.  
  856.              act_reg_hdr = (ACT_REGION_HDR *)(act->data);
  857.  
  858.              theImage->data = (char *)(act_reg_hdr->data);
  859.  
  860.              if (anim_flags & ANIM_LACE) 
  861.              {
  862.                  XPutImage(theDisp,mainW,theGC,theImage,
  863.                      act_reg_hdr->xpos,  act_reg_hdr->ypos/2,
  864.                      act_reg_hdr->xpos,  act_reg_hdr->ypos/2,
  865.                      act_reg_hdr->xsize, act_reg_hdr->ysize/2  );
  866.                          }
  867.                 else 
  868.              {
  869.               XPutImage(theDisp,mainW,theGC,theImage,
  870.                      act_reg_hdr->xpos,  act_reg_hdr->ypos,
  871.                      act_reg_hdr->xpos,  act_reg_hdr->ypos,
  872.                      act_reg_hdr->xsize, act_reg_hdr->ysize  );
  873.              }
  874.              XFlush(theDisp);
  875.              cycle_wait = 1;
  876.             }
  877.             screen_updated = TRUE;
  878.             break;
  879.        /* 
  880.     * Act upon IFF Color Cycling chunk.
  881.     *   currently we don't color cycling during animations. will be fixed.
  882.     */
  883.      case ACT_IFF_CRNG:
  884.                         {
  885.                          CRNG_HDR *crng;
  886.  
  887.                          crng = (CRNG_HDR *)act->data;
  888.                          if (   (crng->active & CRNG_ACTIVE)
  889.                              && (crng->low < crng->high)
  890.                              && (crng->rate != 0)
  891.                              && (anim_flags & ANIM_CYCLE) 
  892.                              && (cycle_on_flag)                 
  893.                             )
  894.                           {
  895.                cycle_cnt++;
  896.                            XtAppAddTimeOut(theContext, 
  897.                   (int)(CRNG_INTERVAL/(crng->rate)),Cycle_It, crng);
  898.                           }
  899.  
  900.                         }
  901.                         break;
  902.        /* 
  903.     *  FLI BRUN chunk.
  904.     */
  905.      case ACT_FLI_BRUN:    
  906.             Decode_Fli_BRUN(act->data,pic);
  907.             theImage->data = pic;
  908.                XPutImage(theDisp,mainW,theGC,theImage,0,0,0,0,
  909.                             imagex,disp_y);
  910.             XFlush(theDisp);
  911.             screen_updated = TRUE;
  912.             break;
  913.        /* 
  914.     *  FLI BRUN chunk
  915.     */
  916.      case ACT_FLI_LC:    
  917.             {
  918.              ACT_FLI_LC_HDR *fli_lc_hdr;
  919.  
  920.              fli_lc_hdr = (ACT_FLI_LC_HDR *)(act->data);
  921.              Decode_Fli_LC( fli_lc_hdr->data, pic, fli_lc_hdr);
  922.              theImage->data = pic;
  923.                 XPutImage(theDisp,mainW,theGC,theImage,
  924.                           fli_lc_hdr->xpos,  fli_lc_hdr->ypos,
  925.                           fli_lc_hdr->xpos,  fli_lc_hdr->ypos,
  926.                           fli_lc_hdr->xsize, fli_lc_hdr->ysize  );
  927.              XFlush(theDisp);
  928.             }
  929.             screen_updated = TRUE;
  930.             break;
  931.        /* 
  932.     *  FLI_COLOR not supported. Actually it become a CMAP when read in.
  933.     */
  934.      case ACT_FLI_COLOR:    
  935.             fprintf(stderr,"fli_color not supported\n");
  936.             break;
  937.        /* 
  938.     *  FLI COPY chunk
  939.     */
  940.      case ACT_FLI_COPY:    
  941.             theImage->data = act->data;
  942.                XPutImage(theDisp,mainW,theGC,theImage,0,0,0,0,
  943.                             imagex,disp_y);
  944.             XFlush(theDisp);
  945.             screen_updated = TRUE;
  946.             break;
  947.        /* 
  948.     *  Display Image of color 0.
  949.     */
  950.      case ACT_FLI_BLACK:    
  951.                         memset(im_buff0,0x00,image_size);
  952.             theImage->data = im_buff0;
  953.                XPutImage(theDisp,mainW,theGC,theImage,0,0,0,0,
  954.                             imagex,disp_y);
  955.             XFlush(theDisp);
  956.             screen_updated = TRUE;
  957.             break;
  958.        /* 
  959.     *  Display IFF body. Note that both buffers are set to this body.
  960.     *  this is necessary since next delta works on 2nd buffer.
  961.     */
  962.      case ACT_IFF_BODY:    
  963.  
  964.             memcpy(im_buff0,act->data,image_size);
  965.             memcpy(im_buff1,act->data,image_size);
  966.             if (anim_flags & ANIM_HAM) 
  967.             {
  968.                 IFF_HAM_To_332(act->data,hbuff);
  969.              theImage->data = hbuff;
  970.             }
  971.             else 
  972.             {
  973.              theImage->data = act->data;
  974.             }
  975.  
  976.                XPutImage(theDisp,mainW,theGC,theImage,0,0,
  977.                             0,0,imagex,disp_y);
  978.             XFlush(theDisp);
  979.             cycle_wait = 1;
  980.             old_dlta[0].minx = old_dlta[1].minx = 0;
  981.             old_dlta[0].miny = old_dlta[1].miny = 0;
  982.             old_dlta[0].maxx = old_dlta[1].maxx = imagex;
  983.             old_dlta[0].maxy = old_dlta[1].maxy = imagey;
  984.             screen_updated = TRUE;
  985.             break;
  986.        /* 
  987.     *  Handle IFF anim op 5.
  988.     */
  989.      case ACT_IFF_DLTA5:
  990.             {
  991.              ACT_IFF_DLTA_HDR *iff_dlta_hdr;
  992.  
  993.              iff_dlta_hdr = (ACT_IFF_DLTA_HDR *)(act->data);
  994.              IFF_Delta5(im_buff0,iff_dlta_hdr->data,iff_dlta_hdr);
  995.  
  996.         /* This mess keeps track of the largest rectangle needed to
  997.          * display all changes. Since things are double buffered, the
  998.          * min/maxes of the corners of the current and previous two
  999.           * images are taken. If the animation is in single step mode
  1000.          * it's best to display the entire image.
  1001.          */
  1002.             if ((anim_running==FALSE) || (anim_forward_flag==FALSE))
  1003.             {
  1004.              old_dlta[0].minx = old_dlta[1].minx = 0;
  1005.              old_dlta[0].miny = old_dlta[1].miny = 0;
  1006.              old_dlta[0].maxx = old_dlta[1].maxx = imagex;
  1007.              old_dlta[0].maxy = old_dlta[1].maxy = imagey;
  1008.             }
  1009.             else
  1010.             {
  1011.              old_dlta[0].minx = 
  1012.                 MIN(old_dlta[0].minx,iff_dlta_hdr->minx);
  1013.              old_dlta[0].miny = 
  1014.                 MIN(old_dlta[0].miny,iff_dlta_hdr->miny);
  1015.              old_dlta[0].maxx = 
  1016.                 MAX(old_dlta[0].maxx,iff_dlta_hdr->maxx);
  1017.              old_dlta[0].maxy = 
  1018.                 MAX(old_dlta[0].maxy,iff_dlta_hdr->maxy);
  1019.              old_dlta[1].minx = 
  1020.                 MIN(old_dlta[1].minx,old_dlta[0].minx);
  1021.              old_dlta[1].miny = 
  1022.                 MIN(old_dlta[1].miny,old_dlta[0].miny);
  1023.              old_dlta[1].maxx = 
  1024.                 MAX(old_dlta[1].maxx,old_dlta[0].maxx);
  1025.              old_dlta[1].maxy = 
  1026.                 MAX(old_dlta[1].maxy,old_dlta[0].maxy);
  1027.             }
  1028.  
  1029.              if (anim_flags & ANIM_HAM) 
  1030.              {
  1031.                  IFF_HAM_To_332(pic,hbuff);
  1032.               theImage->data = hbuff;
  1033.              }
  1034.              else 
  1035.              {
  1036.               theImage->data = im_buff0;
  1037.              }
  1038.  
  1039.              if (anim_flags & ANIM_LACE) 
  1040.              {
  1041.                  XPutImage(theDisp,mainW,theGC,theImage,
  1042.                  old_dlta[1].minx,  old_dlta[1].miny/2,
  1043.                  old_dlta[1].minx,  old_dlta[1].miny/2,
  1044.                  old_dlta[1].maxx - old_dlta[1].minx, 
  1045.                 (old_dlta[1].maxy - old_dlta[1].miny)/2  );
  1046.                          }
  1047.                 else XPutImage(theDisp,mainW,theGC,theImage,
  1048.                  old_dlta[1].minx,  old_dlta[1].miny,
  1049.                  old_dlta[1].minx,  old_dlta[1].miny,
  1050.                  old_dlta[1].maxx - old_dlta[1].minx, 
  1051.                  old_dlta[1].maxy - old_dlta[1].miny  );
  1052.              XFlush(theDisp);
  1053.              pic = im_buff0; im_buff0 = im_buff1; im_buff1 = pic;
  1054.  
  1055.          /* Throw out oldest rectangle and store current
  1056.           * you get the idea.
  1057.           */
  1058.              old_dlta[1].minx = old_dlta[0].minx;
  1059.              old_dlta[1].miny = old_dlta[0].miny;
  1060.              old_dlta[1].maxx = old_dlta[0].maxx;
  1061.              old_dlta[1].maxy = old_dlta[0].maxy;
  1062.              old_dlta[0].minx = iff_dlta_hdr->minx;
  1063.              old_dlta[0].miny = iff_dlta_hdr->miny;
  1064.              old_dlta[0].maxx = iff_dlta_hdr->maxx;
  1065.              old_dlta[0].maxy = iff_dlta_hdr->maxy;
  1066.             }
  1067.             screen_updated = TRUE;
  1068.             break;
  1069.        /* 
  1070.     *  Handle IFF anim op 3 compressed actions.
  1071.      *  NOTE: eventually put in largest rectangle optimization.
  1072.     */
  1073.      case ACT_IFF_DLTA3:
  1074.             {
  1075.                          ACT_IFF_DLTA_HDR *iff_dlta_hdr;
  1076.  
  1077.                          iff_dlta_hdr = (ACT_IFF_DLTA_HDR *)(act->data);
  1078.              IFF_Delta3(im_buff0, iff_dlta_hdr->data);
  1079.              if (anim_flags & ANIM_HAM) 
  1080.              {
  1081.                  IFF_HAM_To_332(pic,hbuff);
  1082.               theImage->data = hbuff;
  1083.              }
  1084.              else 
  1085.              {
  1086.               theImage->data = im_buff0;
  1087.              }
  1088.  
  1089.                 XPutImage(theDisp,mainW,theGC,theImage,0,0,0,0,
  1090.                              imagex,disp_y);
  1091.              XFlush(theDisp);
  1092.              pic = im_buff0; im_buff0 = im_buff1; im_buff1 = pic;
  1093.             }
  1094.             screen_updated = TRUE;
  1095.             break;
  1096.        /* 
  1097.     * Handle IFF anim opt J compressed actions. 
  1098.     */
  1099.      case ACT_IFF_DLTAJ:
  1100.             {
  1101.              ACT_IFF_DLTA_HDR *iff_dlta_hdr;
  1102.  
  1103.                          iff_dlta_hdr = (ACT_IFF_DLTA_HDR *)(act->data);
  1104.              IFF_DeltaJ(im_buff0,iff_dlta_hdr->data,iff_dlta_hdr);
  1105.  
  1106.         /* This mess keeps track of the largest rectangle needed to
  1107.          * display all changes. Since things are double buffered, the
  1108.          * min/maxes of the corners of the current and previous two
  1109.           * images are taken.
  1110.          */
  1111.             if ((anim_running==FALSE) || (anim_forward_flag==FALSE))
  1112.             {
  1113.              old_dlta[0].minx = old_dlta[1].minx = 0;
  1114.              old_dlta[0].miny = old_dlta[1].miny = 0;
  1115.              old_dlta[0].maxx = old_dlta[1].maxx = imagex;
  1116.              old_dlta[0].maxy = old_dlta[1].maxy = imagey;
  1117.             }
  1118.             else
  1119.             {
  1120.              old_dlta[0].minx = 
  1121.                 MIN(old_dlta[0].minx,iff_dlta_hdr->minx);
  1122.              old_dlta[0].miny = 
  1123.                 MIN(old_dlta[0].miny,iff_dlta_hdr->miny);
  1124.              old_dlta[0].maxx = 
  1125.                 MAX(old_dlta[0].maxx,iff_dlta_hdr->maxx);
  1126.              old_dlta[0].maxy = 
  1127.                 MAX(old_dlta[0].maxy,iff_dlta_hdr->maxy);
  1128.              old_dlta[1].minx = 
  1129.                 MIN(old_dlta[1].minx,old_dlta[0].minx);
  1130.              old_dlta[1].miny = 
  1131.                 MIN(old_dlta[1].miny,old_dlta[0].miny);
  1132.              old_dlta[1].maxx = 
  1133.                 MAX(old_dlta[1].maxx,old_dlta[0].maxx);
  1134.              old_dlta[1].maxy = 
  1135.                 MAX(old_dlta[1].maxy,old_dlta[0].maxy);
  1136.             }
  1137.  
  1138.              if (anim_flags & ANIM_HAM) 
  1139.              {
  1140.                  IFF_HAM_To_332(pic,hbuff);
  1141.               theImage->data = hbuff;
  1142.              }
  1143.              else 
  1144.              {
  1145.               theImage->data = im_buff0;
  1146.              }
  1147.  
  1148.               if (anim_flags & ANIM_LACE) 
  1149.               {
  1150.                  XPutImage(theDisp,mainW,theGC,theImage,
  1151.                  old_dlta[1].minx,  old_dlta[1].miny/2,
  1152.                  old_dlta[1].minx,  old_dlta[1].miny/2,
  1153.                  old_dlta[1].maxx - old_dlta[1].minx, 
  1154.                 (old_dlta[1].maxy - old_dlta[1].miny)/2  );
  1155.                          }
  1156.                 else XPutImage(theDisp,mainW,theGC,theImage,
  1157.                  old_dlta[1].minx,  old_dlta[1].miny,
  1158.                  old_dlta[1].minx,  old_dlta[1].miny,
  1159.                  old_dlta[1].maxx - old_dlta[1].minx, 
  1160.                  old_dlta[1].maxy - old_dlta[1].miny  );
  1161.              XFlush(theDisp);
  1162.              pic = im_buff0; im_buff0 = im_buff1; im_buff1 = pic;
  1163.  
  1164.          /* Throw out oldest rectangle and store current
  1165.           * you get the idea.
  1166.           */
  1167.              old_dlta[1].minx = old_dlta[0].minx;
  1168.              old_dlta[1].miny = old_dlta[0].miny;
  1169.              old_dlta[1].maxx = old_dlta[0].maxx;
  1170.              old_dlta[1].maxy = old_dlta[0].maxy;
  1171.              old_dlta[0].minx = iff_dlta_hdr->minx;
  1172.              old_dlta[0].miny = iff_dlta_hdr->miny;
  1173.              old_dlta[0].maxx = iff_dlta_hdr->maxx;
  1174.              old_dlta[0].maxy = iff_dlta_hdr->maxy;
  1175.             }
  1176.             screen_updated = TRUE;
  1177.                         break;
  1178.        /*
  1179.         *  Handle IFF anim op l(small L not one 1) compressed actions.
  1180.         *  NOTE: eventually put in largest rectangle optimization.
  1181.         */
  1182.      case ACT_IFF_DLTAl:
  1183.                         {
  1184.                          ACT_IFF_DLTA_HDR *iff_dlta_hdr;
  1185.  
  1186.                          iff_dlta_hdr = (ACT_IFF_DLTA_HDR *)(act->data);
  1187.                          IFF_Deltal(im_buff0, (short *)iff_dlta_hdr->data,
  1188.                                                 1,iff_dlta_hdr);
  1189.                          if (anim_flags & ANIM_HAM)
  1190.                          {
  1191.                           IFF_HAM_To_332(pic,hbuff);
  1192.                           theImage->data = hbuff;
  1193.                          }
  1194.                          else
  1195.                          {
  1196.                           theImage->data = im_buff0;
  1197.                          }
  1198.  
  1199.                          XPutImage(theDisp,mainW,theGC,theImage,0,0,0,0,
  1200.                                                         imagex,disp_y);
  1201.                          XFlush(theDisp);
  1202.                          pic = im_buff0; im_buff0 = im_buff1; im_buff1 = pic;
  1203.                         }
  1204.             screen_updated = TRUE;
  1205.                         break;
  1206.  
  1207.        /* 
  1208.     *  Update ham_map if it changes during an animation. ham_map is
  1209.      *  needed in order to convert HAM images into 332.
  1210.     */
  1211.      case ACT_IFF_HMAP:    
  1212.             {
  1213.              ColorReg *hptr;
  1214.              int i;
  1215.  
  1216.              hptr = (ColorReg *)act->data;
  1217.              for(i=0;i<HMAP_SIZE;i++)
  1218.              {
  1219.               ham_map[i].red   = hptr[i].red;
  1220.               ham_map[i].green = hptr[i].green;
  1221.               ham_map[i].blue  = hptr[i].blue;
  1222.              }
  1223.             }
  1224.             break;
  1225.      default:        
  1226.             fprintf(stderr,"Unknown not supported %lx\n",act->type);
  1227.     } /* end of switch of action type */
  1228.  } /* end of action valid */
  1229.  
  1230. /* Move on if we're running. If we're in single step mode and the update_flag
  1231.  * is set, we move on until the screen has been updated. 
  1232.  */
  1233.  if (anim_running==TRUE) 
  1234.  {
  1235.   if (anim_forward_flag == TRUE) Step_Action_Next();
  1236.   else Step_Frame_Prev();
  1237.  }
  1238.  else if ((update_flag == TRUE) && (screen_updated==FALSE))
  1239.       {
  1240.        if (anim_forward_flag == TRUE) Step_Frame_Next();
  1241.        else Step_Frame_Prev();
  1242.       }
  1243.       else return;
  1244.  
  1245.   /* Harry, what time is it?
  1246.    */
  1247.  t_frame_end = times(&tms3) - t_frame_start;
  1248.  t_frame_end *= 1000/HZ;  /* convert to milliseconds */
  1249.  
  1250.   /* how much time left 
  1251.    */
  1252.  t_frame_end = t_frame_int - t_frame_end;  
  1253.   /* default to 1 ms, other wise 100 clk_tcks gives 10ms per tick.
  1254.    * NOTE: change all timing to milliseconds, not ticks.
  1255.    */
  1256.  if (t_frame_end <=0 ) t_frame_end = 1; 
  1257.  
  1258.  XtAppAddTimeOut(theContext, t_frame_end, ShowAction, NULL);
  1259. }
  1260.  
  1261. Step_Action_Next()
  1262. {
  1263.  /* Move to next frame
  1264.   */
  1265.  cur_frame++;
  1266.  if (debug_flag) fprintf(stderr,"frame = %ld\n",cur_frame);
  1267.  
  1268.  /* Are we at the end of an anim?
  1269.   */
  1270.  if (   (anim[cur_file].frame_lst[cur_frame] < 0)
  1271.      || (anim[cur_file].frame_lst[cur_frame] >= action_cnt) )
  1272.  {
  1273.    cur_frame = anim[cur_file].loop_frame;
  1274.  
  1275.    cur_floop++;
  1276.    if (debug_flag) fprintf(stderr,"  loop = %ld\n",cur_floop);
  1277.  
  1278.    /* Done looping animation. Move on to next file if present
  1279.     */
  1280.    if (cur_floop >= anim[cur_file].loop_num)
  1281.    {
  1282.      cur_floop = 0;             /* Reset Loop Count */
  1283.  
  1284.      /* This is a special case check.
  1285.       * If more that one file, reset start_file, otherwise
  1286.       * if we're only displaying 1 animation jump to the loop_frame
  1287.       * which has already been set up above.
  1288.       */
  1289.      if (anim_cnt > 1)
  1290.      {
  1291.        start_file = 0;
  1292.        cur_frame = 0;
  1293.      } /* end of move on to next file/anim */
  1294.  
  1295.      cur_file++;
  1296.  
  1297.      if (cur_file >= anim_cnt)
  1298.      {
  1299.        cur_file=0;
  1300.      } /* end done with last file */
  1301.      if (debug_flag) fprintf(stderr,"  file = %ld\n",cur_file);
  1302.    } /* end done looping file */
  1303.  } /* end done with frames in file */
  1304. }
  1305.  
  1306. Step_Frame_Next()
  1307. {
  1308.  /* Move to next frame
  1309.   */
  1310.  cur_frame++;
  1311.  if (debug_flag) fprintf(stderr,"frame = %ld\n",cur_frame);
  1312.  
  1313.  /* Are we at the end of an anim?
  1314.   */
  1315.  if (   (anim[cur_file].frame_lst[cur_frame] < 0)
  1316.      || (anim[cur_file].frame_lst[cur_frame] >= action_cnt) )
  1317.  {
  1318.    cur_frame = anim[cur_file].loop_frame;
  1319.  }
  1320. }
  1321.  
  1322. Step_Frame_Prev()
  1323. {
  1324.  /* Move to next frame
  1325.   */
  1326.  cur_frame--;
  1327.  if (debug_flag) fprintf(stderr,"frame = %ld\n",cur_frame);
  1328.  
  1329.  /* Are we at the beginning of an anim?
  1330.   */
  1331.  if (   (anim[cur_file].frame_lst[cur_frame] < 0)
  1332.      || (anim[cur_file].frame_lst[cur_frame] >= action_cnt) 
  1333.      || (cur_frame < anim[cur_file].loop_frame)
  1334.      || (cur_frame < 0)
  1335.     )
  1336.  {
  1337.    cur_frame = anim[cur_file].last_frame;
  1338.  }
  1339. }
  1340.  
  1341. Step_File_Next()
  1342. {
  1343.   start_file = 0;
  1344.   cur_frame = 0;
  1345.   cur_floop = 0; /* used if things start up again */
  1346.  
  1347.   cur_file++;
  1348.   if (cur_file >= anim_cnt)
  1349.   {
  1350.    cur_file=0;
  1351.   } /* end done with last file */
  1352.  
  1353.   if (debug_flag) fprintf(stderr,"  file = %ld\n",cur_file);
  1354. }
  1355.  
  1356. Step_File_Prev()
  1357. {
  1358.   start_file = 0;
  1359.   cur_frame = 0;
  1360.   cur_floop = 0; /* used if things start up again */
  1361.  
  1362.   cur_file--;
  1363.   if (cur_file < 0)
  1364.   {
  1365.    cur_file = anim_cnt-1;
  1366.   } /* end done with last file */
  1367.  
  1368.   if (debug_flag) fprintf(stderr,"  file = %ld\n",cur_file);
  1369. }
  1370.  
  1371.  
  1372. /*
  1373.  * Simple routine to find out the file type. Defaults to FLI.
  1374.  */
  1375. int Determine_Anim_Type(filename)
  1376. char *filename;
  1377. {
  1378.  if ( Is_IFF_File(filename) ) return(IFF_ANIM); 
  1379.  if ( Is_GIF_File(filename) ) return(GIF_ANIM); 
  1380.  if ( Is_TXT_File(filename) ) return(TXT_ANIM); 
  1381.  return(FLI_ANIM);
  1382. }
  1383.  
  1384. void Cycle_It(crng, id)
  1385. CRNG_HDR   *crng;
  1386. XtIntervalId *id;
  1387. {
  1388.  int             i,c_off,clow,chi;
  1389.  XColor          tmp_def;
  1390.  
  1391.  if ((anim_flags & ANIM_CYCLE) && cycle_on_flag) 
  1392.   XtAppAddTimeOut(theContext,(int)(CRNG_INTERVAL/(crng->rate)),Cycle_It, crng);
  1393.  else cycle_cnt--;
  1394.  
  1395.  c_off = x11_cmap_size - imagec;
  1396.  clow = crng->low;
  1397.  chi = crng->high;
  1398.  
  1399.  if (crng->active & CRNG_REVERSE) 
  1400.  {
  1401.   tmp_def = defs[clow];
  1402.   for (i = clow; i < chi; i++) defs[i] = defs[i + 1];
  1403.   defs[chi] = tmp_def;
  1404.  } 
  1405.  else 
  1406.  {
  1407.   tmp_def = defs[chi];
  1408.   for (i = chi; i > clow; i--) defs[i] = defs[i - 1];
  1409.   defs[clow] = tmp_def;
  1410.  }
  1411.  
  1412.  for (i = clow; i <= chi; i++) defs[i].pixel = i+c_off;
  1413.  
  1414.  XStoreColors(theDisp,theCmap,&defs[clow],(chi - clow + 1) );
  1415.  XFlush(theDisp);
  1416. }
  1417.  
  1418.