[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Axiom-developer] TeX line breaking
From: |
Tim Daly |
Subject: |
[Axiom-developer] TeX line breaking |
Date: |
Wed, 10 Sep 2003 09:34:50 -0400 |
It doesn't optimize anything as far as I can see. Sutor's quite
good at TeX stuff. Essentially it works by inserting \begin{array}
which is the hack I needed. You can try it on an example by:
1) start axiom
2) type: )set output tex on
3) type: integrate(1/(x**3 * (a+b*x)**(1/3)),x)
4) cut the tex output starting with $$ and ending with $$
5) paste it into a buffer
6) replace the opening $$ with \[
7) replace the closing $$ with \]
8) save it into file foo
9) run texbreak <foo >foo.tex
The texbreak code is attached. It appears to be quite Axiom specific
and Axiom uses very old TeX syntax.
Tim
address@hidden
address@hidden
=========================================================================
/* Released under the Modified BSD license attached to Axiom sources.
* TeX Display Math Mode Line Breaking Program
*
* Author: Robert S. Sutor
*
* Date: 1991
*
* Change History:
*
* 01/19/92 RSS Change to use \[ \] instead of $$ $$
*
* 09/01/92 RSS Format and fix =-.
*
* Operation:
*
* This program reads standard input and writes to standard output. Display math
* mode starts with \[ at the beginning of a line and ends with \]. All lines
* not in display math mode are simply printed on standard output. The
* expressions in display math mode are broken so that they fit on a page
* better (line breaking).
*
* The array stuff is being converted to use the array node type.
*
* Restrictions:
*
* 1. Assume \[ and \] start in column 1 and are the only things on the lines.
*
* 2. Comments in display math mode are not preserved.
*
* 3. This is meant to deal with output from the AXIOM computer algebra system.
* Unpredictable results may occur if used with hand-generated TeX code or
* TeX code generated by other programs.
*/
/*
* Include files and #defines.
*/
#include "useproto.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MATHBUFLEN 128*8192
#define MAXMATHTOKEN 80
#define MAXCHARSINLINE 60
#define FATDELIMMULT 2
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define TRUE 1
#define FALSE 0
#define STRCHREQ(str,char) (str[0] == char)
/*
* Type declarations.
*/
enum nodeTypes {
N_NODE,
N_TEXT,
N_ARRAY
};
typedef struct listNodeStruct {
struct listNodeStruct *nextListNode;
struct listNodeStruct *prevListNode;
enum nodeTypes nodeType;
long width;
long realWidth;
union {
char *text;
struct listNodeStruct *node;
struct arrayNodeStruct *array;
} data;
} listNode;
typedef struct arrayNodeStruct {
int cols;
listNode *argsNode;
listNode *entries; /* linked list of nodes, each pointing to a
* row */
} arrayNode;
/*
* Global Variables.
*/
char line[1024];
char blanks[] = " ";
char lastPrinted = '\0';
int indent = 0;
char mathBuffer[MATHBUFLEN], mathToken[MAXMATHTOKEN];
int lineLen, mathBufferLen, mathBufferPtr, mathTokenLen;
listNode *mathList;
int charsOut, fatDelimiter;
int maxLineWidth = 4500; /* 4.5 inches * 1000 */
int maxLineSlop = 0; /* 0.0 inches * 1000 */
int charTable[256];
int avgCharWidth;
int spaceWidths[5], extraOverWidth;
int arrayDepth = 0, arrayMaxDepth = 3;
int charMultNum, charMultDenom;
int sinWidth, cosWidth, tanWidth, erfWidth;
long outLineNum = 0L;
/*
* Function Prototypes.
*/
#ifndef _NO_PROTO
void arrayTooDeep();
int breakFracProd(listNode *, long, char *, char *, int);
int breakFunction(listNode *, long);
int breakList(listNode *, long);
int breakMathList(listNode *, long);
int breakNumber(listNode *, long);
int breakPMEB(listNode *, long);
int breakParen(listNode *, long);
int bufferMathLines();
void buildMathList();
int charWidth(char);
void computeNodeWidth(listNode *);
long computeWidth(listNode *);
void displaySplitMsg(char *, int);
void error(char *, char *);
void freeMathList(listNode *);
void getOptions(int, char **);
void initCharTable();
listNode *insertStringAfter(char *, listNode *);
listNode *insertStringAtBack(char *, listNode *);
listNode *insertStringAtFront(char *, listNode *);
int newLineIfNecessary(int);
listNode *newListNode(enum nodeTypes);
int nextMathToken();
int printChar(char);
int printMathList(listNode *, int);
int printString(char *);
void resetCharMults();
listNode *string2NodeList(char *, listNode *);
void ttCharMults();
#else
void arrayTooDeep();
int breakFracProd();
int breakFunction();
int breakList();
int breakMathList();
int breakNumber();
int breakPMEB();
int breakParen();
int bufferMathLines();
void buildMathList();
int charWidth();
void computeNodeWidth();
long computeWidth();
void displaySplitMsg();
void error();
void freeMathList();
void getOptions();
void initCharTable();
listNode *insertStringAfter();
listNode *insertStringAtBack();
listNode *insertStringAtFront();
int newLineIfNecessary();
listNode *newListNode();
int nextMathToken();
int printChar();
int printMathList();
int printString();
void resetCharMults();
listNode *string2NodeList();
void ttCharMults();
#endif
/*
* Function Definitions.
*/
int
#ifndef _NO_PROTO
main(int argc, char *argv[])
#else
main(argc,argv)
int argc;
char *argv[];
#endif
{
int mathLinesRead;
getOptions(argc, argv);
initCharTable();
/*
* Read stdin line by line. When we come to a line that starts with \[,
* go into math mode.
*/
while (gets(line) != NULL) {
lineLen = strlen(line);
if ((lineLen > 1) && ('\\' == line[0]) && ('[' == line[1])) {
puts("\\[");
outLineNum++;
mathLinesRead = bufferMathLines();
if (mathLinesRead <= 0) {
puts("\\quad");
outLineNum++;
}
else {
fatDelimiter = 1;
arrayDepth = 0;
mathList = newListNode(N_NODE);
buildMathList(mathList);
resetCharMults();
computeWidth(mathList);
if (mathList->width > maxLineWidth)
fprintf(stderr, "Width = %ld units, Output line = %ld.\n",
mathList->width, outLineNum);
breakMathList(mathList, maxLineWidth);
charsOut = 0;
if (FALSE == printMathList(mathList->data.node, TRUE)) {
putc('\n', stdout);
outLineNum++;
}
freeMathList(mathList);
}
puts("\\]");
}
else
puts(line);
outLineNum++;
}
return 0;
}
/*
* breakFracProd:
*
* Arguments:
*
* n : the starting node at which we are to try to break
*
* lineWidth : the maximum width of a line
*
* match : either "\\over" or "\\ "
*
* label : either "quotient" or "product"
*
* paren : add parentheses (TRUE or FALSE)
*
*
* Returns: TRUE or FALSE, depending on whether the expression was broken
*
*
* Function: Tries to break up a quotient t1 \over t2 or a product t1 \ t2 by
* splitting and parenthesizing the numerator and/or the denominator.
*/
int
#ifndef _NO_PROTO
breakFracProd(listNode * n, long lineWidth, char *match, char *label, int paren)
#else
breakFracProd(n,lineWidth,match,label,paren)
listNode * n;
long lineWidth;
char *match;
char *label;
int paren;
#endif
{
listNode *rootNode, *lastNode, *t1, *t2;
int ok;
long workWidth1, workWidth2;
if (n->nodeType != N_NODE)
return FALSE;
rootNode = n;
ok = FALSE;
t1 = n = rootNode->data.node;
n = n->nextListNode;
if (n) {
if ((n->nodeType == N_TEXT) &&
(0 == strcmp(n->data.text, match))) {
t2 = n->nextListNode;
if (t2 && (NULL == t2->nextListNode))
ok = TRUE;
}
}
displaySplitMsg(label, ok);
if (ok) {
/* for products, determine rough widths for the two factors */
if (0 == strcmp(label, "product")) {
computeNodeWidth(t1);
computeNodeWidth(t2);
workWidth1 = lineWidth - charWidth(' ');
if (workWidth1 / 2 > t1->realWidth) {
workWidth2 = workWidth1 - t1->realWidth;
workWidth1 = t1->realWidth;
}
else if (workWidth1 / 2 > t2->realWidth) {
workWidth1 = workWidth1 - t2->realWidth;
workWidth2 = t2->realWidth;
}
else
workWidth1 = workWidth2 = workWidth1 / 2;
if (paren) {
if (t1->realWidth > workWidth1)
workWidth1 = workWidth1 - 4 * FATDELIMMULT * charWidth('(');
if (t2->realWidth > workWidth2)
workWidth2 = workWidth2 - 4 * FATDELIMMULT * charWidth('(');
}
}
else /* "quotient" */
workWidth1 = workWidth2 =
lineWidth - paren * 4 * FATDELIMMULT * charWidth('(');
if ((t1->nodeType == N_NODE) && (t1->realWidth > workWidth1)) {
t1->width = t1->realWidth;
if (breakMathList(t1, workWidth1) && paren) {
/* insert the \left( */
lastNode = insertStringAtFront("\\left(", t1);
while (lastNode->nextListNode)
lastNode = lastNode->nextListNode;
/* insert the \right) */
insertStringAtBack("\\right)", lastNode);
}
}
if ((t2->nodeType == N_NODE) && (t2->realWidth > workWidth2)) {
t2->width = t2->realWidth;
if (breakMathList(t2, workWidth2) && paren) {
/* insert the \left( */
lastNode = insertStringAtFront("\\left(", t2);
while (lastNode->nextListNode)
lastNode = lastNode->nextListNode;
/* insert the \right) */
insertStringAtBack("\\right)", lastNode);
}
}
return TRUE;
}
return FALSE;
}
int
#ifndef _NO_PROTO
breakFunction(listNode * n, long lineWidth)
#else
breakFunction(n,lineWidth)
listNode * n;
long lineWidth;
#endif
{
listNode *rootNode, *tmpNode, *lastNode, *t1, *t2, *t3;
int ok = FALSE;
long workWidth, maxWidth = 0;
if (n->nodeType != N_NODE)
return FALSE;
n = n->data.node;
if (n->nodeType == N_NODE)
return FALSE;
if ((0 == strcmp(n->data.text, "\\sin")) ||
(0 == strcmp(n->data.text, "\\cos")) ||
(0 == strcmp(n->data.text, "\\tan")) ||
(0 == strcmp(n->data.text, "\\log")) ||
(0 == strcmp(n->data.text, "\\arctan")) ||
(0 == strcmp(n->data.text, "\\erf"))) {
computeNodeWidth(n);
ok = TRUE;
}
displaySplitMsg("function", ok);
if (ok) {
t2 = newListNode(N_NODE);
t2->data.node = n->nextListNode;
t2->prevListNode = n;
n->nextListNode = t2;
ok = breakMathList(t2, lineWidth - n->realWidth);
}
return ok;
}
/*
* breakList:
*
* Arguments:
*
* n : the starting node at which we are to try to break
*
* lineWidth : the maximum width of a line
*
*
* Returns: TRUE or FALSE, depending on whether the expression was broken
*
*
* Function: Tries to split an expression that is bracketed by \left[ and
* \right] (or \left\{ and \right\} and contains at least one comma.
*/
int
#ifndef _NO_PROTO
breakList(listNode * n, long lineWidth)
#else
breakList(n,lineWidth)
listNode * n;
long lineWidth;
#endif
{
listNode *rootNode, *tmpNode, *lastNode, *t1, *t2, *t3;
int ok, comma;
long workWidth, maxWidth = 0;
if (n->nodeType != N_NODE)
return FALSE;
rootNode = n;
t1 = n = rootNode->data.node;
comma = ok = FALSE;
if ((t1->nodeType == N_TEXT) &&
(0 == strcmp(t1->data.text, "\\left")) &&
(t1->nextListNode) &&
(t1->nextListNode->nodeType == N_TEXT) &&
((0 == strcmp(t1->nextListNode->data.text, "[")) ||
(0 == strcmp(t1->nextListNode->data.text, "\\{")))) {
t1 = t1->nextListNode->nextListNode;
/*
* Check for a special case: sometimes the whole body of the list is
* a node. Flatten this, if possible.
*/
if ((t1->nodeType == N_NODE) &&
(t1->nextListNode->nodeType == N_TEXT) &&
(0 == strcmp(t1->nextListNode->data.text, "\\right"))) {
tmpNode = t1->prevListNode;
t2 = t1->nextListNode;
t3 = t1->data.node;
tmpNode->nextListNode = t3;
t3->prevListNode = tmpNode;
while (t3->nextListNode)
t3 = t3->nextListNode;
t3->nextListNode = t2;
t2->prevListNode = t3;
free(t1);
t1 = tmpNode->nextListNode;
}
while (t1->nextListNode && !ok) {
if ((t1->nodeType == N_TEXT) &&
(0 == strcmp(t1->data.text, ",")))
comma = TRUE;
else if ((t1->nodeType == N_TEXT) &&
(0 == strcmp(t1->data.text, "\\right")) &&
(t1->nextListNode->nodeType == N_TEXT) &&
((0 == strcmp(t1->nextListNode->data.text, "]")) ||
(0 == strcmp(t1->nextListNode->data.text, "\\}"))) &&
(NULL == t1->nextListNode->nextListNode)) {
ok = comma;
tmpNode = t1->nextListNode;
}
t1 = t1->nextListNode;
}
}
displaySplitMsg("list", ok);
if (ok) {
if (arrayDepth >= arrayMaxDepth) {
arrayTooDeep();
return FALSE;
}
/*
* Create array environment
*/
lastNode = insertStringAtFront("address@hidden", rootNode);
arrayDepth++;
insertStringAtBack("\\end{array}", tmpNode);
/*
* Now break at best place short of width. Start after the
* environment begins and after the \left(
*/
n = lastNode->nextListNode->nextListNode->nextListNode;
/*
* try to split the first expression if too big
*/
tmpNode = n->nextListNode;
if (breakMathList(n, lineWidth)) {
workWidth = n->width;
n = tmpNode;
}
else
workWidth = n->width;
maxWidth = workWidth;
while (n->nextListNode) {
if ((n->nodeType == N_TEXT) &&
((0 == strcmp(n->data.text, ",")) ||
(0 == strcmp(n->data.text, "\\:"))) &&
(workWidth + n->nextListNode->width > lineWidth)) {
maxWidth = max(maxWidth, workWidth);
n = insertStringAfter("\\right. \\\\ \\\\ \\displaystyle
\\left.", n);
/*
* try to split the next expression if too big
*/
tmpNode = n->nextListNode;
if (breakMathList(n, lineWidth)) {
workWidth = n->width;
n = tmpNode;
}
else
workWidth = n->width;
}
else {
workWidth += n->nextListNode->width;
n = n->nextListNode;
}
}
rootNode->width = rootNode->realWidth =
rootNode->data.node->width = rootNode->data.node->realWidth =
maxWidth;
arrayDepth--;
return TRUE;
}
return FALSE;
}
/*
* breakNumber:
*
* Arguments:
*
* rootNode : the starting node at which we are to try to break
*
* lineWidth : the maximum width of a line
*
*
* Returns: TRUE or FALSE, depending on whether the expression was broken
*
*
* Function: Tries to break an expression that contains only digits and possibly
* a decimal point.
*/
int
#ifndef _NO_PROTO
breakNumber(listNode * rootNode, long lineWidth)
#else
breakNumber(rootNode,lineWidth)
listNode * rootNode;
long lineWidth;
#endif
{
int ok = TRUE;
listNode *n, *arrNode, *rowNode, *colNode;
long workWidth, maxWidth = 0;
if (rootNode->nodeType != N_NODE)
return FALSE;
n = rootNode->data.node;
while (n && ok) {
if ((n->nodeType == N_TEXT) &&
(n->data.text[1] == '\0') &&
(isdigit(n->data.text[0]) || ('.' == n->data.text[0]))) {
n = n->nextListNode;
}
else
ok = FALSE;
}
displaySplitMsg("number", ok);
if (ok) {
if (arrayDepth >= arrayMaxDepth) {
arrayTooDeep();
return FALSE;
}
arrayDepth++;
arrNode = newListNode(N_ARRAY);
arrNode->data.array->entries = rowNode = newListNode(N_NODE);
arrNode->data.array->cols = 1;
arrNode->data.array->argsNode = newListNode(N_NODE);
string2NodeList("address@hidden", arrNode->data.array->argsNode);
n = rootNode->data.node;
computeWidth(n);
maxWidth = workWidth = n->width;
rowNode->data.node = colNode = newListNode(N_NODE);
colNode->data.node = n;
n = n->nextListNode;
while (n) {
computeWidth(n);
if (workWidth + n->width > lineWidth) {
maxWidth = max(maxWidth, workWidth);
/*
* time to start a new row
*/
n->prevListNode->nextListNode = NULL;
n->prevListNode = NULL;
workWidth = n->width;
rowNode->nextListNode = newListNode(N_NODE);
rowNode = rowNode->nextListNode;
rowNode->data.node = colNode = newListNode(N_NODE);
colNode->data.node = n;
}
else
workWidth += (n->nextListNode) ? n->nextListNode->width :0 ;
n = n->nextListNode;
}
rootNode->data.node = arrNode;
rootNode->width = rootNode->realWidth =
arrNode->width = arrNode->realWidth = maxWidth;
arrayDepth--;
return TRUE;
}
return FALSE;
}
void
#ifndef _NO_PROTO
resetWidths(listNode * n)
#else
resetWidths(n)
listNode * n;
#endif
{
if (n) {
n->width = -1;
n->realWidth = 0;
if (n->nodeType == N_NODE)
resetWidths(n->data.node);
resetWidths(n->nextListNode);
}
}
/*
* breakParen:
*
* Arguments:
*
* n : the starting node at which we are to try to break
*
* lineWidth : the maximum width of a line
*
*
* Returns: TRUE or FALSE, depending on whether the expression was broken
*
*
* Function: Tries to split an expression that is bracketed by left( and \right)
* (e.g., a factor).
*/
int
#ifndef _NO_PROTO
breakParen(listNode * n, long lineWidth)
#else
breakParen(n,lineWidth)
listNode * n;
long lineWidth;
#endif
{
listNode *tmpNode, *workNode;
int ok = FALSE;
if (n->nodeType != N_NODE)
goto say_msg;
tmpNode = n->data.node;
/*
* check for \left
*/
if ((tmpNode == NULL) ||
(tmpNode->nodeType == N_NODE) ||
(0 != strcmp(tmpNode->data.text, "\\left")))
goto say_msg;
/*
* check for '('
*/
tmpNode = tmpNode->nextListNode;
if ((tmpNode == NULL) ||
(tmpNode->nodeType == N_NODE) ||
('(' != tmpNode->data.text[0]))
goto say_msg;
/*
* now move to the end
*/
tmpNode = tmpNode->nextListNode;
if (tmpNode != NULL) {
while (tmpNode->nextListNode)
tmpNode = tmpNode->nextListNode;
tmpNode = tmpNode->prevListNode;
}
/*
* check for \right
*/
if ((tmpNode == NULL) ||
(tmpNode->nodeType == N_NODE) ||
(0 != strcmp(tmpNode->data.text, "\\right")))
goto say_msg;
/*
* check for ')'
*/
tmpNode = tmpNode->nextListNode;
if ((tmpNode == NULL) ||
(tmpNode->nodeType == N_NODE) ||
(')' != tmpNode->data.text[0]))
goto say_msg;
ok = TRUE;
say_msg:
displaySplitMsg("parenthesized expression", ok);
if (ok) {
/*
* nest the whole inside if necessary, i.e., there is more than one
* term between the ( and the \right
*/
if (tmpNode->prevListNode->prevListNode !=
n->data.node->nextListNode->nextListNode) {
workNode = newListNode(N_NODE);
workNode->data.node = n->data.node->nextListNode->nextListNode;
n->data.node->nextListNode->nextListNode = workNode;
tmpNode->prevListNode->prevListNode->nextListNode = NULL;
tmpNode->prevListNode->prevListNode = workNode;
workNode->prevListNode = n->data.node->nextListNode;
workNode->nextListNode = tmpNode->prevListNode;
resetWidths(workNode);
computeWidth(workNode);
}
return breakMathList(n->data.node->nextListNode->nextListNode,
lineWidth - 4 * FATDELIMMULT * charWidth('('));
}
return FALSE;
}
/*
* breakPMEB:
*
* Arguments:
*
* n : the starting node at which we are to try to break
*
* lineWidth : the maximum width of a line
*
*
* Returns: TRUE or FALSE, depending on whether the expression was broken
*
*
* Function: Tries to split an expression that contains only +, -, = or \ as
* operators. The split occurs after the operator.
*/
int
#ifndef _NO_PROTO
breakPMEB(listNode * n, long lineWidth)
#else
breakPMEB(n,lineWidth)
listNode * n;
long lineWidth;
#endif
{
char *s;
listNode *rootNode, *tmpNode, *lastNode;
int ok, op;
long workWidth, maxWidth = 0;
if (n->nodeType != N_NODE)
return FALSE;
if (n->width <= lineWidth + maxLineSlop) /* allow a little slop here */
return FALSE;
rootNode = n;
tmpNode = n = n->data.node;
ok = TRUE;
op = FALSE;
while (n && ok) {
if (n->nodeType == N_TEXT) {
s = n->data.text;
if (STRCHREQ(s, '+') || STRCHREQ(s, '-') || STRCHREQ(s, '=') ||
(0 == strcmp(s, "\\ ")))
op = TRUE;
else if ((0 == strcmp(s, "\\left")) ||
(0 == strcmp(s, "\\right")) ||
(0 == strcmp(s, "\\over")) ||
STRCHREQ(s, ',')) {
ok = FALSE;
break;
}
}
tmpNode = n;
n = n->nextListNode;
}
ok = ok & op;
displaySplitMsg("(+,-,=, )-expression", ok);
if (ok) {
if (arrayDepth >= arrayMaxDepth) {
arrayTooDeep();
return FALSE;
}
/*
* Create array environment
*/
lastNode = insertStringAtFront("address@hidden", rootNode);
arrayDepth++;
insertStringAtBack("\\end{array}", tmpNode);
/*
* Now break at best place short of width. Start after the
* environment begins.
*/
n = lastNode->nextListNode;
/*
* try to split the first expression if too big
*/
tmpNode = n->nextListNode;
if (breakMathList(n, lineWidth)) {
workWidth = n->width;
n = tmpNode;
}
else
workWidth = n->width;
maxWidth = workWidth;
while (n->nextListNode) {
loop_top:
if ((n->nodeType == N_TEXT) &&
(STRCHREQ(n->data.text, '+') || STRCHREQ(n->data.text, '-') ||
STRCHREQ(n->data.text, '=') ||
(0 == strcmp(n->data.text, "\\ "))) &&
(workWidth > 24) && /* avoid - or + on their own line */
(workWidth + n->nextListNode->width > lineWidth)) {
if ((workWidth < lineWidth / 3) &&
(breakMathList(n->nextListNode, lineWidth - workWidth))) {
n->nextListNode->width = -1;
n->nextListNode->realWidth = 0;
computeNodeWidth(n->nextListNode);
goto loop_top;
}
/*
* \ means multiplication. Use a \cdot to make this clearer
*/
if (0 == strcmp(n->data.text, "\\ "))
n = insertStringAfter("\\cdot \\\\ \\\\ \\displaystyle", n);
else
n = insertStringAfter("\\\\ \\\\ \\displaystyle", n);
maxWidth = max(maxWidth, workWidth);
/*
* try to split the next expression if too big
*/
tmpNode = n->nextListNode;
if (breakMathList(n, lineWidth)) {
workWidth = n->width;
n = tmpNode;
}
else
workWidth = n->width;
}
else {
workWidth += n->nextListNode->width;
n = n->nextListNode;
}
}
rootNode->width = rootNode->realWidth =
rootNode->data.node->width = rootNode->data.node->realWidth =
maxWidth;
arrayDepth--;
return TRUE;
}
return FALSE;
}
/*
* breakMathList:
*
* Arguments:
*
* n : the starting node at which we are to try to break
*
* lineWidth : the maximum width of a line
*
*
* Returns: TRUE or FALSE, depending on whether the expression was broken
*
*
* Function: Tries various methods to break the expression up into multiple
* lines if the expression is too big.
*/
int
#ifndef _NO_PROTO
breakMathList(listNode * n, long lineWidth)
#else
breakMathList(n,lineWidth)
listNode * n;
long lineWidth;
#endif
{
int split = FALSE;
/*
* Don't do anything if already short enough.
*/
if (n->width <= lineWidth)
return FALSE;
/*
* Can't split strings, so just return.
*/
if (n->nodeType == N_TEXT)
return FALSE;
blanks[indent] = ' ';
indent += 2;
blanks[indent] = '\0';
/*
* We know we have a node, so see what we can do.
*/
/*
* Case 1: a product: t1 \ t2
*/
if (split = breakFracProd(n, lineWidth, "\\ ", "product", FALSE))
goto done;
/*
* Case 2: a sequence of tokens separated by +, - or =
*/
if (split = breakPMEB(n, lineWidth))
goto done;
/*
* Case 3: a fraction of terms: t1 \over t2
*/
if (split = breakFracProd(n, lineWidth, "\\over", "quotient", TRUE))
goto done;
/*
* Case 4: a list of terms bracketed by \left[ and \right] with a comma
*/
if (split = breakList(n, lineWidth))
goto done;
/*
* Case 5: a list of digits, possibly with one "."
*/
if (split = breakNumber(n, lineWidth))
goto done;
/*
* Case 6: a parenthesized expression (e.g., a factor)
*/
if (split = breakParen(n, lineWidth))
goto done;
/*
* Case 7: a function application
*/
if (split = breakFunction(n, lineWidth))
goto done;
done:
blanks[indent] = ' ';
indent -= 2;
blanks[indent] = '\0';
return split;
}
void
#ifndef _NO_PROTO
buildMathList(listNode * oldNode)
#else
buildMathList(oldNode)
listNode * oldNode;
#endif
{
listNode *curNode, *tmpNode;
curNode = NULL;
while (nextMathToken()) {
if (mathToken[0] == '}')
break;
if (mathToken[0] == '{') {
tmpNode = newListNode(N_NODE);
buildMathList(tmpNode);
}
else {
tmpNode = newListNode(N_TEXT);
tmpNode->data.text = strdup(mathToken);
}
if (curNode == NULL) {
oldNode->data.node = tmpNode;
}
else {
tmpNode->prevListNode = curNode;
curNode->nextListNode = tmpNode;
}
curNode = tmpNode;
}
/*
* leave with one level of nesting, e.g., {{{x}}} --> {x}
*/
tmpNode = oldNode->data.node;
while ( tmpNode && (tmpNode->nodeType == N_NODE) &&
(tmpNode->nextListNode == NULL) ) {
oldNode->data.node = tmpNode->data.node;
free(tmpNode);
tmpNode = oldNode->data.node;
}
}
int
bufferMathLines()
{
/*
* Returns number of lines read. Returns negative this number if
* end-of-file was reached before final \].
*/
char curChar, lastChar, *eq;
int i, linesRead = 0;
mathBufferPtr = 0;
mathBufferLen = 0;
mathBuffer[0] = '\0';
while (gets(line) != NULL) {
lineLen = strlen(line);
if (('\\' == line[0]) && (']' == line[1]))
return linesRead;
else {
linesRead++;
/*
* Go through the line and change any unescaped % to a \0. Change
* any tab to a blank.
*/
lastChar = ' ';
i = 0;
while ((curChar = line[i]) != '\0') {
if ((curChar == '%') && (lastChar != '\\')) {
line[i] = '\0';
break;
}
else if (curChar == '\t')
curChar = line[i] = ' ';
i++;
lastChar = curChar;
}
lineLen = i;
if (lineLen == 0) /* skip empty lines */
;
else {
/*
* Stick the line in the math buffer.
*/
if (mathBufferLen + 1 + lineLen >= MATHBUFLEN)
error("math buffer exceeded.", "");
if ((mathBufferLen > 0) && (mathBuffer[mathBufferLen - 1] != '
')) {
strcat(mathBuffer, " ");
mathBufferLen++;
}
if (lineLen) {
strcat(mathBuffer, line);
mathBufferLen += lineLen;
}
}
}
}
return (-linesRead);
}
void
#ifndef _NO_PROTO
computeNodeWidth(listNode * n)
#else
computeNodeWidth(n)
listNode * n;
#endif
{
char *s;
int i;
listNode *tmp;
if (n->width != -1) /* only = -1 if unprocessed */
return;
n->realWidth = 0;
if (n->nodeType == N_TEXT) {
s = n->data.text;
if (s[0] == '\\') {
if (s[2] == '\0') {
switch (s[1]) {
case ' ':
n->width = spaceWidths[0];
break;
case ',':
n->width = spaceWidths[1];
break;
case '!':
n->width = spaceWidths[2];
break;
case ':':
n->width = spaceWidths[3];
break;
case ';':
n->width = spaceWidths[4];
break;
default:
n->width = avgCharWidth;
}
n->realWidth = n->width;
}
else if ((0 == strcmp(s, "\\displaystyle")) ||
(0 == strcmp(s, "\\bf")) ||
(0 == strcmp(s, "\\sf")) ||
(0 == strcmp(s, "\\tt")) ||
(0 == strcmp(s, "\\rm")) ||
(0 == strcmp(s, "\\hbox")) ||
(0 == strcmp(s, "\\mbox")) ||
(0 == strcmp(s, "\\overline")) ||
(0 == strcmp(s, "\\textstyle")) ||
(0 == strcmp(s, "\\scriptstyle")) ||
(0 == strcmp(s, "\\scriptscriptstyle"))) {
n->width = 0;
}
else if (0 == strcmp(s, "\\ldots"))
n->width = 3 * charWidth('.');
else if (0 == strcmp(s, "\\left")) {
tmp = n->nextListNode;
if (tmp->nodeType != N_TEXT)
error("unusual token following \\left", "");
n->realWidth = n->width = (tmp->data.text[0] == '.')
? 0
: charWidth(tmp->data.text[0]);
tmp->width = 0;
fatDelimiter = 1;
}
else if (0 == strcmp(s, "\\over")) {
/*
* have already added in width of numerator
*/
computeNodeWidth(n->nextListNode);
n->realWidth = extraOverWidth + max(n->prevListNode->width,
n->nextListNode->width);
n->width = n->realWidth - n->prevListNode->width;
n->nextListNode->width = 0;
fatDelimiter = FATDELIMMULT;
}
else if (0 == strcmp(s, "\\right")) {
tmp = n->nextListNode;
if (tmp->nodeType != N_TEXT)
error("unusual token following \\right", "");
n->realWidth = n->width = fatDelimiter *
((tmp->data.text[0] == '.') ? 0 :
charWidth(tmp->data.text[0]));
tmp->width = 0;
fatDelimiter = 1;
}
else if (0 == strcmp(s, "\\root")) {
computeNodeWidth(n->nextListNode); /* which root */
n->nextListNode->nextListNode->width = 0; /* \of */
tmp = n->nextListNode->nextListNode->nextListNode;
computeNodeWidth(tmp); /* root of */
n->realWidth = n->width = tmp->width + (avgCharWidth / 2) +
max(avgCharWidth, n->nextListNode->width);
n->nextListNode->width = 0;
tmp->width = 0;
}
else if (0 == strcmp(s, "\\sqrt")) {
computeNodeWidth(n->nextListNode);
n->realWidth = n->width =
avgCharWidth + (avgCharWidth / 2) + n->nextListNode->width;
n->nextListNode->width = 0;
}
else if (0 == strcmp(s, "\\zag")) {
computeNodeWidth(n->nextListNode);
computeNodeWidth(n->nextListNode->nextListNode);
n->realWidth = n->width = avgCharWidth +
max(n->nextListNode->width,
n->nextListNode->nextListNode->width);
n->nextListNode->width = 0;
n->nextListNode->nextListNode->width = 0;
fatDelimiter = FATDELIMMULT;
}
else if ((0 == strcmp(s, "\\alpha")) ||
(0 == strcmp(s, "\\beta")) ||
(0 == strcmp(s, "\\pi"))) {
n->realWidth = n->width = avgCharWidth;
}
else if (0 == strcmp(s, "\\sin"))
/* should use table lookup here */
n->realWidth = n->width = sinWidth;
else if (0 == strcmp(s, "\\cos"))
n->realWidth = n->width = cosWidth;
else if (0 == strcmp(s, "\\tan"))
n->realWidth = n->width = tanWidth;
else if (0 == strcmp(s, "\\erf"))
n->realWidth = n->width = erfWidth;
/*
* otherwise just compute length of token after \
*/
else {
n->width = 0;
for (i = 1; i < strlen(s); i++)
n->width += charWidth(s[i]);
n->realWidth = n->width;
}
}
else if (s[1] == '\0')
switch (s[0]) {
case '^':
case '_':
tmp = n->nextListNode;
computeNodeWidth(tmp);
n->width = n->width = tmp->width;
tmp->width = 0;
break;
default:
n->realWidth = n->width = charWidth(s[0]);
}
else {
n->width = 0;
for (i = 0; i < strlen(s); i++)
n->width += charWidth(s[i]);
n->realWidth = n->width;
}
}
else {
n->realWidth = n->width = computeWidth(n->data.node);
}
}
long
#ifndef _NO_PROTO
computeWidth(listNode * n)
#else
computeWidth(n)
listNode * n;
#endif
{
long w = 0;
while (n != NULL) {
if (n->width == -1) {
computeNodeWidth(n);
w += n->width;
}
n = n->nextListNode;
}
return w;
}
/*
* displaySplitMsg:
*
* Arguments:
*
* s : a string describing the kind of expression we are trying to split.
*
* ok : whether we can split it (TRUE or FALSE)
*
*
* Returns: nothing
*
*
* Function: Displays a message on stderr about whether a particular method of
* line breaking will be successful.
*/
void
#ifndef _NO_PROTO
displaySplitMsg(char *s, int ok)
#else
displaySplitMsg(s,ok)
char *s;
int ok;
#endif
{
fprintf(stderr, "%sCan split %s: %s\n", blanks, s, ok ? "TRUE" : "FALSE");
}
void
arrayTooDeep()
{
fprintf(stderr, "%s->Array nesting too deep!\n", blanks);
}
void
#ifndef _NO_PROTO
error(char *msg, char *insert)
#else
error(msg,insert)
char *msg;
char *insert;
#endif
{
fputs("Error (texbreak): ", stderr);
fputs(msg, stderr);
fputs(insert, stderr);
fputc('\n', stderr);
fputs("% Error (texbreak): ", stdout);
fputs(msg, stdout);
fputs(insert, stdout);
fputc('\n', stdout);
exit(1);
}
void
#ifndef _NO_PROTO
freeMathList(listNode * n)
#else
freeMathList(n)
listNode * n;
#endif
{
listNode *tmpNode;
while (n != NULL) {
if (n->nodeType == N_NODE)
freeMathList(n->data.node);
else if (n->nodeType == N_TEXT)
free(n->data.text);
else {
freeMathList(n->data.array->argsNode);
freeMathList(n->data.array->entries);
free(n->data.array);
}
tmpNode = n->nextListNode;
free(n);
n = tmpNode;
}
}
listNode *
#ifndef _NO_PROTO
insertStringAfter(char *s, listNode * n)
#else
insertStringAfter(s,n)
char *s;
listNode * n;
#endif
{
/*
* returns node after inserted string
*/
listNode *workNode, *lastNode;
workNode = newListNode(N_NODE);
lastNode = string2NodeList(s, workNode);
n->nextListNode->prevListNode = lastNode;
lastNode->nextListNode = n->nextListNode;
n->nextListNode = workNode->data.node;
workNode->data.node->prevListNode = n;
free(workNode);
return lastNode->nextListNode;
}
listNode *
#ifndef _NO_PROTO
insertStringAtBack(char *s, listNode * n)
#else
insertStringAtBack(s,n)
char *s;
listNode * n;
#endif
{
/*
* Breaks s up into a list of tokens and appends them onto the end of n.
* n must be non-NULL.
*/
listNode *workNode, *lastNode;
workNode = newListNode(N_NODE);
lastNode = string2NodeList(s, workNode);
n->nextListNode = workNode->data.node;
workNode->data.node->prevListNode = n;
free(workNode);
return lastNode;
}
listNode *
#ifndef _NO_PROTO
insertStringAtFront(char *s, listNode * n)
#else
insertStringAtFront(s,n)
char *s;
listNode * n;
#endif
{
/*
* Breaks s up into a list of tokens and appends them onto the front of
* n. n must be a node.
*/
listNode *workNode, *lastNode;
workNode = newListNode(N_NODE);
lastNode = string2NodeList(s, workNode);
lastNode->nextListNode = n->data.node;
n->data.node->prevListNode = lastNode;
n->data.node = workNode->data.node;
free(workNode);
return lastNode;
}
int
#ifndef _NO_PROTO
newLineIfNecessary(int lastWasNewLine)
#else
newLineIfNecessary(lastWasNewLine)
int lastWasNewLine;
#endif
{
if (!lastWasNewLine || (charsOut > 0)) {
putc('\n', stdout);
outLineNum++;
charsOut = 0;
}
return TRUE;
}
listNode *
#ifndef _NO_PROTO
newListNode(enum nodeTypes nt)
#else
newListNode(nt)
enum nodeTypes nt;
#endif
{
listNode *n;
n = (listNode *) malloc(sizeof(listNode));
n->nextListNode = n->prevListNode = NULL;
n->nodeType = nt;
n->width = -1;
n->realWidth = -1;
if (nt == N_NODE)
n->data.node = NULL;
else if (nt == N_TEXT)
n->data.text = NULL;
else {
n->data.array = (arrayNode *) malloc(sizeof(arrayNode));
n->data.array->argsNode = NULL;
n->data.array->entries = NULL;
n->data.array->cols = 0;
}
return n;
}
int
nextMathToken()
{
/*
* Sets mathToken. Returns 1 if ok, 0 if no more tokens.
*/
char curChar, errChar[2];
errChar[1] = '\0';
mathToken[0] = '\0';
mathTokenLen = 0;
/*
* Kill any blanks.
*/
while ((mathBufferPtr < mathBufferLen) && (mathBuffer[mathBufferPtr] == '
'))
mathBufferPtr++;
/*
* If at end, exit saying so.
*/
if (mathBufferPtr >= mathBufferLen)
return 0;
mathToken[mathTokenLen++] = curChar = mathBuffer[mathBufferPtr++];
if (curChar == '\\') {
curChar = mathBuffer[mathBufferPtr++];
switch (curChar) {
case '\0': /* at end of buffer */
mathToken[mathTokenLen++] = ' ';
goto done;
case '\\':
case ' ':
case '!':
case '#':
case '$':
case '%':
case '&':
case ',':
case ':':
case ';':
case '^':
case '_':
case '{':
case '}':
mathToken[mathTokenLen++] = curChar;
goto done;
}
if (isalpha(curChar) || (curChar == '@')) {
mathToken[mathTokenLen++] = curChar;
while ((curChar = mathBuffer[mathBufferPtr]) &&
(isalpha(curChar) || (curChar == '@'))) {
mathToken[mathTokenLen++] = curChar;
mathBufferPtr++;
}
}
else {
errChar[0] = curChar;
errChar[1] = '\0';
error("strange character following \\: ", errChar);
}
}
else if (isdigit(curChar)) /* digits are individual tokens */
;
else if (isalpha(curChar)) {
while ((curChar = mathBuffer[mathBufferPtr]) &&
(isalpha(curChar))) {
mathToken[mathTokenLen++] = curChar;
mathBufferPtr++;
}
}
else if (curChar == '"') { /* handle strings */
while ((curChar = mathBuffer[mathBufferPtr]) &&
(curChar != '"')) {
mathToken[mathTokenLen++] = curChar;
mathBufferPtr++;
}
mathToken[mathTokenLen++] = '"';
mathBufferPtr++;
}
done:
mathToken[mathTokenLen--] = '\0';
/*
* Some translations.
*/
if (0 == strcmp(mathToken, "\\sp")) {
mathToken[0] = '^';
mathToken[1] = '\0';
mathTokenLen = 1;
}
else if (0 == strcmp(mathToken, "\\sb")) {
mathToken[0] = '_';
mathToken[1] = '\0';
mathTokenLen = 1;
}
return 1;
}
int
#ifndef _NO_PROTO
printChar(char c)
#else
printChar(c)
char c;
#endif
{
if ((charsOut > MAXCHARSINLINE) &&
isdigit(lastPrinted) && isdigit(c)) {
putc('\n', stdout);
outLineNum++;
charsOut = 0;
}
putc(c, stdout);
lastPrinted = c;
charsOut++;
/*
* break lines after following characters
*/
if ((charsOut > MAXCHARSINLINE) && strchr("+- ,_^", c)) {
putc('\n', stdout);
outLineNum++;
charsOut = 0;
lastPrinted = '\0';
return TRUE;
}
return FALSE;
}
int
#ifndef _NO_PROTO
printMathList(listNode * n, int lastWasNewLine)
#else
printMathList(n,lastWasNewLine)
listNode * n;
int lastWasNewLine;
#endif
{
listNode *tmpNode, *rowNode, *colNode;
int begin, group, r, c;
while (n != NULL) {
if (n->nodeType == N_NODE) {
lastWasNewLine = printChar('{');
lastWasNewLine = printMathList(n->data.node, lastWasNewLine);
lastWasNewLine = printChar('}');
}
else if (n->nodeType == N_ARRAY) {
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
lastWasNewLine = printString("\\begin{array}");
lastWasNewLine = printMathList(n->data.array->argsNode,
lastWasNewLine);
lastWasNewLine = printString("\\displaystyle");
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
rowNode = n->data.array->entries; /* node pointing to first row */
while (rowNode) {
colNode = rowNode->data.node;
while (colNode) {
if (colNode->prevListNode) { /* if not first column
*/
lastWasNewLine = printString(" & ");
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
}
lastWasNewLine = printMathList(colNode->data.node,
lastWasNewLine);
colNode = colNode->nextListNode;
}
if (rowNode->nextListNode) /* if not last row */
lastWasNewLine = printString(" \\\\");
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
rowNode = rowNode->nextListNode;
}
lastWasNewLine = printString("\\end{array}");
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
}
else if (n->nodeType == N_TEXT) {
/*
* handle keywords that might appear in math mode
*/
if ((0 == strcmp(n->data.text, "by")) ||
(0 == strcmp(n->data.text, "if")) ||
(0 == strcmp(n->data.text, "then")) ||
(0 == strcmp(n->data.text, "else"))) {
lastWasNewLine = printString(" \\hbox{ ");
lastWasNewLine = printString(n->data.text);
lastWasNewLine = printString(" } ");
}
/*
* handle things that should be in a special font
*/
else if ((0 == strcmp(n->data.text, "true")) ||
(0 == strcmp(n->data.text, "false")) ||
(0 == strcmp(n->data.text, "table")) ||
(0 == strcmp(n->data.text, "Aleph"))
) {
lastWasNewLine = printString(" \\mbox{\\rm ");
lastWasNewLine = printString(n->data.text);
lastWasNewLine = printString("} ");
}
/*
* handle things that should always be on their own line
*/
else if ((0 == strcmp(n->data.text, "\\\\")) ||
(0 == strcmp(n->data.text, "\\displaystyle"))) {
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
lastWasNewLine = printString(n->data.text);
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
}
/*
* handle phrases that should be on their own line.
*/
else if ((0 == strcmp(n->data.text, "\\begin")) ||
(0 == strcmp(n->data.text, "\\end"))) {
lastWasNewLine = newLineIfNecessary(lastWasNewLine);
lastWasNewLine = printString(n->data.text);
begin = (n->data.text[1] == 'b') ? TRUE : FALSE;
n = n->nextListNode; /* had better be a node */
tmpNode = n->data.node;
lastWasNewLine = printChar('{');
lastWasNewLine = printMathList(tmpNode, lastWasNewLine);
lastWasNewLine = printChar('}');
if (begin) {
/*
* if array, print the argument.
*/
if (0 == strcmp(tmpNode->data.text, "array")) {
n = n->nextListNode; /* had better be a node */
lastWasNewLine = printChar('{');
lastWasNewLine = printMathList(n->data.node,
lastWasNewLine);
lastWasNewLine = printChar('}');
}
}
lastWasNewLine = newLineIfNecessary(FALSE);
}
/*
* handle everything else, paying attention as to whether we
* should include a trailing blank.
*/
else {
group = 0;
/* guess whether next word is part of a type */
if ((strlen(n->data.text) > 2) &&
('A' <= n->data.text[0]) &&
('Z' >= n->data.text[0])) {
group = 1;
lastWasNewLine = printString("\\hbox{\\axiomType{");
}
lastWasNewLine = printString(n->data.text);
if (group) {
lastWasNewLine = printString("}\\ }");
group = 0;
}
tmpNode = n->nextListNode;
if ((n->data.text[0] == '_') ||
(n->data.text[0] == '^') ||
(n->data.text[0] == '.') ||
(n->data.text[0] == '(') ||
(0 == strcmp(n->data.text, "\\left")) ||
(0 == strcmp(n->data.text, "\\right")) ||
(0 == strcmp(n->data.text, "\\%")));
else if (tmpNode && (tmpNode->nodeType == N_TEXT)) {
if (((isdigit(n->data.text[0])) &&
(isdigit(tmpNode->data.text[0]))) ||
((isdigit(n->data.text[0])) &&
(',' == tmpNode->data.text[0])) ||
(tmpNode->data.text[0] == '\'') ||
(tmpNode->data.text[0] == '_') ||
(tmpNode->data.text[0] == '^') ||
(tmpNode->data.text[0] == '.') ||
(tmpNode->data.text[0] == ')'));
else
lastWasNewLine = printChar(' ');
}
}
}
n = n->nextListNode;
}
return lastWasNewLine;
}
int
#ifndef _NO_PROTO
printString(char *s)
#else
printString(s)
char *s;
#endif
{
if (s[0]) {
if (!s[1])
return printChar(s[0]);
else {
fputs(s, stdout);
charsOut += strlen(s);
}
}
return FALSE;
}
listNode *
#ifndef _NO_PROTO
string2NodeList(char *s, listNode * n)
#else
string2NodeList(s,n)
char *s;
listNode * n;
#endif
{
/*
* First argument is string to be broken up, second is a node. Return
* value is last item in list.
*/
mathBufferPtr = 0;
strcpy(mathBuffer, s);
mathBufferLen = strlen(s);
buildMathList(n);
n = n->data.node;
while (n->nextListNode) {
/*
* set width to 0: other funs will have to set for real
*/
n->width = 0;
n = n->nextListNode;
}
n->width = 0;
return n;
}
void
resetCharMults()
{
/*
* this is a ratio by which the standard \mit should be multiplied to get
* other fonts, roughly
*/
charMultNum = charMultDenom = 1;
}
void
ttCharMults()
{
/*
* this is a ratio by which the standard \mit should be multiplied to get
* the \tt font, roughly
*/
charMultNum = 11;
charMultDenom = 10;
}
int
#ifndef _NO_PROTO
charWidth(char c)
#else
charWidth(c)
char c;
#endif
{
return (charMultNum * charTable[c]) / charMultDenom;
}
void
#ifndef _NO_PROTO
#else
#endif
initCharTable()
{
int i;
avgCharWidth = 95; /* where 1000 = 1 inch */
spaceWidths[0] = 51; /* \ */
spaceWidths[1] = 25; /* \, */
spaceWidths[2] = -25; /* \! */
spaceWidths[3] = 37; /* \: */
spaceWidths[4] = 42; /* \; */
extraOverWidth = 33; /* extra space in fraction bar */
sinWidth = 186; /* width of \sin */
cosWidth = 203;
tanWidth = 219;
erfWidth = 185;
for (i = 0; i < 256; i++)
charTable[i] = avgCharWidth;
charTable['!'] = 42;
charTable['"'] = 76;
charTable['%'] = 126;
charTable['('] = 59;
charTable[')'] = 59;
charTable['+'] = 185;
charTable[','] = 42;
charTable['-'] = 185;
charTable['.'] = 42;
charTable['/'] = 76;
charTable['0'] = 76;
charTable['1'] = 76;
charTable['2'] = 76;
charTable['3'] = 76;
charTable['4'] = 76;
charTable['5'] = 76;
charTable['6'] = 76;
charTable['7'] = 76;
charTable['8'] = 76;
charTable['9'] = 76;
charTable[':'] = 42;
charTable[';'] = 42;
charTable['<'] = 202;
charTable['='] = 202;
charTable['>'] = 202;
charTable['A'] = 114;
charTable['B'] = 123;
charTable['C'] = 119;
charTable['D'] = 130;
charTable['E'] = 121;
charTable['F'] = 119;
charTable['G'] = 119;
charTable['H'] = 138;
charTable['I'] = 79;
charTable['J'] = 99;
charTable['K'] = 140;
charTable['L'] = 103;
charTable['M'] = 164;
charTable['N'] = 138;
charTable['O'] = 120;
charTable['P'] = 118;
charTable['Q'] = 120;
charTable['R'] = 116;
charTable['S'] = 102;
charTable['T'] = 110;
charTable['U'] = 120;
charTable['V'] = 122;
charTable['W'] = 164;
charTable['X'] = 137;
charTable['Y'] = 122;
charTable['Z'] = 114;
charTable['['] = 42;
charTable[']'] = 42;
charTable['a'] = 80;
charTable['b'] = 65;
charTable['c'] = 66;
charTable['d'] = 79;
charTable['e'] = 71;
charTable['f'] = 91;
charTable['g'] = 78;
charTable['h'] = 87;
charTable['i'] = 52;
charTable['j'] = 71;
charTable['k'] = 84;
charTable['l'] = 48;
charTable['m'] = 133;
charTable['n'] = 91;
charTable['o'] = 73;
charTable['p'] = 76;
charTable['q'] = 73;
charTable['r'] = 73;
charTable['s'] = 71;
charTable['t'] = 55;
charTable['u'] = 87;
charTable['v'] = 79;
charTable['w'] = 113;
charTable['x'] = 87;
charTable['y'] = 80;
charTable['z'] = 77;
charTable['{'] = 76;
charTable['|'] = 42;
charTable['}'] = 76;
}
void
#ifndef _NO_PROTO
getOptions(int argc, char **argv)
#else
getOptions(argc,argv)
int argc;
char **argv;
#endif
{
int i, j;
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-')
break;
else if (0 == strcmp(argv[i], "-help")) {
printf("No help yet.\n");
exit(0);
}
else if (0 == strcmp(argv[i], "-width")) {
if (++i < argc) {
j = atoi(argv[i]);
if (j < 1000) {
printf("A positive integer > 1000 is required after
-width.\n");
exit(3);
}
maxLineWidth = j;
}
else {
printf("A positive integer > 1000 is required after -width.\n");
exit(3);
}
}
else if (0 == strcmp(argv[i], "-slop")) {
if (++i < argc) {
j = atoi(argv[i]);
if (j < 0) {
printf("An integer >= 0 is required after -slop.\n");
exit(3);
}
maxLineSlop = j;
}
else {
printf("An integer >= 0 is required after -slop.\n");
exit(3);
}
}
else if (0 == strcmp(argv[i], "-depth")) {
if (++i < argc) {
j = atoi(argv[i]);
if (j < 0) {
printf("An integer >= 0 is required after -depth.\n");
exit(3);
}
arrayMaxDepth = j;
}
else {
printf("An integer >= 0 is required after -depth.\n");
exit(3);
}
}
else {
printf("Unknown option %s for command %s.\n",
argv[i], argv[0]);
exit(3);
}
}
}
- [Axiom-developer] TeX line breaking,
Tim Daly <=