Source for file rtfclass.php

Documentation is available at rtfclass.php

  1. <?php 
  2. /**
  3.  * Filename:  includes/rtfclass.php
  4.  * Function:  RTF parsing class
  5.  * @author  Markus Fischer
  6.  * @package phpdivinglog
  7.  * @version $Rev: 155 $
  8.  *  Last Modified: $Date: 2007-11-27 14:02:54 +0100 (Tue, 27 Nov 2007) $
  9.  */
  10.  
  11.  
  12. // use tabstop=4
  13. /*
  14. Rich Text Format - Parsing Class
  15. ================================
  16.  
  17. (c) 2000 Markus Fischer
  18. <mfischer@josefine.ben.tuwien.ac.at>
  19. http://josefine.ben.tuwien.ac.at/~mfischer/
  20.  
  21. Latest versions of this class can always be found at
  22.     http://josefine.ben.tuwien.ac.at/~mfischer/developing/php/rtf/rtfclass.phps
  23.  
  24. Testing suite is available at
  25.     http://josefine.ben.tuwien.ac.at/~mfischer/developing/php/rtf/
  26.  
  27. License: GPLv2
  28.  
  29. Specification:
  30.     http://msdn.microsoft.com/library/default.asp?URL=/library/specs/rtfspec.htm
  31.  
  32. General Notes:
  33. ==============
  34. Unknown or unspupported control symbols are silently ignored
  35.  
  36. Group stacking is still not supported :(
  37. group stack logic implemented; however not really used yet
  38.  
  39. Example on how to use this class:
  40. =================================
  41.  
  42. $r = new rtf( stripslashes( $rtf));
  43. $r->output( "xml");
  44. $r->parse();
  45. if( count( $r->err) == 0) // no errors detected
  46.     echo $r->out;
  47.             
  48. History:
  49. ========
  50. Sat Nov 25 09:52:12 CET 2000    mfischer
  51.     First version which has useable but only well-formed xml output; rtf
  52.     data structure is only logically rebuild, no real parsing yet
  53.  
  54. Mon Nov 27 16:17:18 CET 2000    mfischer
  55.     Wrote handler for \plain control word (thanks to Peter Kursawe for this
  56.             one)
  57.  
  58. Tue Nov 28 02:22:16 CET 2000    mfischer
  59.     Implemented alignment (left, center, right) with HTML <DIV .. tags
  60.     Also implemented translation for < and > character when outputting html or xml
  61.  
  62. Mon Oct 25 14:15:03 CET 2004    smanciles
  63.     Implemented parsing of special characteres for spanish and catalan (รบร...)
  64.  
  65. Remarks:
  66. ========
  67. This class and all work done here is dedicated to Tatjana.
  68. */
  69.  
  70. /* was just a brainlag suggestion of my inner link; don't know if I'll use it */
  71. class rtfState {
  72.     var $bold;
  73.     var $italic;
  74.     var $underlined;
  75.  
  76. class rtf {
  77.     var $rtf// rtf core stream
  78.     var $len// length in characters of the stream (get performace due avoiding calling strlen everytime)
  79.     var $err = array()// array of error message, no entities on no error
  80.     
  81.     var $wantXML// convert to XML
  82.     var $wantHTML// convert to HTML
  83.      
  84.     // the only variable which should be accessed from the outside
  85.     var $out// output data stream (depends on which $wantXXXXX is set to true
  86.     var $outstyles// htmlified styles (generated after parsing if wantHTML
  87.     var $styles// if wantHTML, stylesheet definitions are put in here
  88.      
  89.     // internal parser variables --------------------------------
  90.     // control word variables
  91.     var $cword// holds the current (or last) control word, depending on $cw
  92.     var $cw// are we currently parsing a control word ?
  93.     var $cfirst// could this be the first character ? so watch out for control symbols
  94.     
  95.     var $flags = array()// parser flags
  96.     
  97.     var $queue// every character which is no sepcial char, not belongs to a control word/symbol; is generally considered being 'plain'
  98.     
  99.     var $stack = array()// group stack
  100.     
  101.     /* keywords which don't follw the specification (used by Word '97 - 2000) */ 
  102.     // not yet used
  103.     var $control_exception = array("clFitText",
  104.         "clftsWidth(-?[0-9]+)?",
  105.         "clNoWrap(-?[0-9]+)?",
  106.         "clwWidth(-?[0-9]+)?",
  107.         "tdfrmtxtBottom(-?[0-9]+)?",
  108.         "tdfrmtxtLeft(-?[0-9]+)?",
  109.         "tdfrmtxtRight(-?[0-9]+)?",
  110.         "tdfrmtxtTop(-?[0-9]+)?",
  111.         "trftsWidthA(-?[0-9]+)?",
  112.         "trftsWidthB(-?[0-9]+)?",
  113.         "trftsWidth(-?[0-9]+)?",
  114.         "trwWithA(-?[0-9]+)?",
  115.         "trwWithB(-?[0-9]+)?",
  116.         "trwWith(-?[0-9]+)?",
  117.         "spectspecifygen(-?[0-9]+)?"
  118.         );
  119.  
  120.     var $charset_table = array("0" => "ANSI",
  121.         "1" => "Default",
  122.         "2" => "Symbol",
  123.         "77" => "Mac",
  124.         "128" => "Shift Jis",
  125.         "129" => "Hangul",
  126.         "130" => "Johab",
  127.         "134" => "GB2312",
  128.         "136" => "Big5",
  129.         "161" => "Greek",
  130.         "162" => "Turkish",
  131.         "163" => "Vietnamese",
  132.         "177" => "Hebrew",
  133.         "178" => "Arabic",
  134.         "179" => "Arabic Traditional",
  135.         "180" => "Arabic user",
  136.         "181" => "Hebrew user",
  137.         "186" => "Baltic",
  138.         "204" => "Russion",
  139.         "222" => "Thai",
  140.         "238" => "Eastern European",
  141.         "255" => "PC 437",
  142.         "255" => "OEM"
  143.         );
  144.  
  145.     /* note: the only conversion table used */
  146.     var $fontmodifier_table = array("bold" => "b",
  147.         "italic" => "i",
  148.         "underlined" => "u",
  149.         "strikethru" => "strike"
  150.         );
  151.  
  152.     /*
  153.         Class Constructor:
  154.         Takes as argument the raw RTF stream
  155.         (Note under certain circumstances the stream has to be stripslash'ed before handling over)
  156.         Initialises some class-global variables
  157.     */
  158.     function rtf($data)
  159.     {
  160.         $this->len = strlen($data);
  161.         $this->rtf = $data;
  162.  
  163.         $this->wantXML = false;
  164.         $this->wantHTML = false;
  165.  
  166.         $this->out = "";
  167.         $this->outstyles = "";
  168.         $this->styles = array();
  169.         $this->text "";
  170.  
  171.         if ($this->len == 0{
  172.             array_push($this->err"No data in stream found");
  173.         
  174.         echo "<hr>\n<b>RTF</b><br>\n<code>\n";
  175.         echo "--->" $this->rtf . "<---<br>\n";
  176.         echo "</code>\n<br>\n<hr>\n";
  177.     
  178.  
  179.     function parserInit()
  180.     {
  181.         /*
  182.             Default values according to the specs
  183.         */
  184.         $this->flags = array("fontsize" => 24,
  185.             "beginparagraph" => true
  186.             );
  187.     
  188.  
  189.     /*
  190.         Sets the output type
  191.     */
  192.     function output($typ)
  193.     {
  194.         switch ($typ{
  195.             case "xml"$this->wantXML = true;
  196.                 break;
  197.             case "html"$this->wantHTML = true;
  198.                 break;
  199.             defaultbreak;
  200.         
  201.     
  202.  
  203.     function parseControl($control$parameter)
  204.     {
  205.         switch ($control{
  206.             // font table definition start
  207.             case "fonttbl":
  208.                 $this->flags["fonttbl"true// signal fonttable control records they are allowed to behave as expected
  209.                 break
  210.             // define or set font
  211.             case "f":
  212.                 if ($this->flags["fonttbl"]// if its set, the fonttable definition is written to; else its read from
  213.                     $this->flags["fonttbl_current_write"$parameter;
  214.                 else {
  215.                     $this->flags["fonttbl_current_read"$parameter;
  216.                 
  217.                 break;
  218.             case "fcharset"
  219.                 // this is for preparing flushQueue; it then moves the Queue to $this->fonttable .. instead to formatted output
  220.                 $this->flags["fonttbl_want_fcharset"$parameter;
  221.                 break;
  222.             case "fs"
  223.                 // sets the current fontsize; is used by stylesheets (which are therefore generated on the fly
  224.                 $this->flags["fontsize"$parameter;
  225.                 break
  226.             // handle alignment
  227.             case "qc":
  228.                 $this->flags["alignment""center";
  229.                 break;
  230.             case "qr":
  231.                 $this->flags["alignment""right";
  232.                 break
  233.             // reset paragraph settings ( only alignment)
  234.             case "pard":
  235.                 $this->flags["alignment""";
  236.                 break
  237.             // define new paragraph (for now, thats a simple break in html)
  238.             case "par"
  239.                 // begin new line
  240.                 $this->flags["beginparagraph"true;
  241.                 if ($this->wantHTML{
  242.                     $this->out .= "</div>";
  243.                 
  244.                 break
  245.             // bold
  246.             case "bnone":
  247.                 $parameter "0";
  248.             case "b"
  249.                 // haven'y yet figured out WHY I need a (string)-cast here ... hm
  250.                 if ((string)$parameter == "0"{
  251.                     $this->flags["bold"false;
  252.                 else {
  253.                     $this->flags["bold"true;
  254.                 
  255.                 break
  256.             // underlined
  257.             case "ulnone":
  258.                 $parameter "0";
  259.             case "ul":
  260.                 if ((string)$parameter == "0"{
  261.                     $this->flags["underlined"false;
  262.                 else {
  263.                     $this->flags["underlined"true;
  264.                 
  265.                 break
  266.             // italic
  267.             case "inone":
  268.                 $parameter "0";
  269.             case "i":
  270.                 if ((string)$parameter == "0"{
  271.                     $this->flags["italic"false;
  272.                 else {
  273.                     $this->flags["italic"true;
  274.                 
  275.                 break
  276.             // strikethru
  277.             case "strikenone":
  278.                 $parameter "0";
  279.             case "strike":
  280.                 if ((string)$parameter == "0"{
  281.                     $this->flags["strikethru"false;
  282.                 else {
  283.                     $this->flags["strikethru"true;
  284.                 
  285.                 break
  286.             // reset all font modifiers and fontsize to 12
  287.             case "plain":
  288.                 $this->flags["bold"false;
  289.                 $this->flags["italic"false;
  290.                 $this->flags["underlined"false;
  291.                 $this->flags["strikethru"false;
  292.                 $this->flags["fontsize"12;
  293.  
  294.                 $this->flags["subscription"false;
  295.                 $this->flags["superscription"false;
  296.                 break
  297.             // sub and superscription
  298.             case "subnone":
  299.                 $parameter "0";
  300.             case "sub":
  301.                 if ((string)$parameter == "0"{
  302.                     $this->flags["subscription"false;
  303.                 else {
  304.                     $this->flags["subscription"true;
  305.                 
  306.                 break;
  307.  
  308.             case "supernone":
  309.                 $parameter "0";
  310.             case "super":
  311.                 if ((string)$parameter == "0"{
  312.                     $this->flags["superscription"false;
  313.                 else {
  314.                     $this->flags["superscription"true;
  315.                 
  316.                 break;
  317.         
  318.     
  319.  
  320.     /*
  321.         Dispatch the control word to the output stream
  322.     */
  323.     function flushControl()
  324.     {
  325.         if (ereg("^([A-Za-z]+)(-?[0-9]*) ?$"$this->cword$match)) {
  326.             $this->parseControl($match[1]$match[2]);
  327.  
  328.             if ($this->wantXML{
  329.                 $this->out .= "<control word=\"" $match[1"\"";
  330.                 if (strlen($match[2]0{
  331.                     $this->out .= " param=\"" $match[2"\"";
  332.                 
  333.                 $this->out .= "/>";
  334.             
  335.         
  336.     
  337.  
  338.     /*
  339.         If output stream supports comments, dispatch it
  340.     */
  341.     function flushComment($comment)
  342.     {
  343.         if ($this->wantXML || $this->wantHTML{
  344.             $this->out .= "<!-- " $comment " -->";
  345.         
  346.     
  347.  
  348.     /*
  349.         Dispatch start/end of logical rtf groups
  350.         (not every output type needs it; merely debugging purpose)
  351.     */
  352.     function flushGroup($state)
  353.     {
  354.         if ($state == "open"{
  355.             /* push onto the stack */
  356.             array_push($this->stack$this->flags);
  357.  
  358.             if ($this->wantXML{
  359.                 $this->out .= "<group>";
  360.             
  361.         
  362.         if ($state == "close"{
  363.             /* pop from the stack */
  364.             $this->last_flags $this->flags;
  365.             $this->flags = array_pop($this->stack);
  366.  
  367.             $this->flags["fonttbl_current_write"""// on group close, no more font definition will be written to this id 
  368.             // this is not really the right way to do it !
  369.             // of course a '}' not necessarily donates a fonttable end; a fonttable
  370.             // group at least *can* contain sub-groups
  371.             // therefore an stacked approach is heavily needed
  372.             $this->flags["fonttbl"false// no matter what you do, if a group closes, its fonttbl definition is closed too
  373.             
  374.             if ($this->wantXML{
  375.                 $this->out .= "</group>";
  376.             
  377.         
  378.     
  379.  
  380.     function flushHead()
  381.     {
  382.         if ($this->wantXML{
  383.             $this->out .= "<rtf>";
  384.         
  385.     
  386.  
  387.     function flushBottom()
  388.     {
  389.         if ($this->wantXML{
  390.             $this->out .= "</rtf>";
  391.         
  392.     
  393.  
  394.     function checkHtmlSpanContent($command)
  395.     {
  396.         reset($this->fontmodifier_table);
  397.         while (list($rtf$htmleach($this->fontmodifier_table)) {
  398.             if ($this->flags[$rtf== true{
  399.                 if ($command == "start"{
  400.                     $this->out .= "<" $html ">";
  401.                 else {
  402.                     $this->out .= "</" $html ">";
  403.                 
  404.             
  405.         
  406.     
  407.  
  408.     /*
  409.         flush text in queue
  410.     */
  411.     function flushQueue()
  412.     {
  413.         if (strlen($this->queue)) {
  414.             // processing logic
  415.             if (ereg("^[0-9]+$"$this->flags["fonttbl_want_fcharset"])) {
  416.                 $this->fonttable[$this->flags["fonttbl_want_fcharset"]]["charset"$this->queue;
  417.                 $this->flags["fonttbl_want_fcharset""";
  418.                 $this->queue = "";
  419.             
  420.             // output logic
  421.             if (strlen($this->queue)) {
  422.                 /*
  423.                     Everything which passes this is (or, at leat, *should*) be only outputted plaintext
  424.                     Thats why we can safely add the css-stylesheet when using wantHTML
  425.                 */
  426.                 if ($this->wantXML{
  427.                     $this->out .= "<plain>" $this->queue . "</plain>";
  428.                 
  429.  
  430.                 if ($this->wantHTML{
  431.                     // only output html if a valid (for now, just numeric;) fonttable is given
  432.                     if (ereg("^[0-9]+$"$this->flags["fonttbl_current_read"])) {
  433.                         if ($this->flags["beginparagraph"== true{
  434.                             $this->flags["beginparagraph"false;
  435.                             $this->out .= "<div align=\"";
  436.                             switch ($this->flags["alignment"]{
  437.                                 case "right":
  438.                                     $this->out .= "right";
  439.                                     break;
  440.                                 case "center":
  441.                                     $this->out .= "center";
  442.                                     break;
  443.                                 case "left":
  444.                                 default:
  445.                                     $this->out .= "left";
  446.                             
  447.                             $this->out .= "\">";
  448.                         
  449.  
  450.                         /* define new style for that span */
  451.                         $this->styles["f" $this->flags["fonttbl_current_read""s" $this->flags["fontsize"]] "font-family:" $this->fonttable[$this->flags["fonttbl_current_read"]]["charset"" font-size:" $this->flags["fontsize"";";
  452.                         /* write span start */
  453.                         $this->out .= "<span class=\"f" $this->flags["fonttbl_current_read""s" $this->flags["fontsize""\">";
  454.  
  455.                         /* check if the span content has a modifier */
  456.                         $this->checkHtmlSpanContent("start");
  457.                         /* write span content */
  458.                         $this->out .= $this->queue;
  459.                         /* close modifiers */
  460.                         $this->checkHtmlSpanContent("stop");
  461.                         /* close span */
  462.                         "</span>";
  463.                     
  464.                 
  465.                 $this->queue = "";
  466.             
  467.         
  468.     
  469.  
  470.     /*
  471.         handle special charactes like \'ef
  472.     */
  473.     function flushSpecial($special)
  474.     {
  475.         if (strlen($special== 2{
  476.             if ($this->wantXML{
  477.                 $this->out .= "<special value=\"" $special "\"/>";
  478.             
  479.             if ($this->wantHTML{
  480.                 $this->out .= "<special value=\"" $special "\"/>";
  481.                 switch ($special{
  482.                     case "c1"$this->out .= "&Aacute;";
  483.                         break;
  484.                     case "e1"$this->out .= "&aacute;";
  485.                         break;
  486.                     case "c0"$this->out .= "&Agrave;";
  487.                         break;
  488.                     case "e0"$this->out .= "&agrave;";
  489.                         break;
  490.                     case "c9"$this->out .= "&Eacute;";
  491.                         break;
  492.                     case "e9"$this->out .= "&eacute;";
  493.                         break;
  494.                     case "c8"$this->out .= "&Egrave;";
  495.                         break;
  496.                     case "e8"$this->out .= "&egrave;";
  497.                         break;
  498.                     case "cd"$this->out .= "&Iacute;";
  499.                         break;
  500.                     case "ed"$this->out .= "&iacute;";
  501.                         break;
  502.                     case "cc"$this->out .= "&Igrave;";
  503.                         break;
  504.                     case "ec"$this->out .= "&igrave;";
  505.                         break;
  506.                     case "d3"$this->out .= "&Oacute;";
  507.                         break;
  508.                     case "f3"$this->out .= "&oacute;";
  509.                         break;
  510.                     case "d2"$this->out .= "&Ograve;";
  511.                         break;
  512.                     case "f2"$this->out .= "&ograve;";
  513.                         break;
  514.                     case "da"$this->out .= "&Uacute;";
  515.                         break;
  516.                     case "fa"$this->out .= "&uacute;";
  517.                         break;
  518.                     case "d9"$this->out .= "&Ugrave;";
  519.                         break;
  520.                     case "f9"$this->out .= "&ugrave;";
  521.                         break;
  522.                     case "80"$this->out .= "&#8364;";
  523.                         break;
  524.                     case "d1"$this->out .= "&Ntilde;";
  525.                         break;
  526.                     case "f1"$this->out .= "&ntilde;";
  527.                         break;
  528.                     case "c7"$this->out .= "&Ccedil;";
  529.                         break;
  530.                     case "e7"$this->out .= "&ccedil;";
  531.                         break;
  532.                     case "dc"$this->out .= "&Uuml;";
  533.                         break;
  534.                     case "fc"$this->out .= "&uuml;";
  535.                         break;
  536.                     case "bf"$this->out .= "&#191;";
  537.                         break;
  538.                     case "a1"$this->out .= "&#161;";
  539.                         break;
  540.                     case "b7"$this->out .= "&middot;";
  541.                         break;
  542.                     case "a9"$this->out .= "&copy;";
  543.                         break;
  544.                     case "ae"$this->out .= "&reg;";
  545.                         break;
  546.                     case "ba"$this->out .= "&ordm;";
  547.                         break;
  548.                     case "aa"$this->out .= "&ordf;";
  549.                         break;
  550.                     case "b2"$this->out .= "&sup2;";
  551.                         break;
  552.                     case "b3"$this->out .= "&sup3;";
  553.                         break;
  554.                 
  555.             
  556.         
  557.     
  558.  
  559.     /*
  560.         Output errors at end
  561.     */
  562.     function flushErrors()
  563.     {
  564.         if (count($this->err0{
  565.             if ($this->wantXML{
  566.                 $this->out .= "<errors>";
  567.                 while (list($num$valueeach($this->err)) {
  568.                     $this->out .= "<message>" $value "</message>";
  569.                 
  570.                 $this->out .= "</errors>";
  571.             
  572.         
  573.     
  574.  
  575.     function makeStyles()
  576.     {
  577.         $this->outstyles = "<style type=\"text/css\"><!--\n";
  578.         reset($this->styles);
  579.         while (list($stylename$styleattribeach($this->styles)) {
  580.             $this->outstyles .= "." $stylename " { " $styleattrib " }\n";
  581.         
  582.         $this->outstyles .= "--></style>\n";
  583.     
  584.  
  585.     /*
  586.         finally ..
  587.  
  588.         How this parser (is supposed) to work:
  589.         ======================================
  590.         This parse simple starts at the beginning of the rtf core stream, 
  591.         catches every controlling character {,} and \, automatically builds 
  592.         control words and control symbols during his livetime, trashes 
  593.         every other character into the plain text queue
  594.     */
  595.     function parse()
  596.     {
  597.         $this->parserInit();
  598.  
  599.         $i 0;
  600.         $this->cw = false// flag if control word is currently parsed
  601.         $this->cfirst = false// first control character ?
  602.         $this->cword = ""// last or current control word ( depends on $this->cw
  603.         
  604.         $this->queue = ""// plain text data found during parsing
  605.         
  606.         $this->flushHead();
  607.  
  608.         while ($i $this->len{
  609.             switch ($this->rtf[$i]{
  610.                 case "{":
  611.                     if ($this->cw{
  612.                         $this->flushControl();
  613.                         $this->cw = false;
  614.                         $this->cfirst = false;
  615.                     else {
  616.                         $this->flushQueue();
  617.                     
  618.                     $this->flushGroup("open");
  619.                     break;
  620.                 case "}":
  621.                     if ($this->cw{
  622.                         $this->flushControl();
  623.                         $this->cw = false;
  624.                         $this->cfirst = false;
  625.                     else {
  626.                         $this->flushQueue();
  627.                     
  628.                     $this->flushGroup("close");
  629.                     break;
  630.                 case "\\":
  631.                     if ($this->cfirst// catches '\\'
  632.                         $this->queue .= '\\';
  633.                         $this->cfirst = false;
  634.                         $this->cw = false;
  635.                         break;
  636.                     
  637.                     if ($this->cw{
  638.                         $this->flushControl();
  639.                     else {
  640.                         $this->flushQueue();
  641.                     
  642.                     $this->cw = true;
  643.                     $this->cfirst = true;
  644.                     $this->cword = "";
  645.                     break;
  646.                 default:
  647.                     if ((ord($this->rtf[$i]== 10|| (ord($this->rtf[$i]== 13)) break// eat line breaks
  648.                     if ($this->cw// active control word ?
  649.                         /*
  650.                             Watch the RE: there's an optional space at the end which IS part of
  651.                             the control word (but actually its ignored by flushControl)
  652.                         */
  653.                         if (ereg("^[a-zA-Z0-9-]?$"$this->rtf[$i])) // continue parsing
  654.                             $this->cword .= $this->rtf[$i];
  655.                             $this->cfirst = false;
  656.                         else {
  657.                             /*
  658.                                 Control word could be a 'control symbol', like \~ or \* etc.
  659.                             */
  660.                             $specialmatch false;
  661.                             if ($this->cfirst{
  662.                                 if ($this->rtf[$i== '\''// expect to get some special chars
  663.                                     $this->flushQueue();
  664.                                     $this->flushSpecial($this->rtf[$i 1$this->rtf[$i 2]);
  665.                                     $i += 2;
  666.                                     $specialmatch true;
  667.                                     $this->cw = false;
  668.                                     $this->cfirst = false;
  669.                                     $this->cword = "";
  670.                                 else
  671.                                 if (ereg("^[{}\*]$"$this->rtf[$i])) {
  672.                                     $this->flushComment("control symbols not yet handled");
  673.                                     $specialmatch true;
  674.                                 
  675.                                 $this->cfirst = false;
  676.                             else {
  677.                                 if ($this->rtf[$i== ' '// space delimtes control words, so just discard it and flush the controlword
  678.                                     $this->cw = false;
  679.                                     $this->flushControl();
  680.                                     break;
  681.                                 
  682.                             
  683.                             if ($specialmatch{
  684.                                 $this->flushControl();
  685.                                 $this->cw = false;
  686.                                 $this->cfirst = false;
  687.                                 /*
  688.                                     The current character is a delimeter, but is NOT
  689.                                     part of the control word so we hop one step back
  690.                                     in the stream and process it again
  691.                                 */
  692.                                 $i--;
  693.                             
  694.                         
  695.                     else {
  696.                         // < and > need translation before putting into queue when XML or HTML is wanted
  697.                         if (($this->wantHTML|| ($this->wantXML)) {
  698.                             switch ($this->rtf[$i]{
  699.                                 case "<":
  700.                                     $this->queue .= "&lt;";
  701.                                     break;
  702.                                 case ">":
  703.                                     $this->queue .= "&gt;";
  704.                                     break;
  705.                                 default:
  706.                                     $this->queue .= $this->rtf[$i];
  707.                                     break;
  708.                             
  709.                         else {
  710.                             $this->queue .= $this->rtf[$i];
  711.                         
  712.                     
  713.             
  714.             $i++;
  715.         
  716.         $this->flushQueue();
  717.         $this->flushErrors();
  718.         $this->flushBottom();
  719.  
  720.         if ($this->wantHTML{
  721.             $this->makeStyles();
  722.         
  723.         echo "<hr>\n<b>RTF Out</b><br>\n<code>\n";
  724.         echo "--->" $this->out . "<---<br>\n";
  725.         echo "</code>\n<br>\n<hr>\n";
  726.     
  727.  
  728. ?>

Documentation generated on Thu, 22 Jan 2009 09:17:48 +0100 by phpDocumentor 1.4.2