Back to index

texmacs  1.0.7.15
totm.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : totm.cpp
00004 * DESCRIPTION: conversion of TeXmacs trees to the TeXmacs file format
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "convert.hpp"
00013 #include "drd_std.hpp"
00014 
00015 /******************************************************************************
00016 * Conversion of TeXmacs trees to the present TeXmacs string format
00017 ******************************************************************************/
00018 
00019 struct tm_writer {
00020   string  buf;       // the resulting string
00021   string  spc;       // "" or " "
00022   string  tmp;       // not yet flushed characters
00023   int     mode;      // normal: 0, verbatim: 1, mathematics: 2
00024 
00025   int     tab;       // number of tabs after CR
00026   int     xpos;      // current horizontal position in buf
00027   bool    spc_flag;  // true if last printed character was a space or CR
00028   bool    ret_flag;  // true if last printed character was a CR
00029 
00030   tm_writer ():
00031     buf (""), spc (""), tmp (""), mode (0),
00032     tab (0), xpos (0), spc_flag (true), ret_flag (true) {}
00033 
00034   void cr ();
00035   void flush ();
00036   void write_space ();
00037   void write_return ();
00038   void write (string s, bool flag= true, bool encode_space= false);
00039   void br (int indent= 0);
00040   void tag (string before, string s, string after);
00041   void apply (string func, array<tree> args);
00042   void write (tree t);
00043 };
00044 
00045 void
00046 tm_writer::cr () {
00047   int i, n= N(buf);
00048   for (i=n-1; i>=0; i--)
00049     if ((buf[i] != ' ') || ((i>0) && (buf[i-1] == '\\')))
00050       break;
00051   if (i<n-1) {
00052     buf= buf (0, i+1);
00053     n  = n- N(buf);
00054     for (i=0; i<n; i++) buf << "\\ ";
00055   }
00056   buf << '\n';
00057   for (i=0; i<min(tab,20); i++) buf << ' ';
00058   xpos= min(tab,20);
00059 }
00060 
00061 void
00062 tm_writer::flush () {
00063   int i, m= N(spc), n= N(tmp);
00064   if ((m+n)==0) return;
00065   if ((xpos+m+n) < 78) {
00066     buf << spc << tmp;
00067     xpos += m+n;
00068   }
00069   else {
00070     if (spc == " ") {
00071       if (xpos > 40) cr ();
00072       else {
00073        buf << " ";
00074        xpos++;
00075       }
00076     }
00077     if ((xpos+n) < 78) {
00078       buf << tmp;
00079       xpos += n;
00080     }
00081     else for (i=0; i<n; ) {
00082       if (((i+1) < n) && (tmp[i] == '\\') && (tmp[i+1] == ' ')) {
00083        /* not nice when searching text in a .tm file
00084        if (xpos >= 76) {
00085          buf << "\\";
00086          cr ();
00087        }
00088        */
00089        buf << "\\ ";
00090        xpos += 2;
00091        i += 2;
00092       }
00093       else {
00094        /* not nice when searching text in a .tm file
00095        if (xpos >= 77) {
00096          buf << "\\";
00097          cr ();
00098        }
00099        */
00100        buf << tmp[i];
00101        xpos++;
00102        i++;
00103       }
00104     }
00105   }
00106   spc= "";
00107   tmp= "";
00108 }
00109 
00110 void
00111 tm_writer::write_space () {
00112   if (spc_flag) tmp << "\\ ";
00113   else {
00114     flush ();
00115     spc= " ";
00116   }
00117   spc_flag= true;
00118   ret_flag= false;
00119 }
00120 
00121 void
00122 tm_writer::write_return () {
00123   if (ret_flag) {
00124     buf << "\\;\n";
00125     cr ();
00126   }
00127   else {
00128     if ((spc == " ") && (tmp == "")) {
00129       spc= "";
00130       tmp= "\\ ";
00131     }
00132     flush ();
00133     buf << "\n";
00134     cr ();
00135   }
00136   spc_flag= true;
00137   ret_flag= true;
00138 }
00139 
00140 void
00141 tm_writer::write (string s, bool flag, bool encode_space) {
00142   if (flag) {
00143     int i, n=N(s);
00144     for (i=0; i<n; i++) {
00145       char c= s[i];
00146       if ((c == ' ') && (!encode_space)) write_space ();
00147       else {
00148        if (c == ' ') tmp << "\\ ";
00149        else if (c == '\n') tmp << "\\n";
00150        else if (c == '\t') tmp << "\\t";
00151        else if (c == '\0') tmp << "\\0";
00152        else if (c == '\\') tmp << "\\\\";
00153        else if (c == '<') tmp << "\\<";
00154        else if (c == '|') tmp << "\\|";
00155        else if (c == '>') tmp << "\\>";
00156        else if (c == '\34') tmp << c;
00157        else if (((unsigned char) c) < ' ') tmp << '\\' << (c+'@');
00158        else tmp << c;
00159        spc_flag= false;
00160        ret_flag= false;
00161       }
00162     }
00163   }
00164   else {
00165     tmp << s;
00166     if (N(s) != 0) {
00167       spc_flag= false;
00168       ret_flag= false;
00169     }
00170   }
00171 }
00172 
00173 void
00174 tm_writer::br (int indent) {
00175   int i;
00176   flush ();
00177   tab += indent;
00178   for (i=N(buf)-1; i>=0; i--) {
00179     if (buf[i] == '\n') return;
00180     if (buf[i] != ' ') {
00181       cr ();
00182       spc_flag= true;
00183       ret_flag= false;
00184       return;
00185     }
00186   }
00187 }
00188 
00189 void
00190 tm_writer::tag (string before, string s, string after) {
00191   write (before, false);
00192   write (s);
00193   write (after, false);
00194 }
00195 
00196 void
00197 tm_writer::apply (string func, array<tree> args) {
00198   int i, last, n=N(args);
00199   for (i=n-1; i>=0; i--)
00200     if (is_document (args[i]) || is_func (args[i], COLLECTION))
00201       break;
00202   last= i;
00203 
00204   if (last >= 0) {
00205     /*
00206     tag ("<\\", func, ">");
00207     for (i=0; i<n; i++) {
00208       if (is_empty (args[i])) br ();
00209       else {
00210        br (2);
00211        write (args[i]);
00212        br (-2);
00213       }
00214       if (i<(n-1)) tag ("<|", func, ">");
00215     }
00216     tag ("</", func, ">");
00217     */
00218     
00219     for (i=0; i<=n; i++) {
00220       bool flag=
00221        (i<n) && (is_document (args[i]) || is_func (args[i], COLLECTION));
00222       if (i==0) { write ("<\\", false); write (func, true, true); }
00223       else if (i==last+1) {write ("</", false); write (func, true, true); }
00224       else if (is_document (args[i-1]) || is_func (args[i-1], COLLECTION)) {
00225        write ("<|", false); write (func, true, true); }
00226       if (i==n) {
00227        write (">", false);
00228        break;
00229       }
00230 
00231       if (flag) {
00232        write (">", false);
00233        br (2);
00234        write (args[i]);
00235        br (-2);      
00236       }
00237       else {
00238        write ("|", false);
00239        write (args[i]);
00240       }
00241     }
00242   }
00243   else {
00244     write ("<", false);
00245     write (func, true, true);
00246     for (i=0; i<n; i++) {
00247       write ("|", false);
00248       write (args[i]);
00249     }
00250     write (">", false);
00251   }
00252 }
00253 
00254 void
00255 tm_writer::write (tree t) {
00256   if (is_atomic (t)) {
00257     write (t->label);
00258     return;
00259   }
00260 
00261   int i, n= N(t);
00262   switch (L(t)) {
00263   case RAW_DATA:
00264     {
00265       write ("<#", false);
00266       string s= as_string (t[0]);
00267       for (i=0; i<N(s); i++)
00268        write (as_hexadecimal ((unsigned char) s[i], 2), false);
00269       write (">", false);
00270       break;
00271     }
00272   case DOCUMENT:
00273     spc_flag= true;
00274     ret_flag= true;
00275     for (i=0; i<n; i++) {
00276       write (t[i]);
00277       if (i<(n-1)) write_return ();
00278       else if (ret_flag) write ("\\;", false);
00279     }
00280     break;
00281   case CONCAT:
00282     for (i=0; i<n; i++) write (t[i]);
00283     break;
00284   case EXPAND:
00285     if ((n>=1) && is_atomic (t[0])) {
00286       string s= t[0]->label;
00287       if (std_contains (s));
00288       else if ((N(s)>0) && (!is_iso_alpha (s)));
00289       else {
00290        apply (s, A(t(1,n)));
00291        break;
00292       }
00293     }
00294     apply (as_string (EXPAND), A(t));
00295     break;
00296   case COLLECTION:
00297     tag ("<\\", as_string (COLLECTION), ">");
00298     if (n==0) br ();
00299     else {
00300       br (2);
00301       for (i=0; i<n; i++) {
00302        write (t[i]);
00303        if (i<(n-1)) br ();
00304       }
00305       br (-2);
00306     }
00307     tag ("</", as_string (COLLECTION), ">");
00308     break;
00309   default:
00310     apply (as_string (L(t)), A(t));
00311     break;
00312   }
00313 }
00314 
00315 /******************************************************************************
00316 * Conversion of TeXmacs trees to TeXmacs strings
00317 ******************************************************************************/
00318 
00319 string
00320 tree_to_texmacs (tree t) {
00321   if (!is_snippet (t)) {
00322     int i, n= N(t);
00323     tree r (t, n);
00324     for (i=0; i<n; i++)
00325       if (is_compound (t[i], "style", 1)) {
00326        tree style= t[i][0];
00327        if (is_func (style, TUPLE, 1)) style= style[0];
00328        r[i]= copy (t[i]);
00329        r[i][0]= style;
00330       }
00331       else r[i]= t[i];
00332     t= r;
00333   }
00334 
00335   tm_writer tmw;
00336   tmw.write (t);
00337   tmw.flush ();
00338   return tmw.buf;
00339 }