DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦947b946b9⟧ TextFile

    Length: 14550 (0x38d6)
    Types: TextFile
    Names: »ps.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/laser-setters/dvi-to-ps/TeXPS/dvitps/src/ps.c« 

TextFile

/* Copyright 1988 Stephan v. Bechtolsheim */

/* This file is part of the TeXPS Software Package.

The TeXPS Software Package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.  No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing.  Refer to the TeXPS Software Package
General Public License for full details.

Everyone is granted permission to copy, modify and redistribute
the TeXPS Software Package, but only under the conditions described in the
TeXPS Software Package General Public License.   A copy of this license is
supposed to have been given to you along with TeXPS Software Package so you
can know your rights and responsibilities.  It should be in a
file named CopyrightLong.  Among other things, the copyright notice
and this notice must be preserved on all copies.  */

#include <stdio.h>
#if SYS_V == 1
#include <string.h>
#else
#include <strings.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <grp.h>
#include "defs.h"
#include "units.h"
#include "dvitps.h"
#include "extfil.h"
#include "fontd.h"
#include "pdr.h"
#include "emit.h"

extern char *ctime();
extern long time();
extern void PushAndSwitchPsOutput();
extern void PopPsOutputSwitch();
extern EX_FILES ExDvi;
extern char * DvitpsBinaryName;
extern int NumCharsInPixelFonts;
extern FE_P Fonts[MAX_FONTS];
extern int DraftOption;
extern int NumberOfCopies;
extern int CountPages;
extern double PageHOffset; /* Their default is zero */
extern double PageVOffset;
extern char * StrcpyAlloc();
extern int ManualFeed;
extern int ConformingDocument;
extern int Resolution;
extern int ThisPagesOrientation;
extern char *PrologueFilesPath;
extern char *LocateFileWithPath();
extern char *SetUpHashTable();
extern char *GetNextKeyHash();
extern int PssColumn;
extern char *PaperType;
extern int SendPaperSizeSpecOut;
extern char HostName[STRSIZE];
extern int PsPrintEnabled;
extern EX_FILES Ex_PsOutput;
extern double ReadDimensionReturnInches();

char * PsDownLoadHashTable;

void PsEndSend();
void PsMatrixSend();
void PsDownLoad();
void PsSendFile();

/* Fudge factors in X and Y. If portrait mode than X is applied to
 * horizontal movements and Y is applied to vertical movements.
 * If landscape mode then X is applied to the vertical movements to
 * TeX, and Y is applied to the horizontal movements of X, which makes
 * it come out in the same directions on the paper compared to portrait
 * mode.
 * The default is, naturally, 1.0.
 */
double FudgeX;
double FudgeY;

/* The reference time for the current run. */
long ReferenceTime;

/*
 * PsBeginningSend
 * ***************
 * Sends some identification info to the Postscript Printer so things
 * like the current date and time can be printed.
 * Triggers (but doesn't do it itself) also setting up the coordinate
 * transformation matrix.
 */
void
PsBeginningSend()
{
  long    dvi_file_time;
  char    time_as_string[128];
  char * ptr, * ptr2;
  struct stat status;

  PsDownLoad ("texpre.pro", 0);
  PsDownLoad ("pos.pro",    0);
  PsDownLoad ("rules.pro",  0);

  /* Manual Feed ? */
  if (ManualFeed)
    fprintf (EX_FP(Ex_PsOutput), "statusdict begin /manualfeed true def end\n");

  if (Strlen(PaperType) == 0)
    Fatal ("PsBeginningSend(): paper format is empty.");
  if (SendPaperSizeSpecOut)
    fprintf (EX_FP(Ex_PsOutput), "%s\n", PaperType);

  /* Identification of job, dvi file name, hostnames, times etc. */
  fprintf (EX_FP(Ex_PsOutput), "/Dvi-File-Name (%s) def\n",
	Strcmp(ExDvi.ef_fn, "-") == 0 ? "<stdin>": ExDvi.ef_fn);
  if (PsPrintEnabled)
    fprintf (EX_FP(Ex_PsOutput), "(Dvi file name: \") print Dvi-File-Name print (\".\\n) print\n");
  fprintf (EX_FP(Ex_PsOutput), "/Draft-Flag %s def\n", DraftOption? "true":"false");
  fprintf (EX_FP(Ex_PsOutput), "/#copies %d def\n", NumberOfCopies);
  fprintf (EX_FP(Ex_PsOutput), "/NumCharsInPixelFonts %d def\n", NumCharsInPixelFonts);
  fprintf (EX_FP(Ex_PsOutput), "/HostName (%s) def\n", HostName);
  if (PsPrintEnabled) {
    fprintf (EX_FP(Ex_PsOutput), "(This PostScript file was produced on host \\\") print ");
    fprintf (EX_FP(Ex_PsOutput), "HostName print (\\\".\\n) print\n");
  }
  fprintf (EX_FP(Ex_PsOutput), "/PsPrintEnabled %s def\n", PsPrintEnabled ? "true":"false");

  /* Offset is given in inches, convert into pixels */
  fprintf (EX_FP(Ex_PsOutput), "/Page-H-Offset %10.6lf def\n", (double)PageHOffset * Resolution);
  fprintf (EX_FP(Ex_PsOutput), "/Page-V-Offset %10.6lf def\n", (double)PageVOffset * Resolution);

  /* Define a PS routine which expects a dimension in the AFM coordiante
     system on the stack and return pixels. This is needed for the case of
     PostScript procedure characters. */
  fprintf (EX_FP(Ex_PsOutput), "/ExecPsConv {0.30 mul} def\n");

  /* Now send the time, the dvi file has been written,
   * but if it's stdin, then send the current time. */
  if (Strcmp(ExDvi.ef_fn, "-") == 0) {
    dvi_file_time = ReferenceTime;
  } else {
    if (stat(ExDvi.ef_fn, &status) == -1)
      Fatal2 ("PsBeginningSend(): stat on dvi file \"%s\" failed", ExDvi.ef_fn);
    dvi_file_time = status.st_mtime;
  }

  /* Convert the time integer into a string. */
  strcpy (time_as_string, ctime (&dvi_file_time));

  /* Throw out the '\n' in time_as_string. */
  ptr = time_as_string;
  while (*++ptr != '\n')	;
  *ptr = '\0';

  /* Deleate seconds from the string. */
  ptr = time_as_string;
  while (*++ptr != ':')    ;
  while (*++ptr != ':')    ;
  ptr2 = ptr + 3;
  while (*ptr++ = *ptr2++) ;
  fprintf (EX_FP(Ex_PsOutput), "/Date-and-Time (%s) def\n", time_as_string);

  /* Send down the definition of the coordinate transformation matrix. */
  PsMatrixSend();
}

/*
 * PsEndSend
 * *********
 * The PS code generated here is the absolutely last thing
 * written to the output by this driver.
 */
void
PsEndSend ()
{
  EMIT_NEW_LINE;
  if (! ConformingDocument) {
    if (PsPrintEnabled)
      fprintf (EX_FP(Ex_PsOutput), "(\\nEND-JOB %s\\n) print flush\n",
	       Strcmp(ExDvi.ef_fn, "-") == 0 ? "<stdin>" : ExDvi.ef_fn);
    fprintf (EX_FP(Ex_PsOutput), "restore\n");
  } else {
    fprintf (EX_FP(Ex_PsOutput), "%%%%Trailer\n");
    fprintf (EX_FP(Ex_PsOutput), "%%%%Pages: %d\n", CountPages-1);
  }
}

typedef struct pf {
  char * pf_name; /* Name of the paper format. */
  char * pf_off_h_st; /* Offset dimension, horizontal, as string. */
  char * pf_off_v_st; /* Offset dimension, vertical, as string. */
  char * pf_wd_st; /* The width of the paper, as string. */
  char * pf_ht_st; /* The height of the paper, as string. */
  double pf_off_h; /* Now the same four parameters, in inches. */
  double pf_off_v;
  double pf_wd;
  double pf_ht;
} PrinterPaperFormat;

/* Enter all the paper formats here. Note that the dimensions as they
   are lated used (as floating point numbers) will be read in from
   the dimensions as specified by a string. The string definitions of
   those dimensions may refer to any TeX compatible dimension unit.

   I don't currently have the definitions for "note" ... */
PrinterPaperFormat Papers[] = {
  {"letter", "1in", "1in", "8.5in", "11in", 0.0, 0.0, 0.0, 0.0},
  {"legal",  "1in", "1in", "8.5in", "14in", 0.0, 0.0, 0.0, 0.0},
  {"a4",     "1in", "1in", "210mm", "297mm",0.0, 0.0, 0.0, 0.0},
  {"",       "",    "",    "",      "",     0.0, 0.0, 0.0, 0.0}
};

/*
 * InitPaperFormats
 * ****************
 * Initialize the paper format business here.
 */
void
InitPaperFormats()
{
  int i;

  for (i=0; i<1000; i++) {
    /* Quit with last spec (empty name). */
    if (Strlen(Papers[i].pf_name) == 0)
      return;
    /* Now convert the four dimensions into inches. */
    Papers[i].pf_off_h = ReadDimensionReturnInches(Papers[i].pf_off_h_st);
    Papers[i].pf_off_v = ReadDimensionReturnInches(Papers[i].pf_off_v_st);
    Papers[i].pf_wd    = ReadDimensionReturnInches(Papers[i].pf_wd_st);
    Papers[i].pf_ht    = ReadDimensionReturnInches(Papers[i].pf_ht_st);
  }
}

/*
 * PsMatrixSend
 * ************
 * Send down the coordinate transformation matrix.
 * This matrix depends on the global variable ThisPagesOrientation
 * and some other values. Accomodates paper format legalpager.
 */
void
PsMatrixSend()
{
  double fac; /* Pixels multiplied with this factor gives
		 big points (72 per inch). */
  double a, b, c, d;
  double tx, ty;
  int i; /* Index into Papers[]. */

  if (Strlen(PaperType) == 0)
    Fatal ("PsMatrixSend(): PaperType not initialized.");

  /* Compute the conversion factor. */
  fac = 1.0 / (double) Resolution * 72.0;

  /* First determine which paper format is currently used and from
     that derive to what values the dimensions should be set. */
  if ((i = SearchForPaperFormat(PaperType)) == -1)
    Fatal2 ("PsMatrixSend(): cannot find dimensions of paper format \"%s\"", PaperType);

  a = b = c = d = tx = ty = 0.0;

  switch (ThisPagesOrientation) {
    case PORTRAIT_MODE:
      a = fac;
      d = -fac;
      tx = Papers[i].pf_off_h * 72.0;
      ty = (Papers[i].pf_ht - Papers[i].pf_off_v) * 72.0;

      a *= FudgeX;
      d *= FudgeY;

      break;

    case LANDSCAPE_MODE:
      b = -fac;
      c = -fac;
      tx = (Papers[i].pf_wd - Papers[i].pf_off_h) * 72.0;
      ty = (Papers[i].pf_ht - Papers[i].pf_off_v) * 72.0;
      b *= FudgeY;
      c *= FudgeX;
      break;

    case NO_ORIENTATION:
      Fatal ("PsMatrixSend(): No orientation specified.");

    default:
      Fatal ("PsMatrixSend(): illegal orientation.");
  }

  /* Send the translation vector and the DviOrientationMatrix out. */
  fprintf (EX_FP(Ex_PsOutput), "/DviTranslateVector-X %8.3lf def\n", tx);
  fprintf (EX_FP(Ex_PsOutput), "/DviTranslateVector-Y %8.3lf def\n", ty);
  fprintf (EX_FP(Ex_PsOutput), "/DviOrientationMatrix [ %8.3lf %8.3lf %8.3lf\n", a, b, c);
  fprintf (EX_FP(Ex_PsOutput), "\t %8.3lf 0.0 0.0 ] def\n", d);
}

/*
 * PsDownLoad
 * **********
 * Download the file "name" if not already downloaded.
 *
 * name: file being downloaded.
 * count: how many lines in the beginning of this file are to be ignored.
 */
void
PsDownLoad (name, count)
     char * name;
     int count;
{
  /* Check whether already downloaded: if so, return, otherwise insert it
     and download the code. */
  if (InsertKeyIntoHashTableDup (PsDownLoadHashTable, name) != NULL)
    PsSendFile (0, name, count);
}

/*
 * PsSendFile
 * **********
 * Send out a PostScript file (downloadable code).
 * The file is sent, regardless of whether it was sent before or
 * not (that condition is handled by PsDownLoad).
 *
 * mode: 0: it's a prologue file and some comment preceeds and follows the
 *          file. Also follows the path for prologue files.
 *       1: straight include, nothing before and nothing after the file.
 *          file name is not modified.
 * name: name of the file. If mode == 0 use path for prologue files.
 * count: how many lines at the beginning are to be ignored.
 */
void
PsSendFile(mode, name, count)
     int mode;
     char *name;
     int count;
{
  EX_FILES ex_f;
  int	c;
  char *fn; /* file name to be used */

  switch (mode) {
    case 0:
      PushAndSwitchPsOutput(0);
      if ((fn = LocateFileWithPath(name, PrologueFilesPath, NULL, FALSE)) == NULL)
	Fatal2 ("PsSendFile(): \"%s\" could not be located.", name);
      break;
    case 1:
      fn = name;
      break;
    default:
      Fatal ("PsSendFile(): default.");
    }

  /* Open the file, ignore given number of empty lines at the beginning. */
  FExOpen (&ex_f, EFT_READ, EFQ_NO_STDIN, fn, NULL);
  while (count > 0)
    if ((c=getc(EX_FP(ex_f))) == '\n')
      count--;

  /* Some initial comment? */
  switch(mode) {
    case 0:
      fprintf (EX_FP(Ex_PsOutput), "%% %s: BEGIN including file \"%s\"\n", DvitpsBinaryName, fn);
      break;
  }
  
  /* Duplicate the whole file. Then close it. */
  while ((c=getc(EX_FP(ex_f))) != EOF)
    putc (c, EX_FP(Ex_PsOutput));
  FExClose (&ex_f);

  /* Some closing comment? Some final stuff. */
  switch(mode) {
    case 0:
      fprintf (EX_FP(Ex_PsOutput), "%% %s: END including file \"%s\"\n", DvitpsBinaryName, fn);
      PopPsOutputSwitch();
      break;
  }
}

/*
 * ResetBetweenPages
 * *****************
 * This function is called, if a VM reset between pages is requested.
 */
void
ResetBetweenPages()
{
  char *ptr;
  int i, j;

  fprintf (EX_FP(Ex_PsOutput), "restore\n");
  fprintf (EX_FP(Ex_PsOutput), "%% Number of pages processed by driver: %d\n", CountPages);

  if (PsPrintEnabled) {
    fprintf (EX_FP(Ex_PsOutput), "(ResetBetweenPages(), -z option\\n) print flush\n");
  }
  fprintf (EX_FP(Ex_PsOutput), "%% You can cut this PostScript file");
  fprintf (EX_FP(Ex_PsOutput), " IMMEDIATELY AFTER this line\n"); 

  fprintf (EX_FP(Ex_PsOutput), "%%!\n");
  fprintf (EX_FP(Ex_PsOutput), "save\n");

  /* Re-download all the ps code, we had downloaded before. */
  InitNextKeyHash (PsDownLoadHashTable);
  while ((ptr=GetNextKeyHash(PsDownLoadHashTable)) != NULL) {
    fprintf (EX_FP(Ex_PsOutput), "%% Repeat download of %s\n", ptr);
    PsSendFile (0, ptr, 0);
  }
  PsBeginningSend();

  /* No font is defined any more, no character bitmaps are downloaded
   * anymore. */
  for (i=0; i<MAX_FONTS; i++) {
    if (Fonts[i] == NULL)
      continue;

    Fonts[i]->f_new_font = FALSE;

    switch(Fonts[i]->f_type) {
      case CF_PDR:
        for (j=0; j<MAX_CHAR_PS; j++) {
	  if (Fonts[i]->f_ch[j].c_type == CT_EXECPS)
	    Fonts[i]->f_ch[j].c_dl = FALSE;
	} /* for */
	break;
      case CF_PXL:
      case CF_PK:
      case CF_GF:
        for (j=0; j<MAX_CHARS; j++) {
	  Fonts[i]->f_ch[j].c_dl = FALSE;
	}
	break;
    } /* switch */
  } /* for */
}

/*
 * SetTime
 * *******
 * This routine is called to set the reference time for a dvitps execution.
 * It simply sets the global variable ReferenceTime.
 */
void
SetTime()
{
  ReferenceTime = time(0);
}

/*
 * SearchForPaperFormat
 * ********************
 * This routine given a paper format name searches in the
 * paper format table defined above. The index into that
 * table is returned (or -1 if it cannot be found).
 */
int
SearchForPaperFormat(pf)
     char *pf;
{
  int i;

  /* It's a fatal error to be empty. */
  if (Strlen(pf) == 0)
    Fatal ("SearchForPaperFormat(): empty paper format specification.");

  /* Search for it now. */
  for (i=0;; i++) {
    if (Strlen(Papers[i].pf_name) == 0)
      return(-1); /* Not found. */
    if (Strcmp(Papers[i].pf_name, PaperType) == 0)
      return(i);
  }
}