1240 lines
38 KiB
Diff
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> ¶ms);
|
|
+ // 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> ¶ms)
|
|
+ {
|
|
+ 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>
|