openjade/openjade-1.3-starlink-0.1.patch

1240 lines
38 KiB
Diff

diff -C 2 -r -P openjade-1.3/style/jade_version.h openjade-1.3-starlink-0.1/style/jade_version.h
*** openjade-1.3/style/jade_version.h Thu Oct 14 23:00:35 1999
--- openjade-1.3-starlink-0.1/style/jade_version.h Tue Feb 29 11:06:48 2000
***************
*** 1 ****
! #define JADE_VERSION SP_T("1.3")
--- 1 ----
! #define JADE_VERSION SP_T("1.3-starlink-0.1")
diff -C 2 -r -P openjade-1.3/README.latex openjade-1.3-starlink-0.1/README.latex
*** openjade-1.3/README.latex Thu Jan 1 01:00:00 1970
--- openjade-1.3-starlink-0.1/README.latex Tue Feb 29 11:04:58 2000
***************
*** 0 ****
--- 1,25 ----
+
+ This is a patched version of Jade, which adds a back-end which
+ generates portable LaTeX, in the spirit of the SGML Transformation
+ back-end. The patches should be applied against a distribution copy
+ of openjade-1.3.tar.
+
+ The changes consist of:
+
+ - The addition of the files jade/LaTeX*, and suitable edits elsewhere
+ in that directory;
+ - Updating the version number in style/jade_version.h
+ - Adding documentation in the form of jadedoc/latex.htm
+ - Edits to the configure script to enable support for the new
+ back-end.
+
+ To build:
+
+ ./configure --enable-latex
+ make
+
+
+ Norman Gray
+ http://www.astro.gla.ac.uk/users/norman/
+ 8 February 2000
+
diff -C 2 -r -P openjade-1.3/config/configure.in openjade-1.3-starlink-0.1/config/configure.in
*** openjade-1.3/config/configure.in Wed Sep 1 08:25:58 1999
--- openjade-1.3-starlink-0.1/config/configure.in Tue Feb 29 11:05:23 2000
***************
*** 2,6 ****
dnl configure.in
dnl
! AC_REVISION($Id: configure.in,v 1.8.4.2 1999/09/01 07:25:58 clasen Exp $)
dnl
dnl Process this file with autoconf to produce a configure script.
--- 2,6 ----
dnl configure.in
dnl
! AC_REVISION($Id: configure.in,v 1.2 2000/02/29 11:05:23 norman Exp $)
dnl
dnl Process this file with autoconf to produce a configure script.
***************
*** 152,155 ****
--- 152,168 ----
AC_MSG_RESULT(no))
+
+ dnl
+ dnl Simple LaTeX support
+ dnl (added by norman@astro.gla.ac.uk, 19990514)
+ dnl
+ dnl AC_ARG_ENABLE(latex,
+ dnl [ --enable-latex bind in support for LaTeX-Transform output],
+ dnl if test $enableval
+ dnl then
+ dnl AC_DEFINE(JADE_LATEX)
+ dnl fi)
+
+
dnl
dnl optional backends
***************
*** 157,160 ****
--- 170,174 ----
smr_SWITCH(mif, support for FrameMaker MIF output, on, JADE_MIF)
smr_SWITCH(html, support for HTML+CSS output, on, JADE_HTML)
+ smr_SWITCH(latex, support for LaTeX-Transform output, on, JADE_LATEX)
diff -C 2 -r -P openjade-1.3/jade/LaTeXFOTBuilder.cxx openjade-1.3-starlink-0.1/jade/LaTeXFOTBuilder.cxx
*** openjade-1.3/jade/LaTeXFOTBuilder.cxx Thu Jan 1 01:00:00 1970
--- openjade-1.3-starlink-0.1/jade/LaTeXFOTBuilder.cxx Tue Feb 29 11:05:59 2000
***************
*** 0 ****
--- 1,743 ----
+ // LaTeXFOTBuilder.cxx: a backend for Jade which emits LaTeX code,
+ // for subsequent processing by vanilla LaTeX (ie, not jadetex).
+ //
+ // This file heavily based on (read, simplified from) TransformFOTBuilder.cxx
+ //
+ // Written by Norman Gray <norman@astro.gla.ac.uk>
+ // Copyright (c) 2000 Norman Gray
+
+ #include "config.h"
+ #include "LaTeXFOTBuilder.h"
+ //#include "LaTeXMessages.h"
+ #include "FOTBuilder.h"
+ #include "OutputCharStream.h"
+ #include "MessageArg.h"
+ #include "ErrnoMessageArg.h"
+
+ #include <errno.h>
+
+ #ifdef DSSSL_NAMESPACE
+ namespace DSSSL_NAMESPACE {
+ #endif
+
+ const char RE = '\r';
+
+ class LaTeXFOTBuilder : public SerialFOTBuilder {
+ public:
+ // LaTeX output
+ struct CommandNIC {
+ ~CommandNIC();
+ StringC name;
+ Vector<StringC> parameters;
+ };
+ struct EnvironmentNIC {
+ ~EnvironmentNIC();
+ StringC name;
+ Vector<StringC> brackets;
+ Vector<StringC> parameters;
+ StringC reControl;
+ };
+ class LaTeXExtensionFlowObj : public FOTBuilder::ExtensionFlowObj {
+ public:
+ virtual void atomic(LaTeXFOTBuilder &, const NodePtr &) const = 0;
+ };
+ class LaTeXCompoundExtensionFlowObj : public FOTBuilder::CompoundExtensionFlowObj {
+ public:
+ virtual void start(LaTeXFOTBuilder &, const NodePtr &) const = 0;
+ virtual void end(LaTeXFOTBuilder &) const = 0;
+ };
+ class EmptyCommandFlowObj : public LaTeXExtensionFlowObj {
+ void atomic(LaTeXFOTBuilder &fotb, const NodePtr &nd) const {
+ if (nic_.name.size() > 0)
+ fotb.latexCommand(nic_, false);
+ else {
+ // Make a command of the same name as the current element's GI
+ // Is this a good idea?
+ GroveString str;
+ CommandNIC tem(nic_);
+ tem.name = fotb.makeStringC("UnknownCommand");
+ if (nd && nd->getGi(str) == accessOK) {
+ fotb.insertOptString(tem.parameters, str);
+ //tem.name.assign(str.data(), str.size());
+ fotb.latexCommand(tem, false);
+ }
+ else
+ // Can't find a GI - I'm really _not_ sure this is a good idea!
+ fotb.latexCommand(nic_, false);
+ }
+ }
+ bool hasNIC(const StringC &name) const {
+ return name == "name" || name == "parameters";
+ }
+ void setNIC(const StringC &name, const Value &value) {
+ switch (name[0]) {
+ case 'n':
+ value.convertString(nic_.name);
+ break;
+ case 'p':
+ value.convertStringList(nic_.parameters);
+ break;
+ }
+ }
+ ExtensionFlowObj *copy() const { return new EmptyCommandFlowObj(*this); }
+ private:
+ CommandNIC nic_;
+ };
+ class CommandFlowObj : public LaTeXCompoundExtensionFlowObj {
+ void start(LaTeXFOTBuilder &fotb, const NodePtr &nd) const {
+ if (nic_.name.size() > 0)
+ fotb.latexCommand(nic_, true);
+ else {
+ GroveString str;
+ CommandNIC tem(nic_);
+ tem.name = fotb.makeStringC("UnknownCommand");
+ if (nd && nd->getGi(str) == accessOK) {
+ fotb.insertOptString(tem.parameters, str);
+ //tem.name.assign(str.data(), str.size());
+ fotb.latexCommand(tem, true);
+ }
+ else
+ fotb.latexCommand(nic_, true);
+ }
+ }
+ void end(LaTeXFOTBuilder &fotb) const {
+ fotb.endLatexCommand();
+ }
+ bool hasNIC(const StringC &name) const {
+ return name == "name" || name == "parameters";
+ }
+ void setNIC(const StringC &name, const Value &value) {
+ switch (name[0]) {
+ case 'n':
+ value.convertString(nic_.name);
+ break;
+ case 'p':
+ value.convertStringList(nic_.parameters);
+ break;
+ }
+ }
+ ExtensionFlowObj *copy() const { return new CommandFlowObj(*this); }
+ private:
+ CommandNIC nic_;
+ };
+ class EnvironmentFlowObj : public LaTeXCompoundExtensionFlowObj {
+ void start(LaTeXFOTBuilder &fotb, const NodePtr &nd) const {
+ if (nic_.name.size() > 0)
+ fotb.startEnvironment(nic_);
+ else {
+ GroveString str;
+ EnvironmentNIC tem(nic_);
+ tem.name = fotb.makeStringC("UnknownEnvironment");
+ if (nd && nd->getGi(str) == accessOK) {
+ fotb.insertOptString(tem.parameters, str);
+ //tem.name.assign(str.data(), str.size());
+ fotb.startEnvironment(tem);
+ }
+ else {
+ fotb.startEnvironment(tem);
+ }
+ }
+ }
+ void end(LaTeXFOTBuilder &fotb) const {
+ fotb.endEnvironment();
+ }
+ bool hasNIC(const StringC &name) const {
+ return name == "name" || name == "parameters" ||
+ name == "brackets" || name == "recontrol";
+ }
+ void setNIC(const StringC &name, const Value &value) {
+ switch (name[0]) {
+ case 'n':
+ value.convertString(nic_.name);
+ break;
+ case 'p':
+ value.convertStringList(nic_.parameters);
+ break;
+ case 'b':
+ value.convertStringList(nic_.brackets);
+ break;
+ case 'r':
+ value.convertString(nic_.reControl);
+ break;
+ }
+ }
+ ExtensionFlowObj *copy() const { return new EnvironmentFlowObj(*this); }
+ private:
+ EnvironmentNIC nic_;
+ };
+ class EntityFlowObj : public LaTeXCompoundExtensionFlowObj {
+ void start(LaTeXFOTBuilder &fotb, const NodePtr &) const {
+ fotb.startEntity(systemId_);
+ }
+ void end(LaTeXFOTBuilder &fotb) const {
+ fotb.endEntity();
+ }
+ bool hasNIC(const StringC &name) const {
+ return name == "system-id";
+ }
+ void setNIC(const StringC &name, const Value &value) {
+ value.convertString(systemId_);
+ }
+ ExtensionFlowObj *copy() const { return new EntityFlowObj(*this); }
+ private:
+ StringC systemId_;
+ };
+ LaTeXFOTBuilder(CmdLineApp *);
+ ~LaTeXFOTBuilder();
+ void startEnvironment(const EnvironmentNIC &);
+ void endEnvironment();
+ void latexCommand(const CommandNIC &, bool);
+ void endLatexCommand();
+ void startEntity(const StringC &);
+ void endEntity();
+ void characters(const Char *s, size_t n);
+ void charactersFromNode(const NodePtr &, const Char *, size_t);
+ void extension(const ExtensionFlowObj &fo, const NodePtr &);
+ void formattingInstruction(const StringC &);
+
+ // Non-extension flow-objects
+ void startParagraph(const ParagraphNIC &);
+ void endParagraph();
+ //void setParagraphNIC(const ParagraphNIC &);
+
+ void startExtensionSerial(const CompoundExtensionFlowObj &fo, const NodePtr &nd);
+ void endExtensionSerial(const CompoundExtensionFlowObj &fo);
+ void start();
+ void end();
+ StringC LaTeXFOTBuilder::makeStringC(const char *s);
+ void LaTeXFOTBuilder::insertOptString(Vector<StringC> &arr, GroveString str);
+ void setEscapeTeX(bool);
+
+ private:
+ LaTeXFOTBuilder(const LaTeXFOTBuilder &);
+ void operator=(const LaTeXFOTBuilder &);
+
+ OutputCharStream &os() { return *os_; }
+ void parameters(const Vector<StringC> &params);
+ // Support removed from TransformFOTBuilder
+ // flushPendingRe(): not needed - space is gen. less significant in LaTeX
+
+ CmdLineApp *app_;
+ OutputCharStream *os_;
+ Owner<OutputCharStream> topOs_;
+ struct environmentState {
+ ~environmentState();
+ StringC str;
+ bool isEnv;
+ bool reBefore, reMiddle, reEnd;
+ };
+ //Vector<StringC> openEnvironments_;
+ Vector<environmentState> openEnvironments_;
+ StringC undefGi_;
+ struct OpenFile : Link {
+ ~OpenFile();
+ OutputCharStream *saveOs;
+ // fb must be before os so it gets destroyed afterwards
+ FileOutputByteStream fb;
+ Owner<OutputCharStream> os;
+ StringC systemId;
+ };
+ IList<OpenFile> openFileStack_;
+ bool midLine_;
+ bool escapeTeX_;
+ bool internalREs_;
+ // internalREs_ controls whether routines below can freely insert REs
+ // where allowed by LaTeX. Currently, it merely shadows escapeTeX_.
+ // If escapeTeX_ is false, the style is possibly
+ // generating some sort of `verbatim' environment, where it wouldn't want
+ // this code monkeying with the line-breaking. Perhaps solve this by
+ // making ReControl (or similar) be an inherited characteristic like
+ // escapeTeX_
+
+ // really Vector<bool> (I'm copying this from TransformFOTBuilder.cxx!)
+ StringC escapeTeXStack_;
+ void message(const MessageType0 &);
+ };
+
+ FOTBuilder *makeLaTeXFOTBuilder(CmdLineApp *app,
+ const FOTBuilder::Extension *&ext)
+ {
+ static const LaTeXFOTBuilder::EmptyCommandFlowObj emptycommand;
+ static const LaTeXFOTBuilder::CommandFlowObj command;
+ static const LaTeXFOTBuilder::EnvironmentFlowObj environment;
+ static const LaTeXFOTBuilder::EntityFlowObj entity;
+ static const FOTBuilder::Extension extensions[] = {
+ {
+ "UNREGISTERED::Norman Gray//Flow Object Class::environment",
+ 0,
+ 0,
+ 0,
+ 0,
+ &environment
+ },
+ {
+ "UNREGISTERED::Norman Gray//Flow Object Class::command",
+ 0,
+ 0,
+ 0,
+ 0,
+ &command
+ },
+ {
+ "UNREGISTERED::Norman Gray//Flow Object Class::empty-command",
+ 0,
+ 0,
+ 0,
+ 0,
+ &emptycommand
+ },
+ {
+ "UNREGISTERED::James Clark//Flow Object Class::entity",
+ 0,
+ 0,
+ 0,
+ 0,
+ &entity
+ },
+ {
+ "UNREGISTERED::Norman Gray//Characteristic::escape-tex?",
+ (void (FOTBuilder::*)(bool))&LaTeXFOTBuilder::setEscapeTeX,
+ 0,
+ 0,
+ 0,
+ 0,
+ },
+ { 0 }
+ };
+ ext = extensions;
+ return new LaTeXFOTBuilder(app);
+ }
+
+ static
+ void outputNumericCharRef(OutputCharStream &os, Char c)
+ {
+ os << "\\char" << (unsigned long)c << ' ';
+ }
+
+ LaTeXFOTBuilder::LaTeXFOTBuilder(CmdLineApp *app)
+ : app_(app),
+ topOs_(new RecordOutputCharStream(app->makeStdOut())),
+ escapeTeX_(1), internalREs_(1)
+ {
+ undefGi_ = app_->systemCharset().execToDesc("#UNDEF");
+ topOs_->setEscaper(outputNumericCharRef);
+ os_ = topOs_.pointer();
+ escapeTeXStack_ += 0;
+ }
+
+ LaTeXFOTBuilder::~LaTeXFOTBuilder()
+ {
+ }
+
+ static bool contains(const StringC &str, Char c)
+ {
+ for (size_t i = 0; i < str.size(); i++)
+ if (str[i] == c)
+ return 1;
+ return 0;
+ }
+
+ // Insert %+RE where possible, and when internalREs_ is true.
+ void LaTeXFOTBuilder::parameters(const Vector<StringC> &params)
+ {
+ for (size_t i = 0; i < params.size(); i ++) {
+ // If the parameter starts with ?, it's written as an optional
+ // parameter, after stripping the ?. If it starts with !, it's written
+ // as a required parameter (thus allowing you to start parameter values
+ // with ?. Otherwise, it's written as a required parameter.
+ size_t len = params[i].size();
+ const Char *s = params[i].data();
+ bool optional;
+ if (i != 0 && internalREs_)
+ {
+ os() << '%' << RE;
+ midLine_ = false;
+ }
+
+ if (*s == '?')
+ {
+ optional = true;
+ s++;
+ len--;
+ } else if (*s == '!') {
+ optional = false;
+ s++;
+ len--;
+ } else
+ optional = false;
+
+ os() << (optional ? '[' : '{');
+ midLine_ = true;
+ characters(s, len);
+ os() << (optional ? ']' : '}');
+ midLine_ = true;
+ }
+ }
+
+ // Should internalREs_ override the default here?
+ void LaTeXFOTBuilder::startEnvironment(const EnvironmentNIC &nic)
+ {
+ environmentState env;
+ if (nic.reControl.size() == 3) {
+ env.reBefore = (nic.reControl[0] == '/');
+ env.reMiddle = (nic.reControl[1] == '/');
+ env.reEnd = (nic.reControl[2] == '/');
+ }
+ else {
+ env.reBefore = false;
+ env.reMiddle = true;
+ env.reEnd = false;
+ }
+ if (nic.brackets.size() == 2) {
+ os() << nic.brackets[0];
+ env.str = nic.brackets[1];
+ env.isEnv = false;
+ openEnvironments_.push_back(env);
+ }
+ else {
+ const StringC &s = nic.name.size() == 0 ? undefGi_ : nic.name;
+ if (env.reBefore && midLine_)
+ os() << RE;
+ os() << "\\begin";
+ if (env.reMiddle)
+ os() << RE;
+ os() << '{';
+ midLine_ = true;
+ characters(s.data(), s.size());
+ os() << '}'; // os() << '{' << s << '}';
+ if (env.reEnd)
+ {
+ os() << RE;
+ midLine_ = false;
+ } else
+ midLine_ = true;
+ parameters(nic.parameters);
+ env.str = s;
+ env.isEnv = true;
+ openEnvironments_.push_back (env);
+ }
+ start();
+ }
+
+ void LaTeXFOTBuilder::latexCommand(const CommandNIC &nic, bool hasContent)
+ {
+ const StringC &s = nic.name.size() == 0 ? undefGi_ : nic.name;
+ os() << '\\' << s;
+ if (internalREs_)
+ {
+ os() << RE;
+ midLine_ = false;
+ }
+ parameters(nic.parameters);
+ if (hasContent) {
+ os() << '{';
+ start();
+ }
+ else
+ atomic();
+ }
+
+ void LaTeXFOTBuilder::endLatexCommand()
+ {
+ // only called when command has content
+ os() << '}';
+ end();
+ }
+
+ void LaTeXFOTBuilder::endEnvironment()
+ {
+ environmentState env = openEnvironments_.back();
+ openEnvironments_.resize(openEnvironments_.size() - 1);
+ if (env.isEnv) {
+ if (env.reBefore && midLine_)
+ os() << RE;
+ os() << "\\end";
+ if (env.reMiddle)
+ os() << RE;
+ os() << '{' << env.str << '}';
+ if (env.reEnd)
+ {
+ os() << RE;
+ midLine_ = false;
+ } else
+ midLine_ = true;
+ }
+ else
+ os() << env.str;
+ end();
+ }
+
+ void LaTeXFOTBuilder::formattingInstruction(const StringC &s)
+ {
+ //flushPendingRe();
+ os() << s;
+ }
+
+ void LaTeXFOTBuilder::startEntity(const StringC &systemId)
+ {
+ //flushPendingRe();
+ OpenFile *ofp = new OpenFile;
+ openFileStack_.insert(ofp);
+ ofp->systemId = systemId;
+ ofp->saveOs = os_;
+ String<CmdLineApp::AppChar> filename;
+ #ifdef SP_WIDE_SYSTEM
+ filename = systemId;
+ #else
+ filename = app_->codingSystem()->convertOut(systemId);
+ #endif
+ if (filename.size()) {
+ filename += 0;
+ if (!ofp->fb.open(filename.data())) {
+ app_->message(CmdLineApp::openFileErrorMessage(),
+ StringMessageArg(systemId),
+ ErrnoMessageArg(errno));
+ }
+ else {
+ ofp->os
+ = new RecordOutputCharStream(
+ new EncodeOutputCharStream(&ofp->fb,
+ app_->outputCodingSystem()));
+ ofp->os->setEscaper(outputNumericCharRef);
+ os_ = ofp->os.pointer();
+ }
+ }
+ }
+
+ void LaTeXFOTBuilder::endEntity()
+ {
+ //flushPendingRe();
+ OpenFile &of = *openFileStack_.head();
+ if (of.os) {
+ errno = 0;
+ of.os->flush();
+ if (!of.fb.close())
+ app_->message(CmdLineApp::closeFileErrorMessage(),
+ StringMessageArg(of.systemId),
+ ErrnoMessageArg(errno));
+ }
+ os_ = of.saveOs;
+ delete openFileStack_.get();
+ }
+
+ inline
+ OutputCharStream &operator<<(OutputCharStream &os, GroveString &str)
+ {
+ return os.write(str.data(), str.size());
+ }
+
+ void LaTeXFOTBuilder::charactersFromNode(const NodePtr &nd, const Char *s, size_t n)
+ {
+ GroveString name;
+ GroveString text;
+ NodePtr entity;
+ const char quot = '"';
+ #if 0
+ if (n == 1
+ && *s == 0xFFFD
+ && nd->getEntityName(name) == accessOK
+ && nd->getEntity(entity) == accessOK
+ && entity->getText(text) == accessOK)
+ os() << "<sdata name=" << quot << Data(name.data(), name.size()) << quot
+ << " text=" << quot << Data(text.data(), text.size()) << quot
+ << "/>" << RE;
+ else
+ #endif
+ LaTeXFOTBuilder::characters(s, n);
+ #if 0
+ GroveString name;
+ // If the node is an SDATA node, then emit its contents verbatim.
+ // Is this the correct thing to do? The Transform back-end doesn't
+ // do this, but it produces what looks like a multibyte character
+ // reference when presented with SDATA entities, and that doesn't
+ // look right at all....
+ //
+ // The following appears to work with SDATA entities in most cases,
+ // but when an SDATA entity appears in a context such as
+ // (element dt
+ // (make empty-command name: "item"
+ // parameters: (list (string-append "?" (data (current-node))))))
+ // then what actually appears is \char65533, apparently irrespective
+ // of the value of the entity. In other words, it's very similar
+ // behaviour to the Transform back-end. A workaround is to define
+ // the putative SDATA entities to be CDATA entities.
+ if (n == 1 && nd->getSystemData(name) == accessOK)
+ os() << name;
+ else
+ LaTeXFOTBuilder::characters(s, n);
+ #endif
+ }
+
+ // Write out characters, escaping TeX non-letters. Use midLine_ to
+ // keep a little state: suppress blank lines and leading blanks (the
+ // first is necessary to avoid spurious paragraphs, the second simply
+ // seems like a Good Idea, and safe in principle). Note that this
+ // mechanism is probably breakable, since other parts of this class
+ // write stuff to os as well. If there is a problem, then either the
+ // mechanism should be implemented within OutputCharStream (or at
+ // least within os()), or the routine shouldn't try to skip the
+ // blanks.
+ void LaTeXFOTBuilder::characters(const Char *s, size_t n)
+ {
+ if (n == 0)
+ return;
+ // Following lifted with adaptations from TeXFOTBuilder
+ for (; n > 0; n--, s++) { // Since TeX has only 256 characters
+ // by default, two-byte characters
+ // will need special treatment.
+ if (*s > 255) {
+ // Don't complicate matters, just give the character!
+ os() << "\\char" << (unsigned long)(*s) << ' ';
+ midLine_ = true;
+ } else { // Otherwise, check for special
+ // TeX escapes.
+ switch(*s) {
+ default:
+ os() << char(*s);
+ midLine_ = true;
+ break;
+
+ case ' ':
+ case '\t':
+ // Don't try to suppress leading whitespace, since this pointlessly
+ // complicates things (eg, it needs to be suppressed inside
+ // verbatim output).
+ //if (midLine_)
+ os() << ' ';
+ break;
+
+ case '\\': // TeX special characters
+ case '^':
+ case '_':
+ case '~':
+ if (escapeTeX_)
+ os() << "\\char" << int(*s) << "{}";
+ else
+ os() << char(*s);
+ midLine_ = true;
+ break;
+
+ case '{':
+ case '}':
+ case '$':
+ case '&':
+ case '#':
+ case '%':
+ if (escapeTeX_)
+ os() << "\\" << char(*s);
+ else
+ os() << char(*s);
+ midLine_ = true;
+ break;
+
+ case '\r':
+ case '\n':
+ if (midLine_ || !escapeTeX_)
+ os() << RE;
+ midLine_ = false;
+ break;
+ }
+ }
+ }
+ // No need for anything fancy here. I stripped out the state_ mechanism
+ // from TransformFOTBuilder, because I don't think it's necessary for LaTeX
+ //os().put(*s);
+ //os().write(s, n);
+ }
+
+ StringC LaTeXFOTBuilder::makeStringC(const char *s)
+ {
+ StringC tem;
+ if (s)
+ while (*s)
+ tem += (unsigned char)*s++;
+ return tem;
+ }
+
+ void LaTeXFOTBuilder::insertOptString(Vector<StringC> &arr, GroveString str)
+ {
+ arr.resize(arr.size()+1);
+ for (size_t i=arr.size()-1; i>0; i--)
+ arr[i] = arr[i-1];
+ arr[0] = makeStringC("?");
+ arr[0].append(str.data(), str.size());
+ }
+
+ void LaTeXFOTBuilder::extension(const ExtensionFlowObj &fo, const NodePtr &nd)
+ {
+ ((const LaTeXExtensionFlowObj &)fo).atomic(*this, nd);
+ }
+
+ void LaTeXFOTBuilder::startExtensionSerial(const CompoundExtensionFlowObj &fo, const NodePtr &nd)
+ {
+ ((const LaTeXCompoundExtensionFlowObj &)fo).start(*this, nd);
+ }
+
+ void LaTeXFOTBuilder::endExtensionSerial(const CompoundExtensionFlowObj &fo)
+ {
+ ((const LaTeXCompoundExtensionFlowObj &)fo).end(*this);
+ }
+
+ void LaTeXFOTBuilder::message(const MessageType0 &msg)
+ {
+ app_->message(msg);
+ }
+
+ void LaTeXFOTBuilder::startParagraph(const ParagraphNIC &nic)
+ {
+ start();
+ //setParagraphNIC(nic);
+ }
+
+ void LaTeXFOTBuilder::endParagraph()
+ {
+ CommandNIC par;
+ par.name = makeStringC("par");
+ latexCommand(par, false);
+ end();
+ }
+
+ // void LaTeXFOTBuilder::setParagraphNIC(const ParagraphNIC &nic)
+ // {
+ // setDisplayNIC(nic);
+ // }
+
+ void LaTeXFOTBuilder::setEscapeTeX(bool b)
+ {
+ escapeTeX_ = b;
+ internalREs_ = escapeTeX_; // have this simply shadow escapeTeX_
+ }
+
+ void LaTeXFOTBuilder::start()
+ {
+ escapeTeXStack_ += Char(escapeTeX_);
+ }
+
+ void LaTeXFOTBuilder::end()
+ {
+ escapeTeXStack_.resize(escapeTeXStack_.size() - 1);
+ escapeTeX_ = bool(escapeTeXStack_[escapeTeXStack_.size() - 1]);
+ internalREs_ = escapeTeX_;
+ }
+
+ LaTeXFOTBuilder::OpenFile::~OpenFile()
+ {
+ }
+
+ LaTeXFOTBuilder::environmentState::~environmentState()
+ {
+ }
+
+ LaTeXFOTBuilder::CommandNIC::~CommandNIC()
+ {
+ }
+
+ LaTeXFOTBuilder::EnvironmentNIC::~EnvironmentNIC()
+ {
+ }
+
+ #ifdef DSSSL_NAMESPACE
+ }
+ #endif
+
+ #include "LaTeXFOTBuilder_inst.cxx"
diff -C 2 -r -P openjade-1.3/jade/LaTeXFOTBuilder.h openjade-1.3-starlink-0.1/jade/LaTeXFOTBuilder.h
*** openjade-1.3/jade/LaTeXFOTBuilder.h Thu Jan 1 01:00:00 1970
--- openjade-1.3-starlink-0.1/jade/LaTeXFOTBuilder.h Tue Feb 29 11:05:59 2000
***************
*** 0 ****
--- 1,20 ----
+ // Copyright (c) 1999 Norman Gray
+
+ #ifndef LaTeXFOTBuilder_INCLUDED
+ #define LaTeXFOTBuilder_INCLUDED 1
+
+ #include "FOTBuilder.h"
+ #include "CmdLineApp.h"
+
+ #ifdef DSSSL_NAMESPACE
+ namespace DSSSL_NAMESPACE {
+ #endif
+
+ FOTBuilder *makeLaTeXFOTBuilder(CmdLineApp *app,
+ const FOTBuilder::Extension *&);
+
+ #ifdef DSSSL_NAMESPACE
+ }
+ #endif
+
+ #endif /* not LaTeXFOTBuilder_INCLUDED */
diff -C 2 -r -P openjade-1.3/jade/LaTeXFOTBuilder_inst.m4 openjade-1.3-starlink-0.1/jade/LaTeXFOTBuilder_inst.m4
*** openjade-1.3/jade/LaTeXFOTBuilder_inst.m4 Thu Jan 1 01:00:00 1970
--- openjade-1.3-starlink-0.1/jade/LaTeXFOTBuilder_inst.m4 Tue Feb 29 11:05:59 2000
***************
*** 0 ****
--- 1,24 ----
+ // Copyright (c) 1997 James Clark
+ // See the file COPYING for copying permission.
+
+ #include "config.h"
+
+ #ifdef SP_MANUAL_INST
+
+ #define SP_DEFINE_TEMPLATES
+ #include "IList.h"
+ #include "Vector.h"
+ #undef SP_DEFINE_TEMPLATES
+
+ #ifdef DSSSL_NAMESPACE
+ namespace DSSSL_NAMESPACE {
+ #endif
+
+ __instantiate(IList<LaTeXFOTBuilder::OpenFile>)
+ __instantiate(Vector<LaTeXFOTBuilder::environmentState>)
+
+ #ifdef DSSSL_NAMESPACE
+ }
+ #endif
+
+ #endif /* SP_MANUAL_INST */
diff -C 2 -r -P openjade-1.3/jade/Makefile.sub openjade-1.3-starlink-0.1/jade/Makefile.sub
*** openjade-1.3/jade/Makefile.sub Mon Aug 30 11:25:22 1999
--- openjade-1.3-starlink-0.1/jade/Makefile.sub Tue Feb 29 11:05:59 2000
***************
*** 1,5 ****
PROG=openjade
OBJS=jade.o SgmlFOTBuilder.o RtfFOTBuilder.o HtmlFOTBuilder.o \
! TeXFOTBuilder.o TransformFOTBuilder.o MifFOTBuilder.o
INCLUDE=-I$(srcdir)/../grove -I$(srcdir)/../spgrove -I$(srcdir)/../style
XLIBS=../style/libostyle.a ../spgrove/libospgrove.a ../grove/libogrove.a \
--- 1,5 ----
PROG=openjade
OBJS=jade.o SgmlFOTBuilder.o RtfFOTBuilder.o HtmlFOTBuilder.o \
! TeXFOTBuilder.o TransformFOTBuilder.o MifFOTBuilder.o LaTeXFOTBuilder.o
INCLUDE=-I$(srcdir)/../grove -I$(srcdir)/../spgrove -I$(srcdir)/../style
XLIBS=../style/libostyle.a ../spgrove/libospgrove.a ../grove/libogrove.a \
***************
*** 7,11 ****
GENSRCS=JadeMessages.h HtmlMessages.h RtfMessages.h TeXMessages.h \
HtmlFOTBuilder_inst.cxx RtfFOTBuilder_inst.cxx TeXFOTBuilder_inst.cxx \
! TransformFOTBuilder_inst.cxx MifMessages.h MifFOTBuilder_inst.cxx
HtmlFOTBuilder.o: HtmlFOTBuilder_inst.cxx HtmlMessages.h
--- 7,12 ----
GENSRCS=JadeMessages.h HtmlMessages.h RtfMessages.h TeXMessages.h \
HtmlFOTBuilder_inst.cxx RtfFOTBuilder_inst.cxx TeXFOTBuilder_inst.cxx \
! TransformFOTBuilder_inst.cxx MifMessages.h MifFOTBuilder_inst.cxx \
! LaTeXFOTBuilder_inst.cxx
HtmlFOTBuilder.o: HtmlFOTBuilder_inst.cxx HtmlMessages.h
***************
*** 14,16 ****
--- 15,18 ----
MifFOTBuilder.o: MifFOTBuilder_inst.cxx MifMessages.h
TransformFOTBuilder.o: TransformFOTBuilder_inst.cxx
+ LaTeXFOTBuilder.o: LaTeXFOTBuilder_inst.cxx
jade.o: JadeMessages.h
diff -C 2 -r -P openjade-1.3/jade/jade.cxx openjade-1.3-starlink-0.1/jade/jade.cxx
*** openjade-1.3/jade/jade.cxx Sun Oct 17 21:37:39 1999
--- openjade-1.3-starlink-0.1/jade/jade.cxx Tue Feb 29 11:05:59 2000
***************
*** 14,17 ****
--- 14,20 ----
#include "MifFOTBuilder.h"
#endif
+ #ifdef JADE_LATEX
+ #include "LaTeXFOTBuilder.h"
+ #endif
#include "OutputCharStream.h"
#include "macros.h"
***************
*** 42,45 ****
--- 45,51 ----
mifType,
#endif
+ #ifdef JADE_LATEX
+ latexType,
+ #endif
sgmlType, xmlType };
static const AppChar *const outputTypeNames[];
***************
*** 60,63 ****
--- 66,72 ----
SP_T("mif"),
#endif
+ #ifdef JADE_LATEX
+ SP_T("latex"),
+ #endif
SP_T("sgml"),
SP_T("xml")
***************
*** 68,71 ****
--- 77,87 ----
{
registerOption('t',
+ #ifdef JADE_LATEX
+ #ifdef JADE_MIF
+ SP_T("(fot|rtf|tex|mif|latex|sgml|xml)")
+ #else
+ SP_T("(fot|rtf|tex|latex|sgml|xml)")
+ #endif
+ #else
#ifdef JADE_MIF
SP_T("(fot|rtf|tex|mif|sgml|xml)")
***************
*** 73,76 ****
--- 89,93 ----
SP_T("(fot|rtf|tex|sgml|xml)")
#endif
+ #endif
);
registerOption('o', SP_T("output_file"));
***************
*** 145,148 ****
--- 162,168 ----
case htmlType:
#endif
+ #ifdef JADE_LATEX
+ case latexType:
+ #endif
case sgmlType:
case xmlType:
***************
*** 172,175 ****
--- 192,199 ----
return makeMifFOTBuilder(outputFilename_, entityManager(), systemCharset(), this, exts);
#endif /* JADE_MIF */
+ #ifdef JADE_LATEX
+ case latexType:
+ return makeLaTeXFOTBuilder(this, exts);
+ #endif /* JADE_LATEX */
case fotType:
return makeSgmlFOTBuilder(new RecordOutputCharStream(new EncodeOutputCharStream(&outputFile_,
diff -C 2 -r -P openjade-1.3/jadedoc/index.htm openjade-1.3-starlink-0.1/jadedoc/index.htm
*** openjade-1.3/jadedoc/index.htm Sun Oct 17 21:37:40 1999
--- openjade-1.3-starlink-0.1/jadedoc/index.htm Mon Mar 13 13:27:47 2000
***************
*** 61,64 ****
--- 61,66 ----
<li><a href="transform.htm"><font
face="Arial">SGML Transformation</font></a></li>
+ <li><a href="latex.htm"><font
+ face="Arial">LaTeX</font></a></li>
</ul>
</li>
diff -C 2 -r -P openjade-1.3/jadedoc/latex.htm openjade-1.3-starlink-0.1/jadedoc/latex.htm
*** openjade-1.3/jadedoc/latex.htm Thu Jan 1 01:00:00 1970
--- openjade-1.3-starlink-0.1/jadedoc/latex.htm Tue Feb 29 11:06:06 2000
***************
*** 0 ****
--- 1,220 ----
+ <!-- -*- sgml -*- -->
+ <!doctype html public "-//W3C//DTD HTML 3.2//EN">
+ <!-- $Id: latex.htm,v 1.1 2000/02/29 11:06:06 norman Exp $ -->
+
+ <title>Using Jade to generate LaTeX</title>
+
+ <body bgcolor="#ffffff">
+ <h1>Using Jade to generate LaTeX</h1>
+
+ <p><ul>
+ <li><a href="#fo">Flow object extensions</a>
+ <li><a href="#para">Paragraphs and white space</a>
+ <li><a href="#bug">Bugs</a>
+ </ul>
+
+ <p>Jade's <a href="TeX.htm">TeX back-end</a> supports (a subset of)
+ the DSSSL style language, but it requires a special version of TeX.
+ This document describes an alternative approach, using a LaTeX
+ back-end to generate arbitrary LaTeX, in the spirit of Jade's
+ <em>transformation</em> back-end. That is, rather than doing the
+ styling within Jade, using the DSSSL style language, we transform the
+ SGML document into (more-or-less) high-level LaTeX markup, and do all
+ the formatting within LaTeX. You can generate LaTeX using the
+ transformation back-end plus a lot of <code>(literal ...)</code>, but
+ that's rather errorprone, and has potential whitespace problems.
+
+ <p>This approach means that (a) you can generate LaTeX which is itself
+ distributable because it doesn't rely on a particular TeX setup, and
+ (b) you can offload the formatting magic into a LaTeX class, which
+ might be more confortable for you. This approach runs counter to
+ DSSSL's supposedly central virtue, of generating high-quality print
+ output from a format-independent stylesheet. However, as the SGML
+ Transformation back-end has shown, Jade and the DSSSL Style Language
+ together make a powerful general SGML processor, which needn't be
+ limited to final (ie, immediately printable) versions of documents.
+
+ <p>With the patched sources, the version reported by <code>jade
+ -v</code> is `<code>Jade version "1.3-starlink-0.1"</code>'
+
+ <h2><a name="fo">Flow object extensions</a></h2>
+
+ <p>The extensions described here are available in conjunction with the
+ LaTeX back-end, selected with the <code>-t latex</code> option. This
+ requires an appropriately patched version of Jade, built with the
+ <code>--enable-latex</code> option to <code>./configure</code>.
+
+ <p>The extensions, the code which supports them, and even
+ this documentation, are closely based on James Clark's <a
+ href="transform.htm">SGML Transformation back-end</a> (qv).
+
+ <dl>
+ <dt><code>command</code> and <code>empty-command</code>
+ <dd>These flow objects result in LaTeX commands in the output.
+ <code>command</code> is a compound flow object, whilst
+ <code>empty-command</code> is an atomic flow object (it may not have
+ child flow objects). Both flow objects have the following non-inherited
+ characteristics:
+ <dl>
+ <dt><code>name</code>
+ <dd>This is a string-valued characteristic that specifies the name
+ of the environment. It defaults to the generic identifier of the
+ current node.
+
+ <dt><code>parameters</code>
+ <dd>This specifies the command's parameters as a list of
+ strings. If the parameter string starts with a `?' character, the
+ parameter value is the remainder of the string, written as an
+ optional parameter. If the parameter string starts with `!', it is
+ written as a required parameter, allowing you to start parameter
+ values with a `?' character.
+ <p>For example, the following would generate the documentclass line
+ at the beginning of a LaTeX file:
+ <pre>
+ (make empty-command name: "documentclass"
+ parameters: (list "?a4paper" "article"))
+ </pre>
+ </dl>
+
+ <p>The difference between the two
+ flow objects is that the content of the <code>command</code> flow
+ object appears as the command's final parameter. Thus, the following
+ are equivalent:
+ <pre>
+ (element em
+ (make command name: "emph"
+ (process-children)))
+ </pre>
+ and
+ <pre>
+ (element em
+ (make empty-command name: "emph"
+ parameters: (list (data (current-node)))))
+ </pre>
+
+ <dt><code>environment</code>
+ <dd>This flow object results in an environment in the output. It is a
+ compound flow object (it can have child flow objects). It has the
+ following non-inherited characteristics:
+
+ <dl>
+ <dt><code>name</code>
+ <dd>As for <code>command</code>
+
+ <dt><code>parameters</code>
+ <dd>As for <code>command</code>
+
+ <dt><code>brackets</code>
+ <dd>This allows you to specify explicitly what the beginning and end
+ of the environment should be. The characteristic's value is a list
+ consisting of two strings, the first of which is inserted at the
+ beginning, and the second at the end, of the environment. For
+ example, you might specify that an element type
+ <code>equation</code> should be transformed into a LaTeX equation
+ via a flow object constructor such as:
+ <pre>
+ (element mequation
+ (make environment brackets: '("\\[" "\\]")
+ (process-children)))
+ </pre>
+
+ <dt><code>recontrol</code>
+ <dd>The LaTeX generated by the back-end has line-breaks inserted to
+ avoid the lines becoming too long. If these are inappropriate for
+ some reason, you can override the line-breaking by giving a value to
+ the <code>recontrol</code> characteristic. Its value is a string
+ with three characters, controlling the line-breaking before, in the
+ middle of (ie, between the <code>\\begin</code> and the environment
+ name), and after the opening and closing of the environment. If the
+ corresponding character is `/' a RE is inserted at the appropriate
+ point; if it is `-', no RE is inserted. For example, a
+ <code>verbatim</code> element type might be supported via:
+ <pre>
+ (element verbatim
+ (make environment
+ name: "verbatim"
+ recontrol: "/-/"
+ (process-children)))
+ </pre>
+ Thus, the <code>\\begin{verbatim}</code> and
+ <code>\\end{verbatim}</code> will be on lines by themselves, with no
+ RE between the <code>\\begin</code> or <code>\\end</code> and the
+ environment name.
+
+ </dl>
+
+ </dl>
+
+ <p>The <code>entity</code> and <code>formatting-instruction</code>
+ flow object classes are available exactly as in the <a
+ href="transform.htm">SGML transformation back-end</a>.
+
+ <p>In addition, there is also the following characteristic:
+ <dl>
+ <dt><code>escape-tex?</code>
+ <dd>This is an inherited boolean characteristic. When true (the
+ default), characters which are significant to LaTeX, such as
+ backslashes or dollar signs, are escaped on output. If false, this
+ escaping is turned off.
+ <p>For example, the <code>verbatim</code> element type mentioned above
+ would best be implemented as:
+ <pre>
+ (element verbatim
+ (make environment
+ name: "verbatim"
+ recontrol: "/-/"
+ escape-tex?: #f
+ (process-children)))
+ </pre>
+ </dl>
+
+ <p>These classes must be declared using
+ <code>declare-flow-object-class</code> in any DSSSL specification that
+ makes use of them. A suitable set of declarations is:
+ <pre>
+ (declare-flow-object-class command
+ "UNREGISTERED::Norman Gray//Flow Object Class::command")
+ (declare-flow-object-class empty-command
+ "UNREGISTERED::Norman Gray//Flow Object Class::empty-command")
+ (declare-flow-object-class environment
+ "UNREGISTERED::Norman Gray//Flow Object Class::environment")
+ (declare-characteristic escape-tex?
+ "UNREGISTERED::Norman Gray//Characteristic::escape-tex?"
+ #t)
+ </pre>
+
+ <h2><a name="para">Paragraphs and white space</a></h2>
+
+ <p>The back-end attempts to suppress redundant whitespace. It
+ removes blank lines, because they could insert spurious paragraphs.
+ Paragraphs are delimited purely by <code>\\par</code> commands. The
+ back-end provides minimal support for the <code>paragraph</code>
+ flow object class, so you should support paragraph elements with a
+ construction like:
+ <pre>
+ (element para
+ (make paragraph
+ (process-children)))
+ </pre>
+
+ <p>The suppression of blank lines is not terribly sophisticated (it should
+ really be supported at a slightly lower level than it is), and I would
+ be grateful to hear of any problems with it. If there are problems,
+ a workaround is to insert a command <code>\\catcode`\\^^M=10</code>
+ near the beginning of the LaTeX file. This will cause all newlines to
+ be interpreted as simple spaces, so that blank lines will no longer be
+ interpreted as delimiting paragraphs.
+
+ <h2><a name="bug">Bugs</a></h2>
+
+ <p>This is a patch to the official openjade release. I've submitted
+ the patch to the openjade team, but unless and until it's incorporated
+ into the main distribution, any bugs in the LaTeX support should be
+ reported to me rather than to them.
+
+ <div align=right>
+ <p><address>
+ <a href="http://www.astro.gla.ac.uk/users/norman/" >Norman Gray</a><br>
+ 9 February 2000
+ </address>
+ </div>