home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / dv_x / dvix.zip / GENERIC.C < prev    next >
C/C++ Source or Header  |  1992-11-04  |  18KB  |  801 lines

  1. /*
  2.  * DVI previewer for X.
  3.  *
  4.  * Eric Cooper, CMU, September 1985.
  5.  *
  6.  * Code derived from dvi-imagen.c.
  7.  *
  8.  * Modified for X.10 by Bob Scheifler, MIT LCS, January 1986.
  9.  *
  10.  * Modified for X.10.3 (Sun) by Jeff Lee, UWO CSD, February 1987.
  11.  *    -fixed bitmap manipulation to use (short*) for portability
  12.  *    -added [G] for grid and [LRUD] for 1/4 screen motion
  13.  *    -added absolute [LRUD] and relative [lrud] positioning
  14.  *     in 1/10 inch increments.
  15.  *
  16.  * Modified (again) by Jeff Lee, UWO CSD, April 1987.
  17.  *    -added an [i] command to re-init the file
  18.  *
  19.  */
  20.  
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include "dvi.h"
  26. #include "pxl.h"
  27. #include "general.h"
  28. #include "local.h"
  29. #include "bitorder.h"
  30.  
  31. /* these are the interface routines to the viewer */
  32. extern set_char();
  33. extern set_rule();
  34. extern clear_page();
  35. extern put_border();
  36. extern end_page();
  37.  
  38.  
  39. struct frame {
  40.     long pxl_h, dvi_h, pxl_v, dvi_v, w, x, y, z;
  41. };
  42.  
  43. struct frame *stack;
  44. int stackp;
  45.  
  46. #define PXL_H   stack[stackp].pxl_h
  47. #define PXL_V   stack[stackp].pxl_v
  48. #define DVI_H   stack[stackp].dvi_h
  49. #define DVI_V   stack[stackp].dvi_v
  50. #define WW      stack[stackp].w
  51. #define XX      stack[stackp].x
  52. #define YY      stack[stackp].y
  53. #define ZZ      stack[stackp].z
  54.  
  55. /*
  56.  * Command line flags.
  57.  */
  58. extern char *prog;        /* program name */
  59. int debug = 0;
  60. int list_fonts = 0;
  61.  
  62. int pixels_per_inch = PIXELS_PER_INCH;
  63. int shrink_factor = SHRINK_FACTOR;
  64.  
  65. char *dvi_filename;            /* name of user's file */
  66. FILE *dvi_file;                /* user's file */
  67. time_t best_before;            /* stale date for file */
  68. char *tmp_dviname;            /* mod for DV/X, MS-DOS (GBP) */
  69.  
  70.  
  71. int font_not_found = 0;
  72. struct font *current_font = NULL;    /* ptr into circular list of fonts */
  73.  
  74. /*
  75.  * DVI preamble and postamble information.
  76.  */
  77. char job_id[300];
  78. int total_pages, maxstack;
  79. int current_page;
  80. double fraction, conv, specialConv;
  81. long numerator, denominator, magnification;
  82.  
  83. /*
  84.  * Offset in DVI file of last page, set in read_postamble().
  85.  */
  86. long last_page_offset;
  87.  
  88. /*
  89.  * Table of page offsets in DVI file, indexed by page number - 1.
  90.  * Initialized in prepare_pages().
  91.  */
  92. long *page_offset;
  93.  
  94. long win_w, win_h, page_w, page_h;
  95. long min_x, max_x, min_y, max_y;
  96. long smin_x, smax_x, smin_y, smax_y;
  97. int redisplay = 0;
  98. int new_file = 0;
  99.  
  100. unsigned long num();
  101. long snum();
  102.  
  103. extern unsigned char reverse_byte[];
  104. char *malloc(), *calloc(), *index();
  105.  
  106. /*
  107. **    (re)open the dvi file and save the name for later use in the
  108. **    global variable ``dvi_filename''
  109. */
  110. open_dvi_file(name)
  111.     char *name;
  112. {
  113.     struct stat filestat;
  114.     dvi_filename = name;
  115.  
  116.         dvi_file_copy(name);
  117.  
  118.     if (dvi_file) {
  119.         (void) fclose(dvi_file);
  120.         dvi_file = NULL;
  121.         clear_page();
  122.     }
  123.     if ((dvi_file = fopen(tmp_dviname, "rb")) == NULL) {
  124.         printf("File open error\n");
  125.         exit(1);
  126.      }
  127.  
  128.     /* now (re)set the global state */
  129.     process_preamble();
  130.     find_postamble();
  131.     read_postamble();
  132.     prepare_pages();
  133.     init_page();
  134.     redisplay = 0;
  135.     new_file = 1;
  136. }
  137.  
  138. /*
  139. **    check to see if a file has been modified
  140. */
  141. check_if_stale(file_name,date)
  142.     char *file_name;
  143.     time_t date;
  144. {
  145.         FILE *chkd_file;
  146.     struct stat filestat;
  147.  
  148.     if ((chkd_file = fopen(file_name,"rb"))==NULL) {
  149.         printf("Error opening dvi file\n");
  150.         exit(1);
  151.     }
  152.     if (fstat(fileno(chkd_file), &filestat)) {
  153.                 perror("fstat");
  154.                 return (1);
  155.     }
  156.     fclose(chkd_file);
  157.     return (filestat.st_mtime != date);
  158. }
  159.  
  160. /*
  161. **      process_preamble reads the information in the preamble and stores
  162. **      it into global variables for later use.
  163. */
  164. process_preamble()
  165. {
  166.         int   k;
  167.  
  168.         if (one(dvi_file) != PRE)
  169.         error("DVI file doesn't start with preamble");
  170.     if (one(dvi_file) != 2)
  171.         error("Wrong version of DVI output for this program");
  172.     numerator     = four(dvi_file);
  173.     denominator   = four(dvi_file);
  174.     magnification = four(dvi_file);
  175.     fraction = (((double) numerator * magnification)
  176.                                      / ((double) denominator * 1000.));
  177.     define_conv();
  178.     k = one(dvi_file);
  179.     (void) fread(job_id, sizeof(char), k, dvi_file);
  180.     job_id[k] = '\0';
  181. }
  182.  
  183. define_conv ()
  184. {
  185.     conv = ((fraction * pixels_per_inch) / 100000) / (2.54 * shrink_factor);
  186.     specialConv = pixels_per_inch / 1000.0 / shrink_factor;
  187. }
  188.  
  189. /*
  190. **      find_postamble locates the beginning of the postamble
  191. **    and leaves the file ready to start reading at that location.
  192. */
  193. find_postamble()
  194. {
  195.     ubyte byte;
  196.     long offset = -4;        /* At least 4 TRAILERS */
  197.  
  198.     do {
  199.         offset -= 1;
  200.         (void) fseek(dvi_file, offset, 2);
  201.         byte = one(dvi_file);
  202.     } while (byte == TRAILER);
  203.     if (byte != 2)
  204.         error("Wrong version of DVI output for this program");
  205.     offset -= 4;
  206.     (void) fseek(dvi_file, offset, 2);
  207.     (void) fseek(dvi_file, sfour(dvi_file), 0);
  208. }
  209.  
  210. /*
  211. **      read_postamble reads the information in the postamble,
  212. **    storing it into global variables.
  213. **      It also takes care of reading in all of the PXL files for the fonts
  214. **      used in the job.
  215. */
  216. read_postamble()
  217. {
  218.         ubyte   cmnd;
  219.     int page_width, page_height;
  220.  
  221.         if (one(dvi_file) != POST)
  222.         error("Postamble doesn't begin with POST");
  223.     last_page_offset = four(dvi_file);
  224.     if (numerator != four(dvi_file)
  225.               ||  denominator != four(dvi_file)
  226.           ||  magnification != four(dvi_file))
  227.         error("Postamble doesn't match preamble");
  228.     page_height = pixel_round(four(dvi_file));
  229.     page_width = pixel_round(four(dvi_file));
  230.     maxstack = two(dvi_file);
  231.     total_pages = two(dvi_file);
  232.     do {
  233.         switch(cmnd = one(dvi_file)) {
  234.             case FNTDEF1:
  235.             case FNTDEF2:
  236.             case FNTDEF3:
  237.             case FNTDEF4:
  238.             define_font(cmnd);
  239.             break;
  240.         case POSTPOST:
  241.             break;
  242.         default:
  243.             error("Non-fntdef cmnd found in postamble");
  244.         }
  245.     } while (cmnd != POSTPOST);
  246.     if (font_not_found)
  247.         error("Not all PXL files were found");
  248.     list_fonts = 0;
  249. }
  250.  
  251. prepare_pages()
  252. {
  253.     int i;
  254.  
  255.         stack = (struct frame *) malloc((unsigned) sizeof(struct frame) * (maxstack+1));
  256.         if (stack == NULL)
  257.         error("Can't allocate stack space (%d frames)", maxstack);
  258.     page_offset = (long *) malloc((unsigned) total_pages * sizeof(long));
  259.         if (page_offset == NULL)
  260.         error("Can't allocate page directory (%d pages)", total_pages);
  261.     i = total_pages;
  262.     page_offset[--i] = last_page_offset;
  263.     (void) fseek(dvi_file, last_page_offset, 0);
  264.     /*
  265.      * Follow back pointers through pages in the DVI file,
  266.      * storing the offsets in the page_offset table.
  267.      */
  268.     while (i > 0) {
  269.         (void) num(dvi_file, 1+4+(9*4));
  270.         (void) fseek(dvi_file, page_offset[--i] = four(dvi_file), 0);
  271.     }
  272. }
  273.  
  274. #define nope(str)       error("%s not implemented", str)
  275. #define correct()       (PXL_H = pixel_round(DVI_H))
  276.  
  277. do_pages()
  278. {
  279.         register int ch;
  280. #ifdef DEBUG
  281.     int setchar_ctr = 0;
  282.     int changefont_ctr = 0;
  283.     int other_ctr = 0;
  284. #endif /*DEBUG*/
  285.  
  286.     min_x = 0;
  287.     min_y = 0;
  288.     max_x = win_w;
  289.     max_y = win_h;
  290.     current_page = 0;
  291.     for (;;) {
  292.         ch = one(dvi_file);
  293. #ifdef DEBUG
  294.         if (debug & DBG_DVI)
  295.             print_dvi(ch);
  296. #endif /*DEBUG*/
  297.         if (ch <= SETCHAR0 + 127) {
  298. #ifdef DEBUG
  299.             setchar_ctr++;
  300. #endif /*DEBUG*/
  301.             set_char(ch);
  302.             DVI_H += current_font->glyph[ch].dvi_adv;
  303.             PXL_H =  pixel_round(DVI_H);
  304.         } else {
  305.             register long a, b;
  306. #ifdef DEBUG
  307.             other_ctr++;
  308. #endif /*DEBUG*/
  309.  
  310.             switch (ch) {
  311.                 case SET1:
  312.                 ch = one(dvi_file);
  313.                 if (ch < MAXCHARS) {
  314.                     set_char(ch);
  315.                     DVI_H += current_font->glyph[ch].dvi_adv;
  316.                     PXL_H =  pixel_round(DVI_H);
  317.                 } else {
  318.                     error("bad SET1 (%d)", ch);
  319.                 }
  320.                 break;
  321.  
  322.                 case SETRULE:
  323.                 a = sfour(dvi_file); b = sfour(dvi_file);
  324.                 if (a > 0  &&  b > 0) {
  325.                     correct();
  326.                     set_rule(pixel_round(a), pixel_round(b));
  327.                 }
  328.                 DVI_H += b;
  329.                 PXL_H =  pixel_round(DVI_H);
  330.                 break;
  331.  
  332.                 case PUT1:
  333.                 nope("PUT1");
  334.                 break;
  335.  
  336.                 case PUTRULE:
  337.                 a = sfour(dvi_file); b = sfour(dvi_file);
  338.                 if (a > 0  &&  b > 0) {
  339.                     correct();
  340.                     set_rule(pixel_round(a), pixel_round(b));
  341.                 }
  342.                 break;
  343.  
  344.                 case NOP:
  345.                 break;
  346.  
  347.                 case BOP:
  348.                 (void) num(dvi_file, 11*4);
  349.                 stackp = 0;
  350.                 DVI_H = dvi_round(X_PAGE_OFFSET);
  351.                 PXL_H = X_PAGE_OFFSET;
  352.                 DVI_V = dvi_round(Y_PAGE_OFFSET);
  353.                 PXL_V = Y_PAGE_OFFSET;
  354.                 WW = XX = YY = ZZ = 0;
  355.                 smin_x = min_x;
  356.                 smax_x = max_x;
  357.                 smin_y = min_y;
  358.                 smax_y = max_y;
  359.                 begin_page();
  360.                 break;
  361.  
  362.                 case EOP:
  363.                 if (stackp > 0)
  364.                     error("Stack not empty at EOP (%d)",
  365.                            stackp);
  366. #ifdef DEBUG
  367.     printf("SETCHAR=%d CHANGEFONT=%d OTHER=%d\n",
  368.         setchar_ctr, changefont_ctr, other_ctr);
  369. #endif
  370.                 end_page();
  371.                 if (ftell(dvi_file) > last_page_offset)
  372.                     return;
  373.                 break;
  374.  
  375.                 case PUSH:
  376.                 stackp++;
  377.                 if (stackp > maxstack)
  378.                     error("More PUSHes than were promised");
  379.                 stack[stackp] = stack[stackp - 1];
  380.                 break;
  381.  
  382.                 case POP:
  383.                 stackp--;
  384.                 if (stackp < 0)
  385.                     error("More POPs than PUSHes");
  386.                 break;
  387.  
  388.                 case RIGHT1:
  389.                 case RIGHT2:
  390.                 case RIGHT3:
  391.                 case RIGHT4:
  392.                 DVI_H += snum(dvi_file, ch - RIGHT1 + 1);
  393.                 PXL_H = pixel_round(DVI_H);
  394.                 break;
  395.  
  396.                 case X1:
  397.                 case X2:
  398.                 case X3:
  399.                 case X4:
  400.                 XX = snum(dvi_file, ch - X0);
  401.                 case X0:
  402.                 DVI_H += XX;
  403.                 PXL_H += pixel_round(XX);
  404.                 correct();
  405.                 break;
  406.  
  407.                 case W1:
  408.                 case W2:
  409.                 case W3:
  410.                 case W4:
  411.                 WW = snum(dvi_file, ch - W0);
  412.                 case W0:
  413.                 DVI_H += WW;
  414.                 PXL_H = pixel_round(DVI_H);
  415.                 break;
  416.  
  417.                 case Y1:
  418.                 case Y2:
  419.                 case Y3:
  420.                 case Y4:
  421.                 YY = snum(dvi_file, ch - Y0);
  422.                 case Y0:
  423.                 DVI_V += YY;
  424.                 PXL_V = pixel_round(DVI_V);
  425.                 break;
  426.  
  427.                 case Z1:
  428.                 case Z2:
  429.                 case Z3:
  430.                 case Z4:
  431.                 ZZ = snum(dvi_file, ch - Z0);
  432.                 case Z0:
  433.                 DVI_V += ZZ;
  434.                 PXL_V = pixel_round(DVI_V);
  435.                 break;
  436.  
  437.                 case DOWN1:
  438.                 case DOWN2:
  439.                 case DOWN3:
  440.                 case DOWN4:
  441.                 DVI_V += snum(dvi_file, ch - DOWN1 + 1);
  442.                 PXL_V = pixel_round(DVI_V);
  443.                 break;
  444.  
  445.                 case FNT1:
  446.                 case FNT2:
  447.                 case FNT3:
  448.                 case FNT4:
  449.                 change_font(num(dvi_file, ch - FNT1 + 1));
  450.                 break;
  451.  
  452.                 case XXX1:
  453.                 case XXX2:
  454.                 case XXX3:
  455.                 case XXX4:
  456.                 a = num(dvi_file, ch - XXX1 + 1);
  457.                 if(a > 0)
  458.                     special((unsigned long) a);
  459.                 break;
  460.  
  461.                 case FNTDEF1:
  462.                 case FNTDEF2:
  463.                 case FNTDEF3:
  464.                 case FNTDEF4:
  465.                 (void) fseek(dvi_file, (long) (12 + ch - FNTDEF1 + 1), 1);
  466.                 a = one(dvi_file) + one(dvi_file);
  467.                 (void) fseek(dvi_file, (long) a, 1);
  468.                 break;
  469.  
  470.                 case PRE:
  471.                 error("Shouldn't happen: PRE encountered.");
  472.                 break;
  473.  
  474.                 case POST:
  475.                 error("Shouldn't happen: POST encountered.");
  476.                 break;
  477.  
  478.                 case POSTPOST:
  479.                 error("Shouldn't happen: POSTPOST encountered.");
  480.                 break;
  481.  
  482.                 default:
  483.                 if (FNTNUM0 <= ch  &&  ch <= FNTNUM0 + 63) {
  484. #ifdef DEBUG
  485.                     changefont_ctr++;
  486.                     other_ctr--;
  487. #endif /*DEBUG*/
  488.                     change_font((unsigned long) (ch - FNTNUM0));
  489.                 }
  490.                 else
  491.                     error("Unknown op-code %d, offset %d",
  492.                     ch, ftell(dvi_file));
  493.             } /* end switch*/
  494.         } /* end else (ch not a SETCHAR or FNTNUM) */
  495.     } /* end for */
  496. }
  497.  
  498. begin_page()
  499. {
  500.     if (debug)
  501.         return;
  502.     clear_page();
  503.     put_border(0, 0, page_w, page_h, 1);
  504. }
  505.  
  506.  
  507. special(nbytes)
  508.     unsigned long nbytes;
  509. {
  510.     char *cmd;
  511.     int i;
  512.  
  513.     cmd = malloc((unsigned) nbytes+1);
  514.     if (cmd == NULL)
  515.         error("Can't allocate memory for special (%d bytes)", nbytes);
  516.     for (i = 0; i < nbytes; i += 1)
  517.         cmd[i] = getc(dvi_file);
  518.     cmd[i] = '\0';
  519.     applicationDoSpecial(cmd);
  520.     free(cmd);
  521. }
  522.  
  523. /*
  524. **
  525. **      Read size bytes from the FILE fp, constructing them into a
  526. **      signed/unsigned integer.
  527. **
  528. */
  529. unsigned long
  530. num(fp, size)
  531.     register FILE *fp;
  532.     register int size;
  533. {
  534.         register int i;
  535.     register long x;
  536.  
  537.     x = 0;
  538.     for (i = 0; i < size; i += 1)
  539.         x = x * 0x100 + (unsigned) (getc(fp) & 0xff);
  540.     return (x);
  541. }
  542.  
  543. long
  544. snum(fp, size)
  545.     register FILE *fp;
  546.     register int size;
  547. {
  548.         register int i;
  549.     register long x;
  550.  
  551.     x = getc(fp) & 0xff;
  552.     if (x & 0x80)
  553.             x -= 0x100;
  554.     for (i = 1; i < size; i += 1)
  555.         x = x * 0x100 + (unsigned) (getc(fp) & 0xff);
  556.     return (x);
  557. }
  558.  
  559. stop_output(sig)
  560. {
  561.     exit(sig);
  562. }
  563.  
  564. /* VARARGS1 */
  565. error(message, a, b, c, d, e, f)
  566.     char *message;
  567. {
  568.     (void) fprintf(stderr, "%s: ", prog);
  569.     (void) fprintf(stderr, message, a, b, c, d, e, f);
  570.     putc('\n', stderr);
  571.     exit(1);
  572. }
  573.  
  574. init_page()
  575. {
  576.     page_h = PAPER_HEIGHT;
  577.     page_w = PAPER_WIDTH;
  578. }
  579.  
  580. print_char(ch, g)
  581.     ubyte ch;
  582.     struct glyph *g;
  583. {
  584.     (void) printf("char %d", ch);
  585.     if (isprint(ch))
  586.         (void) printf(" (%c)", ch);
  587.     putchar('\n');
  588.     (void) printf("x = %d, y = %d, pxl = %d, dvi = %d\n",
  589.         g->x, g->y, g->pxl_adv, g->dvi_adv);
  590.     print_bitmap(&g->bitmap);
  591. }
  592.  
  593. print_bitmap(bitmap)
  594.     register struct bitmap *bitmap;
  595. {
  596.     register short *ptr;    /* bitmaps are shorts not bytes guys */
  597.     register int x, y, i;
  598.  
  599.     ptr = (short*) bitmap->bits;
  600.     if (ptr == NULL)
  601.         return;
  602.     (void) printf("w = %d, h = %d, bytes wide = %d\n",
  603.         bitmap->w, bitmap->h, bitmap->bytes_wide);
  604.     for (y = 0; y < bitmap->h; y += 1) {
  605.         for (x = 0; x < bitmap->bytes_wide; x += 2) {
  606.             for (i = 0; i < BITS_PER_BYTE*2; i += 1)
  607.                 if (*ptr & (1 << i))
  608.                     putchar('@');
  609.                 else
  610.                     putchar(' ');
  611.             ptr += 1;
  612.         }
  613.         putchar('\n');
  614.     }
  615. }
  616.  
  617. print_dvi(ch)
  618.     int ch;
  619. {
  620.     (void) printf("%4d %4d ", PXL_H, PXL_V);
  621.     if (ch <= SETCHAR0 + 127) {
  622.         (void) printf("SETCHAR%-3d", ch - SETCHAR0);
  623.         if (isprint(ch))
  624.             (void) printf(" (%c)", ch);
  625.     } else if (FNTNUM0 <= ch  &&  ch <= FNTNUM0 + 63) {
  626.         (void) printf("FNTNUM%d", ch - FNTNUM0);
  627.     } else {
  628.         switch (ch) {
  629.             case SET1:
  630.             (void) printf("SET1");
  631.             break;
  632.             case SETRULE:
  633.             (void) printf("SETRULE");
  634.             break;
  635.             case PUT1:
  636.             (void) printf("PUT1");
  637.             break;
  638.             case PUTRULE:
  639.             (void) printf("PUTRULE");
  640.             break;
  641.             case NOP:
  642.             (void) printf("NOP");
  643.             break;
  644.             case BOP:
  645.             (void) printf("BOP");
  646.             break;
  647.             case EOP:
  648.             (void) printf("EOP");
  649.             break;
  650.             case PUSH:
  651.             (void) printf("PUSH");
  652.             break;
  653.             case POP:
  654.             (void) printf("POP");
  655.             break;
  656.             case RIGHT1:
  657.             case RIGHT2:
  658.             case RIGHT3:
  659.             case RIGHT4:
  660.             (void) printf("RIGHT%d", ch - RIGHT1 + 1);
  661.             break;
  662.             case X0:
  663.             case X1:
  664.             case X2:
  665.             case X3:
  666.             case X4:
  667.             (void) printf("X%d", ch - X0);
  668.             break;
  669.             case W0:
  670.             case W1:
  671.             case W2:
  672.             case W3:
  673.             case W4:
  674.             (void) printf("W%d", ch - W0);
  675.             break;
  676.             case Y0:
  677.             case Y1:
  678.             case Y2:
  679.             case Y3:
  680.             case Y4:
  681.             (void) printf("Y%d", ch - Y0);
  682.             break;
  683.             case Z0:
  684.             case Z1:
  685.             case Z2:
  686.             case Z3:
  687.             case Z4:
  688.             (void) printf("Z%d", ch - Z0);
  689.             break;
  690.             case DOWN1:
  691.             case DOWN2:
  692.             case DOWN3:
  693.             case DOWN4:
  694.             (void) printf("DOWN%d", ch - DOWN1 + 1);
  695.             break;
  696.             case FNT1:
  697.             case FNT2:
  698.             case FNT3:
  699.             case FNT4:
  700.             (void) printf("FNT%d", ch - FNT1 + 1);
  701.             break;
  702.             case XXX1:
  703.             case XXX2:
  704.             case XXX3:
  705.             case XXX4:
  706.             (void) printf("XXX%d", ch - XXX1 + 1);
  707.             break;
  708.             case FNTDEF1:
  709.             case FNTDEF2:
  710.             case FNTDEF3:
  711.             case FNTDEF4:
  712.             (void) printf("FNTDEF%d", ch - FNTDEF1 + 1);
  713.             break;
  714.             case PRE:
  715.             (void) printf("PRE");
  716.             break;
  717.             case POST:
  718.             (void) printf("POST");
  719.             break;
  720.             case POSTPOST:
  721.             (void) printf("POSTPOST");
  722.             break;
  723.             default:
  724.             error("Unknown op-code %d, offset %d",
  725.                 ch, ftell(dvi_file));
  726.         } /* end switch*/
  727.     } /* end else (ch not a SETCHAR or FNTNUM) */
  728.     putchar('\n');
  729. }
  730.  
  731. /* mod for DV/X, MS-DOS, (GBP) */
  732. /*------------------------- dvi_file_copy ----------------------*/
  733. dvi_file_copy( char *from_name )
  734. {
  735.     FILE *from_file, *to_file;
  736.     char *from_name_dvi, *tmp_data;
  737.     int tmp_c, n_len;
  738.     struct stat filestat;
  739.     long filesize;
  740.  
  741. /* if dvi_file is open, close it */
  742.    if (dvi_file) fclose(dvi_file);
  743.    
  744. /* open dvi input file */
  745.     if ((from_file = fopen(from_name, "rb")) == NULL) {
  746.         n_len = strlen(from_name); 
  747.     if (strcmp(from_name + n_len - sizeof(".dvi"), ".dvi") == 0) {
  748.             perror(from_name);
  749.         exit(1);
  750.     }
  751.         from_name_dvi = malloc((unsigned) n_len + sizeof(".dvi"));
  752.         (void) sprintf(from_name_dvi, "%s.dvi", from_name);
  753.         if ((from_file = fopen(from_name_dvi, "rb")) == NULL) {
  754.         perror(from_name_dvi);            
  755.             exit(1);
  756.         }
  757.         else {
  758.             dvi_filename = from_name_dvi;
  759.     }    
  760.     }
  761.     else {
  762.         dvi_filename = from_name;
  763.     }
  764.  
  765. /* create the tmp file */
  766.     if ((to_file = fopen(tmp_dviname,"wb+")) == NULL ) {
  767.        printf("Temp file create error\n");
  768.        exit(1);
  769.     }
  770.  
  771. /* find size of dvi (from) file  */
  772.     fseek(from_file,0L,2);
  773.     filesize = ftell(from_file);
  774.     fseek(from_file,0L,0);
  775.     
  776. /* copy the file, in one shot if possible, or byte by byte */
  777.     if(!(tmp_data = (char *) malloc(filesize))) {
  778.         while ((tmp_c=getc(from_file))!=EOF)
  779.           putc(tmp_c,to_file);
  780.     }
  781.     else {
  782.         if (fread(tmp_data, filesize, 1, from_file)!=1) {
  783.            printf("Error on dvi file read\n");
  784.            exit(1);
  785.         }
  786.         if (fwrite(tmp_data, filesize, 1, to_file)!=1) {
  787.        printf("Error on tmp file write\n");
  788.        exit(1);
  789.     }
  790.         free(tmp_data);
  791.     }
  792.  
  793. /* record the modification date for later testing */
  794.     fstat(fileno(from_file), &filestat);
  795.     best_before = filestat.st_mtime;
  796.  
  797. /* close the files */    
  798.     fclose(from_file);
  799.     fclose(to_file);
  800. }
  801.