aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rwxr-xr-xconfigure18
-rw-r--r--configure.ac2
-rw-r--r--configure.ac.pamphlet2
-rwxr-xr-xcontrib/texmacs/Makefile18
-rwxr-xr-xcontrib/texmacs/README.txt53
-rwxr-xr-xcontrib/texmacs/packages/session/openaxiom.ts42
-rwxr-xr-xcontrib/texmacs/progs/init-openaxiom.scm23
-rwxr-xr-xcontrib/texmacs/progs/openaxiom-input.scm53
-rwxr-xr-xcontrib/texmacs/src/texbreaker.c2007
-rwxr-xr-xcontrib/texmacs/src/tm_openaxiom.c603
-rwxr-xr-xcontrib/texmacs/src/useproto.h43
12 files changed, 2857 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index fc6d5981..3bf9bf91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-07-04 Alfredo Portes <doyenatccny@gmail.com>
+
+ * contrib/texmacs: New.
+
2009-07-02 Gabriel Dos Reis <gdr@cse.tamu.edu>
* configure.ac.pamphlet: Support --enable-profiling.
diff --git a/configure b/configure
index 39fa8a4f..00ed6ffc 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.63 for OpenAxiom 1.4.0-2009-07-03.
+# Generated by GNU Autoconf 2.63 for OpenAxiom 1.4.0-2009-07-04.
#
# Report bugs to <open-axiom-bugs@lists.sf.net>.
#
@@ -745,8 +745,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='OpenAxiom'
PACKAGE_TARNAME='openaxiom'
-PACKAGE_VERSION='1.4.0-2009-07-03'
-PACKAGE_STRING='OpenAxiom 1.4.0-2009-07-03'
+PACKAGE_VERSION='1.4.0-2009-07-04'
+PACKAGE_STRING='OpenAxiom 1.4.0-2009-07-04'
PACKAGE_BUGREPORT='open-axiom-bugs@lists.sf.net'
ac_unique_file="src/Makefile.pamphlet"
@@ -1502,7 +1502,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures OpenAxiom 1.4.0-2009-07-03 to adapt to many kinds of systems.
+\`configure' configures OpenAxiom 1.4.0-2009-07-04 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1572,7 +1572,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of OpenAxiom 1.4.0-2009-07-03:";;
+ short | recursive ) echo "Configuration of OpenAxiom 1.4.0-2009-07-04:";;
esac
cat <<\_ACEOF
@@ -1675,7 +1675,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-OpenAxiom configure 1.4.0-2009-07-03
+OpenAxiom configure 1.4.0-2009-07-04
generated by GNU Autoconf 2.63
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1689,7 +1689,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by OpenAxiom $as_me 1.4.0-2009-07-03, which was
+It was created by OpenAxiom $as_me 1.4.0-2009-07-04, which was
generated by GNU Autoconf 2.63. Invocation command line was
$ $0 $@
@@ -17704,7 +17704,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by OpenAxiom $as_me 1.4.0-2009-07-03, which was
+This file was extended by OpenAxiom $as_me 1.4.0-2009-07-04, which was
generated by GNU Autoconf 2.63. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -17767,7 +17767,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
-OpenAxiom config.status 1.4.0-2009-07-03
+OpenAxiom config.status 1.4.0-2009-07-04
configured by $0, generated by GNU Autoconf 2.63,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.ac b/configure.ac
index 186a4dcd..4bd9bec5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
sinclude(config/open-axiom.m4)
sinclude(config/aclocal.m4)
-AC_INIT([OpenAxiom], [1.4.0-2009-07-03],
+AC_INIT([OpenAxiom], [1.4.0-2009-07-04],
[open-axiom-bugs@lists.sf.net])
AC_CONFIG_AUX_DIR(config)
diff --git a/configure.ac.pamphlet b/configure.ac.pamphlet
index d7945d12..7785a67a 100644
--- a/configure.ac.pamphlet
+++ b/configure.ac.pamphlet
@@ -1141,7 +1141,7 @@ information:
<<Autoconf init>>=
sinclude(config/open-axiom.m4)
sinclude(config/aclocal.m4)
-AC_INIT([OpenAxiom], [1.4.0-2009-07-03],
+AC_INIT([OpenAxiom], [1.4.0-2009-07-04],
[open-axiom-bugs@lists.sf.net])
@
diff --git a/contrib/texmacs/Makefile b/contrib/texmacs/Makefile
new file mode 100755
index 00000000..3109524e
--- /dev/null
+++ b/contrib/texmacs/Makefile
@@ -0,0 +1,18 @@
+
+###############################################################################
+# MODULE : Make file for opeenaxiom plugin
+# BY : Joris van der Hoeven
+# COPYRIGHT : This software falls under the GNU general public license;
+# see the file 'LICENSE', which is provided with this package.
+###############################################################################
+
+CC = gcc
+RM = rm -f
+
+all: bin/tm_openaxiom
+
+bin/tm_openaxiom: src/tm_openaxiom.c
+ $(CC) src/tm_openaxiom.c src/texbreaker.c -o bin/tm_openaxiom
+
+clean:
+ $(RM) bin/tm_openaxiom
diff --git a/contrib/texmacs/README.txt b/contrib/texmacs/README.txt
new file mode 100755
index 00000000..52181db8
--- /dev/null
+++ b/contrib/texmacs/README.txt
@@ -0,0 +1,53 @@
+tm_openaxiom - TeXmacs OpenAxiom Interface Program
+
+ Version 0.0.1
+ 3 July 2009
+
+Original Version by: Bill Page
+Modified by: Alfredo Portes
+
+Compile this program within the MSYS environment on Windows using
+the command:
+
+ gcc tm_openaxiom.c texbreaker.c -o tm_openaxiom
+
+Copy the executable file 'tm_openaxiom.exe' to the OPENAXIOM bin directory:
+
+ ... /installation-directory/bin
+
+Default options can be specified by the environment variable:
+
+ export TM_OPENAXIOM='break 1, over 1, cdot 1, space 0, big( 1, width 4.500'
+
+These can be overridden by on the command line:
+
+ tm_openaxiom 'break 1, over 1, cdot 1, space 0, big( 1, width 4.500'
+
+and can be modified dynamically via the simulated OpenAxiom command:
+
+ )set output texmacs break 1, over 1, cdot 1, space 0, big( 1, width 4.500
+
+You may use 1 yes or on and 0 no or off.
+
+ break <on>|<off> line-break algorithm
+ over <on>|<off> convert 2-d \over to 1-d /
+ cdot <on>|<off> convert \cdot to \ (space)
+ space <on>|<off> convert \ (space) to \,
+ big( <on>|<off> convert \left( \right to ( )
+ width <9.99> line width in inches
+
+I have also included an updated style file for OPENAXIOM
+
+ openaxiom.ts
+
+which corrects the positioning of the OpenAxiom Type: clause.
+
+After installing TeXmacs for Windows, copy this file into the
+TeXmacs directory:
+
+ c:\Program Files\wintexmacs\texmacs\plugins\openaxiom\packages\session
+
+or the equivalent location for the Cygwin version of TeXmacs.
+
+Questions? bill.page1@sympatico.ca
+ doyenatccy@gmail.com \ No newline at end of file
diff --git a/contrib/texmacs/packages/session/openaxiom.ts b/contrib/texmacs/packages/session/openaxiom.ts
new file mode 100755
index 00000000..3dbb7cfe
--- /dev/null
+++ b/contrib/texmacs/packages/session/openaxiom.ts
@@ -0,0 +1,42 @@
+<TeXmacs|WinTeXmacs-1.0.4.4>
+
+<style|source>
+
+<\body>
+ <active*|<\src-title>
+ <src-package|openaxiom|1.0>
+
+ <\src-purpose>
+ Markup for OpenAxiom sessions.
+ </src-purpose>
+
+ <src-copyright|2002--2004|Joris van der Hoeven>
+
+ <\src-license>
+ This <TeXmacs> style package falls under the <hlink|GNU general public
+ license|$TEXMACS_PATH/LICENSE> and comes WITHOUT ANY WARRANTY
+ WHATSOEVER. If you do not have a copy of the license, then write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+ </src-license>
+ </src-title>>
+
+ <assign|openaxiom-input|<macro|prompt|body|<style-with|src-compact|none|<generic-input|<resize|<arg|prompt>|||1.75fn||>|<arg|body>>>>>
+
+ <assign|openaxiom-output|<macro|body|<style-with|src-compact|none|<surround|<vspace*|1fn>|<vspace|1fn>|<with|par-left|<plus|<value|par-left>|1.75fn>|<generic-output*|<arg|body>>>>>>>
+
+ \;
+
+ <assign|leqno|<macro|<htab|5mm>>>
+
+ <assign|openaxiomtype|<macro|type|<vspace*|0.5fn><next-line><hflush><with|color|brown|Type:
+ <arg|type>>>>
+
+ \;
+</body>
+
+<\initial>
+ <\collection>
+ <associate|preamble|true>
+ </collection>
+</initial> \ No newline at end of file
diff --git a/contrib/texmacs/progs/init-openaxiom.scm b/contrib/texmacs/progs/init-openaxiom.scm
new file mode 100755
index 00000000..b6d485a3
--- /dev/null
+++ b/contrib/texmacs/progs/init-openaxiom.scm
@@ -0,0 +1,23 @@
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; MODULE : init-openaxiom.scm
+;; DESCRIPTION : Initialize openaxiom plugin
+;; COPYRIGHT : (C) 1999 Joris van der Hoeven
+;;
+;; This software falls under the GNU general public license and comes WITHOUT
+;; ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for details.
+;; If you don't have this file, write to the Free Software Foundation, Inc.,
+;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (openaxiom-initialize)
+ (import-from (texmacs plugin plugin-convert))
+ (lazy-input-converter (openaxiom-input) openaxiom))
+
+(plugin-configure openaxiom
+ (:require (url-exists-in-path? "open-axiom"))
+ (:initialize (openaxiom-initialize))
+ (:launch "tm_openaxiom")
+ (:session "OpenAxiom"))
diff --git a/contrib/texmacs/progs/openaxiom-input.scm b/contrib/texmacs/progs/openaxiom-input.scm
new file mode 100755
index 00000000..81da0b8f
--- /dev/null
+++ b/contrib/texmacs/progs/openaxiom-input.scm
@@ -0,0 +1,53 @@
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; MODULE : openopenaxiom-input.scm
+;; DESCRIPTION : OpenAxiom input converters
+;; COPYRIGHT : (C) 1999 Joris van der Hoeven
+;;
+;; This software falls under the GNU general public license and comes WITHOUT
+;; ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for details.
+;; If you don't have this file, write to the Free Software Foundation, Inc.,
+;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(texmacs-module (openaxiom-input)
+ (:use (texmacs plugin plugin-convert)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Specific conversion routines
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (openaxiom-input-var-row r)
+ (if (not (null? r))
+ (begin
+ (display ", ")
+ (plugin-input (car r))
+ (openaxiom-input-var-row (cdr r)))))
+
+(define (openaxiom-input-row r)
+ (display "[")
+ (plugin-input (car r))
+ (openaxiom-input-var-row (cdr r))
+ (display "]"))
+
+(define (openaxiom-input-var-rows t)
+ (if (not (null? t))
+ (begin
+ (display ", ")
+ (openaxiom-input-row (car t))
+ (openaxiom-input-var-rows (cdr t)))))
+
+(define (openaxiom-input-rows t)
+ (display "matrix([")
+ (openaxiom-input-row (car t))
+ (openaxiom-input-var-rows (cdr t))
+ (display "])"))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Initialization
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(plugin-input-converters openaxiom
+ (rows openaxiom-input-rows))
diff --git a/contrib/texmacs/src/texbreaker.c b/contrib/texmacs/src/texbreaker.c
new file mode 100755
index 00000000..49a5966c
--- /dev/null
+++ b/contrib/texmacs/src/texbreaker.c
@@ -0,0 +1,2007 @@
+/* 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 8*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];
+char bufout[2*MATHBUFLEN];
+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 putcBuf(char, char []);
+void putsBuf(char [], 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 putsBuf();
+void putcBuf();
+void resetCharMults();
+listNode *string2NodeList();
+void ttCharMults();
+#endif
+
+
+/*
+ * Function Definitions.
+ */
+
+int
+#ifndef _NO_PROTO
+texbreak(char bufinp[])
+#else
+texbreak(bufinp)
+char bufinp[];
+#endif
+{
+ initCharTable();
+ strcpy(bufout,"");
+ mathBufferLen=strlen(bufinp);
+ if (mathBufferLen > MATHBUFLEN) {
+ fprintf(stderr, "mathBuffer too small. Need: %d\n", mathBufferLen);
+ return 0;
+ };
+ mathBufferPtr = 0;
+ strcpy(mathBuffer,bufinp);
+/* fprintf(stderr, "bufinp: %s\n", mathBuffer); */
+ 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;
+ printMathList(mathList->data.node, TRUE);
+ freeMathList(mathList);
+ return 1;
+}
+
+/*
+ * 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("\\begin{array}{@{}l}\\displaystyle", 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("{@{}l}", 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("\\begin{array}{@{}l}\\displaystyle", 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;
+ }
+}
+
+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)) {
+ putcBuf('\n', bufout);
+ 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)) {
+ putcBuf('\n', bufout);
+ outLineNum++;
+ charsOut = 0;
+ }
+
+ putcBuf(c, bufout);
+ lastPrinted = c;
+ charsOut++;
+
+ /*
+ * break lines after following characters
+ */
+
+ if ((charsOut > MAXCHARSINLINE) && strchr("+- ,_^", c)) {
+ putcBuf('\n', bufout);
+ 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 {
+ putsBuf(s,bufout);
+ charsOut += strlen(s);
+ }
+ }
+ return FALSE;
+}
+
+void
+#ifndef _NO_PROTO
+putsBuf(char s[], char buf[])
+#else
+putsBuf(s,buf)
+char s[], buf[]
+#endif
+{
+ strcat(buf,s);
+}
+
+void
+#ifndef _NO_PROTO
+putcBuf(char c,char buf[])
+#else
+putcBuf(c,buf)
+char c, buf[]
+#endif
+{
+ char s[2];
+
+ s[0] = c;
+ s[1] = '\0';
+ strcat(buf,s);
+}
+
+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;
+}
diff --git a/contrib/texmacs/src/tm_openaxiom.c b/contrib/texmacs/src/tm_openaxiom.c
new file mode 100755
index 00000000..edad4f68
--- /dev/null
+++ b/contrib/texmacs/src/tm_openaxiom.c
@@ -0,0 +1,603 @@
+/* tm_openaxiom.c
+ * COPYRIGHT : (C) 2004 Bill Page <bill.page1@sympatico.ca>
+ * (Portions) COPYRIGHT : (C) 1999 Andrey Grozin
+ ***********************************************************************
+ * This software falls under the GNU general public license and comes
+ * WITHOUT ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE
+ * for more details. If you don't have this file, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ ***********************************************************************
+ *
+ * The program runs OPENAXIOMsys as a separate process under Windows
+ * using CreateProcess() and asynchronous reader threads. It provides
+ * an interface between OpenAxiom and TeXmacs for windows.
+ *
+ * Before launching, stdin/out/err are each redirected into pipes
+ * so that OPENAXIOM can be fed commands and its output read from
+ * those pipes. A separate thread is created to manage reading the
+ * output of OpenAxiom and sending it (appropriatedly modified) to
+ * TeXmacs. The main thread reads from TeXmacs and sends it's
+ * output to OpenAxiom. In this way the input and output is completely
+ * asynchronous. There may be some advantage to the use of such
+ * "light weight" threads in Windows.
+ *
+ * Build with the command:
+ * gcc tm_openaxiom.c texbreaker.c -o tm_openaxiom.exe
+ * It is known to compile with gcc version 3.4.2 (mingw-special)
+ * under MinGW/MSYS. Other compilers may also work.
+ *
+ * Install the tm_openaxiom.exe file in the directory
+ * C:\Program Files\WinTeXmacs\TeXmacs\bin
+ *
+ * Written by Bill Page 20041203
+ * - based on Maxima test version by Mike Thomas 20030624
+ * (Thankyou Mike!)
+ * and on the TeXmacs tm_openaxiom.c program (linux)
+ * Modified by Bill Page 20041215
+ * - add call to Robert Sutor line-break routine
+ * Modified by Bill Page 20041217
+ * - initialize OPENAXIOM_exe from OPENAXIOM environment variable
+ * Modified by Bill Page 20041220
+ * - use args, TM_OPENAXIOM environment variable and/or
+ * )set output texmacs option,option, ...
+ * to specify options
+ * break no -- disables line-break algorithm
+ * over no -- converts 2-d \over to 1-d /
+ * cdot no -- converts \cdot to \ (space)
+ * space no -- convert \ (space) to \,
+ * big( no -- convert \left( \right to ( )
+ * width 4.5 -- 4.5 inches * 1000
+ * - process OpenAxiom output with no LaTeX content, e.g.
+ * )set output tex off
+ * )set output algebra on
+ * */
+
+#include <windows.h>
+#include <process.h>
+#include <memory.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <io.h>
+
+/* Allow some debugging output from the IO threads */
+/*#define DEBUG_OUT*/
+
+int option_texbreak = 1, /* default options */
+ option_use_over = 1,
+ option_use_cdot = 1,
+ option_big_space = 0,
+ option_big_paren = 1;
+
+#define INP_BUFF_SIZE 3072
+#define OUT_BUFF_SIZE 8192
+char szBuffer[OUT_BUFF_SIZE];
+#define MATHBUFLEN 8*8192
+extern int maxLineWidth;
+extern char bufout[2*MATHBUFLEN];
+
+int nBuffer=0;
+int nRead;
+int IgnorePrompts=0;
+
+#define READ_HANDLE 0
+#define WRITE_HANDLE 1
+
+char OPENAXIOM_cmd[256];
+char ENV_OPENAXIOM[256];
+
+int fdStdOutPipe[2], fdStdInPipe[2], fdStdErrPipe[2];
+
+HANDLE hProcess;
+STARTUPINFO si; /* Only need to set si.cb */
+PROCESS_INFORMATION pi; /* Post launch child process information. */
+
+/* consult the environment */
+
+void parse_options(int nargs, char *args[]) {
+ char *pOPENAXIOM, *pTM_OPENAXIOM, *pOption;
+ int i;
+ float w;
+
+ if (pOPENAXIOM=getenv("OPENAXIOM")) {
+ strcpy(OPENAXIOM_cmd,pOPENAXIOM); strcat(OPENAXIOM_cmd, "/../../../../bin/open-axiom.exe");
+ strcat(OPENAXIOM_cmd," --system=\""); strcat(OPENAXIOM_cmd,pOPENAXIOM);
+ strcat(OPENAXIOM_cmd,"\"");
+ strcpy(ENV_OPENAXIOM,"OPENAXIOM="); strcat(ENV_OPENAXIOM, pOPENAXIOM);
+ }
+ else {
+ printf("You must set the OPENAXIOM environment variable, e.g.\n");
+ exit(1);
+ }
+
+/* e.g. TM_OPENAXIOM='break off, over yes, ...
+ * if not found or different options, ignore silently */
+ for (i=0;i<nargs;i++) {
+ pTM_OPENAXIOM=args[i]; /* args override environment */
+ if (i>0 || (pTM_OPENAXIOM=getenv("TM_OPENAXIOM"))) {
+ if (strstr(pTM_OPENAXIOM,"break off")
+ || strstr(pTM_OPENAXIOM,"break n")
+ || strstr(pTM_OPENAXIOM,"break 0"))
+ option_texbreak=0;
+ if (strstr(pTM_OPENAXIOM,"break on")
+ || strstr(pTM_OPENAXIOM,"break y")
+ || strstr(pTM_OPENAXIOM,"break 1"))
+ option_texbreak=1;
+ if (strstr(pTM_OPENAXIOM,"over off")
+ || strstr(pTM_OPENAXIOM,"over n")
+ || strstr(pTM_OPENAXIOM,"over 0"))
+ option_use_over=0;
+ if (strstr(pTM_OPENAXIOM,"over on")
+ || strstr(pTM_OPENAXIOM,"over y")
+ || strstr(pTM_OPENAXIOM,"over 1"))
+ option_use_over=1;
+ if (strstr(pTM_OPENAXIOM,"cdot off")
+ || strstr(pTM_OPENAXIOM,"cdot n")
+ || strstr(pTM_OPENAXIOM,"cdot 0"))
+ option_use_cdot=0;
+ if (strstr(pTM_OPENAXIOM,"cdot on")
+ || strstr(pTM_OPENAXIOM,"cdot y")
+ || strstr(pTM_OPENAXIOM,"cdot 1"))
+ option_use_cdot=1;
+ if (strstr(pTM_OPENAXIOM,"space off")
+ || strstr(pTM_OPENAXIOM,"space n")
+ || strstr(pTM_OPENAXIOM,"space 0"))
+ option_big_space=0;
+ if (strstr(pTM_OPENAXIOM,"space on")
+ || strstr(pTM_OPENAXIOM,"space y")
+ || strstr(pTM_OPENAXIOM,"space 1"))
+ option_big_space=1;
+ if (strstr(pTM_OPENAXIOM,"big( off")
+ || strstr(pTM_OPENAXIOM,"big( n")
+ || strstr(pTM_OPENAXIOM,"big( 0"))
+ option_big_paren=0;
+ if (strstr(pTM_OPENAXIOM,"big( on")
+ || strstr(pTM_OPENAXIOM,"big( y")
+ || strstr(pTM_OPENAXIOM,"big( 1"))
+ option_big_paren=1;
+ if (pOption=strstr(pTM_OPENAXIOM,"width ")) {
+ sscanf(pOption+strlen("width "),"%f",&w);
+ maxLineWidth=trunc(1000.0*w);
+ };
+ };
+ };
+}
+
+/* This is the OpenAxiom Reader thread. It runs asynchronously and
+ * in parallel with the main thread. It reads output from OpenAxiom
+ * and after some selection and conversion, it is sent on to
+ * TeXmacs. */
+
+unsigned __stdcall StdOutReadThread ( void* pArguments )
+{
+ int nExitCode = STILL_ACTIVE;
+
+ fputs("\2verbatim:",stdout); /* ---> to TeXmacs */
+
+ GetExitCodeProcess ( hProcess, (unsigned long*) &nExitCode );
+
+ while ( nExitCode == STILL_ACTIVE ) {
+ #ifdef DEBUG_OUT
+ fprintf ( stderr, " - Stdout read loop\n" );
+ fflush ( stderr );
+ #endif /* DEBUG_OUT */
+ nRead = _read ( fdStdOutPipe[READ_HANDLE], &szBuffer[nBuffer],
+ OUT_BUFF_SIZE-nBuffer ); /* Read <--- from OpenAxiom */
+
+ szBuffer[nBuffer+nRead]='\0';
+ #ifdef DEBUG_OUT
+ fprintf ( stderr, "After _read on stdoutpipe (%d bytes read)\n%s\n",
+ nRead, &szBuffer[nBuffer] ); fflush ( stderr );
+ #endif /* DEBUG_OUT */
+ while (nRead>0) { /* fill buffer until we see OpenAxiom prompt */
+ if ( strncmp(&szBuffer[nBuffer],"-> ",3)==0 ) { /* done */
+ HandleOutput(szBuffer, nBuffer); /* send output ---> to TeXmacs */
+ nRead = nRead-3; /* keep the left overs */
+ if (nRead>0) strncpy(szBuffer,&szBuffer[nBuffer+3],nRead);
+ nBuffer = 0; szBuffer[nRead]='\0';
+ #ifdef DEBUG_OUT
+ fprintf(stderr, "Leftovers\n%s\n",&szBuffer);
+ fflush(stderr);
+ #endif /* DEBUG_OUT */
+ } else {
+ nBuffer++;
+ nRead--;
+ };
+ };
+ GetExitCodeProcess ( hProcess, (unsigned long*) &nExitCode );
+ };
+
+ fputs("\2latex:\\red The end\\black\5\5",stdout); /* The ends --> TeXmacs */
+ fflush(stdout);
+ _endthreadex(0);
+}
+
+/* This routine parses all OpenAxiom output between -> prompts */
+
+HandleOutput(char Buffer[], int n) /* sends output ---> to TeXmacs */
+{
+ int mmode, i, j;
+
+ #ifdef DEBUG_OUT
+ fprintf(stderr, "HandleOutput IgnorePrompts:%d\n%s\n",IgnorePrompts,
+ Buffer);
+ fflush(stderr);
+ #endif /* DEBUG_OUT */
+ if (IgnorePrompts) --IgnorePrompts; /* counting down */
+ else { /* its a good packet */
+ while (n>0 && Buffer[n-1]=='\n') n--;
+ Buffer[n]='\0'; /* mark the real end */
+ mmode = 0; j=0;
+ while (Buffer[j]=='\n') j++; /* find the real start */
+ for (i=j;i<n;i++) {
+ if (strncmp(&Buffer[i],"$$\n",3)==0) { /* Found a LaTeX marker */
+ #ifdef DEBUG_OUT
+ fprintf(stderr, "LaTeX marker at: %d, mode: %d\n",i,mmode);
+ fflush(stderr);
+ #endif /* DEBUG_OUT */
+ Buffer[i]='\0'; /* something ends here */
+ if (mmode<=0) { /* we were not in mathmode */
+ fputs(&Buffer[j],stdout); /* send the plain text ---> to TeXmacs */
+ mmode = i+3; /* start of LaTeX */
+ fputs("\2latex:$$",stdout);/* tell ---> TeXmacs */
+ } else { /* we were in mathmode */
+ HandleLatex(&Buffer[mmode]); /* make some adjustments */
+ fputs("$$\5",stdout); /* Say "that's all" ---> to TeXmacs */
+ mmode = -1; j=i+3; /* aftermath */
+ }
+ } else { /* this is not a marker */
+ if (mmode<=0) { /* if not in mathmode */
+ if (strncmp(&Buffer[i],"Type:",5)==0) { /* look for OpenAxiom Type */
+ int k;
+ k=i-1; while (Buffer[k]==' ') k--;
+ Buffer[k]='\0'; /* mark end of previous */
+ fputs(&Buffer[j],stdout); /* send the plain text -> to TeXmacs */
+ fprintf(stdout,"\2latex:\\openaxiomtype{%s}\5",
+ &Buffer[i+6]);
+ i=n; j=n; /* and we are done */
+ }
+ }
+ }
+ };
+ if (j<n) {
+ fputs(&Buffer[j],stdout); /* send the plain text ---> to TeXmacs */
+ };
+ /* ask for some more work from ---> TeXmacs */
+ fputs("\2channel:prompt\5\2latex:\\red$\\rightarrow$\\ \5\5",stdout);
+ fflush(stdout); /* Say "give me a prompt" ---> to TeXmacs */
+ fputs("\2verbatim:",stdout); /* maybe plain text next ---> to TeXmacs */
+ }
+}
+
+HandleLatex(char buf[]) { /* fixup Latex coding */
+
+ char *ptr1, *ptr2, *ptr3;
+ char label[64];
+
+/* /n -> blank */
+ while (ptr1=strchr(buf,'\n')) { *ptr1=' '; };
+
+if (option_texbreak) { /* break long TeX lines */
+
+/* prepare OpenAxiom output in buf for call to texbreak */
+
+/* remove the label and save it for later */
+ label[0]='\0';
+ while (ptr1=strstr(buf,"\\leqno(")) {
+ if ((ptr2=strchr(ptr1,')')) && (ptr2-ptr1<64)) {
+ ptr2++;
+ strncpy(label,ptr1,ptr2-ptr1); label[ptr2-ptr1]='\0';
+ strcpy(ptr1,ptr2);
+ }
+ };
+
+ texbreak(buf); /* output is in global external called bufout */
+ strcat(bufout,"\\hfill \\leqno ");
+ strcat(bufout,&label[6]); /* put label back */
+} else {
+ strcpy(bufout,buf);
+};
+
+/* do some LaTex conversions for TeXmacs */
+
+/* \root { a } \of { b } ---> \sqrt[ a ] { b } */
+/* ptr1^ ptr2^ ^ptr3 ^ ^ ptr1^ ^ */
+
+ while (ptr1=strstr(bufout,"\\root")) {
+ ptr2=ptr1+5; while (*ptr2==' ') ptr2++;
+ if ((*ptr2=='{') && (ptr3=strstr(ptr2,"}"))) {
+ #ifdef DEBUG_OUT
+ fprintf(stderr, "ptr1: %s\nptr2: %s\nptr3: %s\n",ptr1,ptr2,ptr3);
+ fflush(stderr);
+ #endif /* DEBUG_OUT */
+ strncpy(ptr1,"\\sqrt[",6); ptr1=ptr1+6;
+ strncpy(ptr1,ptr2+1,ptr3-ptr2-1); ptr1=ptr1+(ptr3-ptr2-1);
+ strncpy(ptr1,"]",1); ptr1++;
+ ptr3++; while (*ptr3==' ') ptr3++;
+ #ifdef DEBUG_OUT
+ fprintf(stderr, "ptr1: %s\nptr2: %s\nptr3: %s\n",ptr1,ptr2,ptr3);
+ fflush(stderr);
+ #endif /* DEBUG_OUT */
+ if (strncmp(ptr3,"\\of",3)==0) {
+ ptr3+=3; while (*ptr3==' ') ptr3++;
+ if (*ptr3=='{') {
+ strcpy(ptr1,ptr3);
+ } else {
+ error("No \\of { \n");
+ }
+ } else {
+ error("No \\of \n");
+ }
+ } else {
+ error("No \\root { } \n");
+ }
+ };
+
+ if (!option_big_space) { /* use smaller spaces \ ---> \, */
+ while (ptr1=strstr(bufout,"\\ ")) {
+ strncpy(ptr1,"\\,",2); /* use thin spaces */
+ };
+ };
+
+/* other possible conversions */
+
+ if (!option_use_cdot) {
+ while (ptr1=strstr(bufout,"\\cdot")) {
+ strncpy(ptr1,"\\ ",2);
+ strcpy(ptr1+2,ptr1+5);
+ };
+ };
+
+ if (!option_big_paren) {
+ while (ptr1=strstr(bufout,"\\left(")) {
+ strncpy(ptr1,"(",1);
+ strcpy(ptr1+1,ptr1+6);
+ };
+ while (ptr1=strstr(bufout,"\\right)")) {
+ strncpy(ptr1,")",1);
+ strcpy(ptr1+1,ptr1+7);
+ };
+ };
+ if (!option_use_over) {
+ while (ptr1=strstr(bufout,"\\over")) {
+ strncpy(ptr1,"/",1);
+ strcpy(ptr1+1,ptr1+5);
+ };
+ };
+ #ifdef DEBUG_OUT
+ fprintf(stderr, "HandleLatex:\n%s\n",bufout);
+ fflush(stderr);
+ #endif /* DEBUG_OUT */
+ fputs(bufout,stdout); /* send the LaTeX code ---> to TeXmacs */
+}
+
+unsigned __stdcall StdErrReadThread ( void* pArguments )
+{
+ int nExitCode = STILL_ACTIVE;
+ int nRead;
+ char szBuffer[OUT_BUFF_SIZE];
+
+ GetExitCodeProcess ( hProcess, (unsigned long*) &nExitCode );
+
+ while ( nExitCode == STILL_ACTIVE ) {
+ #ifdef DEBUG_OUT
+ fprintf ( stderr, " - Stderr read loop\n" ); fflush ( stderr );
+ #endif /* DEBUG_OUT */
+ nRead = _read ( fdStdErrPipe[READ_HANDLE], szBuffer, OUT_BUFF_SIZE );
+ #ifdef DEBUG_OUT
+ fprintf ( stderr, "After _read on stderrpipe (%d bytes read)\n",
+ nRead );
+ fflush ( stderr );
+ #endif /* DEBUG_OUT */
+ if ( nRead ) { /* just pass the message on through to TeXmacs */
+ fwrite(szBuffer, 1, nRead, stderr);
+ }
+ GetExitCodeProcess ( hProcess, (unsigned long*) &nExitCode );
+ }
+ _endthreadex(0);
+}
+
+void pipe_write(int fdPipe, char Buffer[])
+{
+ _write(fdPipe, Buffer, strlen(Buffer) );
+}
+
+/* process texmacs options */
+
+process_options(char line[]) {
+ char *optargs[2];
+
+ optargs[1]=line;
+ if (*(optargs[1])!='\n') {
+ parse_options(2,optargs);
+ } else { /* display current options */
+ show_options();
+ };
+ /* ask for some more work from ---> TeXmacs */
+ fputs("\2channel:prompt\5\2latex:\\red$\\rightarrow$\\ \5\5",stdout);
+ fflush(stdout); /* Say "give me a prompt" ---> to TeXmacs */
+ fputs("\2verbatim:",stdout); /* maybe plain text next ---> to TeXmacs */
+
+ #ifdef DEBUG_OUT
+ fprintf ( stderr,
+ "TM_OPENAXIOM=texbreak:%d,use_over:%d,use_cdot:%d,big_space:%d,big_paren:%d,\n",
+ option_texbreak, option_use_over, option_use_cdot,
+ option_big_space, option_big_paren );
+ fprintf ( stderr,
+ " maxLineWidth:%d\n", maxLineWidth );
+ fflush ( stderr );
+ #endif /* DEBUG_OUT */
+}
+
+show_options() {
+ fprintf(stdout,
+"--------------------------- The texmacs Option ----------------------------\n\
+\n\
+ Description: options for display of OPENAXIOM output in TeXmacs\n\
+\n\
+ )set output texmacs is used to control the TeXmacs-OPENAXIOM interface\n\
+The default values are controlled by environment variable TM_OPENAXIOM\n\
+and may be overriden by command line options.\n\
+\n\
+Syntax: )set output texmacs <arg>\n\
+ where arg can be one or more of\n\
+ break <on>|<off> line-break algorithm\n\
+ over <on>|<off> convert 2-d \\over to 1-d /\n\
+ cdot <on>|<off> convert \\cdot to \\ (space)\n\
+ space <on>|<off> convert \\ (space) to \\,\n\
+ big( <on>|<off> convert \\left( \\right to ( )\n\
+ width <9.99> line width in inches\n\
+\n\
+ <on> may be on, yes, 1\n\
+ <off> may be off, no , 0\n\
+\n\
+The current settings are:\n\
+ break %d, over %d, cdot %d, space %d, big( %d, width %2.3f\n",
+ option_texbreak, option_use_over, option_use_cdot,
+ option_big_space, option_big_paren, maxLineWidth/1000.0 );
+
+};
+
+int main(int nargs, char *args[])
+{
+ HANDLE hStdOutReadThread;
+ int fdStdOut, fdStdIn;
+ unsigned threadIDOut;
+ HANDLE hStdErrReadThread;
+ int fdStdErr;
+ unsigned threadIDErr;
+ int i;
+ char line[INP_BUFF_SIZE];
+
+ parse_options(nargs,args);
+
+ #ifdef DEBUG_OUT
+ fprintf ( stderr, "CREATE PROCESS: %s\n", OPENAXIOM_cmd );
+ fprintf ( stderr, "Setting env var: %s\n", ENV_OPENAXIOM );
+ fprintf ( stderr,
+ "TM_OPENAXIOM=texbreak:%d,use_over:%d,use_cdot:%d,big_space:%d,big_paren:%d,\n",
+ option_texbreak, option_use_over, option_use_cdot,
+ option_big_space, option_big_paren );
+ fprintf ( stderr,
+ " maxLineWidth:%d\n", maxLineWidth );
+ fflush ( stderr );
+ #endif /* DEBUG_OUT */
+
+ if ( -1 == _setmode( _fileno( stdin ), _O_BINARY ) ) {
+ perror ( "machinfo: Cannot set stdin BINARY mode" ); exit(1);
+ };
+ if ( -1 == _setmode( _fileno( stdout ), _O_BINARY ) ) {
+ perror ( "machinfo: Cannot set stdout BINARY mode" ); exit(1);
+ };
+ if ( -1 == _setmode( _fileno( stderr ), _O_BINARY ) ) {
+ perror ( "machinfo: Cannot set stderr BINARY mode" ); exit(1);
+ };
+
+ /* Make pipes to be passed to the spawned process as stdin/out/err */
+ if ( _pipe ( fdStdOutPipe, 512, O_BINARY | O_NOINHERIT ) == -1 ) return 1;
+ if ( _pipe ( fdStdInPipe, 512, O_BINARY | O_NOINHERIT ) == -1 ) return 1;
+ if ( _pipe ( fdStdErrPipe, 512, O_BINARY | O_NOINHERIT ) == -1 ) return 1;
+
+ /* Duplicate and save original stdin/out/err handles */
+ fdStdOut = _dup ( _fileno(stdout) );
+ fdStdIn = _dup ( _fileno(stdin) );
+ fdStdErr = _dup ( _fileno(stderr) );
+
+ /* Duplicate write end of new pipes to current stdout/err handles,
+ * read to stdin */
+ if ( _dup2 ( fdStdOutPipe[WRITE_HANDLE], _fileno(stdout) ) != 0 ) return 2;
+ if ( _dup2 ( fdStdInPipe[READ_HANDLE], _fileno(stdin) ) != 0 ) return 2;
+ if ( _dup2 ( fdStdErrPipe[WRITE_HANDLE], _fileno(stderr) ) != 0 ) return 2;
+ /* Close the duplicated handles to the new pipes */
+ close ( fdStdOutPipe[WRITE_HANDLE] );
+ close ( fdStdInPipe[READ_HANDLE] );
+ close ( fdStdErrPipe[WRITE_HANDLE] );
+
+ putenv ( ENV_OPENAXIOM );
+
+ /* Zero startup and process info structures, take care of Windows
+ * startup info structure future proofing. */
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Start the child process. */
+ if ( !CreateProcess(
+ NULL, /* No module name (use command line). */
+ OPENAXIOM_cmd, /* Command line. */
+ NULL, /* Process handle not inheritable. */
+ NULL, /* Thread handle not inheritable. */
+ TRUE, /* Allow handle inheritance. */
+ 0, /* No creation flags. */
+ NULL, /* Use parent's environment block. */
+ NULL, /* Use parent's starting directory. */
+ &si, /* Pointer to STARTUPINFO structure.*/
+ &pi ) /* Pointer to PROCESS_INFORMATION structure. */ ) {
+ fprintf(stderr, "CreateProcess failed: %s\n", args[1]);
+ fflush(stderr);
+ return -1;
+ }
+ hProcess = pi.hProcess;
+
+ /* Now that the process is launched,
+ * replace the original stdin/out/err handles */
+ if ( _dup2 ( fdStdOut, _fileno ( stdout ) ) != 0 ) return 3;
+ if ( _dup2 ( fdStdIn, _fileno ( stdin ) ) != 0 ) return 3;
+ if ( _dup2 ( fdStdErr, _fileno ( stderr ) ) != 0 ) return 3;
+
+ /* Close duplicates */
+ close(fdStdOut);
+ close(fdStdIn);
+ close(fdStdErr);
+
+ /* The child process will become the OpenAxiom read filter and
+ * we will be the OpenAxiom write filter. */
+
+ /* Create the OpenAxiom stderr listening thread. (Doesn't do much.) */
+ hStdErrReadThread = (HANDLE)_beginthreadex( NULL, 0, &StdErrReadThread,
+ NULL, 0, &threadIDErr );
+ if ( 0 == hStdErrReadThread ) return 5;
+
+ /* * * * * * * * * */
+ /* start talking! */
+ /* * * * * * * * * */
+
+ IgnorePrompts = 5; /* Tell the OpenAxiom Reader to ignore first 5 prompts */
+ /* then create the OpenAxiom stdout Reader thread.*/
+ hStdOutReadThread = (HANDLE)_beginthreadex( NULL, 0, &StdOutReadThread,
+ NULL, 0, &threadIDOut );
+ if ( 0 == hStdOutReadThread ) return 5;
+ /* start force-feeding ---> to OpenAxiom */
+ pipe_write(fdStdInPipe[WRITE_HANDLE],")set message prompt plain\n" ); /* 1 */
+ pipe_write(fdStdInPipe[WRITE_HANDLE],")set messages autoload off\n" );/* 2 */
+ pipe_write(fdStdInPipe[WRITE_HANDLE],")set quit unprotected\n" ); /* 3 */
+ pipe_write(fdStdInPipe[WRITE_HANDLE],")set output tex on\n" ); /* 4 */
+ pipe_write(fdStdInPipe[WRITE_HANDLE],")set output algebra off\n" ); /* 5 */
+ while (fgets(line,INP_BUFF_SIZE,stdin)!=NULL) { /* wait <--- for TeXmacs */
+ #ifdef DEBUG_OUT
+ fprintf ( stderr, "Input:\n%s", line );
+ #endif /* DEBUG_OUT */
+ if (strncmp(line,")set output texmacs",
+ strlen(")set output texmacs"))==0) { /* process texmacs options */
+ process_options(&line[strlen(")set output texmacs")]);
+ } else {
+ pipe_write(fdStdInPipe[WRITE_HANDLE], line ); /* Start ---> OpenAxiom */
+ }
+ };
+ if (nBuffer) HandleOutput(szBuffer,nBuffer); /* anything leftover? */
+ pipe_write(fdStdInPipe[WRITE_HANDLE], ")quit\n" ); /* stop work */
+
+ WaitForSingleObject ( hStdErrReadThread, INFINITE );
+ WaitForSingleObject ( hStdOutReadThread, INFINITE );
+
+ /* Wait until child process exits to block the terminal. */
+ WaitForSingleObject( pi.hProcess, INFINITE );
+
+ /* As we are using gebinthreadex/endthreadex,
+ * we must close the thread handles. */
+ CloseHandle ( hStdOutReadThread );
+ CloseHandle ( hStdErrReadThread );
+
+ return 0;
+}
diff --git a/contrib/texmacs/src/useproto.h b/contrib/texmacs/src/useproto.h
new file mode 100755
index 00000000..ed7f76f8
--- /dev/null
+++ b/contrib/texmacs/src/useproto.h
@@ -0,0 +1,43 @@
+
+/* released under the Modified BSD License */
+
+#ifndef _USEPROTO_H_
+#define _USEPROTO_H_ 1
+
+#if defined(SGIplatform)||defined(LINUXplatform)||defined(HPplatform) ||defined(RIOSplatform) ||defined(RIOS4platform) || defined(SUN4OS5platform)
+#ifdef _NO_PROTO
+#undef _NO_PROTO
+#endif
+#ifndef NeedFunctionPrototypes
+#define NeedFunctionPrototypes 1
+#endif
+#endif /*SGIplatform ... */
+
+
+#if defined(ALPHAplatform)
+#ifdef __STDC__
+
+#ifdef _NO_PROTO
+#undef _NO_PROTO
+#endif
+#ifndef NeedFunctionPrototypes
+#define NeedFunctionPrototypes 1
+#endif
+
+#else
+
+#define _NO_PROTO
+#undef NeedFunctionPrototypes
+
+#endif
+#endif /* ALPHA */
+
+
+
+#ifdef SUNplatform
+#define _NO_PROTO
+#define const
+#endif
+
+#endif /* _USEPROTO_H_ */
+