home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / tex / lametex_.z / lametex_ / lametex / src / Document.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-02  |  9.2 KB  |  300 lines

  1. /* Document.C
  2.  *
  3.  * Of all the parameters, those in the derived class Document are probably
  4.  * the most basic. Calls to class Document routines can usually be resolved
  5.  * directly into some simple PostScript output involving no nesting.
  6.  *
  7.  * Copyright 1992 Jonathan Monsarrat. Permission given to freely distribute,
  8.  * edit and use as long as this copyright statement remains intact.
  9.  *
  10.  */
  11.  
  12. #include "Operator.h"
  13. #include "Global.h"
  14. #include "Document.h"
  15. #include "Font.h"
  16. #include <string.h>
  17. #include <stdio.h>
  18.  
  19. float Document::start_page;
  20.  
  21. Document::Document()
  22. {
  23.    for(int x=0; x < LastType; x++)
  24.       values[x] = 0.0;
  25.    begin_command[0] = '\0';
  26.    start_page = 0;
  27. }
  28.  
  29. Document::Document(Document *base)
  30. {
  31.    for(int x=0; x < LastType; x++)
  32.       values[x] = base->values[x];
  33.    strcpy(begin_command, base->begin_command);
  34. }
  35.  
  36. Param *Document::copy()
  37. {
  38.    Document *doc = new Document(this);
  39.    doc->set(End, 0.0, begin_command);
  40.    return doc;
  41. }
  42.  
  43. int Document::set(int subtype, float value, char *replacestr)
  44. {
  45.    switch(subtype) {
  46.    case Begin:
  47.       strcpy(begin_command,replacestr);
  48.       break;
  49.    case DocumentStart:
  50.       values[DocumentStart] = value;
  51.       break;
  52.    case End:
  53.       if(strcmp(begin_command,replacestr) != 0) {
  54.      char message[MAXSTRING];
  55.      sprintf(message, "\\end{%s} does not match a \\begin{%s}",
  56.          replacestr, begin_command);
  57.      Global::files->fatal_error(message);
  58.       }
  59.       begin_command[0] = '\0';
  60.       break;
  61.    case NewLine:
  62.       Operator::do_vspace(0, 0,
  63.           Global::stack->get(Environment::PLength, Length::Parameter,
  64.                  "\\baselineskip"), "");
  65.       break;
  66.    case StartPage:
  67.       start_page = value;
  68.       break;
  69.    case Stealth:
  70.       if(!Stack::get(Environment::PDocument, Document::Comment, ""))
  71.      Global::files->fatal_error(
  72.          "\\stealth must go on a comment line to be compatible with LaTeX");
  73.       values[Stealth] = value;
  74.       break;
  75.    default:
  76.       values[subtype] = value;
  77.       break;
  78.    }
  79.    return TRUE;
  80. }
  81.  
  82. float Document::get(int subtype, char *comparestr)
  83. {
  84.    switch(subtype) {
  85.    case CloseBrace:
  86.       if(begin_command[0] != '\0') {
  87.      char message[MAXSTRING];
  88.      sprintf(message, "\\begin{%s} closed with '}' instead of \\end{%s}",
  89.           begin_command, begin_command);
  90.      Global::files->fatal_error(message);
  91.       }
  92.       break;
  93.    case Begin:
  94.    case End:
  95.       return !strcmp(comparestr, begin_command);
  96.    case ShutDown:         // only happens in Stack::shutdown()
  97.       if(begin_command[0] != '\0') {
  98.      char message[MAXSTRING];
  99.      sprintf(message, "\\begin{%s} not closed at end of input",
  100.           begin_command);
  101.      Global::files->fatal_error(message);
  102.       }
  103.       break;
  104.    case StartPage:
  105.       return start_page;
  106.    default:
  107.       break;
  108.    }
  109.    return values[subtype];
  110. }
  111.  
  112. void Document::revert(Param *from)
  113. {
  114.    for(int subtype=0; subtype < LastType; subtype++) {
  115.       switch(subtype) {
  116.       case End:
  117.       case Begin:
  118.       case CloseBrace:
  119.       case ShutDown:
  120.      break;
  121.       default:
  122.      if(values[subtype] != from->get(subtype,"revert"))
  123.         postscript_set(subtype);
  124.      break;
  125.       }
  126.    }
  127. }
  128.  
  129. void Document::postscript_set(int subtype)
  130. {
  131.    switch(subtype) {
  132.    case DocumentStart:          // No postscript output needed
  133.    default:
  134.       break;
  135.    }
  136. }
  137.  
  138. /* Begins an environment */
  139. void Document::begin(int paramtype, int subtype, float value,
  140.           char *replacestr)
  141. {
  142.    Token openbrace;
  143.    if(!openbrace.match("{"))
  144.       Global::files->fatal_error("Expecting '{' after \\begin statement");
  145.    
  146.    Token command;
  147.    if(command.match("}"))
  148.       Global::files->
  149.      fatal_error("Expecting command before closing '}' in \\begin");
  150.    
  151.    if(!command.match("stealth"))
  152.       Stack::push(paramtype, subtype, value, replacestr);
  153.    
  154.    Token closebrace;
  155.    if(!closebrace.match("}"))
  156.       Global::files->
  157.      fatal_error("More than one word before closing '}' in \\begin");
  158.    
  159.    char begin_command[MAXSTRING];
  160.    strcpy(begin_command,"\\");  // Make the token "foo" into command "\foo"
  161.    char *tokentext = command.get_text();
  162.  
  163.    // One of the values in parameter "Document" keeps track of the
  164.    // command executed by the last \begin command, to that when the \end
  165.    // command is called, we can check it against the \begin command.
  166.    if(!command.match("stealth"))
  167.       Stack::set(Environment::PDocument, Document::Begin, 0.0, tokentext);
  168.  
  169.    strcat(begin_command,tokentext);
  170.    command.make_text(begin_command);
  171.    command.handle();          // Handle the command.
  172.  
  173. }
  174.  
  175. /* Ends an environment */
  176. void Document::end(int, int, float, char *)
  177. {
  178.    Token openbrace;
  179.    if(!openbrace.match("{"))
  180.       Global::files->fatal_error("Expecting '{' after \\end");
  181.  
  182.    Token command;     // Assume it's the same as the last begin command
  183.    if(command.match("}"))
  184.       Global::files->fatal_error(
  185.           "Expecting command before '}' in \\end statement");
  186.    if(!command.match("stealth")) {
  187.       char *begin_command = command.get_text();
  188.       Stack::set(Environment::PDocument, Document::End, 0.0, begin_command);
  189.    }
  190.  
  191.    Token closebrace;
  192.    if(!closebrace.match("}"))
  193.       Global::files->
  194.      fatal_error("More than one word before closing '}' in \\end");
  195.  
  196.    if(command.match("stealth"))
  197.       Stack::set(Environment::PDocument, Document::Stealth, 0.0, "");
  198.    else
  199.       Stack::pop(0, Document::End, 0.0, "");
  200. }
  201.  
  202. void Document::documentstyle(int, int, float, char *)
  203. {
  204.    Token openbrace;
  205.    if(openbrace.match("[")) {
  206.       Global::files->comma_delimiter(TRUE); // Commas are valid delimiters
  207.       
  208.       for(Token option = Token(); !option.match("]"); option = Token()) {
  209.      if(option.match(""))
  210.         continue;
  211.  
  212.      if(option.match("10pt")) {
  213.         // Do nothing. This is the default.
  214.      } else if(option.match("11pt")) {
  215.         // Makes 11 point type the default size
  216.         Stack::set(Environment::PFont, Font::Base11pt, 0.0, "");
  217.         Stack::set(Environment::PLength, Length::Parameter, 23.5,
  218.                "\\bigskipamount");
  219.         Stack::set(Environment::PLength, Length::Parameter, 18.6,
  220.                "\\medskipamount");
  221.         Stack::set(Environment::PLength, Length::Parameter, 16.0,
  222.                "\\smallskipamount");
  223.      } else if(option.match("12pt")) {
  224.         // Makes 12 point type the default size
  225.         Stack::set(Environment::PFont, Font::Base12pt, 0.0, "");
  226.         Stack::set(Environment::PLength, Length::Parameter, 25.7,
  227.                "\\bigskipamount");
  228.         Stack::set(Environment::PLength, Length::Parameter, 20.3,
  229.                "\\medskipamount");
  230.         Stack::set(Environment::PLength, Length::Parameter, 17.4,
  231.                "\\smallskipamount");
  232.      } else if(option.match("twoside")) {
  233.         // Formats the output for printing on both sides of a page
  234.             Global::files->warning("twoside option not supported in LameTeX");
  235.      } else if(option.match("twocolumn")) {
  236.         // Makes two-column pages
  237.             Global::files->warning(
  238.                      "twocolumn option not supported in LameTeX");
  239.      } else if(option.match("titlepage")) {
  240.         // article option only!
  241.             Global::files->warning("twoside option not supported in LameTeX");
  242.      } else if(option.match("openbib")) {
  243.             Global::files->warning("openbib option not supported in LameTeX");
  244.      } else if(option.match("leqno")) {
  245.             Global::files->warning("leqno option not supported in LameTeX");
  246.      } else if(option.match("fleqn")) {
  247.             Global::files->warning("fleqn option not supported in LameTeX");
  248.      } else
  249.             Global::files->warning("Unknown option in \\documentstyle[]");
  250.       }
  251.       Global::files->comma_delimiter(FALSE);  // Commas not valid delimiters
  252.       openbrace = Token();               // An openbrace should come now
  253.    }
  254.  
  255.    if(openbrace.match("{")) {
  256.    } else
  257.       Global::files->fatal_error("Expecting '{' or '[' in \\documentstyle");
  258.  
  259.    Token style;
  260.    if(style.match("}"))
  261.       Global::files->fatal_error(
  262.            "Expecting style before '}' in \\documentstyle");
  263.    
  264.    if(style.match("article")) {
  265.       // the article style does not have a \chapter command
  266.       // the default pagestyle is plain
  267.       // \flushbottom if [twoside], else \raggedbottom
  268.       // numbers figures and tables consecutively throughout
  269.       // if [titlepage] is used \abstract looks like normal article paragraph
  270.       // \parskip is zero
  271.    } else if(style.match("book")) {
  272.       // \flushbottom
  273.       // numbers figures and tables by chapter
  274.       // there is no \abstract environment
  275.       // \parskip is zero
  276.    } else if(style.match("letter")) {
  277.       // same as the \letter command. Very complex.
  278.       // special commands \opening, \address, \signature, \cc, \encl, etc.
  279.       // \raggedbottom
  280.       // \parskip is non-zero
  281.       Global::files->warning("letter style not supported in LameTeX");
  282.    } else if(style.match("report")) {
  283.       // the default pagestyle is plain
  284.       // \flushbottom if [twoside], else \raggedbottom
  285.       // numbers figures and tables by chapter
  286.       // \abstract is placed on a separate page
  287.       // \parskip is zero
  288.    } else if(style.match("slides")) {
  289.       // same as the \slide command. Very complex.
  290.       Global::files->warning("slides style not supported in LameTeX");
  291.    } else
  292.       Global::files->warning(
  293.       "Unknown style in \\documentstyle. User-defined styles not supported.");
  294.  
  295.    Token closebrace;
  296.    if(!closebrace.match("}"))
  297.       Global::files->fatal_error(
  298.          "Only one word allowed between braces in \\documentstyle");
  299. }
  300.