home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / msdos / animutil / anim13 / animate2.c < prev    next >
Text File  |  1990-04-03  |  28KB  |  806 lines

  1. /**************/
  2. /*            */
  3. /* animate2.c */
  4. /*            */
  5. /**************/
  6.  
  7. /*
  8. Second half of animate.c containing the functions called by
  9. the main function.
  10. Jon Ahlquist, 24 Sep 1988, 28 Feb 1989, 1 Jan 1990.
  11.  
  12. Copyright 1990 by Jon Ahlquist, Department of Meteorology B-161,
  13. Florida State University, Tallahassee, Florida 32306-3034, USA.
  14. Telephone: (904) 644-1558.
  15. Telnet address: ahlquist@metsat.met.fsu.edu (ahlquist@128.186.5.2)
  16.  
  17. This software may be freely copied without charge.
  18. Copyright is made to prevent anyone from trying to impose restrictions
  19. on this software.
  20. All software and documentation is provided "as is" without warranty
  21. of any kind.
  22.  
  23. Development of this material was sponsored by NSF grant ATM-8714674.
  24. */
  25.  
  26. /**************/
  27. /*            */
  28. /* Prototypes */
  29. /*            */
  30. /**************/
  31.  
  32. #include <conio.h>   /* getch().       */
  33. #include <ctype.h>   /* toupper().     */
  34. #include <dos.h>     /* outportb().    */
  35. #include <dir.h>     /* chdir(), getcwd(), findfirst, findnext(), setdisk(). */
  36. #include <errno.h>   /* errno, EMFILE. */
  37. #include <graphics.h>/* All graphics routines. */
  38. #include <io.h>      /* _read(), _write().     */
  39. #include <process.h> /* exit().        */
  40. #include <stdio.h>   /* printf().      */
  41. #include <stdlib.h>  /* qsort().       */
  42. #include <string.h>  /* strcat().      */
  43.  
  44. /* Global variables. */
  45. float   X_scale, X_offset, Y_scale, Y_offset;
  46.  
  47. /******************************************************************/
  48.  
  49. FILE      *read_graphics_parms
  50.   (char   *file_name,
  51.    int    *ptr_to_graph_driver,
  52.    int    *ptr_to_graph_mode,
  53.    int    *ptr_to_num_bit_planes,
  54.    struct  palettetype *ptr_to_palette,
  55.    int    *ptr_to_frame_num_color,
  56.    int    *ptr_to_xloc,
  57.    int    *ptr_to_yloc,
  58.    int   (**ptr_to_ptr_to_display_raster)(),
  59.    void  (**ptr_to_ptr_to_save_raster)())
  60.  
  61. /*
  62. This function reads graphics parameters from file "file_name."
  63. Jon Ahlquist, 1 Jan 1990.
  64. */
  65. {
  66. int   i;              /* Loop index. */
  67. char  video_mode[9];  /* Either "EGA" or "Hercules". */
  68. FILE *fp;             /* File pointer to parameter file. */
  69.  
  70. /* Function prototypes. */
  71. int  display_EGA_raster (int handle, int page, int num_bit_planes);
  72. int  display_Herc_raster(int handle, int page, int num_bit_planes);
  73. void save_EGA_raster    (int handle, int page, int num_bit_planes);
  74. void save_Herc_raster   (int handle, int page, int num_bit_planes);
  75.  
  76.  
  77. /* Open the file containing the graphics instructions. */
  78. fp = fopen(file_name, "rt");
  79. if (fp == NULL) return(NULL); /* No parameter file found. */
  80.  
  81. /* Read the graphics mode to be used. */
  82. fscanf(fp, "%s", video_mode);
  83.  
  84. if (strnicmp(video_mode, "EGA", 3) == 0)
  85.    {
  86.    *ptr_to_graph_driver = EGA;
  87.    *ptr_to_graph_mode   = EGAHI;
  88.  
  89.    /* Read the number of bit planes to be loaded
  90.    and the colors to be assigned to the bit planes. */
  91.    fscanf(fp, "%d", ptr_to_num_bit_planes);
  92.  
  93.    /* Define the colors to be used. */
  94.    ptr_to_palette->size = 16; /* No. of colors. */
  95.    for (i=0; i<16; i++) fscanf(fp, "%d", &ptr_to_palette->colors[i]);
  96.  
  97.    /* Select which of the palette colors will be used when writing
  98.    the frame number. */
  99.    fscanf(fp, "%d", ptr_to_frame_num_color);
  100.  
  101.    /*
  102.    ptr_to_ptr_to_save_raster and ptr_to_ptr_to_display_raster
  103.    are pointers to pointers.
  104.    Here, we store the starting address of save_EGA_raster and
  105.    display_EGA_raster in the address pointed to by ptr_to_ptr_to_save_raster
  106.    and ptr_to_ptr_to_display_raster, respectively.
  107.    */
  108.    *ptr_to_ptr_to_save_raster    = save_EGA_raster;
  109.    *ptr_to_ptr_to_display_raster = display_EGA_raster;
  110.    }
  111.  
  112. else if (strnicmp(video_mode, "Her", 3) == 0)
  113.    {
  114.    *ptr_to_graph_driver = HERCMONO;
  115.    *ptr_to_graph_mode   = HERCMONOHI;
  116.  
  117.    *ptr_to_ptr_to_save_raster    = save_Herc_raster;
  118.    *ptr_to_ptr_to_display_raster = display_Herc_raster;
  119.    /* See explanation of ptr_to_ptr_to_save_raster
  120.    and ptr_to_ptr_to_display_raster above. */
  121.    }
  122.  
  123. else
  124.    {
  125.    printf("Invalid graphics mode listed at the beginning of file %s.\n"
  126.           "Only EGA or Hercules are acceptable.\n", file_name);
  127.    fclose(fp);
  128.    exit(0);
  129.    }
  130.  
  131. /* Read the position at which the left edge of the frame number
  132. should be displayed when that option is selected. */
  133. fscanf(fp, "%d %d", ptr_to_xloc, ptr_to_yloc);
  134.  
  135. return(fp);
  136. }
  137.  
  138. /******************************************************************/
  139.  
  140. void change_directory(void)
  141. {
  142.  
  143. char  drive[3], directory[81], filename[9], ext[5], string_buffer[81];
  144.  
  145. TRY_AGAIN:
  146. printf("\nEnter disc:\\directory\n");
  147. scanf ("%s", string_buffer);
  148.  
  149. /* Split the string into the drive name and directory using
  150. fnsplit(), which parses a string into a drive, directory, and filename.
  151. The directory and filename strings must be merged (concatenated)
  152. because actually they are both part of the directory name. */
  153. fnsplit(string_buffer, drive, directory, filename, ext);
  154. /* fnsplit is Borland function, not part of the ANSI standard. */
  155. strcat(directory,filename); /* ANSI concatenation function. */
  156.  
  157. /* To change the disk drive, we convert the disk drive name
  158. to upper case ASCII.  Then we call setdisk with 0 for drive A,
  159. 1 for drive B, etc.  Since A is coded in ASCII as 65 (base 10),
  160. we convert from the ASCII letter to the integer we want
  161. by subtracting 65 (base 10). */
  162. if (drive[0]     != '\0') setdisk(toupper(drive[0]) - 65);
  163. if (directory[0] != '\0')
  164.    {
  165.    if (chdir(directory))
  166.       {
  167.       printf("Path not found.  Try again.\n");
  168.       goto TRY_AGAIN;
  169.       }
  170.    }
  171. } /* End of change_directory(). */
  172.  
  173. /******************************************************************/
  174.  
  175. void create_parms_file(void)
  176. /* This function creates a file containing adjustable parameters.
  177. Jon Ahlquist, 23 July 1988, 27 Nov 1989, 1 Jan 1990.
  178. */
  179.  
  180. {
  181. char      response,          /* Response to question about graphics type.*/
  182.           num_bit_planes,    /* No. of bit planes to be loaded (1 to 4). */
  183.           graphics_type[9];  /* Graphics driver;
  184.                                 either 'EGA' or 'Hercules'.              */
  185.  
  186. int       i,                 /* 'For' loop index.                        */
  187.           color,             /* Color index, value of 0 to 63.           */
  188.           frame_num_color,   /* Palette number (1-16) of the color
  189.                                 in which the frame number will be
  190.                                 written.                                 */
  191.           power_of_2,        /* 2 to the power num_bit_planes.           */
  192.           xloc, yloc;        /* Pixel coordinates at which the frame
  193.                                 number is displayed if requested.        */
  194.  
  195. FILE      *fp_par;           /* FILE pointer to the parameter file.      */
  196.  
  197.  
  198. /* Open the parameter file. */
  199. fp_par = fopen("animate.par", "wt+");
  200. if (fp_par == NULL)
  201.    {
  202.    printf("\nTrouble opening parameter file ANIMATE.PAR.\n");
  203.    exit(1);
  204.    }
  205.  
  206. /* Get the default graphics type. */
  207. printf("\nDoes your computer have EGA graphics?\n"
  208.        "(If not, we'll assume it has Hercules graphics.)\n");
  209. do {
  210.    printf("Type 'y' or 'Y' for yes, 'n' or 'N' for no.\n");
  211.    response = toupper(getch());
  212.    if ((response == '\x1b'/* Escape key */ )|
  213.        (response == '\x03'/* Control C  */ )) exit(1);
  214.    } while (! ((response=='Y') || (response=='N')));
  215.  
  216.  
  217. if (response == 'Y')
  218.    strcpy(graphics_type, "EGA");
  219. else
  220.    strcpy(graphics_type, "Hercules");
  221. fprintf(fp_par, "%s\n", graphics_type);
  222.  
  223. /* There are extra questions if you have EGA graphics. */
  224. if (strcmp(graphics_type,"EGA") == 0)
  225.    {
  226.    /* Get the number of bit planes to be loaded. */
  227.    do {
  228.       printf("\nWhen reading or writing rasterized images,\n"
  229.              "how many bit planes should be loaded "
  230.              "under default conditions?\n"
  231.              "Normally this is 1, but it could be as large as 4.\n");
  232.       /* Get response and convert from an ASCII character to integer form. */
  233.       num_bit_planes = getche() - 48; /* Character '1' is 49, '4' is 52. */
  234.       } while (num_bit_planes<1 || num_bit_planes>4);
  235.    fprintf(fp_par, "%d\n", num_bit_planes);
  236.  
  237.    /* Get the color assignments for the palette. */
  238.    printf("\n\nSpecify the assignment of colors for the palette "
  239.           "of 16 colors.\n"
  240.           "These are 16 integers, each lying between 0 and 63.\n"
  241.           "If you just stated that you will usually load "
  242.           "more than 1 bit plane,\n"
  243.           "you can get the default EGA colors by entering:\n"
  244.           "0 1 2 3 4 5 7 20  56 57 58 59 60 61 62 63\n"
  245.           "If you just stated that only 1 bit plane will usually be loaded,\n"
  246.           "a reasonable choice is\n"
  247.           "1 62 0 0 0 0 0 0  0 0 0 0 0 0 0 0\n"
  248.           "which will give yellow lines on a blue background.\n");
  249.    for (i = 0; i < 16; i++)
  250.       {
  251.       scanf("%d", &color);
  252.       fprintf(fp_par, "%d ", color);
  253.       }
  254.    fprintf(fp_par, "\n");
  255.  
  256.    /* Get the color for displaying frame numbers. */
  257.    if (num_bit_planes == 1) /* No choice if num_bit_planes = 1. */
  258.       fprintf(fp_par, "1\n");
  259.    else
  260.       {
  261.       for (power_of_2=1, i=0; i<num_bit_planes; i++) power_of_2 *= 2;
  262.       do {
  263.          printf("\nIf and when you display frame numbers on your plots,\n"
  264.                 "in which palette color do you want the numbers written?\n"
  265.                 "Your answer should lie between 1 and %d."
  266.                 "  (0 is the background color.)\n", power_of_2 - 1);
  267.          scanf("%d", &frame_num_color);
  268.          } while (frame_num_color<1 || frame_num_color>=power_of_2);
  269.       fprintf(fp_par, "%d\n", frame_num_color);
  270.       }
  271.    } /* End of section for bit planes and colors for EGA. */
  272.  
  273. /* Ask where to display frame numbers when that option is selected. */
  274. printf("\nSpecify the pixel column and row at which the left edge of the\n"
  275.        "frame number will be displayed if that option is selected.\n"
  276.        "EGA coordinates run from (0,0) in the upper left corner\n"
  277.        "to (639,349) in the lower right corner.\n"
  278.        "Hercules coordinates run from (0,0) in the upper left corner\n"
  279.        "to (719,347) in the lower right corner.\n"
  280.        "0 10  is often a good choice for either EGA or Hercules graphics.\n");
  281. scanf ("%d %d", &xloc, &yloc);
  282. fprintf(fp_par, "%d %d\n", xloc, yloc);
  283.  
  284. fclose (fp_par); /* Close the parameter file. */
  285. } /* End of create_parms_file. */
  286.  
  287. /******************************************************************/
  288.  
  289. void display_directory(void)
  290. /*
  291. List all the files in the current directory.
  292. Jon Ahlquist, 1 Jan 1990.
  293. */
  294. {
  295.  
  296. #define NCHARS 13
  297.    /* Max. no. of characters in an MS/DOS file name, counting
  298.    the final null terminator at the end of the character string. */
  299. #define MAX_FILES 100
  300.    /* Max. no. of files to display. */
  301.  
  302. int    done,    /* =0 if a file is found.
  303.                    =-1 if no file is found. */
  304.        i,       /* Loop counter.           */
  305.        nfiles;  /* Number of files.        */
  306.  
  307. struct ffblk  ffblk; /* See Borland's documentation for findfirst(). */
  308.  
  309. char   current_working_directory[81],
  310.        file_name[MAX_FILES][NCHARS]; /* file_name will hold up to MAX_FILES
  311.                                     files from the current directory. */
  312.  
  313. getcwd(current_working_directory, 80);/* Get current working directory.*/
  314. printf("\nCurrent Working Directory: %s\n", current_working_directory);
  315.  
  316. done = findfirst("*.*",&ffblk,0);
  317. i    = 0;
  318. while (!done && i<MAX_FILES)
  319.    {
  320.    strcpy(file_name[i],ffblk.ff_name);
  321.    done = findnext(&ffblk);
  322.    i++;
  323.    }
  324. nfiles=i;
  325.  
  326. /* Alphabetize the list of files using the quicksort algorithm. */
  327. qsort(&file_name, nfiles, NCHARS, strcmp);
  328.  
  329. for (i = 0; i<nfiles; i++)
  330.    {
  331.    printf("  %-12s",file_name[i]);
  332.    if (i%5 == 4) printf("\n");
  333.    }
  334. printf("\n");
  335. }
  336.  
  337. /******************************************************************/
  338.  
  339. void setscaling(int x_res_Tek, int y_res_Tek)
  340. /* x_res_Tek = No. of columns of pixels.
  341.    y_res_Tek = No. of rows    of pixels. */
  342.  
  343. /* This function determines scaling parameters that are used to
  344. translate Tektronix graphics into graphics for the local
  345. graphics device.
  346.  
  347. Jon Ahlquist, 23 June 1988, 1 Dec 1989.
  348. */
  349.  
  350. /* define global variables that will be accessed
  351. during Tektronix emulation. */
  352.  
  353. {
  354.  
  355. int     X_res, Y_res, x_asp, y_asp;
  356. float   aspect_ratio, pixel_aspect_ratio, aspect_ratio_Tek, ratio;
  357.  
  358. /* Determine the aspect ratio of the Tektronix graphics.
  359. Tektronix pixels are square.
  360. The origin for Tektronix coordinates is in the lower left corner
  361. of the screen. */
  362. aspect_ratio_Tek = (float)x_res_Tek / (float)y_res_Tek;
  363.  
  364. /* Pixel addresses start with zero, so we subtract 1 from each of
  365. the Tektronix dimensions to get their maximum values.
  366. For example, for the Tektronix 4010, x runs from 0 through 1023
  367. and y runs from 0 through 779.*/
  368. x_res_Tek--;
  369. y_res_Tek--;
  370.  
  371. /* Determine the resolution of the graphics mode. */
  372. X_res = getmaxx(); /* No. of columns of pixels, less 1. */
  373. Y_res = getmaxy(); /* No. of rows    of pixels, less 1. */
  374.  
  375. /* Determine the relative width and height of a pixel.  */
  376. getaspectratio (&x_asp, &y_asp);
  377. pixel_aspect_ratio = (float) x_asp / (float) y_asp;
  378.  
  379. /* Determine the ratio of width to height of a full screen
  380.    in the local graphics mode. */
  381. aspect_ratio = pixel_aspect_ratio * (X_res + 1) / (Y_res + 1);
  382.  
  383.  
  384.  
  385. /* Set the scaling and offset factors in order to
  386. convert from Tektronix graphics coordinates to the coordinates
  387. used by the graphics mode selected.
  388. (x,y) refers to Tektronix coordinates.
  389. (X,Y) refers to the user's local graphics mode coordinates.
  390. Y_scale is negative because (x,y) = (0,0) is in the lower left
  391. corner with Tektronix graphics, while (X,Y) = (0,0) is in the
  392. upper left corner with Borland graphics. */
  393.  
  394. ratio = aspect_ratio_Tek / aspect_ratio;
  395.  
  396. if (ratio >= 1)
  397.    /* If ratio >= 1, then the Tektronix screen is relatively wider
  398.    than the screen for the graphics mode selected.
  399.    In that case, we need to adjust the scaling so that the
  400.    width of the Tektronix plot will fill the width of the screen,
  401.    and the height of the Tektronix plot will be vertically
  402.    centered.  That is, the middle value of y in
  403.    Tektronix coordinates, i.e. 0.5 * y_res_Tek,
  404.    should be mapped to the middle value of the user's
  405.    Y coordinate, i.e. 0.5 * Y_res. */
  406.    {
  407.    X_scale  =  ((float) X_res) / ((float) x_res_Tek);
  408.    Y_scale  = -X_scale *  pixel_aspect_ratio;
  409.    X_offset =  0.5;
  410.    Y_offset =  0.5 * (Y_res  -  Y_scale * y_res_Tek)  +  0.5;
  411.    }
  412.  
  413.  
  414. else
  415.    /* If ratio < 1, then the Tektronix screen is relatively narrower
  416.    than the screen for the graphics mode selected.
  417.    In that case, we need to adjust the scaling so that the
  418.    height of the Tektronix plot will fill the height of the screen,
  419.    and the width of the Tektronix plot will be horizontally
  420.    centered.  That is, the middle value of x in
  421.    Tektronix coordinates, i.e. 0.5 * x_res_Tek,
  422.    should be mapped to the middle value of the user's
  423.    X coordinate, i.e. 0.5 * X_res. */
  424.    {
  425.    Y_scale  = -((float) Y_res) / ((float) y_res_Tek);
  426.    X_scale  = -Y_scale / pixel_aspect_ratio;
  427.    X_offset =  0.5 * (X_res  -  X_scale * x_res_Tek)  +  0.5;
  428.    Y_offset =  Y_res   +  0.5;
  429.    }
  430. } /*End of function setscaling(); */
  431.  
  432. /******************************************************************/
  433.  
  434. int  Tek4010 (FILE *fp)
  435.  
  436. /*
  437. Tek4010() emulates a Tektronix 4010 graphics terminal
  438. based on the description of Tek4010 operation given in chapter 5
  439. of the manual for Flexi-Tek communications software.
  440. Tek4010() ignores all alphanumeric input as well as
  441. any position/status enquiry.
  442. We assume that a graph is finished when either a screen clear command
  443. is received or when alphanumeric mode is entered after previously being
  444. in graphics mode.
  445.  
  446. Return value: Tek4010() returns integer 1 if an EOF was encountered
  447. without meeting any graphics instructions.
  448. 0 is returned if a graph has been drawn.
  449.  
  450. Tek4010() uses global variables X_scale, X_offset, Y_scale, and Y_offset
  451. computed by function setscaling().
  452.  
  453. Jon Ahlquist, 1 July 1988, 15 Sep 1989, 8 Jan 1990, 3 April 1990.
  454. */
  455.  
  456. {
  457. /* ASCII characters. */
  458. #define LF  0x0a /* Line feed */
  459. #define FF  0x0c /* Form feed */
  460. #define CR  0x0d /* Carriage return   */
  461. #define ESC 0x1b /* Escape (Control [)*/
  462. #define GS  0x1d /* Control ] */
  463. #define US  0x1f /* Control _ (underscore) */
  464.  
  465. /* Define masks 2 bytes long which will keep the rightmost 5 bits and
  466. the next 5 significant bits when used with the bitwise
  467. "and" operation (&). */
  468. #define keep_lo_5 0x001f
  469. #define keep_hi_5 0x03e0
  470.  
  471. #define FALSE 0
  472. #define TRUE  1
  473.  
  474. typedef  int  boolean; /* Boolean variables are either TRUE or FALSE. */
  475. boolean  lo_y_set,     /* FALSE if lowest 5 bits of Tektronix coordinate y
  476.                           are not yet defined.  TRUE if defined. */
  477.          start_line;   /* FALSE if (x,y) does not begin a line,
  478.                           TRUE  if (x,y) does begin a line. */
  479.  
  480. char     byte;         /* byte from the Tektronix file. */
  481.  
  482. int      x, y,         /* Tektronix 4010 coordinates. */
  483.          X, Y;         /* Pixel coordinates. */
  484.  
  485. /* Skip all alphanumeric characters that may reside in the file
  486. before graphics mode is invoked.
  487. Return to the calling program if we hit an end of file. */
  488. do {
  489.    byte = fgetc(fp);
  490.    if (byte == EOF) return(1);
  491.    } while (byte != GS);
  492. /* Reaching this point means that we have encountered ASCII character GS,
  493. which invokes graphics mode. */
  494.  
  495.  
  496. /* Initialize variables. */
  497. lo_y_set = FALSE;
  498. x = 0;
  499. y = 0;
  500.  
  501. /* Decode the Tek 4010 graphics instructions and plot the graph. */
  502. while (1)
  503. {
  504. switch(byte=getc(fp))
  505. {
  506.  
  507. /* First consider the cases that call for return to the calling function. */
  508. case EOF: /* End of file. */
  509. case  US: /* Alphanumeric mode invoked. */
  510.    return(0);
  511.  
  512. case  CR:
  513.    /* Ignore a "carriage return, line feed" combination, but
  514.    consider a graph to be complete if alphanumeric mode is entered
  515.    after being in graphics mode. */
  516.    if (getc(fp) != LF) return(0);
  517.    else break;
  518.  
  519. case ESC:
  520.    /* ESC FF clears the screen.
  521.    Thus, it is a signal that a graph is complete. */
  522.    if (getc(fp) == FF) return(0);
  523.    else break;
  524.  
  525. case GS: /* Graphics mode re-invoked. */
  526.    start_line = TRUE; /* The next point will start a line. */
  527.    break;
  528.  
  529. default:
  530.    /* The only remaining case of interest to us is when the byte has a value
  531.    that could be a graphics coordinate.  Throw it away otherwise. */
  532.    if ((byte < 32)|| (byte>127)) break;
  533.  
  534.    /* At this point we are guaranteed that the byte is an x or y coordinate.
  535.    Check the leftmost 3 bits of the byte to see whether the rightmost
  536.    5 bits are the low or high 5 bits of an x or y coordinate. */
  537.    switch(byte >> 5)
  538.       {
  539.  
  540.       case 0x01: /* Set the high bits of x or y. */
  541.          /* If the low 5 bits of y have been set,
  542.          the bits are the high 5 bits of x. */
  543.          if (lo_y_set) x = ( ((int)(keep_lo_5 & byte)) << 5) |
  544.                                    (keep_lo_5 & x);
  545.          /* Otherwise, the bits are the high 5 bits of y. */
  546.          else          y = ( ((int)(keep_lo_5 & byte)) << 5) |
  547.                                    (keep_lo_5 & y);
  548.          break;
  549.  
  550.  
  551.       case 0x02: /* Set low 5 bits of x and plot. */
  552.          x = (keep_hi_5 & x) | (keep_lo_5 & byte);
  553.  
  554.          /* Convert from Tektronix coordinates to pixel coordinates. */
  555.          X = x * X_scale + X_offset;
  556.          Y = y * Y_scale + Y_offset;
  557.  
  558.          /* Perform the requested graphics operation. */
  559.          if (start_line) moveto (X, Y);
  560.          else            lineto (X, Y);
  561.  
  562.          /* Reset indicator to indicate that the next coordinate received
  563.          will NOT be the start of a new line. */
  564.          start_line = FALSE;
  565.          /* Reset indicator to say that the low 5 bits of y have
  566.          NOT been set since the last point was plotted. */
  567.          lo_y_set = FALSE;
  568.          break;
  569.  
  570.       case 0x03: /* Set the low 5 bits of y.  */
  571.          y = (keep_hi_5 & y) | (keep_lo_5 & byte);
  572.          /* Set the flag that says that the low 5 bits
  573.          of y have been set. */
  574.          lo_y_set = TRUE;
  575.       } /* End of "switch(byte>>5)" */
  576. } /* End of "switch (byte)" */
  577. } /* End of "while(1)" */
  578. /* The following return statement is unreachable, but its presence suppresses
  579. a compiler warning saying that the function should return a value.
  580. Tek4010() does return a value, but all the return statements are internal
  581. to the function. */
  582. return(1);
  583. } /* End of Tek4010(). */
  584.  
  585. /**********************************************************************/
  586.  
  587. void open_status(int handle)
  588.  
  589. /* Function to check on the status of an open() statement.
  590.    It always returns a value of 0.
  591.    Jon Ahlquist, 8 July 1988.
  592. */
  593. {
  594. if (handle < 0)
  595.    {
  596.    if (errno == EMFILE)
  597.       {
  598.       printf("\nToo many files open.\n"
  599.              "Add FILES=20 to CONFIG.SYS,\n"
  600.              "or reduce the number of files.\n");
  601.       exit(1);
  602.       }
  603.    else
  604.       {
  605.       printf("\nTrouble opening file.\n"
  606.              "If you made a typing error, retype the file.\n"
  607.              "Otherwise, hit control C to abort.\n");
  608.       }
  609.     }
  610. }
  611.  
  612. /*********************************************************************/
  613.  
  614. /* FROM HERE TO THE END, THERE ARE FUNCTIONS THAT DEPEND ON A PARTICULAR
  615. GRAPHICS DRIVER.*/
  616.  
  617. /*********************************************************************/
  618. /*** HERCULES VERSIONS ***/
  619. /*********************************************************************/
  620.  
  621. void save_Herc_raster(int handle_out, int page, int num_bit_planes)
  622.  
  623. /* This function stores a Hercules image to disc in rasterized form,
  624. i.e. pixel by pixel.
  625.  
  626.  
  627. Variable        Meaning
  628.  
  629. handle_out      Handle to the file to which the image will be written.
  630.  
  631. page            Video page to be saved, either 0 or 1.
  632.  
  633. num_bit_planes  Unused dummy variable included to provide consistency with
  634.                 save_EGA_raster().
  635.  
  636.  
  637. Jon Ahlquist, 22 July 1988, 1 Dec 1989.
  638. */
  639.  
  640. {
  641. #define  NBYTES_HERC 32768U /* Number of bytes in a Hercules image. */
  642.  
  643. unsigned  nbytes_written;
  644. void far  *fptr;
  645.  
  646. /* Define the address on the grahics board from which the image will
  647. be read. */
  648. fptr = page ? (void far *) 0xb8000000L : (void far *) 0xb0000000L;
  649.  
  650. nbytes_written = _write(handle_out, fptr, NBYTES_HERC);
  651. if (nbytes_written < NBYTES_HERC)
  652.    {
  653.    closegraph();
  654.    printf("Can't save image.  Disc is probably full.\n");
  655.    exit(1);
  656.    }
  657. } /* End of save_Herc_raster().
  658. Don't worry about a compilation warning saying that num_bit_planes is never
  659. used.  num_bit_planes is not needed by save_Herc_raster() and was included
  660. only so that the call to save_Herc_raster() would be like the call to
  661. save_EGA_raster, where num_bit_planes is required. */
  662.  
  663. /*********************************************************************/
  664.  
  665. int display_Herc_raster (int handle_in, int page, int num_bit_planes)
  666.  
  667. /* This function reads and displays a rasterized Hercules image.
  668. It returns a value of 1 if an EOF was hit,
  669. a value of 0 if at least some bits were read to the video board.
  670.  
  671. Variable        Meaning
  672.  
  673. handle_in       Handle to the file from which the image will be read.
  674.  
  675. page            Video page to be saved, either 0 or 1.
  676.  
  677. num_bit_planes  Unused dummy variable included to provide consistency with
  678.                 display_EGA_raster().
  679.  
  680. Jon Ahlquist, 22 July 1988, 8 Jan 1990.
  681. */
  682.  
  683. {
  684. #define  NBYTES_HERC 32768U /* Number of bytes in a Hercules image. */
  685. unsigned nbytes_read;
  686. void far *fptr;
  687.  
  688. /* Define the address on the grahics board to which the image will
  689. be written. */
  690. fptr = page ? (void far *) 0xb8000000L : (void far *) 0xb0000000L;
  691.  
  692. /* Read the image from disc. */
  693. nbytes_read = _read(handle_in, fptr, NBYTES_HERC);
  694. return(nbytes_read == 0);
  695. } /* End of display_Herc_raster().
  696. Don't worry about a compilation warning saying that num_bit_planes is never
  697. used.  num_bit_planes is not needed by display_Herc_raster() and was included
  698. only so that the call to display_Herc_raster() would be like the call to
  699. display_EGA_raster, where num_bit_planes is required. */
  700.  
  701.  
  702. /**************************************************************************/
  703. /*** EGA VERSIONS ***/
  704. /**************************************************************************/
  705.  
  706. void save_EGA_raster(int handle_out, int page, int num_bit_planes)
  707.  
  708. /* This function stores an EGA image to disc in rasterized form,
  709. i.e. pixel by pixel.
  710.  
  711. Variable        Meaning
  712.  
  713. handle_out      Handle to the file to which the image will be written.
  714.  
  715. page            Video page to be saved, either 0 or 1.
  716.  
  717. num_bit_planes  Number of bit planes to store.
  718.                 Any value between 1 and 4, inclusive, is acceptable.
  719.  
  720. Jon Ahlquist, 22 July 1988, 1 Dec 1989.
  721. */
  722.  
  723. {
  724. #define  ONE          0x01
  725. #define  NBYTES_EGA 28000U /* Number of bytes in an EGA bit plane. */
  726.  
  727. int      bit_plane;
  728. unsigned nbytes_written;
  729. void far *fptr;
  730.  
  731.  
  732. /* Define the address on the grahics board from which the image will
  733. be read. */
  734. fptr = page ? (void far *) 0xa8000000L : (void far *) 0xa0000000L;
  735.  
  736. /* Tell the graphics board that one or more bit planes will be read. */
  737. outportb(0x3ce, 4);
  738.  
  739. /* Loop through the bit plane(s) and write the image to the output file. */
  740. for (bit_plane = 0; bit_plane < num_bit_planes; bit_plane++)
  741.    {
  742.    /* Toggle the bit plane from which the image will be taken. */
  743.    outportb(0x3cf, bit_plane);
  744.  
  745.    /* Write the image to the output file. */
  746.    nbytes_written = _write(handle_out, fptr, NBYTES_EGA);
  747.    if (nbytes_written < NBYTES_EGA)
  748.       {
  749.       closegraph();
  750.       printf("Can't save image.  Disc is probably full.\n");
  751.       exit(1);
  752.       }
  753.    }
  754. } /* End of save_EGA_raster(). */
  755.  
  756. /*********************************************************************/
  757.  
  758. int display_EGA_raster(int handle_in, int page, int num_bit_planes)
  759.  
  760. /* This function reads and displays a rasterized EGA image.
  761. It returns a value of 1 if an EOF was hit,
  762. a value of 0 if at least some bits were read to the video board.
  763.  
  764.  
  765. Variable        Meaning
  766.  
  767. handle_in       Handle to the file from which the image will be read.
  768.  
  769. page            Video page to be saved, either 0 or 1.
  770.  
  771. num_bit_planes  Number of bit planes to store.
  772.                 Any value between 1 and 4, inclusive, is acceptable.
  773.  
  774. Jon Ahlquist, 22 July 1988, 8 Jan 1990.
  775. */
  776.  
  777. {
  778. #define  ONE          0x01
  779. #define  NBYTES_EGA  28000U /* Number of bytes in an EGA bit plane. */
  780.  
  781. int      bit_plane;
  782. unsigned nbytes_read;
  783. void far *fptr;
  784.  
  785.  
  786. /* Define the address on the grahics board to which the image will
  787. be written. */
  788. fptr = page ? (void far *) 0xa8000000L : (void far *) 0xa0000000L;
  789.  
  790. /* Tell the graphics board that bits will be written into the video board. */
  791. outportb(0x3c4, 0x02);
  792.  
  793. /* Read the image from the input file,
  794. writing it to the requested bit planes. */
  795. for (bit_plane = 0; bit_plane < num_bit_planes; bit_plane++)
  796.    {
  797.    /* Select which bit plane will receive the next record from disc. */
  798.    outportb(0x3c5, ONE << bit_plane);
  799.  
  800.    /* Read a record from disc into the bit plane. */
  801.    nbytes_read = _read(handle_in, fptr, NBYTES_EGA);
  802.    if (nbytes_read == 0) return(1); /* An EOF was hit. */
  803.    }
  804. return(0);
  805. } /* End of display_EGA_raster(). */
  806.