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

  1. /* Counter.C
  2.  *
  3.  * LameTeX needs to keep track of a number of counters, just like LaTeX does,
  4.  * for things like tables, footnotes, chapters and sections, and enumerations.
  5.  * Since all counters need to be handled in much the same way, the Counter
  6.  * derived class under the Parameters class has been defined.
  7.  *
  8.  * Copyright 1992 Jonathan Monsarrat. Permission given to freely distribute,
  9.  * edit and use as long as this copyright statement remains intact.
  10.  *
  11.  */
  12.  
  13. #include "Operator.h"
  14. #include "Global.h"
  15. #include "Counter.h"
  16. #include "Document.h"
  17. #include "Font.h"
  18. #include <string.h>
  19. #include <stdio.h>
  20.  
  21. Counter::Counter()
  22. {
  23.    for(int x=0; x < LastType; x++)
  24.       counters[x] = 0;
  25. }
  26.  
  27. Counter::Counter(Counter *base)
  28. {
  29.    for(int x=0; x < LastType; x++)
  30.       counters[x] = base->counters[x];
  31. }
  32.  
  33. Param *Counter::copy()
  34. {
  35.    return new Counter(this);
  36. }
  37.  
  38. int Counter::set(int subtype, float print_number, char *)
  39. {
  40.    char number[10];
  41.    char message[20];
  42.    char output[20];
  43.    if(subtype >= Part && subtype <= Subparagraph) {
  44.       Token openbrace;
  45.       if(!openbrace.match("{"))
  46.      Global::files->fatal_error("Expecting '{' after section statement");
  47.       if(print_number) {
  48.        counters[subtype]++;
  49.        switch(subtype) {
  50.          case Part:
  51.         counters[Chapter]=0;
  52.          case Chapter:
  53.         counters[Section]=0;
  54.          case Section:
  55.         counters[Subsection]=0;
  56.          case Subsection:
  57.         counters[Subsubsection]=0;
  58.          case Subsubsection:
  59.         counters[Paragraph]=0;
  60.          case Paragraph:
  61.         counters[Subparagraph]=0;
  62.          case Subparagraph:
  63.          default:
  64.         break;
  65.        }
  66.       } else
  67.        counters[subtype] = -1;
  68.    }
  69.  
  70.    float fontsize = Global::stack->get(Environment::PFont, Font::Size, "");
  71.  
  72.    switch(subtype) {
  73.    case Part:
  74.       Global::files->outfile << endl;
  75.       if(print_number) {
  76.        Operator::plaintext("Part");
  77.        upcase_roman(counters[Part], number);
  78.        Operator::plaintext(number);
  79.       }
  80.       Operator::do_vspace(0, 0, 200.0, "");
  81.       break;
  82.    case Chapter:
  83.       Global::files->outfile << endl;
  84.       if(Global::files->plain_text_output)
  85.        Operator::do_vspace(0, 0, 13.0, "");
  86.       else
  87.        Operator::do_vspace(0, 0, 112.5 + (fontsize-18.0) * 0.85, "");
  88.       if(print_number) {
  89.        Operator::plaintext("Chapter");
  90.        arabic(counters[Chapter], number);
  91.        Operator::plaintext(number);
  92.  
  93.        if(Global::files->plain_text_output)
  94.         Operator::do_vspace(0, 0, 13.0, "");
  95.        else
  96.         Operator::do_vspace(0, 0, 50.0 + (fontsize-22.0) * 0.85, "");
  97.       }
  98.       Stack::set(Environment::PFont, Font::Huge, 0.0, "");
  99.       break;
  100.    case Section:
  101.       Global::files->outfile << endl;
  102.       if(Global::files->plain_text_output)
  103.        Operator::do_vspace(0, 0, 8.0, "");
  104.       else
  105.        Operator::do_vspace(0, 0, 20.7 + (fontsize-13.0) * 3.4, "");
  106.       if(print_number) {
  107.          sprintf(number,"%d.%d",counters[Chapter],counters[Section]);
  108.          Operator::plaintext(number);
  109.          Global::files->outfile << endl;
  110.          Global::files->outfile << 15.0 + (fontsize-13.0) * 1.1
  111.           << " HSpace" << endl;
  112.       }
  113.       break;
  114.    case Subsection:
  115.       Global::files->outfile << endl;
  116.       Operator::do_vspace(0, 0, 4.5 + (fontsize-11.0) * 3.4, "");
  117.       if(print_number) {
  118.        sprintf(number,"%d.%d.%d",counters[Chapter],counters[Section],
  119.            counters[Subsection]);
  120.        Operator::plaintext(number);
  121.        Global::files->outfile << endl;
  122.        Global::files->outfile << 15.0 + (fontsize-11.0) * 1.1
  123.         << " HSpace" << endl;
  124.       }
  125.       break;
  126.    case Subsubsection:
  127.    case Paragraph:
  128.    case Subparagraph:
  129.       break;
  130.    case Page:
  131.       break;
  132.    case Equation:
  133.       break;
  134.    case Figure:
  135.       break;
  136.    case Table:
  137.       break;
  138.    case Footnote:
  139.       break;
  140.    case Mpfootnote:
  141.       break;
  142.    case Description:
  143.       counters[Item] = Description;   // Mark Description most recent
  144.       counters[Description]=0;
  145.       break;
  146.    case Itemize:
  147.       counters[Item] = Itemize;   // Mark Itemize most recent
  148.       break;
  149.    case Enum:
  150.       if(++counters[Enum] > 4)
  151.      Global::files->fatal_error(
  152.             "Can't have more than four nested enumerates");
  153.       counters[Item] = Enum;      // Mark Enumerate most recent
  154.       switch(counters[Enum]) {
  155.       case 1:
  156.      counters[Enumi]=0;
  157.      break;
  158.       case 2:
  159.       counters[Enumii]=0;
  160.      break;
  161.       case 3:
  162.      counters[Enumiii]=0;
  163.      break;
  164.       case 4:
  165.      counters[Enumiv]=0;
  166.      break;
  167.       }
  168.       break;
  169.    case Enumi:
  170.       break;
  171.    case Enumii:
  172.       break;
  173.    case Enumiii:
  174.       break;
  175.    case Enumiv:
  176.       break;
  177.    case Item:
  178.       switch(counters[Item]) {
  179.       case Description:
  180.      description();
  181.      break;
  182.       case Itemize:
  183.      Stack::set(Environment::PDocument, Document::NewLine, 0.0, "");
  184.      Global::files->force_start_page();
  185.      Global::files->outfile << endl;
  186.      Global::files->outfile << "BULLET" << endl;
  187.      break;
  188.       case Enum:
  189.      Stack::set(Environment::PDocument, Document::NewLine, 0.0, "");
  190.      Global::files->force_start_page();
  191.      Global::files->outfile << endl;
  192.      switch(counters[Enum]) {
  193.      case 1:
  194.         arabic(++counters[Enumi], message);
  195.         strcat(message, ".");
  196.         break;
  197.      case 2:
  198.         message[0]='(';
  199.         downcase_alpha(++counters[Enumii], &message[1]);
  200.         strcat(message, ")");
  201.         break;
  202.      case 3:
  203.         downcase_roman(++counters[Enumiii], message);
  204.         strcat(message, ".");
  205.         break;
  206.      case 4:
  207.         upcase_alpha(++counters[Enumiv], message);
  208.         strcat(message, ".");
  209.         break;
  210.      }
  211.      Global::files->force_start_page();
  212.      Operator::registrar(message, output);
  213.      Global::files->outfile << " " << output << " ENUMERATE" << endl;
  214.          break;
  215.       default:
  216.          break;
  217.       }
  218.       break;
  219.    default:
  220.       break;
  221.    }
  222.    return TRUE;
  223. }
  224.  
  225. /* Handles the \item command in a description. If the item is the 0th
  226.  * item, then make an indentation.
  227.  */
  228. void Counter::description()
  229. {
  230.    Stack::relative_set(Environment::PLength, Length::Parameter,
  231.                -22.5, "\\oddsidemargin");
  232.    Stack::relative_set(Environment::PLength, Length::Parameter,
  233.                22.5, "\\textwidth");
  234.    Stack::set(Environment::PDocument, Document::NewLine, 0.0, "");
  235.    Global::files->force_start_page();
  236.    Global::files->outfile << endl;
  237.  
  238.    Token openbrace;
  239.    if(!openbrace.match("["))
  240.       Global::files->fatal_error("Expecting '[' after \\item");
  241.    Stack::set(Environment::PFont, Font::Bold, 0.0,  "");
  242.    
  243.    for(Token description; !description.match("]"); description=Token())
  244.       description.handle();
  245.    
  246.    Global::files->outfile << endl << "13.0 HSpace" << endl;
  247.    Stack::set(Environment::PFont, Font::Roman, 0.0,  "");
  248.    
  249.    Stack::relative_set(Environment::PLength, Length::Parameter,
  250.                22.5, "\\oddsidemargin");
  251.    Stack::relative_set(Environment::PLength, Length::Parameter,
  252.                -22.5, "\\textwidth");
  253. }
  254.  
  255. float Counter::get(int subtype, char *)
  256. {
  257.    return counters[subtype];
  258. }
  259.  
  260. void Counter::postscript_set(int subtype)
  261. {
  262.    switch(subtype) {
  263.    default:
  264.       break;
  265.    }
  266. }
  267.  
  268. void Counter::revert(Param *from)
  269. {
  270.    int count;
  271.    for(int subtype=0; subtype < LastType; subtype++)
  272.       if((count = (int)from->get(subtype,"revert")) != counters[subtype]) {
  273.      if(count > 0)
  274.         counters[subtype] = count;
  275.      switch(subtype) {
  276.      case Part:
  277.         Stack::set(Environment::PDocument, Document::NewLine, 0.0, "");
  278.      case Chapter:
  279.         if(Global::files->plain_text_output)
  280.          Operator::do_vspace(0, 0, 13.0, "");
  281.         else
  282.          Operator::do_vspace(0, 0, 52, "");
  283.         break;
  284.      case Section:
  285.         if(Global::files->plain_text_output)
  286.          Operator::do_vspace(0, 0, 8.0, "");
  287.         else
  288.          Operator::do_vspace(0, 0, 22.4, "");
  289.         break;
  290.      case Subsection:
  291.         if(Global::files->plain_text_output)
  292.          Operator::do_vspace(0, 0, 8.0, "");
  293.         else
  294.          Operator::do_vspace(0, 0, 18.0, "");
  295.         break;
  296.      case Subsubsection:
  297.      case Paragraph:
  298.      case Subparagraph:
  299.         Stack::set(Environment::PDocument, Document::NewLine, 0.0, "");
  300.         break;
  301.      case Page:
  302.         break;
  303.      case Equation:
  304.         break;
  305.      case Figure:
  306.         break;
  307.      case Table:
  308.         break;
  309.      case Footnote:
  310.         break;
  311.      case Mpfootnote:
  312.         break;
  313.      case Enum:
  314.         counters[Enum]--;
  315.         break;
  316.      case Enumi:
  317.         break;
  318.      case Enumii:
  319.         break;
  320.      case Enumiii:
  321.         break;
  322.      case Enumiv:
  323.         break;
  324.      case Itemize:
  325.         break;
  326.      }
  327.       }
  328. }
  329.  
  330. void Counter::downcase_roman(int count, char *number)
  331. {
  332.    switch(count/100) {
  333.    case 1:
  334.       strcpy(number,"c");
  335.       break;
  336.    case 2:
  337.       strcpy(number,"cc");
  338.       break;
  339.    case 3:
  340.       strcpy(number,"ccc");
  341.       break;
  342.    case 4:
  343.       strcpy(number,"cd");
  344.       break;
  345.    case 5:
  346.       strcpy(number,"d");
  347.       break;
  348.    case 0:
  349.    default:
  350.       strcpy(number,"");
  351.       break;
  352.    }
  353.  
  354.    switch(count%100/10) {
  355.    case 0:
  356.       break;
  357.    case 1:
  358.       strcat(number,"x");
  359.       break;
  360.    case 2:
  361.       strcat(number,"xx");
  362.       break;
  363.    case 3:
  364.       strcat(number,"xxx");
  365.       break;
  366.    case 4:
  367.       strcat(number,"xl");
  368.       break;
  369.    case 5:
  370.       strcat(number,"l");
  371.       break;
  372.    case 6:
  373.       strcat(number,"lx");
  374.       break;
  375.    case 7:
  376.       strcat(number,"lxx");
  377.       break;
  378.    case 8:
  379.       strcat(number,"lxxx");
  380.       break;
  381.    case 9:
  382.       strcat(number,"xc");
  383.       break;
  384.    }
  385.  
  386.    switch(count%10) {
  387.    case 0:
  388.       break;
  389.    case 1:
  390.       strcat(number,"i");
  391.       break;
  392.    case 2:
  393.       strcat(number,"ii");
  394.       break;
  395.    case 3:
  396.       strcat(number,"iii");
  397.       break;
  398.    case 4:
  399.       strcat(number,"iv");
  400.       break;
  401.    case 5:
  402.       strcat(number,"v");
  403.       break;
  404.    case 6:
  405.       strcat(number,"vi");
  406.       break;
  407.    case 7:
  408.       strcat(number,"vii");
  409.       break;
  410.    case 8:
  411.       strcat(number,"viii");
  412.       break;
  413.    case 9:
  414.       strcat(number,"ix");
  415.       break;
  416.    }
  417. };
  418.  
  419. void Counter::upcase_roman(int count, char *number)
  420. {
  421.    switch(count/100) {
  422.    case 1:
  423.       strcpy(number,"C");
  424.       break;
  425.    case 2:
  426.       strcpy(number,"CC");
  427.       break;
  428.    case 3:
  429.       strcpy(number,"CCC");
  430.       break;
  431.    case 4:
  432.       strcpy(number,"CD");
  433.       break;
  434.    case 5:
  435.       strcpy(number,"D");
  436.       break;
  437.    case 0:
  438.    default:
  439.       strcpy(number,"");
  440.       break;
  441.    }
  442.  
  443.    switch(count%100/10) {
  444.    case 0:
  445.       break;
  446.    case 1:
  447.       strcat(number,"X");
  448.       break;
  449.    case 2:
  450.       strcat(number,"XX");
  451.       break;
  452.    case 3:
  453.       strcat(number,"XXX");
  454.       break;
  455.    case 4:
  456.       strcat(number,"XL");
  457.       break;
  458.    case 5:
  459.       strcat(number,"L");
  460.       break;
  461.    case 6:
  462.       strcat(number,"LX");
  463.       break;
  464.    case 7:
  465.       strcat(number,"LXX");
  466.       break;
  467.    case 8:
  468.       strcat(number,"LXXX");
  469.       break;
  470.    case 9:
  471.       strcat(number,"XC");
  472.       break;
  473.    }
  474.  
  475.    switch(count%10) {
  476.    case 0:
  477.       break;
  478.    case 1:
  479.       strcat(number,"I");
  480.       break;
  481.    case 2:
  482.       strcat(number,"II");
  483.       break;
  484.    case 3:
  485.       strcat(number,"III");
  486.       break;
  487.    case 4:
  488.       strcat(number,"IV");
  489.       break;
  490.    case 5:
  491.       strcat(number,"V");
  492.       break;
  493.    case 6:
  494.       strcat(number,"VI");
  495.       break;
  496.    case 7:
  497.       strcat(number,"VII");
  498.       break;
  499.    case 8:
  500.       strcat(number,"VIII");
  501.       break;
  502.    case 9:
  503.       strcat(number,"IX");
  504.       break;
  505.    }
  506. };
  507.  
  508. void Counter::arabic(int count, char *number)
  509. {
  510.    sprintf(number,"%d",count);
  511. };
  512.  
  513. void Counter::downcase_alpha(int count, char *number)
  514. {
  515.    if(count >= 26) {
  516.       sprintf(number,"%c%c",('a'+count/26-1),('a'+count%26-1));
  517.    }
  518.    sprintf(number,"%c",('a'+count%26-1));
  519. };
  520.  
  521. void Counter::upcase_alpha(int count, char *number)
  522. {
  523.    if(count >= 26) {
  524.       sprintf(number,"%c%c",('A'+count/26-1),('A'+count%26-1));
  525.    }
  526.    sprintf(number,"%c",('A'+count%26-1));
  527. };
  528.