home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Graphics / graphics-16000.iso / msdos / animutil / anim13 / animate1.c < prev    next >
Text File  |  1990-04-03  |  33KB  |  826 lines

  1. /**************/
  2. /*            */
  3. /* animate1.c */
  4. /*            */
  5. /**************/
  6.  
  7. /*
  8. Date of most recent change in main() or any of its functions: 3 April 1990.
  9.  
  10. This program emulates a Tektronix 4010 monochrome graphics display
  11. and can replay files containing rasterized images.
  12.  
  13. The parameter file which is required by ANIMATE.EXE is ANIMATE.PAR.
  14. A copy of ANIMATE.PAR for EGA/VGA graphics is supplied with the source code.
  15. If you have Hercules monochrome graphics, you can get a Hercules
  16. version of ANIMATE.PAR by renaming ANIMATE.PAR (the EGA version) to
  17. ANIMATE.PAE and by renaming ANIMATE.PAH to ANIMATE.PAR.
  18.  
  19. Information for users of Turbo C (version 2 or newer) who wish to
  20. modify ANIMATE:
  21. The function "main" is in file ANIMATE1.C, and the functions it calls
  22. are contained in file ANIMATE2.C.
  23. The project file required by Turbo C's MAKE facility is ANIMATE.PRJ.
  24.  
  25. This program uses Borland's registerbgidriver() function to register
  26. the Hercules and EGA/VGA graphics driver.
  27. This means that you must use Borland's BGIOBJ utility to convert
  28. the Hercules and EGA/VGA graphics drivers into object (.OBJ) files.
  29. To do this, get into your Turbo C directory and type
  30. BGIOBJ HERC  and BGIOBJ EGAVGA
  31. Then copy HERC.OBJ and EGAVGA.OBJ into the directory where you intend
  32. to compile this animation program.
  33. Then compile this program using the project file ANIMATE.PRJ.
  34.  
  35. Jon Ahlquist, 24 Sep 1988, 28 Feb 1989, 1 Jan 1990.
  36.  
  37. Copyright 1990 by Jon Ahlquist, Department of Meteorology B-161,
  38. Florida State University, Tallahassee, Florida 32306-3034, USA.
  39. Telephone: (904) 644-1558.
  40. Telnet address: ahlquist@metsat.met.fsu.edu (ahlquist@128.186.5.2)
  41.  
  42. This software may be freely copied without charge.
  43. Copyright is made to prevent anyone from trying to impose restrictions
  44. on this software.
  45. All software and documentation is provided "as is" without warranty
  46. of any kind.
  47.  
  48. Development of this material was sponsored by NSF grant ATM-8714674.
  49. */
  50.  
  51. /***********************/
  52. /*                     */
  53. /* Include statements. */
  54. /*                     */
  55. /***********************/
  56.  
  57.                      /* Prototypes for: */
  58. #include <conio.h>   /* clrscr(). */
  59. #include <ctype.h>   /* toupper().*/
  60. #include <dos.h>     /* delay().  */
  61. #include <errno.h>   /* errno and error messages.*/
  62. #include <fcntl.h>   /* Macros for open()        */
  63. #include <graphics.h>/* All graphics routines.   */
  64. #include <io.h>      /* open(), write()          */
  65. #include <process.h> /* exit()                   */
  66. #include <stdio.h>   /* fopen(), fwrite(), fread(), fclose(). */
  67. #include <stdlib.h>  /* itoa(), max().           */
  68. #include <string.h>  /* strnicomp()              */
  69. #include <sys\stat.h>/* Definition of S_IREAD and S_IWRITE.   */
  70.  
  71.  
  72. /**********************/
  73. /*                    */
  74. /* Define statements. */
  75. /*                    */
  76. /**********************/
  77.  
  78. #define MAX_FILES (10)
  79. /* MAX_FILES is the maximum number of files to be opened by this program. */
  80.  
  81. #define ESC '\x1b'
  82. /* ASCII 'Escape' character. */
  83.  
  84. #define Ctrl_C '\x03'
  85. /* ASCII Control C */
  86.  
  87. /*****************************/
  88. /*                           */
  89. /* Start the main procedure. */
  90. /*                           */
  91. /*****************************/
  92.  
  93. void main(void)
  94. {
  95. int       display_frame_num, /* 1 if frame numbers should be displayed,
  96.                                 0 if not.                                */
  97.           EOF_flag,          /* 1 if an EOF was hit while trying to load
  98.                                 an image,
  99.                                 0 if the image was loaded ok.            */
  100.           first_frame_save,  /* Number of first frame to be saved in
  101.                                 rasterized form if rasterize==1.         */
  102.           first_loop,        /* 1 during the first loop through
  103.                                 the pictures,
  104.                                 0 on any subsequent loops.               */
  105.           frame_num,         /* Index for frame number.                  */
  106.           frame_num_color,   /* Palette color to be used for frame
  107.                                 number counter.                          */
  108.           frame_num_color_default, /* Default frame_num_color.           */
  109.           graph_driver,      /* Either EGA or HERCMONO.                  */
  110.           graph_driver_default, /* Default graph_driver                  */
  111.           graph_error,       /* Error code from graphresult().           */
  112.           graph_mode,        /* Either EGAHI or HERCMONOHI.              */
  113.           graph_mode_default,/* Default graph_mode.                      */
  114.           handle_background = 0,
  115.                              /* Handle to read rasterized image
  116.                                 onto which each Tektronix graph is drawn.
  117.                                 "Handle" refers to the integer returned
  118.                                 by open() which is then used by read()
  119.                                 and/or write().
  120.                                 'handle_background' is initialized
  121.                                 here only to prevent a compilation
  122.                                 warning about possible use before
  123.                                 initialization.                          */
  124.           handle[MAX_FILES], /* Handles  to rasterized image files.      */
  125.           handle_out = 0,    /* Handle for writing rasterized images.
  126.                                 'handle_out' is initialized here only to
  127.                                 prevent a compilation warning about
  128.                                 possible use before initialization.      */
  129.           ifile,             /* Loop index for counting files.           */
  130.           last_frame_save,   /* Number of last frame to be saved in
  131.                                 rasterized form if rasterize==1.         */
  132.           last_page,         /* 1 for double bufffereing of images,
  133.                                 0 for no double buffering.               */
  134.           last_file = -1,    /* No. of last input file.  The input files
  135.                                 are numbered beginning with zero.
  136.                                 last_file is initialized to -1 so that
  137.                                 the MAIN_MENU section of the program will
  138.                                 respond correctly.                       */
  139.           num_bit_planes,    /* No. of bit planes to load or save when
  140.                                 handling rasterized images.
  141.                                 EGA graphics have up to 4 bit planes.
  142.                                 This parameter is ignored for Hercules
  143.                                 graphics, which has only 1 bit plane.    */
  144.           num_bit_planes_default=1, /* Default num_bit_planes.           */
  145.           page,              /* Counter for video pages: 0 or 1.         */
  146.           pause,             /* 0 for no pause at end of picture loop,
  147.                                 1 for a brief pause before going back
  148.                                 to restart the loop of rasterized
  149.                                 pictures.                                */
  150.           rast_background=0, /* 1 to read a rasterized background image,
  151.                                 such as a map, onto which is plotted
  152.                                 each Tektronix graph.
  153.                                 0 for no background image to be part of
  154.                                 each Tektronix graph.                    */
  155.           rasterize = 0,     /* 1 to save images in rasterized form.
  156.                                 0 for no save of rasterized images.      */
  157.           single_step,       /* 1 if images should be shown one at a time
  158.                                 by hitting the 'n' or 'N' (next) key,
  159.                                 0 if pictures should be looped
  160.                                 automatically.                           */
  161.           xloc, yloc,        /* Pixel coordinates at which the frame
  162.                                 number is displayed if
  163.                                 display_frame_num == 1.                  */
  164.           xloc_default, yloc_default, /* Default xloc and yloc.          */
  165.           wait_increment=25, /* Number of milliseconds which is added
  166.                                 to or deducted from wait_time by
  167.                                 striking 's' or 'f' during image display.*/
  168.           wait_time;         /* Time in milliseconds to wait after
  169.                                 finishing the display of one image
  170.                                 before going on to start loading
  171.                                 the next image. */
  172.  
  173. char      frame_num_string[7],/* Frame number of displayed image
  174.                                 in ASCII form.                           */
  175.           purpose = 'T',     /* Single character chosen from main menu.
  176.                                 'purpose' is initialized here only to
  177.                                 prevent a compilation warning about
  178.                                 possible use before initialization.      */
  179.           response,          /* Response to questions: 'Y' or 'N' .      */
  180.           string_buffer[129],/* Buffer to hold  string input from the
  181.                                 user.                                    */
  182.           user_input;        /* Single character instruction while
  183.                                 displaying pictures.                     */
  184.  
  185. FILE      *fp[MAX_FILES];    /* File pointers to Tektronix files.        */
  186.  
  187.  
  188. struct palettetype palette,  /* Structure for use by setallpalette().    */
  189.                    palette_default; /* Default palette.                  */
  190.  
  191. /*
  192. Prototypes for functions contained in ANIMATE2.C.
  193. display_raster() and save_raster() are function pointers that are assigned
  194. to either EGA or Hercules versions of display_raster and save_raster
  195. by read_graphics_parms(). */
  196.  
  197.  
  198. int       display_EGA_raster       (int handle, int page, int num_bit_planes);
  199. int       display_Herc_raster      (int handle, int page, int num_bit_planes);
  200. int       (*display_raster)        (int handle, int page, int num_bit_planes);
  201. int       (*display_raster_default)(int handle, int page, int num_bit_planes);
  202.  
  203. int       Tek4010(FILE *fp);
  204.  
  205. void      change_directory (void);
  206. void      create_parms_file(void);
  207. void      display_directory(void);
  208. void      open_status(int handle);
  209. void      save_EGA_raster          (int handle, int page, int num_bit_planes);
  210. void      save_Herc_raster         (int handle, int page, int num_bit_planes);
  211. void      (*save_raster)           (int handle, int page, int num_bit_planes);
  212. void      (*save_raster_default)   (int handle, int page, int num_bit_planes);
  213. void      setscaling(int x_res_Tek, int y_res_Tek);
  214. FILE      *read_graphics_parms
  215.   (char   *file_name,
  216.    int    *ptr_to_graph_driver,  int *ptr_to_graph_mode,
  217.    int    *ptr_to_num_bit_planes,
  218.    struct palettetype *ptr_to_palette,
  219.    int    *ptr_to_frame_num_color,
  220.    int    *ptr_to_xloc,
  221.    int    *ptr_to_yloc,
  222.    int    (**ptr_to_ptr_to_display_raster)(),
  223.    void   (**ptr_to_ptr_to_save_raster)());
  224.  
  225.  
  226. /*****************************/
  227. /*                           */
  228. /* Read graphics parameters. */
  229. /*                           */
  230. /*****************************/
  231. {
  232. FILE *fp_par; /* File pointer to parameter file. */
  233. do {
  234.    fp_par = read_graphics_parms("ANIMATE.PAR",
  235.                &  graph_driver_default, &     graph_mode_default,
  236.                &num_bit_planes_default,
  237.                &       palette_default, &frame_num_color_default,
  238.                &          xloc_default, &           yloc_default,
  239.                &display_raster_default, &    save_raster_default);
  240.    if (fp_par == NULL) /* No parameter file found. */
  241.       {
  242.       printf("No parameter file found, so one will be created.\n");
  243.       create_parms_file();
  244.       }
  245.    }while (fp_par == NULL);
  246. fclose(fp_par); /* Close the parameter file. */
  247.  
  248. if (registerbgidriver(EGAVGA_driver) < 0)
  249.    {
  250.    printf("Unable to register EGA/VGA graphics driver.");
  251.    exit(1);
  252.    }
  253. if (registerbgidriver(Herc_driver)   < 0)
  254.    {
  255.    printf("Unable to register Hercules graphics driver.");
  256.    exit(1);
  257.    }
  258. } /* End of parameter file section. */
  259.  
  260.  
  261. /****************************************************/
  262. /*                                                  */
  263. /*                    Main menu.                    */
  264. /*                                                  */
  265. /****************************************************/
  266.  
  267. MAIN_MENU:
  268.  
  269. /* Close files opened by a prior menu selection.
  270. When this section is encountered for the first time, no files are closed
  271. because last_file = -1, rast_background = 0, and rasterize = 0.
  272. Thus, do not worry about compilation warnings stating that variables
  273. in this 'close file' section might be used before they are defined. */
  274. if (last_file >= 0)
  275.    for (ifile = 0; ifile <= last_file; ifile++)
  276.       {
  277.       if (purpose == 'T') fclose (fp    [ifile]);/* Do not worry about   */
  278.       else                 close (handle[ifile]);/* compilation warnings */
  279.       }                                          /* about the possibility*/
  280. if (rast_background) close (handle_background);  /* of using these       */
  281. if (rasterize)       close (handle_out);         /* variables before they*/
  282.                                                  /* are defined.         */
  283.  
  284. /* (Re)set default values. */
  285. closegraph();
  286. graph_driver      = graph_driver_default;
  287. graph_mode        = graph_mode_default;
  288. num_bit_planes    = num_bit_planes_default;
  289. save_raster       = save_raster_default;
  290. display_raster    = display_raster_default;
  291. palette           = palette_default;
  292. frame_num_color   = frame_num_color_default;
  293. xloc              = xloc_default;
  294. yloc              = yloc_default;
  295.  
  296. last_file         =-1; /* No files chosen yet for display.              */
  297. first_loop        = 1; /* First loop through the pictures.              */
  298. rast_background   = 0; /* No rasterized background image for Tek plots. */
  299. rasterize         = 0; /* No rasterized saves of images.                */
  300. wait_time         = 0; /* Millisecs to wait before showing next image.  */
  301. single_step       = 0; /* No single step through the pictures.          */
  302. display_frame_num = 0; /* No display of frame numbers in each picture.  */
  303. pause             = 0; /* No brief pause after the last rasterized
  304.                           picture before going back to the first
  305.                           picture to restart the loop.                  */
  306.  
  307. /* Display the menu. */
  308. restorecrtmode();
  309. clrscr();
  310. printf("             >>> ANIMATE   version 1.3 <<<\n"
  311.        "                c. 1990 by Jon Ahlquist\n\n"
  312.        "     Hit  To invoke\n\n"
  313.        "      C   Change disc:\\directory\n"
  314.        "      T   Tektronix 4010 emulation\n"
  315.        "      R   Rasterized image replay\n"
  316.        "      S   Script replay of rasterized images\n"
  317.        "     Esc  Escape (exit) this program\n");
  318.  
  319. /* Display the directory of the logged disc drive. */
  320. display_directory();
  321.  
  322. /****************************************************/
  323. /*                                                  */
  324. /*                 Get the menu choice.             */
  325. /*                 and enact it.                    */
  326. /*                                                  */
  327. /****************************************************/
  328.  
  329. /* Get the purpose of this run, and make sure that it is in upper case. */
  330. purpose = toupper(getch());
  331.  
  332. switch (purpose) /* Each section of code below is a different 'case.' */
  333. {
  334.  
  335. /*****************************/
  336. /*                           */
  337. /* Change working directory. */
  338. /*                           */
  339. /*****************************/
  340.  
  341. case 'C':
  342.    change_directory();
  343.    goto MAIN_MENU;
  344.  
  345. /************************/
  346. /*                      */
  347. /* Tektronix emulation. */
  348. /*                      */
  349. /************************/
  350. case 'T':
  351.  
  352.  
  353.    printf("\nTektronix emulation selected.\n"
  354.           "As prompted, enter names of files holding Tektronix graphs.\n"
  355.           "Enter MENU to interrupt input and return to main menu.\n"
  356.           "Enter DONE after all files are entered.\n");
  357.    for (ifile = 0; ifile < MAX_FILES; ifile++)
  358.       {
  359.       do {
  360.          printf ("Name of file %d? \n", ifile+1);
  361.          scanf  ("%s", string_buffer);
  362.  
  363.          /* Return to the main menu and reset all counters if
  364.          the user enters "menu." */
  365.          if (strnicmp(string_buffer, "menu", 4) == 0)
  366.             {
  367.             last_file = ifile-1;
  368.             goto MAIN_MENU;
  369.             }
  370.  
  371.          /* Break out of this "for" loop if the user enters "done." */
  372.          if (strnicmp(string_buffer, "done", 4) == 0)
  373.             {
  374.             last_file = ifile-1;
  375.             /* Jump down a few lines outside the "for" loop. */
  376.             goto ALL_FILES_ENTERED;
  377.             }
  378.  
  379.          fp[ifile] = fopen (string_buffer, "rb");
  380.          if (fp[ifile] == NULL)
  381.             {
  382.             if (errno == EMFILE)
  383.                {
  384.                printf("\nToo many files open.\n");
  385.                printf("Add FILES=20 to CONFIG.SYS,\n");
  386.                printf("or reduce the number of files.\n");
  387.                exit(1);
  388.                }
  389.             else
  390.                {
  391.                printf("\nUnable to open %s.\n", string_buffer);
  392.                printf("Check for a typing error, and try again.\n");
  393.                }
  394.             }
  395.          } while (fp[ifile] == NULL);
  396.    } /* End of 'for' loop. */
  397.    last_file = MAX_FILES-1;
  398.  
  399.    ALL_FILES_ENTERED:
  400.    printf("\nDo you want to READ a rasterized image onto which\n"
  401.           "each Tektronix graph will be plotted?\n");
  402.    do {
  403.       printf("Type 'y' or 'Y' for yes, 'n' or 'N' for no.\n");
  404.       response = toupper(getch());
  405.       if (response == ESC) goto MAIN_MENU;
  406.       if (response == Ctrl_C) exit(0);
  407.       } while (! ((response=='Y') || (response=='N')));
  408.  
  409.    rast_background = (response == 'Y');
  410.    if (rast_background)
  411.       {
  412.       do {
  413.          printf ("\nSpecify disc:\\subdirectory\\file for "
  414.                  "the rasterized background\n");
  415.          scanf  ("%s", string_buffer);
  416.          handle_background = open (string_buffer, O_RDONLY | O_BINARY);
  417.          open_status(handle_background);
  418.          } while (handle_background < 0);
  419.       }
  420.  
  421.    break; /* End of 'Tektronix emulation.'
  422.              The 'break' command jumps to the first statement
  423.              following the 'switch' section below. */
  424.  
  425.  
  426. /*****************************/
  427. /*                           */
  428. /* Replay rasterized images. */
  429. /*                           */
  430. /*****************************/
  431.  
  432. case 'R':
  433.    printf("\nRasterized replay selected.\n"
  434.           "As prompted, enter names of files holding rasterized images.\n"
  435.           "Enter MENU to interrupt input and return to main menu.\n"
  436.           "Enter DONE after all files are entered.\n");
  437.    for (ifile = 0; ifile < MAX_FILES; ifile++)
  438.       {
  439.       do {
  440.          printf ("Name of file %d?\n", ifile+1);
  441.          scanf  ("%s", string_buffer);
  442.  
  443.          /* Return to the main menu and reset all counters if
  444.          the user enters "menu." */
  445.          if (strnicmp(string_buffer, "menu", 4) == 0)
  446.             {
  447.             last_file = ifile-1;
  448.             goto MAIN_MENU;
  449.             }
  450.  
  451.          /* Break out of this "for" loop if the user enters "done." */
  452.          if (strnicmp(string_buffer, "done", 4) == 0)
  453.             {
  454.             last_file = ifile-1;
  455.             /* Jump down a few lines outside the "for" loop. */
  456.             goto all_files_entered;
  457.             }
  458.  
  459.          handle[ifile] = open (string_buffer, O_RDONLY | O_BINARY);
  460.          open_status(handle[ifile]);
  461.  
  462.          } while (handle[ifile] < 0);
  463.       } /* End of 'for' loop for entering file names. */
  464.    last_file = MAX_FILES-1;
  465.  
  466.    all_files_entered:
  467.    break; /* End of 'Replay rasterized images.'
  468.              The 'break' command jumps to the first statement
  469.              following the 'switch' section below. */
  470.  
  471.  
  472. /***************************************/
  473. /*                                     */
  474. /* Script replay of rasterized images. */
  475. /*                                     */
  476. /***************************************/
  477.  
  478. case 'S': /* Script replay of rasterized images. */
  479.    {
  480.    FILE *fp_script;
  481.    do {
  482.       printf("Enter the name of the file containing the script.\n"
  483.              "Enter MENU to interrupt input and return to main menu.\n");
  484.          scanf("%s", string_buffer);
  485.  
  486.          /* Return to the main menu and reset all counters if
  487.          the user enters "menu." */
  488.          if (strnicmp(string_buffer, "menu", 4) == 0) goto MAIN_MENU;
  489.  
  490.          fp_script = read_graphics_parms(string_buffer,
  491.             &graph_driver,   &graph_mode,      &num_bit_planes,
  492.             &palette,        &frame_num_color, &xloc, &yloc,
  493.             &display_raster, &save_raster);
  494.          if (fp_script == NULL)
  495.             {
  496.             if (errno == EMFILE)
  497.                {
  498.                printf("\nToo many files open to open script file.\n"
  499.                       "Add FILES=20 to CONFIG.SYS,\n"
  500.                       "or reduce the number of files.\n");
  501.                exit(1);
  502.                }
  503.             else
  504.                printf("\nUnable to open %s.\n"
  505.                       "Check for a typing error, and try again.\n",
  506.                       string_buffer);
  507.             }
  508.          } while (fp_script == NULL);
  509.  
  510.    /* Read the file(s) containing the images. */
  511.    for (ifile=0; ifile<MAX_FILES; ifile++)
  512.       {
  513.       /*Keep reading files until we hit an EOF or we read the
  514.       maximum number of files. */
  515.       if(fscanf(fp_script, "%s", string_buffer) == EOF)
  516.          {
  517.          last_file = ifile-1;
  518.          /* Jump down a few lines outside the "for" loop. */
  519.          goto ALL_files_entered;
  520.          }
  521.  
  522.       /* Open the file whose name was just read. */
  523.       handle[ifile] = open (string_buffer, O_RDONLY | O_BINARY);
  524.       if (handle[ifile] == -1)
  525.          {
  526.          printf("Unable to open file %s listed in your script file.\n",
  527.                 string_buffer);
  528.          exit(1);
  529.          }
  530.       }
  531.    last_file = MAX_FILES-1;
  532.  
  533.    ALL_files_entered:
  534.    fclose(fp_script);
  535.    }
  536.    break; /* End of 'Script replay of rasterized images.'
  537.              The 'break' command jumps to the first statement
  538.              following the 'switch' section below. */
  539.  
  540. /*********************/
  541. /*                   */
  542. /* Exit the program. */
  543. /*                   */
  544. /*********************/
  545.  
  546. case ESC:
  547. case Ctrl_C: exit(0);
  548.  
  549. default: goto MAIN_MENU; /* Choose again.  An undefined key was hit. */
  550. } /* End of 'switch' section. */
  551.  
  552. /**************************/
  553. /*                        */
  554. /* Ask about rasterizing. */
  555. /*                        */
  556. /**************************/
  557.  
  558. printf("\nDo you want to STORE rasterized versions of the images?\n");
  559. do {
  560.    printf("Type 'y' or 'Y' for yes, 'n' or 'N' for no.\n");
  561.    response = toupper(getch());
  562.    if (response == ESC) goto MAIN_MENU;
  563.    if (response == Ctrl_C) exit(0);
  564.    } while (! ((response=='Y') || (response=='N')));
  565.  
  566. rasterize = (response=='Y'); /* Set flag for rasterizing. */
  567.  
  568. if (rasterize)
  569.    {
  570.    do {
  571.       printf("\nSpecify disc:\\subdir\\file to hold rasterized images.\n");
  572.       scanf("%s", string_buffer);
  573.       handle_out = open(string_buffer,
  574.          O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IREAD | S_IWRITE);
  575.       if (handle_out < 0)
  576.       open_status(handle_out);
  577.       } while (handle_out < 0);
  578.  
  579.    do {
  580.       printf("\nSpecify the first and last frame numbers to be saved.\n"
  581.          "The images are numbered beginning with 1.\n"
  582.          "To save ALL images, type 1 and a large integer < 32768.\n");
  583.       scanf("%s", string_buffer); first_frame_save = atoi(string_buffer);
  584.       scanf("%s", string_buffer); last_frame_save  = atoi(string_buffer);
  585.       /* Repeat if an improper response was given, such as
  586.       a nonpositive integer,
  587.       a noninteger, in which case atoi() returned 0, or
  588.       the last frame is less than the first. */
  589.       } while ((first_frame_save < 1) || (last_frame_save < 1)
  590.             || (last_frame_save  < first_frame_save));
  591.  
  592.    /* Create a script file describing the rasterized images. */
  593.    if (purpose == 'S')
  594.       {
  595.       int  i;
  596.       char script_file[81];
  597.       FILE *fp_script;
  598.       printf("\nSpecify disc:\\subdir\\file to hold the SCRIPT for "
  599.              "the rasterized images.\n");
  600.       scanf("%s", script_file);
  601.       if ((fp_script = fopen(script_file, "wt+")) == NULL)
  602.          {
  603.          printf("Unable to open script file.\n");
  604.          exit(1);
  605.          }
  606.       if (graph_driver == EGA)
  607.          {
  608.          fprintf(fp_script, "EGA\n");
  609.          fprintf(fp_script, "%d\n", num_bit_planes);
  610.          for (i=0; i<16; i++) fprintf(fp_script, "%d ", palette.colors[i]);
  611.          fprintf(fp_script, "\n%d\n", frame_num_color);
  612.          }
  613.       else fprintf(fp_script, "Hercules\n");
  614.  
  615.       /* The remaining information is the same for EGA or Hercules. */
  616.       fprintf(fp_script, "%d  %d\n", xloc, yloc);
  617.       fprintf(fp_script, "%s", string_buffer);
  618.       fclose (fp_script);
  619.       } /* End of section for script file creation. */
  620.    } /* End of section for holding rasterized images. */
  621.  
  622.  
  623. /************************/
  624. /*                      */
  625. /* Initialize graphics. */
  626. /*                      */
  627. /************************/
  628.  
  629. /* Check to see whether frame_num_color lies within range. */
  630. {
  631. int  i, power_of_2;
  632. if (graph_driver == EGA)
  633.    {
  634.    /* Compute 2 raised to the power num_bit_planes. */
  635.    for (power_of_2 = 1, i = 0; i < num_bit_planes; i++) power_of_2 *= 2;
  636.    if (frame_num_color >= power_of_2)
  637.       {
  638.       printf("\n\n"
  639.              "The frame number color in ");
  640.       if (purpose == 'S')printf("in your script file is out of range.\n");
  641.       else               printf("ANIMATE.PAR is out of range.\n");
  642.       printf("It must lie between 1 and %d.\n"
  643.              "For now, the first palette color will be used.\n"
  644.              "Image display will begin in about 10 seconds.\n"
  645.              "In the meantime, make a note to correct this error.\n",
  646.              power_of_2 - 1);
  647.       frame_num_color = 1;
  648.       delay(10000);
  649.       }
  650.    }
  651. } /* End of check on frame_num_color. */
  652.  
  653. initgraph(&graph_driver,&graph_mode, "");
  654. graph_error = graphresult();
  655. if (graph_error < 0)
  656.    {
  657.    printf("Error while trying to initialize graphics.\n");
  658.    printf("%s\n", grapherrormsg(graph_error));
  659.    exit(1);
  660.    }
  661.  
  662. if (graph_driver == EGA)  /* Set colors for EGA mode. */
  663.    {
  664.    setallpalette(&palette);
  665.    setcolor(frame_num_color); /* Set drawing color for frame numbers. */
  666.    }
  667.  
  668. if (purpose == 'T')
  669.    /* Set scaling constants to transform from Tektronix 4010 coordinates
  670.    to graphics mode coordinates. */
  671.    setscaling(1024, 780);
  672.  
  673. /* We'll set up things not to use double buffering for Tektronix
  674. emulation and double buffering for other modes. */
  675. if (purpose == 'T') last_page = 0;
  676. else                last_page = 1;
  677. page  = last_page;
  678. ifile = 0;
  679.  
  680. /*******************/
  681. /*                 */
  682. /* Display images. */
  683. /*                 */
  684. /*******************/
  685.  
  686. /* Each execution of this "while" block displays all the images
  687. in the chosen files one time. */
  688. while (1)
  689.    {
  690.    frame_num = 0;
  691.    while (1) /* This block is executed once per input file. */
  692.       {
  693.       /* Toggle the page between 0 and last_page. */
  694.       page = last_page - page;
  695.       setactivepage(page);
  696.  
  697.       /* Display an image. */
  698.       if (purpose == 'T') /* Invoke the Tektronix emulator. */
  699.          {
  700.          if (rast_background) /* Plot the graph on a background image. */
  701.             {
  702.             do {
  703.                EOF_flag =
  704.                   display_raster(handle_background, page, num_bit_planes);
  705.                if (EOF_flag) lseek(handle_background, 0L, SEEK_SET);
  706.                } while(EOF_flag);
  707.             }
  708.          else cleardevice(); /* Plot the graph on a blank screen. */
  709.          EOF_flag = Tek4010(fp[ifile]); /* Plot the graph. */
  710.          }
  711.  
  712.       else /* Invoke rasterized image replay.
  713.               'display_raster' is a function pointer to either
  714.               'display_EGA_raster' or display_Herc_raster.'
  715.            */
  716.          EOF_flag = display_raster(handle[ifile], page, num_bit_planes);
  717.  
  718.       /*********************************************************/
  719.       /*                                                       */
  720.       /* See whether the user has given keyboard instructions. */
  721.       /*                                                       */
  722.       /*********************************************************/
  723.  
  724.       while (kbhit())
  725.          {
  726.          user_input = toupper( getch() );
  727.  
  728.          USER_INPUT:
  729.          switch(user_input)
  730.             {
  731.             case 'F': wait_time = (int) max(0, wait_time - wait_increment);
  732.                       break;
  733.             case 'S': wait_time = (int) min(25000, wait_time + wait_increment);
  734.                       break;
  735.             case '1': single_step       = 1 - single_step;       break;
  736.             case 'D': display_frame_num = 1 - display_frame_num; break;
  737.             case 'P': pause             = 1 - pause;             break;
  738.             case ESC:
  739.             case Ctrl_C: goto MAIN_MENU;
  740.             }
  741.          }
  742.  
  743.       if (EOF_flag) /* An EOF was hit without getting an image.*/
  744.          {
  745.          /* Reset the page and go for the next image. */
  746.          page = last_page - page;
  747.  
  748.          /* We read Tektronix files only once, so we do not need to rewind
  749.          them.  Otherwise, we would have fseek(fp(++ifile), 0L, SEEK_SET);
  750.          instead of ifile++; and else{fseek(fp[ifile=0],0L,SEEK_SET);break;}
  751.          instead of else break; */
  752.          if (purpose == 'T')
  753.             {
  754.             if (ifile < last_file) ifile++;
  755.             else break;
  756.             }
  757.  
  758.          /* Go to the next file and rewind it. */
  759.          else /* purpose == 'R' or 'S' */
  760.             {
  761.             if (ifile < last_file) lseek(handle[++ifile], 0L, SEEK_SET);
  762.             else /* ifile = last_file */
  763.                {
  764.                lseek(handle[ifile=0], 0L, SEEK_SET);
  765.                break; /* Jump outside the "while" block,
  766.                          and start the next loop. */
  767.                }
  768.             }
  769.          }/* End of "EOF hit" section. */
  770.  
  771.       else /* Image plotted. */
  772.          {
  773.          /* If single stepping, wait till user hits 'n' or 'N' before
  774.             showing the next frame.
  775.             If the user hits something else, take it as a user input
  776.             instruction.
  777.          */
  778.          if (single_step)
  779.             {
  780.             user_input = toupper(getch());
  781.             if (user_input != 'N') goto USER_INPUT;
  782.             }
  783.  
  784.          /* Display frame number if requested. */
  785.          frame_num++;
  786.          if (display_frame_num)
  787.             {
  788.             /* Convert the frame number to a base 10 ASCII string.
  789.             We call outtextxy twice because once is not always enough
  790.             to make it work correctly.  I presume the problem arises
  791.             because Turbo C graphics were not designed with the idea
  792.             of users messing with the bit planes on their own. */
  793.             itoa(frame_num, frame_num_string, 10);
  794.             outtextxy(xloc, yloc, frame_num_string);
  795.             outtextxy(xloc, yloc, frame_num_string);
  796.             }
  797.  
  798.          setvisualpage(page);
  799.  
  800.          if (rasterize && first_loop)
  801.             {
  802.             if ((frame_num >= first_frame_save) &&
  803.                 (frame_num <= last_frame_save))
  804.                save_raster(handle_out, page, num_bit_planes);
  805.             }
  806.  
  807.          delay((unsigned)wait_time); /* Pause between pictures. */
  808.          }/* End of "Image plotted" section. */
  809.       } /* End of "while" block which is executed once per input file.
  810.            Reaching this point means that we have displayed each of the
  811.            desired images.
  812.         */
  813.  
  814.       /* Go back to the main menu if we are Tektronix mode. */
  815.       if (purpose == 'T') goto MAIN_MENU;
  816.  
  817.       /* Reset the "first_loop" flag to indicate that the next loop
  818.       through the images is not the first. */
  819.       first_loop = 0;
  820.  
  821.       /* Pause for a second on the last image if the user wants to pause
  822.       and if we are not in single step mode. */
  823.       if (pause && !single_step) delay(1000);
  824.  
  825.    } /* End of block to loop images.  */
  826. } /* End of main. */