home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 643b.lha / 2View_v1.50 / Source.LZH / Source / 2View.c next >
Encoding:
C/C++ Source or Header  |  1992-05-15  |  19.6 KB  |  709 lines

  1.  
  2. /***********************************************************************\
  3. *                 2View V1.50                *
  4. *     A simple, fast ILBM viewer, for use under AmigaOS V2.x.    *
  5. *    Written and ©1991-1992 by Dave Schreiber.    All Rights Reserved.    *
  6. *                                    *
  7. * Usage:                                *
  8. *  2View FILE/A/M,FROM/K,SECS=SECONDS/K/N,TICKS/K/N,LOOP/S,PRINT    *
  9. *                                    *
  10. *  Where the following arguments are defined as follows:        *
  11. *   FILE - The name of one (or more) IFF ILBM files                     *
  12. *   FROM - A file containing a list of filenames.  Used instead of FILE *
  13. *   SECS - Number of seconds to display a file                *
  14. *   TICKS - Number of ticks (1/60ths of a second)                       *
  15. *   LOOP - When finished showing the last pictures, start over        *
  16. *   PRINT - Print each picture as it is shown                *
  17. *                                    *
  18. *  To compile (with SAS/C V5.10a):                                      *
  19. *     lc -v 2View ARexx                         *
  20. *     lc -v -b0 Misc                            *
  21. *     asm 2ViewAsm.a                            *
  22. *     blink with 2View.lnk                        *
  23. *                                    *
  24. *  Version history:                            *
  25. *     1.50 - Rewrote the subroutine that reads the ILBM from disk in    *
  26. *         assembly language, for speed.  Added support for SHAM and    *
  27. *         Macro Paint images, and for color cycling (both            *
  28. *         traditional (CRNG, i.e. continutout cycle ranges) and      *
  29. *         DPaint-IV style cycling (DRNG, i.e. non-continuous cycle   *
  30. *         ranges).  A 'tick' (as used with the "TICK" keyword, above)*
  31. *         has been redefined as 1/60th of a second.    Finally, the    *
  32. *         source code in 2View.c has been split into two files    *
  33. *         (2View.c and  Misc.c).                                     *
  34. *         Released 3/24/92                        *
  35. *                                    *
  36. *     1.11 - Improved error reporting (with this version, if the user   *
  37. *         run 2View from Workbench and there's an error, a requester *
  38. *         is put up.  Previously, the user was not notified at all    *
  39. *         of the error).                        *
  40. *         Released 9/11/91                        *
  41. *                                    *
  42. *     1.10 - Added support for Workbench, ARexx, scrollable bitmaps,    *
  43. *         and printing.  Also, the user can now use CTRL-C to advance*
  44. *         to the next frame, and CTRL-D to abort a playlist.     *
  45. *         Released 9/3/91                        *
  46. *                                    *
  47. *     1.00 - Original version.    Released 7/24/91            *
  48. *                                    *
  49. \************************************************************************/
  50.  
  51.  
  52. unsigned long availBytes,curPos,bufSize;
  53.  
  54. /*Include files*/
  55.  
  56. #include <exec/types.h>
  57. #include <libraries/iffparse.h>
  58. #include <dos/dos.h>
  59. #include <dos/dosasl.h>
  60. #include <intuition/intuition.h>
  61. #include <exec/memory.h>
  62. #include <workbench/startup.h>
  63. #include <graphics/gfxbase.h>
  64.  
  65. /*Prototypes*/
  66. #include <clib/exec_protos.h>
  67. #include <clib/intuition_protos.h>
  68. #include <clib/iffparse_protos.h>
  69.  
  70. /*Pragmas*/
  71. #include <pragmas/exec_pragmas.h>
  72. #include <pragmas/intuition_pragmas.h>
  73. #include <pragmas/graphics_pragmas.h>
  74. #include <pragmas/iffparse_pragmas.h>
  75. #include <pragmas/dos_pragmas.h>
  76.  
  77. /*Other include files*/
  78. #include "iff.h"
  79. #include "2View.h"
  80. #include "arexx.h"
  81.  
  82. /*Libraries we'll need*/
  83. struct Library *IFFParseBase=NULL;
  84. struct Library *IntuitionBase=NULL;
  85. struct GfxBase *GfxBase=NULL;
  86.  
  87. /*Provided by the compiler*/
  88. extern struct Library *SysBase;
  89. extern struct Library *DOSBase;
  90.  
  91. /*Generic screen and window definitions.  They will be used to define*/
  92. /*the screen and window that the various pictures will be shown on*/
  93. struct NewScreen newScreen=
  94. {
  95.    0,0,0,0,0,1,0,NULL,CUSTOMSCREEN|SCREENBEHIND|AUTOSCROLL,NULL,NULL,NULL,
  96.    NULL
  97. };
  98.  
  99. struct NewWindow newWindow =
  100. {
  101.    0,0,0,0,0,1,MENUDOWN|SELECTDOWN|ACTIVEWINDOW|VANILLAKEY,
  102.       RMBTRAP|BORDERLESS|NOCAREREFRESH,NULL,NULL,NULL,NULL,NULL,
  103.       0,0,640,400,CUSTOMSCREEN
  104. };
  105.  
  106. struct Screen *screen=NULL;
  107. struct Window *window=NULL;
  108.  
  109. UWORD *storage;
  110. int counter;
  111.  
  112. /*A true here indicates the current ILBM file is compressed*/
  113. BYTE Compression;
  114.  
  115. /*An error message that used in various places*/
  116. char *errorMsg="An error occured while reading";
  117.  
  118. /*The version string.  Do a 'version 2View' to display it*/
  119. char *version="$VER: QView V1.50 (24.3.92)";
  120.  
  121. /*Just so that the © message is part of the actual program*/
  122. char *copyRightMsg="Copyright 1991-1992 by Dave Schreiber.  All Rights Reserved.";
  123.  
  124. BYTE ExitFlag=FALSE;    /*'Exit now' flag*/
  125. UWORD ticks=0;          /*Delay requested by user.*/
  126.  
  127. /*The previous screen and window*/
  128. struct Window *prevWindow=NULL;
  129. struct Screen *prevScreen=NULL;
  130.  
  131. /*Data for a blank pointer*/
  132. UWORD chip fakePointerData[]={0,0,0,0,0};
  133.  
  134. struct IFFHandle *iff=NULL;   /*IFF handle*/
  135. BPTR pL=NULL;              /*Playlist file pointer*/
  136. BOOL masking,print,toFront,printPics;
  137. extern struct WBStartup *WBenchMsg;
  138.  
  139. char *playListFilename=NULL;
  140.  
  141. /*Variables that have to be global so that ARexx.c can access them*/
  142. ButtonTypes rexxAbort=none;
  143. extern void dispRexxPort(void);
  144. extern void dnRexxPort();
  145. long arexxSigBit;
  146. UWORD ticksRemaining=0;
  147. BOOL loop=FALSE;
  148. BYTE specialModes;
  149.  
  150. char *picFilename;
  151. char trashBuf[512];      /* A place to dump mask information */
  152. char *buf=trashBuf;
  153.  
  154. void _main();
  155.  
  156. struct TagItem TagList[]=
  157. {
  158.       /* This defines what part of the displayed picture is shown.  It's */
  159.       /* necessary to have a line like this in here in order to get     */
  160.       /* 2.0 autoscrolling to work.                     */
  161.    {SA_Overscan,OSCAN_VIDEO},
  162.    {TAG_DONE,NULL}
  163. };
  164.  
  165. char *about1="2View";
  166. char *about2="Please";
  167.  
  168. extern struct EasyStruct erError1Line;
  169. BOOL cycle=FALSE;
  170. UBYTE numColors;
  171. UWORD destMap[32];
  172. UBYTE numCycleColors;
  173. UBYTE rate;
  174.  
  175. /* The assembly-language reader routine */
  176. extern int  ReadIntoBitMapAsm(PLANEPTR,APTR,struct IFFHandle *,
  177.                   ULONG,ULONG,UWORD,UBYTE,UBYTE,UBYTE);
  178.  
  179. char **filenames;
  180. UWORD numFilenames=0,numSlots;
  181.  
  182. void _main()
  183. {
  184.    UWORD c;
  185.    LONG args[7];
  186.    char **filenames;
  187.    char curFilename[140];
  188.    BYTE playList; /*True if a playlist is being used, false otherwise*/
  189.  
  190.       /*Initialize the argument buffers to NULL*/
  191.    for(c=0;c<7;c++)
  192.       args[c]=NULL;
  193.  
  194.       /*Open the libraries*/
  195.    IFFParseBase=(struct Library *)OpenLibrary("iffparse.library",0L);
  196.    if(IFFParseBase==NULL)
  197.    {
  198.       cleanup();
  199.       exit(50);
  200.    }
  201.  
  202.    IntuitionBase=(struct Library *)OpenLibrary("intuition.library",0L);
  203.    if(IntuitionBase==NULL)
  204.    {
  205.       cleanup();
  206.       exit(75);
  207.    }
  208.  
  209.    GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
  210.    if(GfxBase==NULL)
  211.    {
  212.       cleanup();
  213.       exit(85);
  214.    }
  215.  
  216.       /*Get the arguments*/
  217.    if(WBenchMsg==NULL)
  218.    {
  219.       ParseArgs(args);
  220.  
  221.      /*If a playlist filename was provided, store it for later use*/
  222.       if(args[4]!=NULL)
  223.       {
  224.      playListFilename=(char *)args[4];
  225.      playList=TRUE;
  226.       }
  227.       else  /*Otherwise, read the filenames from the command line*/
  228.      playList=FALSE;
  229.  
  230.      /*If a time was provided (in ticks), use it*/
  231.       if(args[1]!=NULL)
  232.      ticks=*(ULONG *)args[1]*50;
  233.  
  234.      /*If a time was provided (in seconds), use it (overrides ticks)*/
  235.       if(args[2]!=NULL && *(ULONG *)args[2]!=0)
  236.      ticks=*(ULONG *)args[2];
  237.  
  238.      /*If neither a picture filename, nor a playlist filename, was*/
  239.      /*specified, print an error and exit.*/
  240.       if(args[0]==NULL && !playList)
  241.       {
  242.      printError("Please enter one or more filenames","");
  243.      cleanup();
  244.      exit(45);
  245.       }
  246.  
  247.      /*Determine if we should print the pictures we display or not*/
  248.       printPics=(args[5]!=NULL);
  249.  
  250.      /*Get the pointer to the list of filename*/
  251.       filenames=(char **)args[0];
  252.  
  253.      /*Will we loop back to the beginning once we finish displaying all*/
  254.      /*the pictures?*/
  255.       loop=(args[3]!=NULL);
  256.    }
  257.    else
  258.       if(WBenchMsg->sm_NumArgs==1)
  259.       {
  260.      EasyRequest(NULL,&erError1Line,NULL,
  261.              "2View V1.50 (March 24, 1992)",
  262.              "Written by Dave Schreiber");
  263.      cleanup();
  264.      exit(0);
  265.       }
  266.  
  267.  
  268.       /* Initialize the ARexx port */
  269.    arexxSigBit=initRexxPort();
  270.    if(arexxSigBit==0)
  271.    {
  272.       cleanup();
  273.       exit(47);
  274.    }
  275.  
  276.       /*Allocate the IFF structure*/
  277.    iff=AllocIFF();
  278.  
  279.       /*If the allocation failed, abort*/
  280.    if(iff==NULL)
  281.    {
  282.       printError("Couldn't allocate necessary resources","");
  283.       cleanup();
  284.       exit(100);
  285.    }
  286.  
  287.       /*Run until we run out of filenames, or the user aborts*/
  288.    while(!ExitFlag)
  289.    {
  290.       picFilename=curFilename;     /*Get a pointer to the filename buffer*/
  291.  
  292.      /*Check to see if we're running from Workbench.  If so, and the*/
  293.      /*user provided names of pictures to display (by clicking on their*/
  294.      /*icons), display those pictures*/
  295.       if(WBenchMsg!=NULL && WBenchMsg->sm_NumArgs>1)
  296.       {
  297.      CurrentDir(WBenchMsg->sm_ArgList[1].wa_Lock);
  298.      picFilename=WBenchMsg->sm_ArgList[1].wa_Name;
  299.       }
  300.       else if(playList) /*If a playlist is being used*/
  301.       {
  302.      pL=Open(playListFilename,MODE_OLDFILE);   /*Open the playlist*/
  303.  
  304.      if(pL==NULL)   /*If we couldn't open the playlist, abort*/
  305.      {
  306.         printError("Can't open playlist","");
  307.         cleanup();
  308.         exit(199);
  309.      }
  310.  
  311.      do    /*Loop until we run out of playlist, or get a valid name*/
  312.      {
  313.         if(FGets(pL,picFilename,140)==NULL) /*If end-of-file*/
  314.            picFilename=NULL;       /*Set as NULL as a flag*/
  315.      }
  316.      while(picFilename!=NULL && picFilename[0]==0x0A);
  317.  
  318.      if(picFilename!=NULL)        /*If not NULL, it's a valid filename*/
  319.         picFilename[strlen(picFilename)-1]=NULL; /*Remove the linefeed*/
  320.       }
  321.       else  /*Otherwise, if a playlist isn't being used, get the current*/
  322.      picFilename=filenames[0];     /*filename*/
  323.  
  324.  
  325.      /*Loop while the user hasn't requested an abort, and while*/
  326.      /*there are still files to display*/
  327.       for(c=0;!ExitFlag && picFilename!=NULL;c++)
  328.       {
  329.      if((iff->iff_Stream=Open(picFilename,MODE_OLDFILE))==NULL)
  330.      {     /*If the ILBM file can't be opened...*/
  331.  
  332.            /*Print an error...*/
  333.         printError("Can't open:  ", picFilename);
  334.  
  335.         cleanup();
  336.         exit(200);
  337.      }
  338.  
  339.      InitIFFasDOS(iff);      /*The IFF file will be read from disk*/
  340.  
  341.      OpenIFF(iff,IFFF_READ); /*Make iffparse.library aware of the*/
  342.                  /*ILBM file*/
  343.  
  344.      /*Read in the file and display*/
  345.      ReadAndDisplay(picFilename,iff);
  346.  
  347.      CloseIFF(iff);          /*Release iffparse's hold on the file*/
  348.  
  349.      Close(iff->iff_Stream); /*Close the file*/
  350.  
  351.         /*Get the next filename, either from Workbench,*/
  352.      if(WBenchMsg!=NULL)
  353.      {
  354.         if(WBenchMsg->sm_NumArgs > c+2)
  355.         {
  356.            CurrentDir(WBenchMsg->sm_ArgList[c+2].wa_Lock);
  357.            picFilename=WBenchMsg->sm_ArgList[c+2].wa_Name;
  358.         }
  359.         else
  360.            picFilename=NULL;
  361.      }
  362.      else if(playList)   /*The playlist*/
  363.      {
  364.         do
  365.         {
  366.            if(FGets(pL,picFilename,140)==NULL)
  367.           picFilename=NULL;
  368.         }
  369.         while(picFilename!=NULL && picFilename[0]==0x0A);
  370.  
  371.         if(picFilename!=NULL)
  372.            picFilename[strlen(picFilename)-1]=NULL;
  373.      }
  374.      else  /*or the command line*/
  375.         picFilename=filenames[c+1];
  376.       }
  377.  
  378.      /*We're finished with this run of pictures*/
  379.       if(playList)         /*Close playlist, if open*/
  380.      Close(pL);
  381.       pL=NULL;
  382.  
  383.       if(!loop && !printPics) /*If the loop flag wasn't given, exit*/
  384.      ExitFlag=TRUE;
  385.    }
  386.  
  387.       /*Time to exit, so close stuff*/
  388.  
  389.    cleanup();
  390.    exit(0); /*And exit*/
  391. }
  392.  
  393. LONG ilbmprops[] = { ID_ILBM,ID_CMAP,ID_ILBM,ID_BMHD,ID_ILBM,ID_CAMG,
  394.              ID_ILBM,ID_CRNG,ID_ILBM,ID_DRNG,ID_ILBM,ID_SHAM,
  395.              ID_ILBM,ID_CTBL };
  396.  
  397. /*Read in an ILBM file and display it*/
  398. void ReadAndDisplay(char *filename,struct IFFHandle *iff)
  399. {
  400.    int error;
  401.    UBYTE *bodyBuffer;    /*Pointer to buffer holding 'BODY' chunk info*/
  402.    ULONG ViewModes;    /*Holds the viewmodes flags*/
  403.    UWORD c;
  404.    ButtonTypes button;
  405.    UBYTE cycleTable[32];
  406.    UBYTE countDown;
  407.  
  408.       /*Structures required for IFF parsing*/
  409.    struct StoredProperty *bmhd,*cmap,*camg,*crng,*drng,*sham,*ctbl;
  410.    struct ContextNode *bodyContext;
  411.  
  412.       /*IntuiMessage...*/
  413.    struct IntuiMessage *mesg;
  414.  
  415.       /*Indentify chunks that should be stored during parse*/
  416.       /*(in this case, CMAP, BMHD, CRNG, DRNG, CAMG, and SHAM)*/
  417.    error=PropChunks(iff,ilbmprops,7);
  418.  
  419.       /*If there was an error, print a message and return*/
  420.    if(error!=0)
  421.    {
  422.       printError(errorMsg,filename);
  423.       ExitFlag=TRUE;
  424.       return;
  425.    }
  426.  
  427.       /*Tell iffparse to stop at a 'BODY' chunk*/
  428.    error=StopChunk(iff,ID_ILBM,ID_BODY);
  429.  
  430.       /*Error handling yet again*/
  431.    if(error!=0 && error!=-1)
  432.    {
  433.       printError(errorMsg,filename);
  434.       ExitFlag=TRUE;
  435.       return;
  436.    }
  437.  
  438.       /*Do the actual parsing*/
  439.    error=ParseIFF(iff,IFFPARSE_SCAN);
  440.  
  441.       /*Check for errors yet again*/
  442.    if(error!=0 && error !=-1)
  443.    {
  444.       printError(errorMsg,filename);
  445.       ExitFlag=TRUE;
  446.       return;
  447.    }
  448.  
  449.       /*Get the chunks that were found in the file*/
  450.    bmhd = FindProp(iff,ID_ILBM,ID_BMHD);  /*Bitmap information*/
  451.    cmap = FindProp(iff,ID_ILBM,ID_CMAP);  /*Color map*/
  452.    camg = FindProp(iff,ID_ILBM,ID_CAMG);  /*Amiga viewmode information*/
  453.    crng = FindProp(iff,ID_ILBM,ID_CRNG);  /*Color-cycling ranges*/
  454.    drng = FindProp(iff,ID_ILBM,ID_DRNG);  /*New (DPaint IV) color-cycling*/
  455.    sham = FindProp(iff,ID_ILBM,ID_SHAM);  /*SHAM color tables*/
  456.    ctbl = FindProp(iff,ID_ILBM,ID_CTBL);  /*Macro Paint color table info*/
  457.  
  458.       /*Get the descriptor for the BODY chunk*/
  459.    bodyContext=CurrentChunk(iff);
  460.  
  461.       /*If there wasn't a BMHD, CMAP, or BODY chunk, abort*/
  462.    if(!bmhd | !cmap | !bodyContext)
  463.    {
  464.       printError(filename,"is corrupted or is not in Amiga ILBM format");
  465.       ExitFlag=TRUE;
  466.       return;
  467.    }
  468.  
  469.       /*Prepare to determine screen modes*/
  470.    newScreen.ViewModes=NULL;
  471.  
  472.       /*If there was a CAMG chunk, use it to get the viewmodes*/
  473.    if(camg!=NULL)
  474.    {
  475.       ViewModes=( ((CAMG *)(camg->sp_Data))->viewmodes );
  476.  
  477.       if(ViewModes & HAM)
  478.      newScreen.ViewModes|=HAM;
  479.  
  480.       if(ViewModes & EXTRA_HALFBRITE)
  481.      newScreen.ViewModes|=EXTRA_HALFBRITE;
  482.  
  483.       if(ViewModes & LACE)
  484.      newScreen.ViewModes|=LACE;
  485.  
  486.       if(ViewModes & HIRES)
  487.      newScreen.ViewModes|=HIRES;
  488.    }
  489.  
  490.  
  491.    if(crng==NULL)
  492.       if(drng==NULL) /*No color cycling*/
  493.      numCycleColors=0;
  494.       else  /* DPaint-IV--style color cycling*/
  495.      numCycleColors=interpretDRNG(cycleTable,(DRNG *)(drng->sp_Data),&rate);
  496.    else  /*DPaint I-III--style color cycling*/
  497.       numCycleColors=interpretCRNG( cycleTable,(CRNG *)(crng->sp_Data),&rate);
  498.  
  499.    if(numCycleColors != 0)
  500.       cycle=TRUE;    /*Start cycling if there are colors to cycle*/
  501.    else
  502.       cycle=FALSE;
  503.  
  504.       /*Interpret the BMHD chunk*/
  505.    getBMHD((struct BitMapHeader *)bmhd->sp_Data);
  506.  
  507.       /*Don't open an interlace screen if the image is in SHAM mode*/
  508.       /*(the Amiga OS doesn't properly handle user copper lists on */
  509.       /*interlaced screens for some reason)*/
  510.    if(sham!=NULL)
  511.       newScreen.ViewModes&=~LACE;
  512.  
  513.       /*Open a screen, defined by the BMHD and CAMG chunks*/
  514.    screen=OpenScreenTagList(&newScreen,TagList);
  515.  
  516.       /*If the screen couldn't be opened, abort*/
  517.    if(screen==NULL)
  518.    {
  519.       printError("Cannot open screen!","");
  520.       ExitFlag=TRUE;
  521.       return;
  522.    }
  523.  
  524.       /*This more properly centers the screen, for some reason */
  525.    MoveScreen(screen,1,1);
  526.    MoveScreen(screen,-1,-1);
  527.  
  528.       /*Set the window dimensions from the screen dimensions*/
  529.    newWindow.Screen=screen;
  530.    newWindow.Width=newScreen.Width;
  531.    newWindow.Height=newScreen.Height;
  532.  
  533.       /*Open the window*/
  534.    window=OpenWindow(&newWindow);
  535.  
  536.       /*Abort if the window couldn't be opened*/
  537.    if(window==NULL)
  538.    {
  539.       printError("Cannot open window!","");
  540.  
  541.       ExitFlag=TRUE;
  542.       return;
  543.    }
  544.  
  545.       /*Allocate enough memory to hold the BODY data*/
  546.       /*We want to find out what the biggest block of memory is.  If*/
  547.       /*we have enough memory to hold the entire body chunk, we'll load*/
  548.       /*the whole thing into memory and decompress from there.    If not,*/
  549.       /*we'll load as much as we can and refill the buffer when it*/
  550.       /*empties*/
  551.       /*We do a Forbid() to keep anyone from allocating memory between*/
  552.       /*the AvailMem() and AllocMem() calls.  This way, we're guaranteed*/
  553.       /*that a memory block of the size given by Availmem() can be */
  554.       /*allocated.  For this reason, we don't need to check the result*/
  555.       /*of the AllocMem();  we're guaranteed that it worked*/
  556.    Forbid();
  557.    bufSize=AvailMem(MEMF_LARGEST);
  558.    bufSize=MIN(bufSize,bodyContext->cn_Size+1);
  559.    if(bufSize==0)    /*It'll never happen, but just in case...*/
  560.    {
  561.       Permit();
  562.       ExitFlag=TRUE;
  563.       return;
  564.    }
  565.  
  566.    bodyBuffer=AllocMem(bufSize,0L);
  567.    Permit();
  568.  
  569.    availBytes = bufSize;
  570.    curPos = bufSize;
  571.  
  572.       /*Blank out the pointer*/
  573.    SetPointer(window,fakePointerData,1,16,0,0);
  574.  
  575.       /*Set the screen colors to those provided in the CMAP chunk*/
  576.    setScreenColors(screen,cmap->sp_Data,newScreen.Depth,destMap,&numColors);
  577.  
  578.       /*Uncompress an ILBM and copy it into the bitmap*/
  579.    if(ReadIntoBitmapAsm(&(screen->BitMap.Planes),bodyBuffer,iff,bufSize,
  580.              (ULONG)screen->BitMap.BytesPerRow,
  581.              screen->BitMap.Rows,
  582.              screen->BitMap.Depth,(Compression==1) ? 1 : 0,
  583.              (masking) ? 1 : 0))
  584.    {
  585.       printError(errorMsg,"");
  586.       cleanup();
  587.       exit(2000);
  588.    }
  589.  
  590.  
  591.       /*Activate the window, and flush any IDCMP message*/
  592.    ActivateWindow(window);
  593.    while((mesg=(struct IntuiMessage *)GetMsg(window->UserPort))!=NULL)
  594.       ReplyMsg((struct Message *)mesg);
  595.  
  596.  
  597.       /*If this is a SHAM image, setup the copper list appropriately*/
  598.    if(sham!=NULL)
  599.    {
  600.       specialModes=SHAM;
  601.       setupSHAM(screen,(UWORD *)(sham->sp_Data));
  602.    }
  603.    else
  604.      /*If this is a MacroPaint image, setup the copper list*/
  605.       if(ctbl!=NULL)
  606.       {
  607.      specialModes=MACROPAINT;
  608.      setupDynHires(screen,(UWORD *)(ctbl->sp_Data));
  609.       }
  610.       else
  611.         /* Otherwise, this is a normal ILBM*/
  612.      specialModes=NORMAL;
  613.  
  614.       /*Bring the screen to the front*/
  615.    ScreenToFront(screen);
  616.  
  617.       /*If the user used the 'print' flag on the command line, print*/
  618.       /*the picture (but not if this is a SHAM or MacroPaint image)*/
  619.    if(printPics && specialModes == NORMAL)
  620.       dumpRastPort(&(screen->RastPort),&(screen->ViewPort));
  621.  
  622.    print=TRUE;
  623.  
  624.       /*Close the previous window and screen*/
  625.    if(prevWindow!=NULL)
  626.       CloseWindow(prevWindow);
  627.    if(prevScreen!=NULL)
  628.       CloseScreen(prevScreen);
  629.  
  630.       /*Free the buffer that holds the BODY chunk information*/
  631.    FreeMem(bodyBuffer,bufSize);
  632.  
  633.       /*Store the current window & screen structures, so they can be*/
  634.       /*closed later*/
  635.    prevWindow=window;
  636.    prevScreen=screen;
  637.  
  638.    screen=NULL;
  639.    window=NULL;
  640.  
  641.    rexxAbort=none;
  642.    countDown=rate;
  643.    if(ticks==0)   /*If ticks==0, this means that no delay was specified*/
  644.    {          /*by the user.  So just wait for him to click a button*/
  645.       int prevTopEdge=prevScreen->TopEdge;
  646.  
  647.       while((button=checkButton())==none && rexxAbort==none)
  648.       {
  649.         /*Wait for 1/60th of a second*/
  650.      WaitTOF();
  651.  
  652.         /*Refresh the SHAM copper list if required*/
  653.      if(prevTopEdge!=prevScreen->TopEdge && sham!=NULL)
  654.      {
  655.         prevTopEdge=prevScreen->TopEdge;
  656.         setupSHAM(prevScreen,(UWORD *)(sham->sp_Data));
  657.      }
  658.  
  659.         /*Refresh the MacroPaint copper list if required*?
  660.      if(prevTopEdge!=prevScreen->TopEdge && ctbl!=NULL)
  661.      {
  662.         prevTopEdge=prevScreen->TopEdge;
  663.         setupDynHires(prevScreen,(UWORD *)(ctbl->sp_Data));
  664.      }
  665.  
  666.         /*If its time to cycle the colors, then cycle them*/
  667.      if(cycle && numCycleColors!=0 && --countDown==0)
  668.      {
  669.         cycleColors(cycleTable,destMap,numCycleColors,numColors);
  670.         countDown=rate;
  671.      }
  672.      dispRexxPort();
  673.       }
  674.  
  675.      /*Check to see if the user wants to abort*/
  676.       if(button==menu || rexxAbort==menu)
  677.      ExitFlag=TRUE;
  678.    }
  679.    else     /*Otherwise, wait for the specified amount of time*/
  680.    {
  681.       for(c=0;c<ticks;c++)
  682.       {
  683.         /*Wait 1/60th of a second*/
  684.      WaitTOF();
  685.  
  686.         /*Cycle colors if necessary*/
  687.      if(cycle && numCycleColors!=0 && --countDown==0)
  688.      {
  689.         cycleColors(cycleTable,destMap,numCycleColors,numColors);
  690.         countDown=rate;
  691.      }
  692.  
  693.      dispRexxPort();         /*Check ARexx port*/
  694.  
  695.      button=checkButton();   /*After each 25 ticks, check to see if*/
  696.      if(button==menu || rexxAbort==menu)    /*the user wants to abort*/
  697.      {
  698.         ExitFlag=TRUE;
  699.         return;
  700.      }
  701.      if(button==select || rexxAbort==select)  /*Or advance prematurely*/
  702.         return;
  703.       }
  704.    }
  705. }
  706.  
  707. /*End of 2View.c*/
  708.  
  709.