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 s

⟦fd3dca6fd⟧ TextFile

    Length: 7852 (0x1eac)
    Types: TextFile
    Names: »send2.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/send2.c« 

TextFile

/* Copyright 1988 Stephan v. Bechtolsheim */

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

The TPS 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 TPS Software Package
General Public License for full details.

Everyone is granted permission to copy, modify and redistribute
the TPS Software Package, but only under the conditions described in the
TPS Software Package General Public License.   A copy of this license is
supposed to have been given to you along with TPS 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.  */


/*
 * This file here contains all the code for sending information
 * to the printer.
 */

#include <stdio.h>
#include "defs.h"
#include "dvitps.h"
#include "units.h"
#include "extfil.h"
#include "emit.h"

extern PXLU AccDeltaH;
extern PXLU AccDeltaV;
extern EX_FILES Ex_PsOutput;

void PssFlushStringAndPos();
void pss_flush_a();
void pss_flush_b();
void pss_flush_c_1();
void pss_flush_c_2();
void pss_flush_d();
void PssHexSend();
void PssSendInteger();
void PssSendCommand();
char *digit = "0123456789ABCDEF";

PXLU DeltaPrinter; /* delta in the PS code of pos.pro */


/* Accumulate strings to be written to the PostScript output
 * file here. The index points to the last OCCUPIED element
 * in PssStringBuffer. A value of -1 therefore means that
 * the string is empty. */
int PssStringIndex;

/* Maximum of string lengths which can be accumulated before
   being sent out to the printer. Generously set below! */
#define PSS_STRING_BUFFER_LENGTH 512
char PssStringBuffer[PSS_STRING_BUFFER_LENGTH];

int PssSentAString; /* TRUE if a string was sent in PssSendString(), otherwise
		       FALSE */

/* How many characters are filled in the current line of text output. */
int PssColumn = 0;

/* Either PSS_FOR_FREE or PSS_FOR_CONT. */
int PssFormat;

/* PSS_LAST_* */
int PssLastThingSent;

/* PssNeedSpaceMatrix[i][j] == 1 iff space needed if i followed by j */
int PssNeedSpaceMatrix[4][4] = {
  {0, 0, 0, 0},
  {0, 0, 0, 0},
  {0, 0, 1, 1},
  {0, 0, 1, 1}
};

/*
 * PssSendString
 * *************
 * Send, if non empty, the string stored in PssStringBuffer.
 * Sets flag "PssSentAString" if this really happened.
 * Only calling routine is PssFlushStringAndPos().
 */
void
PssSendString()
{
  int i; /* Loop variable. */

  if (PssStringIndex == -1) {
    PssSentAString = FALSE;
    return; /* No string stored, nothing to do. */
  }

  if (PssStringIndex >= PSS_STRING_BUFFER_LENGTH-2)
    Fatal ("PssSendString(): index problem");

  PSS_NEXT_INSTRUCTION(PSS_LAST_STRING, PssStringIndex+5);

  /* Send out the current string. */
  EMITC ('('); /* Opening parenthesis. */
  for (i=0; i<= PssStringIndex; i++) {
    if (PssStringBuffer[i] < ' ' || PssStringBuffer[i] >= 0177)	{
      /* Characters outside the range of printable ASCII characters
	 are sent as octal numbers. */
      PSS_SEND_OCT(PssStringBuffer[i]);
    } else {
      /* Printable ASCII characters, three characters which must
	 be escaped. */
      if (PssStringBuffer[i] == '(' ||
	  PssStringBuffer[i] == ')' ||
	  PssStringBuffer[i] == '\\') {
	EMITC('\\');
	EMITC(PssStringBuffer[i]); 
      } else {
	/* Regular printable ASCII character. */
	EMITC(PssStringBuffer[i]);
      }
    }
  } /* for */
  EMITC (')'); /* Closing parenthesis. */

  PssStringIndex = -1; /* The buffer is cleared out. */
  PssSentAString = TRUE;
}

/*
 * PssSendCommand
 * **************
 * Output some command to the PostScript file.
 *
 * com: command, a string, to be sent to the PostScript file.
 */
void
PssSendCommand (com)
     char *com;
{
  PSS_NEXT_INSTRUCTION(PSS_LAST_COMMAND, strlen(com));
  fprintf (EX_FP(Ex_PsOutput), com);
  PssColumn += strlen(com);
}

/*
 * PssSendInteger
 * **************
 * Output an integer to the PostScript file.
 *
 * n: the integer to write.
 */
void
PssSendInteger(n)
     register int n;
{
  char buf[10];
  register char *b;

  PSS_NEXT_INSTRUCTION(PSS_LAST_NUM,5);
  if (n == 0) {
    EMITC('0'); 
  } else {
    if (n < 0) {
      EMITC('-');
      n = -n;
    }
    
    for (b=buf;  n>0; ) {
      *b++ = digit[n%10];
      n /= 10;
    }
    
    for (; b>buf; ) {
      EMITC(*--b);
    }
  }
}

/*
 * PssFlushStringAndPos
 * ********************
 * Send the string accumulated so far out (if any) followed
 * by any accumulated position. Then the appropriate code
 * for actually printing the string (if the string is not empty)
 * is generated.
 * This routine tries to be smart and save on the number
 * of PS code calls. It uses some of the short
 * codes for movements as they are defined in pos.pro (a PS prologue
 * file).
 */
void
PssFlushStringAndPos()
{
  PssSendString();

  if (AccDeltaH != 0) {
    if (AccDeltaV != 0)
      pss_flush_a(); /* h!=0, v!=0 */
    else {
      /* h!=0, v==0 */
      if (PssSentAString)
	pss_flush_c_1();
      else
	pss_flush_c_2();
    }
  } else { /* h==0 */
    if (AccDeltaV != 0)
      pss_flush_b(); /* h==0, v!=0 */
    else
      pss_flush_d(); /* h==0, v==0 */
  }
}

/*
 * pss_flush_a
 * ***********
 * AccDeltaH != 0
 * AccDeltaV != 0
 */
void
pss_flush_a()
{
  /* If we had a string print it first before you move */
  PssSendInteger (AccDeltaH);
  PssSendInteger (AccDeltaV);
  if (PssSentAString) {
    EMIT_SCC('y');
  } else {
    EMIT_SCC('a');
  }
  AccDeltaH = 0;
  AccDeltaV = 0;
}

/*
 * pss_flush_b
 * ***********
 * AccDeltaH == 0
 * AccDeltaV != 0
 */
void
pss_flush_b()
{
  if (PssSentAString) {
    EMIT_SCC ('p');
  }
  PssSendInteger (AccDeltaV);
  EMIT_SCC ('w');

  AccDeltaV = 0;
}


/*
 * pss_flush_c_1
 * *************
 * AccDeltaH != 0
 * AccDeltaV == 0
 * A string was printed (compare with pss_flush_c_2)
 */
void
pss_flush_c_1()
{
  int diff;

  /* This is the most common case: print a
     string followed by some horizontal movement or there
     is just some horizontal movement by itself.
     */
  if (-4 <= AccDeltaH && AccDeltaH <= 4) {
    /* String followed by small movement (kern probably) */
    switch (AccDeltaH) {
      case -4: EMIT_SCC ('l'); break;
      case -3: EMIT_SCC ('m'); break;
      case -2: EMIT_SCC ('n'); break;
      case -1: EMIT_SCC ('o'); break;
      case 0:  Fatal ("pss_flush_c_1(): 1");
      case 1:  EMIT_SCC ('q'); break;
      case 2:  EMIT_SCC ('r'); break;
      case 3:  EMIT_SCC ('s'); break;
      case 4:  EMIT_SCC ('t'); break;
      default: Fatal ("pss_flush_c_1(): 2");
    }
  } else {
    /* String followed by movement within [delta-4..delta+4] ? */
    diff = AccDeltaH - DeltaPrinter;
    if (-4 <= diff && diff <= 4) {
      switch (diff) {
        case -4: EMIT_SCC ('c'); break;
        case -3: EMIT_SCC ('d'); break;
        case -2: EMIT_SCC ('e'); break;
	case -1: EMIT_SCC ('f'); break;
	case  0: EMIT_SCC ('g'); break;
	case  1: EMIT_SCC ('h'); break;
	case  2: EMIT_SCC ('i'); break;
	case  3: EMIT_SCC ('j'); break;
	case  4: EMIT_SCC ('k'); break;
	default: Fatal("PssFlushStringAndPos(): c-k");
      }
      DeltaPrinter = AccDeltaH;
    } else {
      /* String sent out, no movement special case though! */
      PssSendInteger (AccDeltaH);
      EMIT_SCC ('b');

      DeltaPrinter = AccDeltaH;
    }
  }

  AccDeltaH = 0;
}

/*
 * pss_flush_c_2
 * *************
 * AccDeltaH != 0
 * AccDeltaV == 0
 * NO string
 */
void
pss_flush_c_2()
{
  PssSendInteger(AccDeltaH);
  EMIT_SCC('x');

  AccDeltaH = 0;
}

/*
 * pss_flush_d
 * ***********
 * AccDeltaH == 0
 * AccDeltaV == 0
 */
void
pss_flush_d()
{
  if (PssSentAString) {
    EMIT_SCC('p');
  }
}