|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 7852 (0x1eac) Types: TextFile Names: »send2.c«
└─⟦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«
/* 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'); } }