diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dvi2tty/dvistuff.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvi2tty/dvistuff.c')
-rw-r--r-- | Build/source/texk/dvi2tty/dvistuff.c | 1180 |
1 files changed, 1180 insertions, 0 deletions
diff --git a/Build/source/texk/dvi2tty/dvistuff.c b/Build/source/texk/dvi2tty/dvistuff.c new file mode 100644 index 00000000000..7ee7c37ac8c --- /dev/null +++ b/Build/source/texk/dvi2tty/dvistuff.c @@ -0,0 +1,1180 @@ + +#include "dvi2tty.h" +#include <sys/types.h> +#include <sys/stat.h> +#if defined(VMS) +#include types.h +#include stat +#endif +#if defined(MSDOS) +#include <math.h> +#endif +#include "commands.h" + +#if defined(VMS) +#define mseek vmsseek +#define ROUND(a) (a>=0.0 ? (int) (a + 0.5) : (int) (a - 0.5) ) +#else +#define mseek fseek +#endif + +#define VERSIONID 2 /* dvi version number that pgm handles */ +#define VERTICALEPSILON 450000L /* crlf when increasing v more than this */ + +#define rightmargin 152 /* nr of columns allowed to the right of h=0*/ +#define leftmargin -50 /* give some room for negative h-coordinate */ +#define LINELEN 203 /* rightmargin - leftmargin + 1 */ + +#define MOVE TRUE /* if advancing h when outputing a rule */ +#define STAY FALSE /* if not advancing h when outputing a rule */ + +#define absolute 0 /* for seeking in files */ +#define relative 1 + +#define FORM 12 /* formfeed */ +#define SPACE 32 /* space */ +#define DEL 127 /* delete */ + +#define LASTCHAR 127 /* max dvi character, above are commands */ + +#define IMIN(a, b) (a<b ? a : b) +#define IMAX(a, b) (a>b ? a : b) + +#define get1() num(1) +#define get2() num(2) +#define get3() num(3) +#define get4() num(4) +#define sget1() snum(1) +#define sget2() snum(2) +#define sget3() snum(3) +#define sget4() snum(4) + +char *dvistuff = "@(#) dvistuff.c 4.1 27/03/90 M.J.E. Mol (c) 1989, 1990"; + +/*---------------------------------------------------------------------------*/ + +typedef struct { + long hh; + long vv; + long ww; + long xx; + long yy; + long zz; +} stackitem; + +typedef struct lineptr { /* the lines of text to be output to outfile */ + long vv; /* vertical position of the line */ + int charactercount; /* pos of last char on line */ + struct lineptr *prev; /* preceding line */ + struct lineptr *next; /* succeeding line */ + char text[LINELEN+1]; /* leftmargin...rightmargin */ +} linetype; + +typedef struct _font { + long num; + struct _font * next; + char * name; +} font; + + +/*---------------------------------------------------------------------------*/ + +bool pageswitchon; /* true if user-set pages to print */ +bool sequenceon; /* false if pagesw-nrs refers to TeX-nrs */ +bool scascii; /* if true make Scand. nat. chars right */ +bool noffd; /* if true output ^L instead of formfeed */ + +int opcode; /* dvi-opcodes */ + +long h, v; /* coordinates, horizontal and vertical */ +long w, x, y, z; /* horizontal and vertical amounts */ + +long pagecounter; /* sequence page number counter */ +long backpointer; /* pointer for offset to previous page */ +long pagenr; /* TeX page number */ +int stackmax; /* stacksize required */ + +long maxpagewidth; /* width of widest page in file */ +long charwidth; /* aprox width of character */ + +linetype * currentline; /* pointer to current line on current page */ +linetype * firstline; /* pointer to first line on current page */ +linetype * lastline; /* pointer to last line on current page */ +int firstcolumn; /* 1st column with something to print */ + +stackitem * stack; /* stack for dvi-pushes */ +int sptr; /* stack pointer */ + +font * fonts = NULL; /* List of fontnames defined */ +int symbolfont = FALSE; /* true if font is a symbol font */ + +/*---------------------------------------------------------------------------*/ + +#ifdef KPATHSEA +void postamble P1H(void); +void preamble P1H(void); +void walkpages P1H(void); +void initpage P1H(void); +void dopage P1H(void); +void skippage P1H(void); +void printpage P1H(void); +bool inlist P1H(long); +void rule P3H(bool, long, long); +void ruleaux P3H(long, long, char); +long horizontalmove P1H(long); +int skipnops P1H(void); +linetype * getline P1H(void); +linetype * findline P1H(void); +unsigned long num P1H(int); +long snum P1H(int); +void dochar P1H(char); +void symchar P1H(char); +void normchar P1H(char); +void outchar P1H(unsigned char); +void putcharacter P1H(long); +void setchar P1H(long); +void fontdef P1H(int); +void setfont P1H(long); +#else +# if defined(MSDOS) +void postamble (void); +void preamble (void); +void walkpages (void); +void initpage (void); +void dopage (void); +void skippage (void); +void printpage (void); +bool inlist (long); +void rule (bool, long, long); +void ruleaux (long, long, char); +long horizontalmove (long); +int skipnops (void); +linetype * getline (void); +linetype * findline (void); +unsigned long num (int); +long snum (int); +void dochar (char); +void symchar (char); +void normchar (char); +void outchar (unsigned char); +void putcharacter (long); +void setchar (long); +void fontdef (int); +void setfont (long); +#else +void postamble (); +void preamble (); +void walkpages (); +void initpage (); +void dopage (); +void skippage (); +void printpage (); +bool inlist (); +void rule (); +void ruleaux (); +long horizontalmove (); +int skipnops (); +linetype * getline (); +linetype * findline (); +unsigned long num (); +long snum (); +void dochar (); +void symchar (); +void normchar (); +void outchar (); +void putcharacter (); +void setchar (); +void fontdef (); +void setfont (); +#if defined(VMS) +long vmsseek (); +long vms_ftell (); +long vms_ungetc (); +#endif +#endif +#endif + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/* + * The main function for processing the dvi file. + * Here we assume there are to file pointers: DVIfile and output. + * Also we have a list of pages pointed to by 'currentpage', + * which is only used (in 'inlist()') when a page list is given. + */ + +void dvimain() +{ + + postamble(); /* seek and process the postamble */ + /* note that walkpages *must* immediately follow preamble */ + preamble(); /* process preamble */ + walkpages(); /* time to do the actual work! */ + +} /* dvimain */ + +/*---------------------------------------------------------------------------*/ + +void postamble() /* find and process postamble, use random access */ +{ + register long size; + register int count; + struct stat st; + + fstat (fileno(DVIfile), &st); + size = (long) st.st_size; /* get size of file */ + count = -1; + do { /* back file up past signature bytes (223), to id-byte */ + if (size == 0) + errorexit(nopst); + size--; + mseek(DVIfile, size, absolute); + opcode = (int) get1(); + count++; + } while (opcode == TRAILER); + if (count < 4) { /* must have 4 trailer bytes */ + foo = count; + errorexit(fwsgn); + } + if (opcode != VERSIONID) + errorexit(badid); + mseek(DVIfile, size-4, absolute); /* back up to back-pointer */ + mseek(DVIfile, sget4(), absolute); /* and to start of postamble */ + if (get1() != POST) + errorexit(nopst); + mseek(DVIfile, 20L, relative); /* lastpageoffset, numerator, denominator */ + /* magnification, maxpageheight */ + maxpagewidth = sget4(); + charwidth = maxpagewidth / (ttywidth + espace); + stackmax = (int) get2(); + if ((stack = (stackitem *) malloc(stackmax * sizeof(stackitem))) == NULL) + errorexit(stkrq); + + /* get2() -- totalpages */ + /* fontdefs do fontdefs in flight ... */ + +} /* postamble */ + +/*---------------------------------------------------------------------------*/ + +void preamble() /* process preamble, use random access */ +{ + + mseek(DVIfile, 0L, absolute); /* read the dvifile from the start */ + if ((opcode = skipnops()) != PRE) + errorexit(nopre); + opcode = (int) get1(); /* check id in preamble, ignore rest of it */ + if (opcode != VERSIONID) + errorexit(badid); + mseek(DVIfile, 12L, relative); /* numerator, denominator, magnification */ + mseek(DVIfile, get1(), relative); /* skip job identification */ + +} /* preamble */ + +/*----------------------------------------------------------------------------*/ + +void walkpages() /* process the pages in the DVI-file */ +{ + register bool wantpage; + + pagecounter = 0L; + while ((opcode = skipnops()) != POST) { + if (opcode != BOP) /* should be at start of page now */ + errorexit(nobop); + else { + pagecounter++; + pagenr = sget4(); /* get TeX page number */ + mseek(DVIfile, 36L, relative); /* skip page header */ + backpointer = sget4(); /* get previous page offset */ + if (pageswitchon) + if (sequenceon) + wantpage = inlist(pagecounter); + else + wantpage = inlist(pagenr); + else + wantpage = TRUE; + + if (wantpage) { + initpage(); + dopage(); + printpage(); + } + else { + skippage(); + } + } + } + +} /* walkpages */ + +/*---------------------------------------------------------------------------*/ + +void initpage() +{ + + h = 0L; v = 0L; /* initialize coordinates */ + x = 0L; w = 0L; y = 0L; z = 0L; /* initialize amounts */ + sptr = 0; /* initialize stack */ + currentline = getline(); /* initialize list of lines */ + currentline->vv = 0L; + firstline = currentline; + lastline = currentline; + firstcolumn = rightmargin; + if (pageswitchon) { + if ((sequenceon && (pagecounter != firstpage->pag)) || + (!sequenceon && (pagenr != firstpage->pag))) { + if (noffd) + fprintf(output, "^L\n"); + else + putc(FORM, output); + } + } + else + if (backpointer != -1) { /* not FORM at first page */ + if (noffd) + fprintf(output, "^L\n"); + else + putc(FORM, output); + } + +} /* initpage */ + +/*----------------------------------------------------------------------------*/ + +void dopage() +{ + + while ((opcode = (int) get1()) != EOP) { /* process page until eop */ + if (opcode <= LASTCHAR) + dochar((char) opcode); + else if ((opcode >= FONT_00) && (opcode <= FONT_63)) + setfont(opcode - FONT_00); + else if (opcode > POST_POST) + errorexit(illop); + else + switch (opcode) { + case SET1 : setchar(get1()); break; + case SET2 : setchar(get2()); break; + case SET3 : setchar(get3()); break; + case SET4 : setchar(get4()); break; + case SET_RULE : { long height = sget4(); + rule(MOVE, sget4(), height); break; + } + case PUT1 : putcharacter(get1()); break; + case PUT2 : putcharacter(get2()); break; + case PUT3 : putcharacter(get3()); break; + case PUT4 : putcharacter(get4()); break; + case PUT_RULE : { long height = sget4(); + rule(STAY, sget4(), height); break; + } + case NOP : break; /* no-op */ + case BOP : errorexit(bdbop); break; +/* case EOP : break; strange place to have EOP */ + case PUSH : if (sptr >= stackmax) /* push */ + errorexit(stkof); + stack[sptr].hh = h; + stack[sptr].vv = v; + stack[sptr].ww = w; + stack[sptr].xx = x; + stack[sptr].yy = y; + stack[sptr].zz = z; + sptr++; + break; + case POP : if (sptr == 0) /* pop */ + errorexit(stkuf); + sptr--; + h = stack[sptr].hh; + v = stack[sptr].vv; + w = stack[sptr].ww; + x = stack[sptr].xx; + y = stack[sptr].yy; + z = stack[sptr].zz; + break; + case RIGHT1 : (void) horizontalmove(sget1()); break; + case RIGHT2 : (void) horizontalmove(sget2()); break; + case RIGHT3 : (void) horizontalmove(sget3()); break; + case RIGHT4 : (void) horizontalmove(sget4()); break; + case W0 : h += w; break; + case W1 : w = horizontalmove(sget1()); break; + case W2 : w = horizontalmove(sget2()); break; + case W3 : w = horizontalmove(sget3()); break; + case W4 : w = horizontalmove(sget4()); break; + case X0 : h += x; break; + case X1 : x = horizontalmove(sget1()); break; + case X2 : x = horizontalmove(sget2()); break; + case X3 : x = horizontalmove(sget3()); break; + case X4 : x = horizontalmove(sget4()); break; + case DOWN1 : v += sget1(); break; + case DOWN2 : v += sget2(); break; + case DOWN3 : v += sget3(); break; + case DOWN4 : v += sget4(); break; + case Y0 : v += y; break; + case Y1 : y = sget1(); v += y; break; + case Y2 : y = sget2(); v += y; break; + case Y3 : y = sget3(); v += y; break; + case Y4 : y = sget4(); v += y; break; + case Z0 : v += z; break; + case Z1 : z = sget1(); v += z; break; + case Z2 : z = sget2(); v += z; break; + case Z3 : z = sget3(); v += z; break; + case Z4 : z = sget4(); v += z; break; + case FNT1 : + case FNT2 : + case FNT3 : + case FNT4 : setfont(num(opcode - FNT1 + 1)); + break; + case XXX1 : mseek(DVIfile, get1(), relative); break; + case XXX2 : mseek(DVIfile, get2(), relative); break; + case XXX3 : mseek(DVIfile, get3(), relative); break; + case XXX4 : mseek(DVIfile, get4(), relative); break; + case FNT_DEF1 : + case FNT_DEF2 : + case FNT_DEF3 : + case FNT_DEF4 : fontdef(opcode - FNT_DEF1 + 1); + break; + case PRE : errorexit(bdpre); break; + case POST : errorexit(bdpst); break; + case POST_POST: errorexit(bdpp); break; + } + } + +} /* dopage */ + +/*----------------------------------------------------------------------------*/ + +void skippage() /* skip past one page */ +{ + register int opcode; + + while ((opcode = (int) get1()) != EOP) { + if (opcode > POST_POST) + errorexit(illop); + else + switch (opcode) { + case SET1 : + case PUT1 : + case RIGHT1 : + case W1 : + case X1 : + case DOWN1 : + case Y1 : + case Z1 : /* assume FNT change can also be skipped */ + case FNT1 : mseek(DVIfile, 1L, relative); break; + case SET2 : + case PUT2 : + case RIGHT2 : + case W2 : + case X2 : + case DOWN2 : + case Y2 : + case Z2 : + case FNT2 : mseek(DVIfile, 2L, relative); break; + case SET3 : + case PUT3 : + case RIGHT3 : + case W3 : + case X3 : + case DOWN3 : + case Y3 : + case Z3 : + case FNT3 : mseek(DVIfile, 3L, relative); break; + case SET4 : + case PUT4 : + case RIGHT4 : + case W4 : + case X4 : + case DOWN4 : + case Y4 : + case Z4 : + case FNT4 : mseek(DVIfile, 4L, relative); break; + case SET_RULE : + case PUT_RULE : mseek(DVIfile, 8L, relative); break; + case BOP : errorexit(bdbop); break; + case XXX1 : mseek(DVIfile, get1(), relative); break; + case XXX2 : mseek(DVIfile, get2(), relative); break; + case XXX3 : mseek(DVIfile, get3(), relative); break; + case XXX4 : mseek(DVIfile, get4(), relative); break; + case FNT_DEF1 : + case FNT_DEF2 : + case FNT_DEF3 : + case FNT_DEF4 : fontdef(opcode - FNT_DEF1 + 1); break; + case PRE : errorexit(bdpre); break; + case POST : errorexit(bdpst); break; + case POST_POST: errorexit(bdpp); break; + } + } + +} /* skippage */ + +/*---------------------------------------------------------------------------*/ + +void printpage() /* 'end of page', writes lines of page to output file */ +{ + register int i, j; + register unsigned char ch; + + if (sptr != 0) + fprintf(stderr, "dvi2tty: warning - stack not empty at eop.\n"); + for (currentline = firstline; currentline != nil; + currentline = currentline->next) { + if (currentline != firstline) { + foo = ((currentline->vv - currentline->prev->vv)/VERTICALEPSILON)-1; + if (foo > 3) + foo = 3; /* linespacings not too large */ + for (i = 1; i <= (int) foo; i++) + putc('\n', output); + } + if (currentline->charactercount >= leftmargin) { + foo = ttywidth - 2; + for (i = firstcolumn, j = 1; i <= currentline->charactercount; + i++, j++) { + ch = currentline->text[i - leftmargin]; + if (ch >= SPACE) + putc(ch, output); + if ((j > (int) foo) && (currentline->charactercount > i+1)) { + fprintf(output, "*\n"); /* if line to large */ + fprintf(output, " *"); /* mark output */ + j = 2; + } + } + } + putc('\n', output); + } + + currentline = firstline; + while (currentline->next != nil) { + currentline = currentline->next; + free(currentline->prev); + } + free(currentline); /* free last line */ + currentline = nil; + +} /* printpage */ + +/*----------------------------------------------------------------------------*/ + +bool inlist(pagenr) /* ret true if in list of pages */ +register long pagenr; +{ + + while ((currentpage->pag < 0) && (currentpage->pag != pagenr) && + !currentpage->all && (currentpage->nxt != nil)) + currentpage = currentpage->nxt; + if ((currentpage->all && (pagenr < currentpage->pag)) || + (currentpage->pag == pagenr)) + return TRUE; + else if (pagenr > 0) { + while ((currentpage->pag < pagenr) && (currentpage->nxt != nil)) + currentpage = currentpage->nxt; + if (currentpage->pag == pagenr) + return TRUE; + } + return FALSE; + +} /* inlist */ + +/*----------------------------------------------------------------------------*/ + +void rule(bool moving, long rulewt, long ruleht) +{ /* output a rule (vertical or horizontal), increment h if moving is true */ + + register char ch; /* character to set rule with */ + register long saveh = 0, savev; + /* rule -- starts up the recursive routine */ + if (!moving) + saveh = h; + if ((ruleht <= 0) || (rulewt <= 0)) + h += rulewt; + else { + savev = v; + if ((ruleht / rulewt) > 0) /* value < 1 truncates to 0 */ + ch = '|'; + else if (ruleht > (VERTICALEPSILON / 2)) + ch = '='; + else + ch = '_'; + ruleaux(rulewt, ruleht, ch); + v = savev; + } + if (!moving) + h = saveh; + +} /* rule */ + + + +void ruleaux(long rulewt, long ruleht, char ch) /* recursive that does the job */ +{ + register long wt, lmh, rmh; + + wt = rulewt; + lmh = h; /* save left margin */ + if (h < 0) { /* let rules that start at negative h */ + wt -= h; /* start at coordinate 0, but let it */ + h = 0; /* have the right length */ + } + while (wt > 0) { /* output the part of the rule that */ + rmh = h; /* goes on this line */ + outchar(ch); + wt -= (h-rmh); /* decrease the width left on line */ + } + ruleht -= VERTICALEPSILON; /* decrease the height */ + if (ruleht > VERTICALEPSILON) { /* still more vertical? */ + rmh = h; /* save current h (right margin) */ + h = lmh; /* restore left margin */ + v -= (VERTICALEPSILON + VERTICALEPSILON / 10); + ruleaux(rulewt, ruleht, ch); + h = rmh; /* restore right margin */ + } + +} /* ruleaux */ + +/*----------------------------------------------------------------------------*/ + +long horizontalmove(amount) +register long amount; +{ + +#if defined(MSDOS) + if (labs(amount) > charwidth / 4L) { +#else + if (abs(amount) > charwidth / 4L) { +#endif + foo = 3*charwidth / 4; + if (amount > 0) + amount = ((amount+foo) / charwidth) * charwidth; + else +#if defined(VMS) + amount = (ROUND( (float) (amount-foo) / charwidth) + 1)* charwidth; +#else + amount = ((amount-foo) / charwidth) * charwidth; +#endif + h += amount; + return amount; + } + else + return 0; + +} /* horizontalmove */ + +/*----------------------------------------------------------------------------*/ + +int skipnops() /* skips by no-op commands */ +{ + register int opcode; + + while ((opcode = (int) num(1)) == NOP); + return opcode; + +} /* skipnops */ + +/*----------------------------------------------------------------------------*/ + +linetype *getline() /* returns an initialized line-object */ +{ + register int i; + register linetype *temp; + + if ((temp = (linetype *) malloc(sizeof(linetype))) == NULL) + errorexit(lnerq); + temp->charactercount = leftmargin - 1; + temp->prev = nil; + temp->next = nil; + for (i = 0; i < LINELEN; i++) + temp->text[i] = ' '; + temp->text[i] = '\0'; + return temp; + +} /* getline */ + +/*----------------------------------------------------------------------------*/ + +linetype *findline() /* find best fit line were text should go */ +{ /* and generate new line if needed */ + register linetype *temp; + register long topd, botd; + + if (v <= firstline->vv) { /* above first line */ + if (firstline->vv - v > VERTICALEPSILON) { + temp = getline(); + temp->next = firstline; + firstline->prev = temp; + temp->vv = v; + firstline = temp; + } + return firstline; + } + + if (v >= lastline->vv) { /* below last line */ + if (v - lastline->vv > VERTICALEPSILON) { + temp = getline(); + temp->prev = lastline; + lastline->next = temp; + temp->vv = v; + lastline = temp; + } + return lastline; + } + + temp = lastline; /* in between two lines */ + while ((temp->vv > v) && (temp != firstline)) + temp = temp->prev; + + /* temp->vv < v < temp->next->vv --- temp is above, temp->next is below */ + topd = v - temp->vv; + botd = temp->next->vv - v; + if ((topd < VERTICALEPSILON) || (botd < VERTICALEPSILON)) { + if (topd < botd) /* take best fit */ + return temp; + else + return temp->next; + } + + /* no line fits suitable, generate a new one */ + currentline = getline(); + currentline->next = temp->next; + currentline->prev = temp; + temp->next->prev = currentline; + temp->next = currentline; + currentline->vv = v; + return currentline; + +} /* findline */ + +/*----------------------------------------------------------------------------*/ + +unsigned long num(size) +register int size; +{ + register int i; + register long x = 0; + + for (i = 0; i < size; i++) + x = (x << 8) + (unsigned) getc(DVIfile); + return x; + +} /* num */ + + +long snum(size) +register int size; +{ + register int i; + register long x = 0; + + x = getc(DVIfile); + if (x & 0x80) + x -= 0x100; + for (i = 1; i < size; i++) + x = (x << 8) + (unsigned) getc(DVIfile); + return x; + +} /* snum */ + +/*----------------------------------------------------------------------------*/ + +void dochar(char ch) +{ + + if (symbolfont == TRUE) + symchar(ch); + else + normchar(ch); + + return; + +} /* dochar */ + + + +void symchar(char ch) /* output ch to appropriate line */ +{ + + switch (ch) { /* can do a lot more on MSDOS machines ... */ + case 0: ch = '-'; break; + case 1: ch = '.'; break; + case 2: ch = 'x'; break; + case 3: ch = '*'; break; + case 13: ch = 'O'; break; + case 14: ch = 'O'; break; + case 15: ch = 'o'; break; + case 24: ch = '~'; break; + case 102: ch = '{'; break; + case 103: ch = '}'; break; + case 104: ch = '<'; break; + case 105: ch = '>'; break; + case 106: ch = '|'; break; + case 110: ch = '\\'; break; + } + outchar(ch); + + return; + +} /* symchar */ + + + +void normchar(char ch) +{ + + switch (ch) { + case 11 : outchar('f'); ch = 'f'; break; /* ligature */ + case 12 : outchar('f'); ch = 'i'; break; /* ligature */ + case 13 : outchar('f'); ch = 'l'; break; /* ligature */ + case 14 : outchar('f'); outchar('f'); + ch = 'i'; break; /* ligature */ + case 15 : outchar('f'); outchar('f'); + ch = 'l'; break; /* ligature */ + case 16 : ch = 'i'; break; + case 17 : ch = 'j'; break; + case 25 : if (scascii) /* German sz ligature */ + ch = 0xdf; + else + {outchar('s'); ch = 's';} + break; + case 26 : if (scascii) /* Dane/Norw ae */ + ch = 0xe6; + else + {outchar('a'); ch = 'e';} + break; + case 27 : outchar('o'); ch = 'e'; break; /* Dane/Norw oe */ + case 28 : if (scascii) /* Dane/Norw /o */ + ch = 0xf8; + else + ch = 'o'; + break; + case 29 : if (scascii) /* Dane/Norw AE */ + ch = 0xc6; + else + {outchar('A'); ch = 'E';} + break; + case 30 : outchar('O'); ch = 'E'; break; /* Dane/Norw OE */ + case 31 : if (scascii) + ch = 0xd8; /* Dane/Norw /O */ + else + ch = 'O'; + break; + case 92 : ch = '"'; break; /* \ from `` */ + case 123 : ch = '-'; break; /* { from -- */ + case 124 : ch = '_'; break; /* | from --- */ + case 125 : ch = '"'; break; /* } from \H */ + case 126 : ch = '"'; break; /* ~ from \~ */ + case 127 : ch = '"'; break; /* DEL from \" */ +#if 0 + case 18 : ch = '`'; break /* from \` */ + case 19 : ch = ''''; break /* from \' */ + case 20 : ch = '~'; break /* from \v */ + case 21 : ch = '~'; break /* from \u */ + case 22 : ch = '~'; break /* from \= */ + case 24 : ch = ','; break /* from \c */ + case 94 : ch = '^'; break /* ^ from \^ */ + case 95 : ch = '`'; break /* _ from \. */ +#endif + } + outchar(ch); + + return; + +} /*normchar */ + + + +void outchar(unsigned char ch) /* output ch to appropriate line */ +{ + register int i, j; + +#if defined(MSDOS) + if (labs(v - currentline->vv) > VERTICALEPSILON / 2L) +#else + if (abs(v - currentline->vv) > VERTICALEPSILON / 2L) +#endif + currentline = findline(); + +#if 0 + j = (int) (((double) h / (double) maxpagewidth) * (ttywidth-1)) + 1; +#else + j = (int) (h / charwidth); +#endif + if (j > rightmargin) /* leftmargin <= j <= rightmargin */ + j = rightmargin; + else if (j < leftmargin) + j = leftmargin; + foo = leftmargin - 1; + /* + * This code does not really belong here ... + * + *-------------------------------------------------------------* + * The following is very specialized code, it handles some eu- * + * ropean characters. These are: a, o, u with two dots ("a & * + * "o & "u), and a with a circle (Oa). TeX outputs these by * + * first issuing the dots or circle and then backspace and set * + * the a, o, or u. When dvitty finds an a, o, or u it sear- * + * ches in the near vicinity for the character codes that re- * + * present circle or dots and if one is found the correspon- * + * ding Latin-1 character replaces the special character code. * + *-------------------------------------------------------------*/ + if (scascii) { + if ((ch == 'a') || (ch == 'A') || (ch == 'o') || (ch == 'O') || + (ch == 'u') || (ch == 'U')) { + for (i = IMAX(leftmargin, j-2); + i <= IMIN(rightmargin, j+2); + i++) + if ((currentline->text[i - leftmargin] == 127) || + (currentline->text[i - leftmargin] == 34) || + (currentline->text[i - leftmargin] == 23)) + foo = i; + if (foo >= leftmargin) { + j = (int) foo; + switch (currentline->text[j - leftmargin]) { + case 127 : case 34: + if (ch == 'a') + ch = 0xe4; + else if (ch == 'A') /* dots ... */ + ch = 0xc4; + else if (ch == 'o') + ch = 0xf6; + else if (ch == 'O') + ch = 0xd6; + else if (ch == 'u') + ch = 0xfc; + else if (ch == 'U') + ch = 0xdc; + break; + case 23 : if (ch == 'a') + ch = 0xe5; + else if (ch == 'A') /* circle */ + ch = 0xc5; + break; + } + } + } + } + /*----------------- end of 'Scandinavian code' ----------------*/ + if (foo == leftmargin-1) + while ((currentline->text[j - leftmargin] != SPACE) + && (j < rightmargin)) { + j++; + h += charwidth; + } + if ( ((ch >= SPACE) && (ch != DEL)) || + (scascii && (ch == 23)) ) { + /* (scascii && (ch == DEL)) ) { if VMS ??? */ + if (j < rightmargin) + currentline->text[j - leftmargin] = ch; + else + currentline->text[rightmargin - leftmargin] = '@'; + if (j > currentline->charactercount) + currentline->charactercount = j; + if (j < firstcolumn) + firstcolumn = j; + h += charwidth; + } + +} /* outchar */ + +/*----------------------------------------------------------------------------*/ + +void putcharacter(charnr) /* output character, don't change h */ +register long charnr; +{ + register long saveh; + + saveh = h; + if ((charnr >= 0) && (charnr <= LASTCHAR)) + outchar((char) charnr); + else + setchar(charnr); + h = saveh; + +} /* putcharacter */ + +/*----------------------------------------------------------------------------*/ + +void setchar(charnr) +long charnr; +{ /* should print characters with character code>127 from current font */ + /* note that the parameter is a dummy, since ascii-chars are<=127 */ + + outchar((unsigned char)(charnr)); + +} /* setchar */ + + +/*----------------------------------------------------------------------------*/ + + +void fontdef(x) +register int x; +{ + register int i; + char * name; + font * fnt; + int namelen; + long fntnum; + int new = 0; + + fntnum = num(x); + (void) get4(); /* checksum */ + (void) get4(); /* scale */ + (void) get4(); /* design */ + namelen = (int) get1() + (int) get1(); + fnt = fonts; + while (fnt != NULL && fnt->num != fntnum) /* does fontnum exist */ + fnt = fnt->next; + if (fnt == NULL) { + if ((fnt = (font *) malloc(sizeof(font))) == NULL) { + perror("fontdef"); + exit(1); + } + fnt->num = fntnum; + new = 1; + } + else + free(fnt->name); /* free old name */ + if ((name = (char *) malloc((namelen+1) * sizeof(char))) == NULL) { + perror("fontdef"); + exit(1); + } + + for (i = 0; i < namelen; i++) + name[i] = get1(); + name[namelen] = '\0'; + fnt->name = name; + if (new) { + fnt->next = fonts; + fonts = fnt; + } + + return; + +} /* fontdef */ + + + +void setfont(fntnum) +long fntnum; +{ + font * fnt; + char * s; + + fnt = fonts; + while (fnt != NULL && fnt->num != fntnum) + fnt = fnt->next; + if (fnt == NULL) { + /* error : font not found */ + symbolfont = FALSE; + return; + } + + s = fnt->name; + while ((s = strchr(s, 's')) != NULL) { + if (strncmp("sy", s, 2) == 0) { + symbolfont = TRUE; + return; + } + s++; /* New line to fix bug; font names with 's' would hang */ + } + + symbolfont = FALSE; + return; + +} /* setfont */ + + + +/*----------------------------------------------------------------------------*/ + + +#if defined(VMS) +long vmsseek(fp,n,dir) +FILE *fp; +long n; +long dir; +{ + long k,m,pos,val,oldpos; + struct stat buffer; + + for (;;) { /*loops only once or twice*/ + switch (dir) { + case 0: /*from BOF*/ + oldpos = vms_ftell(fp); + k = n & 511; + m = n >> 9; + if (((*fp)->_cnt) && ((oldpos >> 9) == m)) { + val = 0; /* still in */ + (*fp)->_ptr = ((*fp)->_base) + k; + (*fp)->_cnt = 512 - k; + } + else { + val = fseek(fp, m << 9, 0); + if (val == 0) { + (*fp)->_cnt = 0; + (void) fgetc(fp); + (*fp)->_ptr = ((*fp)->_base) + k; + (*fp)->_cnt = 512 - k; + } + } + return(val); + + case 1: pos = vms_ftell(fp); + if (pos == EOF) + return (EOF); + n += pos; + dir = 0; + break; + + case 2: val = fstat(fileno(fp), &buffer); + if (val == EOF) + return (EOF); + n += buffer.st_size - 1; + + dir = 0; + break; + + default : return (EOF); + } + } + +} /* vmsseek */ + + + +long vms_ftell(fp) +FILE *fp; +{ + char c; + long pos; + long val; + if ((*fp)->_cnt == 0) { + c = fgetc(fp); + val = vms_ungetc(c, fp); + if (val != c) + return (EOF); + } + pos = ftell(fp); + if (pos >= 0) + pos += ((*fp)->_ptr) - ((*fp)->_base); + return (pos); + +} /* vms_ftell */ + + + +long vms_ungetc(c,fp) +char c; +FILE *fp; +{ + if ((c == EOF) && feof(fp)) + return (EOF); + else if ((*fp)->_cnt >= 512) + return (EOF); + else { + (*fp)->_cnt++; + (*fp)->_ptr--; + *((*fp)->_ptr) = c; + return (c); + } + +} /*vms_ungetc */ +#endif |